Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(549)

Side by Side Diff: third_party/polymer/v1_0/components-chromium/iron-dropdown/iron-dropdown-scroll-manager-extracted.js

Issue 1261403002: Add paper-menu-button and its dependencies to third_party/polymer (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: reproduce.sh Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1
2 (function() {
3 'use strict';
4
5 /**
6 * The IronDropdownScrollManager is intended to provide a central source
7 * of authority and control over which elements in a document are currently
8 * allowed to scroll.
9 */
10
11 Polymer.IronDropdownScrollManager = {
12
13 /**
14 * The current element that defines the DOM boundaries of the
15 * scroll lock. This is always the most recently locking element.
16 */
17 get currentLockingElement() {
18 return this._lockingElements[this._lockingElements.length - 1];
19 },
20
21
22 /**
23 * Returns true if the provided element is "scroll locked," which is to
24 * say that it cannot be scrolled via pointer or keyboard interactions.
25 *
26 * @param {HTMLElement} element An HTML element instance which may or may
27 * not be scroll locked.
28 */
29 elementIsScrollLocked: function(element) {
30 var currentLockingElement = this.currentLockingElement;
31 var scrollLocked;
32
33 if (this._hasCachedLockedElement(element)) {
34 return true;
35 }
36
37 if (this._hasCachedUnlockedElement(element)) {
38 return false;
39 }
40
41 scrollLocked = !!currentLockingElement &&
42 currentLockingElement !== element &&
43 !this._composedTreeContains(currentLockingElement, element);
44
45 if (scrollLocked) {
46 this._lockedElementCache.push(element);
47 } else {
48 this._unlockedElementCache.push(element);
49 }
50
51 return scrollLocked;
52 },
53
54 /**
55 * Push an element onto the current scroll lock stack. The most recently
56 * pushed element and its children will be considered scrollable. All
57 * other elements will not be scrollable.
58 *
59 * Scroll locking is implemented as a stack so that cases such as
60 * dropdowns within dropdowns are handled well.
61 *
62 * @param {HTMLElement} element The element that should lock scroll.
63 */
64 pushScrollLock: function(element) {
65 if (this._lockingElements.length === 0) {
66 this._lockScrollInteractions();
67 }
68
69 this._lockingElements.push(element);
70
71 this._lockedElementCache = [];
72 this._unlockedElementCache = [];
73 },
74
75 /**
76 * Remove an element from the scroll lock stack. The element being
77 * removed does not need to be the most recently pushed element. However,
78 * the scroll lock constraints only change when the most recently pushed
79 * element is removed.
80 *
81 * @param {HTMLElement} element The element to remove from the scroll
82 * lock stack.
83 */
84 removeScrollLock: function(element) {
85 var index = this._lockingElements.indexOf(element);
86
87 if (index === -1) {
88 return;
89 }
90
91 this._lockingElements.splice(index, 1);
92
93 this._lockedElementCache = [];
94 this._unlockedElementCache = [];
95
96 if (this._lockingElements.length === 0) {
97 this._unlockScrollInteractions();
98 }
99 },
100
101 _lockingElements: [],
102
103 _lockedElementCache: null,
104
105 _unlockedElementCache: null,
106
107 _originalBodyStyles: {},
108
109 _isScrollingKeypress: function(event) {
110 return Polymer.IronA11yKeysBehavior.keyboardEventMatchesKeys(
111 event, 'pageup pagedown home end up left down right');
112 },
113
114 _hasCachedLockedElement: function(element) {
115 return this._lockedElementCache.indexOf(element) > -1;
116 },
117
118 _hasCachedUnlockedElement: function(element) {
119 return this._unlockedElementCache.indexOf(element) > -1;
120 },
121
122 _composedTreeContains: function(element, child) {
123 // NOTE(cdata): This method iterates over content elements and their
124 // corresponding distributed nodes to implement a contains-like method
125 // that pierces through the composed tree of the ShadowDOM. Results of
126 // this operation are cached (elsewhere) on a per-scroll-lock basis, to
127 // guard against potentially expensive lookups happening repeatedly as
128 // a user scrolls / touchmoves.
129 var contentElements;
130 var distributedNodes;
131 var contentIndex;
132 var nodeIndex;
133
134 if (element.contains(child)) {
135 return true;
136 }
137
138 contentElements = Polymer.dom(element).querySelectorAll('content');
139
140 for (contentIndex = 0; contentIndex < contentElements.length; ++contentI ndex) {
141
142 distributedNodes = Polymer.dom(contentElements[contentIndex]).getDistr ibutedNodes();
143
144 for (nodeIndex = 0; nodeIndex < distributedNodes.length; ++nodeIndex) {
145
146 if (this._composedTreeContains(distributedNodes[nodeIndex], child)) {
147 return true;
148 }
149 }
150 }
151
152 return false;
153 },
154
155 _scrollInteractionHandler: function(event) {
156 if (Polymer
157 .IronDropdownScrollManager
158 .elementIsScrollLocked(event.target)) {
159 if (event.type === 'keydown' &&
160 !Polymer.IronDropdownScrollManager._isScrollingKeypress(event)) {
161 return;
162 }
163
164 event.preventDefault();
165 }
166 },
167
168 _lockScrollInteractions: function() {
169 // Memoize body inline styles:
170 this._originalBodyStyles.overflow = document.body.style.overflow;
171 this._originalBodyStyles.overflowX = document.body.style.overflowX;
172 this._originalBodyStyles.overflowY = document.body.style.overflowY;
173
174 // Disable overflow scrolling on body:
175 // TODO(cdata): It is technically not sufficient to hide overflow on
176 // body alone. A better solution might be to traverse all ancestors of
177 // the current scroll locking element and hide overflow on them. This
178 // becomes expensive, though, as it would have to be redone every time
179 // a new scroll locking element is added.
180 document.body.style.overflow = 'hidden';
181 document.body.style.overflowX = 'hidden';
182 document.body.style.overflowY = 'hidden';
183
184 // Modern `wheel` event for mouse wheel scrolling:
185 window.addEventListener('wheel', this._scrollInteractionHandler, true);
186 // Older, non-standard `mousewheel` event for some FF:
187 window.addEventListener('mousewheel', this._scrollInteractionHandler, tr ue);
188 // IE:
189 window.addEventListener('DOMMouseScroll', this._scrollInteractionHandler , true);
190 // Mobile devices can scroll on touch move:
191 window.addEventListener('touchmove', this._scrollInteractionHandler, tru e);
192 // Capture keydown to prevent scrolling keys (pageup, pagedown etc.)
193 document.addEventListener('keydown', this._scrollInteractionHandler, tru e);
194 },
195
196 _unlockScrollInteractions: function() {
197 document.body.style.overflow = this._originalBodyStyles.overflow;
198 document.body.style.overflowX = this._originalBodyStyles.overflowX;
199 document.body.style.overflowY = this._originalBodyStyles.overflowY;
200
201 window.removeEventListener('wheel', this._scrollInteractionHandler, true );
202 window.removeEventListener('mousewheel', this._scrollInteractionHandler, true);
203 window.removeEventListener('DOMMouseScroll', this._scrollInteractionHand ler, true);
204 window.removeEventListener('touchmove', this._scrollInteractionHandler, true);
205 document.removeEventListener('keydown', this._scrollInteractionHandler, true);
206 }
207 };
208 })();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698