<!-- @license Copyright (c) 2016 The Polymer Project Authors. All rights reserved. This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as part of the polymer project is also subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt --> <link rel="import" href="../polymer/polymer.html"> <script> /** * `Polymer.IronScrollTargetBehavior` allows an element to respond to scroll events from a * designated scroll target. * * Elements that consume this behavior can override the `_scrollHandler` * method to add logic on the scroll event. * * @demo demo/scrolling-region.html Scrolling Region * @demo demo/document.html Document Element * @polymerBehavior */ Polymer.IronScrollTargetBehavior = { properties: { /** * Specifies the element that will handle the scroll event * on the behalf of the current element. This is typically a reference to an element, * but there are a few more posibilities: * * ### Elements id * *```html * <div id="scrollable-element" style="overflow: auto;"> * <x-element scroll-target="scrollable-element"> * <!-- Content--> * </x-element> * </div> *``` * In this case, the `scrollTarget` will point to the outer div element. * * ### Document scrolling * * For document scrolling, you can use the reserved word `document`: * *```html * <x-element scroll-target="document"> * <!-- Content --> * </x-element> *``` * * ### Elements reference * *```js * appHeader.scrollTarget = document.querySelector('#scrollable-element'); *``` * * @type {HTMLElement} */ scrollTarget: { type: HTMLElement, value: function() { return this._defaultScrollTarget; } } }, observers: [ '_scrollTargetChanged(scrollTarget, isAttached)' ], _scrollTargetChanged: function(scrollTarget, isAttached) { var eventTarget; if (this._oldScrollTarget) { eventTarget = this._oldScrollTarget === this._doc ? window : this._oldScrollTarget; eventTarget.removeEventListener('scroll', this._boundScrollHandler); this._oldScrollTarget = null; } if (!isAttached) { return; } // Support element id references if (scrollTarget === 'document') { this.scrollTarget = this._doc; } else if (typeof scrollTarget === 'string') { this.scrollTarget = this.domHost ? this.domHost.$[scrollTarget] : Polymer.dom(this.ownerDocument).querySelector('#' + scrollTarget); } else if (this._isValidScrollTarget()) { eventTarget = scrollTarget === this._doc ? window : scrollTarget; this._boundScrollHandler = this._boundScrollHandler || this._scrollHandler.bind(this); this._oldScrollTarget = scrollTarget; eventTarget.addEventListener('scroll', this._boundScrollHandler); } }, /** * Runs on every scroll event. Consumer of this behavior may override this method. * * @protected */ _scrollHandler: function scrollHandler() {}, /** * The default scroll target. Consumers of this behavior may want to customize * the default scroll target. * * @type {Element} */ get _defaultScrollTarget() { return this._doc; }, /** * Shortcut for the document element * * @type {Element} */ get _doc() { return this.ownerDocument.documentElement; }, /** * Gets the number of pixels that the content of an element is scrolled upward. * * @type {number} */ get _scrollTop() { if (this._isValidScrollTarget()) { return this.scrollTarget === this._doc ? window.pageYOffset : this.scrollTarget.scrollTop; } return 0; }, /** * Gets the number of pixels that the content of an element is scrolled to the left. * * @type {number} */ get _scrollLeft() { if (this._isValidScrollTarget()) { return this.scrollTarget === this._doc ? window.pageXOffset : this.scrollTarget.scrollLeft; } return 0; }, /** * Sets the number of pixels that the content of an element is scrolled upward. * * @type {number} */ set _scrollTop(top) { if (this.scrollTarget === this._doc) { window.scrollTo(window.pageXOffset, top); } else if (this._isValidScrollTarget()) { this.scrollTarget.scrollTop = top; } }, /** * Sets the number of pixels that the content of an element is scrolled to the left. * * @type {number} */ set _scrollLeft(left) { if (this.scrollTarget === this._doc) { window.scrollTo(left, window.pageYOffset); } else if (this._isValidScrollTarget()) { this.scrollTarget.scrollLeft = left; } }, /** * Scrolls the content to a particular place. * * @method scroll * @param {number} left The left position * @param {number} top The top position */ scroll: function(left, top) { if (this.scrollTarget === this._doc) { window.scrollTo(left, top); } else if (this._isValidScrollTarget()) { this.scrollTarget.scrollLeft = left; this.scrollTarget.scrollTop = top; } }, /** * Gets the width of the scroll target. * * @type {number} */ get _scrollTargetWidth() { if (this._isValidScrollTarget()) { return this.scrollTarget === this._doc ? window.innerWidth : this.scrollTarget.offsetWidth; } return 0; }, /** * Gets the height of the scroll target. * * @type {number} */ get _scrollTargetHeight() { if (this._isValidScrollTarget()) { return this.scrollTarget === this._doc ? window.innerHeight : this.scrollTarget.offsetHeight; } return 0; }, /** * Returns true if the scroll target is a valid HTMLElement. * * @return {boolean} */ _isValidScrollTarget: function() { return this.scrollTarget instanceof HTMLElement; } }; </script>