From 2d577cd4a695310e02db1217d9f8eff5f9bdf1d1 Mon Sep 17 00:00:00 2001 From: Sebastian Helbig Date: Wed, 9 Aug 2017 22:57:00 +0200 Subject: [PATCH] configurable scroll element (#67) * configurable scroll element * removing some lines --- README.md | 9 ++++++++ addon/index.js | 12 ++++++++++- addon/services/router-scroll.js | 37 +++++++++++++++++++++++++++++++-- 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index a0111075..68f972cd 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,15 @@ ember install ember-router-scroll ``` +### Options +You can specify the id of an element for which the scroll position is saved and set. Default is `window` for using the scroll position of the whole viewport. You can pass an options object in your application's `config/environment.js` file. + +```javascript +ENV['routerScroll'] = { + scrollElement: '#mainScrollElement' +}; +``` + ### A small note Like all good ember addons, this behavior was considered for core implementation. Good news, people like the idea. For now, the feature will live under the flag `ember-unique-location-history-state` until it's finally released in Ember 2.13. You can follow along for yourself [here](https://github.com/emberjs/ember.js/pull/14011/) and read up on the [RFC](https://github.com/emberjs/rfcs/pull/186#issuecomment-271416805) if you'd like as well. diff --git a/addon/index.js b/addon/index.js index 81168241..77c8564e 100644 --- a/addon/index.js +++ b/addon/index.js @@ -28,13 +28,23 @@ export default Mixin.create({ }, updateScrollPosition(transitions) { + const scrollElement = get(this, 'service.scrollElement'); let scrollPosition = get(this, 'service.position'); let preserveScrollPosition = transitions[transitions.length - 1] .handler.controller.get('preserveScrollPosition'); if (!preserveScrollPosition) { - window.scrollTo(scrollPosition.x, scrollPosition.y); + if ('window' === scrollElement) { + window.scrollTo(scrollPosition.x, scrollPosition.y); + } else if ('#' === scrollElement.charAt(0)) { + let element = document.getElementById(scrollElement.substring(1)); + + if (element) { + element.scrollLeft = scrollPosition.x; + element.scrollTop = scrollPosition.y; + } + } } } }); diff --git a/addon/services/router-scroll.js b/addon/services/router-scroll.js index b25fa74f..09480cb3 100644 --- a/addon/services/router-scroll.js +++ b/addon/services/router-scroll.js @@ -1,20 +1,41 @@ /* eslint-disable */ +import Ember from 'ember'; import Service from '@ember/service'; import { getWithDefault, computed, set, get } from '@ember/object'; +const { getOwner, typeOf } = Ember; + export default Service.extend({ + scrollElement: 'window', + init(...args) { this._super(...args); + this._loadConfig(); set(this, 'scrollMap', {}); set(this, 'key', null); }, update() { + const scrollElement = get(this, 'scrollElement'); const scrollMap = get(this, 'scrollMap'); const key = get(this, 'key'); + let x; + let y; + + if ('window' === scrollElement) { + x = window.scrollX; + y = window.scrollY; + } else if ('#' === scrollElement.charAt(0)) { + let element = document.getElementById(scrollElement.substring(1)); + + if (element) { + x = element.scrollLeft; + y = element.scrollTop; + } + } - if (key) { - set(scrollMap, key, { x: window.scrollX, y: window.scrollY }); + if (key && 'number' === typeOf(x) && 'number' === typeOf(y)) { + set(scrollMap, key, { x, y }); } }, @@ -27,4 +48,16 @@ export default Service.extend({ return getWithDefault(scrollMap, key, { x: 0, y: 0 }); }).volatile(), + + _loadConfig() { + const config = getOwner(this).resolveRegistration('config:environment'); + + if (config && config.routerScroll && config.routerScroll.scrollElement) { + const scrollElement = config.routerScroll.scrollElement; + + if ('string' === typeOf(config.routerScroll.scrollElement)) { + set(this, 'scrollElement', config.routerScroll.scrollElement); + } + } + } });