| Index: polymer_1.0.4/bower_components/iron-dropdown/iron-dropdown-scroll-manager.html
|
| diff --git a/polymer_1.0.4/bower_components/iron-dropdown/iron-dropdown-scroll-manager.html b/polymer_1.0.4/bower_components/iron-dropdown/iron-dropdown-scroll-manager.html
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..d895dd603ad353c994e6812be090b1d74ff03de8
|
| --- /dev/null
|
| +++ b/polymer_1.0.4/bower_components/iron-dropdown/iron-dropdown-scroll-manager.html
|
| @@ -0,0 +1,222 @@
|
| +<!--
|
| +@license
|
| +Copyright (c) 2015 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">
|
| +<link rel="import" href="../iron-a11y-keys-behavior/iron-a11y-keys-behavior.html">
|
| +
|
| +<script>
|
| + (function() {
|
| + 'use strict';
|
| +
|
| + /**
|
| + * The IronDropdownScrollManager is intended to provide a central source
|
| + * of authority and control over which elements in a document are currently
|
| + * allowed to scroll.
|
| + */
|
| +
|
| + Polymer.IronDropdownScrollManager = {
|
| +
|
| + /**
|
| + * The current element that defines the DOM boundaries of the
|
| + * scroll lock. This is always the most recently locking element.
|
| + */
|
| + get currentLockingElement() {
|
| + return this._lockingElements[this._lockingElements.length - 1];
|
| + },
|
| +
|
| +
|
| + /**
|
| + * Returns true if the provided element is "scroll locked," which is to
|
| + * say that it cannot be scrolled via pointer or keyboard interactions.
|
| + *
|
| + * @param {HTMLElement} element An HTML element instance which may or may
|
| + * not be scroll locked.
|
| + */
|
| + elementIsScrollLocked: function(element) {
|
| + var currentLockingElement = this.currentLockingElement;
|
| + var scrollLocked;
|
| +
|
| + if (this._hasCachedLockedElement(element)) {
|
| + return true;
|
| + }
|
| +
|
| + if (this._hasCachedUnlockedElement(element)) {
|
| + return false;
|
| + }
|
| +
|
| + scrollLocked = !!currentLockingElement &&
|
| + currentLockingElement !== element &&
|
| + !this._composedTreeContains(currentLockingElement, element);
|
| +
|
| + if (scrollLocked) {
|
| + this._lockedElementCache.push(element);
|
| + } else {
|
| + this._unlockedElementCache.push(element);
|
| + }
|
| +
|
| + return scrollLocked;
|
| + },
|
| +
|
| + /**
|
| + * Push an element onto the current scroll lock stack. The most recently
|
| + * pushed element and its children will be considered scrollable. All
|
| + * other elements will not be scrollable.
|
| + *
|
| + * Scroll locking is implemented as a stack so that cases such as
|
| + * dropdowns within dropdowns are handled well.
|
| + *
|
| + * @param {HTMLElement} element The element that should lock scroll.
|
| + */
|
| + pushScrollLock: function(element) {
|
| + if (this._lockingElements.length === 0) {
|
| + this._lockScrollInteractions();
|
| + }
|
| +
|
| + this._lockingElements.push(element);
|
| +
|
| + this._lockedElementCache = [];
|
| + this._unlockedElementCache = [];
|
| + },
|
| +
|
| + /**
|
| + * Remove an element from the scroll lock stack. The element being
|
| + * removed does not need to be the most recently pushed element. However,
|
| + * the scroll lock constraints only change when the most recently pushed
|
| + * element is removed.
|
| + *
|
| + * @param {HTMLElement} element The element to remove from the scroll
|
| + * lock stack.
|
| + */
|
| + removeScrollLock: function(element) {
|
| + var index = this._lockingElements.indexOf(element);
|
| +
|
| + if (index === -1) {
|
| + return;
|
| + }
|
| +
|
| + this._lockingElements.splice(index, 1);
|
| +
|
| + this._lockedElementCache = [];
|
| + this._unlockedElementCache = [];
|
| +
|
| + if (this._lockingElements.length === 0) {
|
| + this._unlockScrollInteractions();
|
| + }
|
| + },
|
| +
|
| + _lockingElements: [],
|
| +
|
| + _lockedElementCache: null,
|
| +
|
| + _unlockedElementCache: null,
|
| +
|
| + _originalBodyStyles: {},
|
| +
|
| + _isScrollingKeypress: function(event) {
|
| + return Polymer.IronA11yKeysBehavior.keyboardEventMatchesKeys(
|
| + event, 'pageup pagedown home end up left down right');
|
| + },
|
| +
|
| + _hasCachedLockedElement: function(element) {
|
| + return this._lockedElementCache.indexOf(element) > -1;
|
| + },
|
| +
|
| + _hasCachedUnlockedElement: function(element) {
|
| + return this._unlockedElementCache.indexOf(element) > -1;
|
| + },
|
| +
|
| + _composedTreeContains: function(element, child) {
|
| + // NOTE(cdata): This method iterates over content elements and their
|
| + // corresponding distributed nodes to implement a contains-like method
|
| + // that pierces through the composed tree of the ShadowDOM. Results of
|
| + // this operation are cached (elsewhere) on a per-scroll-lock basis, to
|
| + // guard against potentially expensive lookups happening repeatedly as
|
| + // a user scrolls / touchmoves.
|
| + var contentElements;
|
| + var distributedNodes;
|
| + var contentIndex;
|
| + var nodeIndex;
|
| +
|
| + if (element.contains(child)) {
|
| + return true;
|
| + }
|
| +
|
| + contentElements = Polymer.dom(element).querySelectorAll('content');
|
| +
|
| + for (contentIndex = 0; contentIndex < contentElements.length; ++contentIndex) {
|
| +
|
| + distributedNodes = Polymer.dom(contentElements[contentIndex]).getDistributedNodes();
|
| +
|
| + for (nodeIndex = 0; nodeIndex < distributedNodes.length; ++nodeIndex) {
|
| +
|
| + if (this._composedTreeContains(distributedNodes[nodeIndex], child)) {
|
| + return true;
|
| + }
|
| + }
|
| + }
|
| +
|
| + return false;
|
| + },
|
| +
|
| + _scrollInteractionHandler: function(event) {
|
| + if (Polymer
|
| + .IronDropdownScrollManager
|
| + .elementIsScrollLocked(event.target)) {
|
| + if (event.type === 'keydown' &&
|
| + !Polymer.IronDropdownScrollManager._isScrollingKeypress(event)) {
|
| + return;
|
| + }
|
| +
|
| + event.preventDefault();
|
| + }
|
| + },
|
| +
|
| + _lockScrollInteractions: function() {
|
| + // Memoize body inline styles:
|
| + this._originalBodyStyles.overflow = document.body.style.overflow;
|
| + this._originalBodyStyles.overflowX = document.body.style.overflowX;
|
| + this._originalBodyStyles.overflowY = document.body.style.overflowY;
|
| +
|
| + // Disable overflow scrolling on body:
|
| + // TODO(cdata): It is technically not sufficient to hide overflow on
|
| + // body alone. A better solution might be to traverse all ancestors of
|
| + // the current scroll locking element and hide overflow on them. This
|
| + // becomes expensive, though, as it would have to be redone every time
|
| + // a new scroll locking element is added.
|
| + document.body.style.overflow = 'hidden';
|
| + document.body.style.overflowX = 'hidden';
|
| + document.body.style.overflowY = 'hidden';
|
| +
|
| + // Modern `wheel` event for mouse wheel scrolling:
|
| + window.addEventListener('wheel', this._scrollInteractionHandler, true);
|
| + // Older, non-standard `mousewheel` event for some FF:
|
| + window.addEventListener('mousewheel', this._scrollInteractionHandler, true);
|
| + // IE:
|
| + window.addEventListener('DOMMouseScroll', this._scrollInteractionHandler, true);
|
| + // Mobile devices can scroll on touch move:
|
| + window.addEventListener('touchmove', this._scrollInteractionHandler, true);
|
| + // Capture keydown to prevent scrolling keys (pageup, pagedown etc.)
|
| + document.addEventListener('keydown', this._scrollInteractionHandler, true);
|
| + },
|
| +
|
| + _unlockScrollInteractions: function() {
|
| + document.body.style.overflow = this._originalBodyStyles.overflow;
|
| + document.body.style.overflowX = this._originalBodyStyles.overflowX;
|
| + document.body.style.overflowY = this._originalBodyStyles.overflowY;
|
| +
|
| + window.removeEventListener('wheel', this._scrollInteractionHandler, true);
|
| + window.removeEventListener('mousewheel', this._scrollInteractionHandler, true);
|
| + window.removeEventListener('DOMMouseScroll', this._scrollInteractionHandler, true);
|
| + window.removeEventListener('touchmove', this._scrollInteractionHandler, true);
|
| + document.removeEventListener('keydown', this._scrollInteractionHandler, true);
|
| + }
|
| + };
|
| + })();
|
| +</script>
|
|
|