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> |