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

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

Issue 1862213002: Roll third_party/polymer. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Remove obsolete appearance_browsertest.js, result of a previous bad merge. Created 4 years, 8 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
1 (function() { 1 (function() {
2 'use strict'; 2 'use strict';
3 3
4 Polymer({ 4 Polymer({
5 is: 'iron-dropdown', 5 is: 'iron-dropdown',
6 6
7 behaviors: [ 7 behaviors: [
8 Polymer.IronControlState, 8 Polymer.IronControlState,
9 Polymer.IronA11yKeysBehavior, 9 Polymer.IronA11yKeysBehavior,
10 Polymer.IronOverlayBehavior, 10 Polymer.IronOverlayBehavior,
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
70 type: Number, 70 type: Number,
71 value: 0, 71 value: 0,
72 notify: true 72 notify: true
73 }, 73 },
74 74
75 /** 75 /**
76 * The element that should be used to position the dropdown when 76 * The element that should be used to position the dropdown when
77 * it is opened. 77 * it is opened.
78 */ 78 */
79 positionTarget: { 79 positionTarget: {
80 type: Object, 80 type: Object
81 observer: '_positionTargetChanged'
82 }, 81 },
83 82
84 /** 83 /**
85 * An animation config. If provided, this will be used to animate the 84 * An animation config. If provided, this will be used to animate the
86 * opening of the dropdown. 85 * opening of the dropdown.
87 */ 86 */
88 openAnimationConfig: { 87 openAnimationConfig: {
89 type: Object 88 type: Object
90 }, 89 },
91 90
(...skipping 24 matching lines...) Expand all
116 115
117 /** 116 /**
118 * By default, the dropdown will constrain scrolling on the page 117 * By default, the dropdown will constrain scrolling on the page
119 * to itself when opened. 118 * to itself when opened.
120 * Set to true in order to prevent scroll from being constrained 119 * Set to true in order to prevent scroll from being constrained
121 * to the dropdown when it opens. 120 * to the dropdown when it opens.
122 */ 121 */
123 allowOutsideScroll: { 122 allowOutsideScroll: {
124 type: Boolean, 123 type: Boolean,
125 value: false 124 value: false
126 },
127
128 /**
129 * We memoize the positionTarget bounding rectangle so that we can
130 * limit the number of times it is queried per resize / relayout.
131 * @type {?Object}
132 */
133 _positionRectMemo: {
134 type: Object
135 } 125 }
136 }, 126 },
137 127
138 listeners: { 128 listeners: {
139 'neon-animation-finish': '_onNeonAnimationFinish' 129 'neon-animation-finish': '_onNeonAnimationFinish'
140 }, 130 },
141 131
142 observers: [ 132 observers: [
143 '_updateOverlayPosition(verticalAlign, horizontalAlign, verticalOffset , horizontalOffset)' 133 '_updateOverlayPosition(positionTarget, verticalAlign, horizontalAlign , verticalOffset, horizontalOffset)'
144 ], 134 ],
145 135
146 attached: function() { 136 attached: function() {
147 if (this.positionTarget === undefined) { 137 this.positionTarget = this.positionTarget || this._defaultPositionTarg et;
148 this.positionTarget = this._defaultPositionTarget; 138 // Memoize this to avoid expensive calculations & relayouts.
149 } 139 this._isRTL = window.getComputedStyle(this).direction == 'rtl';
150 }, 140 },
151 141
152 /** 142 /**
153 * The element that is contained by the dropdown, if any. 143 * The element that is contained by the dropdown, if any.
154 */ 144 */
155 get containedElement() { 145 get containedElement() {
156 return Polymer.dom(this.$.content).getDistributedNodes()[0]; 146 return Polymer.dom(this.$.content).getDistributedNodes()[0];
157 }, 147 },
158 148
159 /** 149 /**
160 * The element that should be focused when the dropdown opens. 150 * The element that should be focused when the dropdown opens.
161 * @deprecated 151 * @deprecated
162 */ 152 */
163 get _focusTarget() { 153 get _focusTarget() {
164 return this.focusTarget || this.containedElement; 154 return this.focusTarget || this.containedElement;
165 }, 155 },
166 156
167 /** 157 /**
168 * Whether the text direction is RTL
169 */
170 _isRTL: function() {
171 return window.getComputedStyle(this).direction == 'rtl';
172 },
173
174 /**
175 * The element that should be used to position the dropdown when 158 * The element that should be used to position the dropdown when
176 * it opens, if no position target is configured. 159 * it opens, if no position target is configured.
177 */ 160 */
178 get _defaultPositionTarget() { 161 get _defaultPositionTarget() {
179 var parent = Polymer.dom(this).parentNode; 162 var parent = Polymer.dom(this).parentNode;
180 163
181 if (parent.nodeType === Node.DOCUMENT_FRAGMENT_NODE) { 164 if (parent.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
182 parent = parent.host; 165 parent = parent.host;
183 } 166 }
184 167
185 return parent; 168 return parent;
186 }, 169 },
187 170
188 /** 171 /**
189 * The bounding rect of the position target. 172 * The horizontal align value, accounting for the RTL/LTR text direction .
190 */ 173 */
191 get _positionRect() { 174 get _localeHorizontalAlign() {
192 if (!this._positionRectMemo && this.positionTarget) { 175 // In RTL, "left" becomes "right".
193 this._positionRectMemo = this.positionTarget.getBoundingClientRect() ; 176 if (this._isRTL) {
177 return this.horizontalAlign === 'right' ? 'left' : 'right';
178 } else {
179 return this.horizontalAlign;
194 } 180 }
195
196 return this._positionRectMemo;
197 }, 181 },
198 182
199 /** 183 /**
200 * The horizontal offset value used to position the dropdown. 184 * The horizontal offset value used to position the dropdown.
185 * @param {ClientRect} dropdownRect
186 * @param {ClientRect} positionRect
187 * @param {boolean=false} fromRight
188 * @return {number} pixels
189 * @private
201 */ 190 */
202 get _horizontalAlignTargetValue() { 191 _horizontalAlignTargetValue: function(dropdownRect, positionRect, fromRi ght) {
203 var target; 192 var target;
204 193 if (fromRight) {
205 // In RTL, the direction flips, so what is "right" in LTR becomes "lef t". 194 target = document.documentElement.clientWidth - positionRect.right - (this._fitWidth - dropdownRect.right);
206 var isRTL = this._isRTL();
207 if ((!isRTL && this.horizontalAlign === 'right') ||
208 (isRTL && this.horizontalAlign === 'left')) {
209 target = document.documentElement.clientWidth - this._positionRect.r ight;
210 } else { 195 } else {
211 target = this._positionRect.left; 196 target = positionRect.left - dropdownRect.left;
212 } 197 }
213
214 target += this.horizontalOffset; 198 target += this.horizontalOffset;
215 199
216 return Math.max(target, 0); 200 return Math.max(target, 0);
217 }, 201 },
218 202
219 /** 203 /**
220 * The vertical offset value used to position the dropdown. 204 * The vertical offset value used to position the dropdown.
205 * @param {ClientRect} dropdownRect
206 * @param {ClientRect} positionRect
207 * @param {boolean=false} fromBottom
208 * @return {number} pixels
209 * @private
221 */ 210 */
222 get _verticalAlignTargetValue() { 211 _verticalAlignTargetValue: function(dropdownRect, positionRect, fromBott om) {
223 var target; 212 var target;
224 213 if (fromBottom) {
225 if (this.verticalAlign === 'bottom') { 214 target = document.documentElement.clientHeight - positionRect.bottom - (this._fitHeight - dropdownRect.bottom);
226 target = document.documentElement.clientHeight - this._positionRect. bottom;
227 } else { 215 } else {
228 target = this._positionRect.top; 216 target = positionRect.top - dropdownRect.top;
229 } 217 }
230
231 target += this.verticalOffset; 218 target += this.verticalOffset;
232 219
233 return Math.max(target, 0); 220 return Math.max(target, 0);
234 }, 221 },
235 222
236 /** 223 /**
237 * The horizontal align value, accounting for the RTL/LTR text direction .
238 */
239 get _localeHorizontalAlign() {
240 // In RTL, "left" becomes "right".
241 if (this._isRTL()) {
242 return this.horizontalAlign === 'right' ? 'left' : 'right';
243 } else {
244 return this.horizontalAlign;
245 }
246 },
247
248 /**
249 * Called when the value of `opened` changes. 224 * Called when the value of `opened` changes.
250 * 225 *
251 * @param {boolean} opened True if the dropdown is opened. 226 * @param {boolean} opened True if the dropdown is opened.
252 */ 227 */
253 _openedChanged: function(opened) { 228 _openedChanged: function(opened) {
254 if (opened && this.disabled) { 229 if (opened && this.disabled) {
255 this.cancel(); 230 this.cancel();
256 } else { 231 } else {
257 this.cancelAnimation(); 232 this.cancelAnimation();
258 this._prepareDropdown(); 233 this.sizingTarget = this.containedElement || this.sizingTarget;
234 this._updateAnimationConfig();
259 Polymer.IronOverlayBehaviorImpl._openedChanged.apply(this, arguments ); 235 Polymer.IronOverlayBehaviorImpl._openedChanged.apply(this, arguments );
260 } 236 }
261 }, 237 },
262 238
263 /** 239 /**
264 * Overridden from `IronOverlayBehavior`. 240 * Overridden from `IronOverlayBehavior`.
265 */ 241 */
266 _renderOpened: function() { 242 _renderOpened: function() {
267 if (!this.allowOutsideScroll) { 243 if (!this.allowOutsideScroll) {
268 Polymer.IronDropdownScrollManager.pushScrollLock(this); 244 Polymer.IronDropdownScrollManager.pushScrollLock(this);
269 } 245 }
270 246
271 if (!this.noAnimations && this.animationConfig && this.animationConfig .open) { 247 if (!this.noAnimations && this.animationConfig && this.animationConfig .open) {
248 if (this.withBackdrop) {
249 this.backdropElement.open();
250 }
272 this.$.contentWrapper.classList.add('animating'); 251 this.$.contentWrapper.classList.add('animating');
273 this.playAnimation('open'); 252 this.playAnimation('open');
274 } else { 253 } else {
275 Polymer.IronOverlayBehaviorImpl._renderOpened.apply(this, arguments) ; 254 Polymer.IronOverlayBehaviorImpl._renderOpened.apply(this, arguments) ;
276 } 255 }
277 }, 256 },
278 257
279 /** 258 /**
280 * Overridden from `IronOverlayBehavior`. 259 * Overridden from `IronOverlayBehavior`.
281 */ 260 */
282 _renderClosed: function() { 261 _renderClosed: function() {
283 Polymer.IronDropdownScrollManager.removeScrollLock(this); 262 Polymer.IronDropdownScrollManager.removeScrollLock(this);
284 if (!this.noAnimations && this.animationConfig && this.animationConfig .close) { 263 if (!this.noAnimations && this.animationConfig && this.animationConfig .close) {
264 if (this.withBackdrop) {
265 this.backdropElement.close();
266 }
285 this.$.contentWrapper.classList.add('animating'); 267 this.$.contentWrapper.classList.add('animating');
286 this.playAnimation('close'); 268 this.playAnimation('close');
287 } else { 269 } else {
288 Polymer.IronOverlayBehaviorImpl._renderClosed.apply(this, arguments) ; 270 Polymer.IronOverlayBehaviorImpl._renderClosed.apply(this, arguments) ;
289 } 271 }
290 }, 272 },
291 273
292 /** 274 /**
293 * Called when animation finishes on the dropdown (when opening or 275 * Called when animation finishes on the dropdown (when opening or
294 * closing). Responsible for "completing" the process of opening or 276 * closing). Responsible for "completing" the process of opening or
295 * closing the dropdown by positioning it or setting its display to 277 * closing the dropdown by positioning it or setting its display to
296 * none. 278 * none.
297 */ 279 */
298 _onNeonAnimationFinish: function() { 280 _onNeonAnimationFinish: function() {
299 this.$.contentWrapper.classList.remove('animating'); 281 this.$.contentWrapper.classList.remove('animating');
300 if (this.opened) { 282 if (this.opened) {
301 Polymer.IronOverlayBehaviorImpl._renderOpened.apply(this); 283 Polymer.IronOverlayBehaviorImpl._finishRenderOpened.apply(this);
302 } else { 284 } else {
303 Polymer.IronOverlayBehaviorImpl._renderClosed.apply(this); 285 Polymer.IronOverlayBehaviorImpl._finishRenderClosed.apply(this);
304 } 286 }
305 }, 287 },
306 288
307 /** 289 /**
308 * Called when an `iron-resize` event fires.
309 */
310 _onIronResize: function() {
311 var containedElement = this.containedElement;
312 var scrollTop;
313 var scrollLeft;
314
315 if (this.opened && containedElement) {
316 scrollTop = containedElement.scrollTop;
317 scrollLeft = containedElement.scrollLeft;
318 }
319
320 if (this.opened) {
321 this._updateOverlayPosition();
322 }
323
324 Polymer.IronOverlayBehaviorImpl._onIronResize.apply(this, arguments);
325
326 if (this.opened && containedElement) {
327 containedElement.scrollTop = scrollTop;
328 containedElement.scrollLeft = scrollLeft;
329 }
330 },
331
332 /**
333 * Called when the `positionTarget` property changes.
334 */
335 _positionTargetChanged: function() {
336 this._updateOverlayPosition();
337 },
338
339 /**
340 * Constructs the final animation config from different properties used 290 * Constructs the final animation config from different properties used
341 * to configure specific parts of the opening and closing animations. 291 * to configure specific parts of the opening and closing animations.
342 */ 292 */
343 _updateAnimationConfig: function() { 293 _updateAnimationConfig: function() {
344 var animationConfig = {}; 294 var animationConfig = {};
345 var animations = []; 295 var animations = [];
346 296
347 if (this.openAnimationConfig) { 297 if (this.openAnimationConfig) {
348 // NOTE(cdata): When making `display:none` elements visible in Safar i, 298 // NOTE(cdata): When making `display:none` elements visible in Safar i,
349 // the element will paint once in a fully visible state, causing the 299 // the element will paint once in a fully visible state, causing the
(...skipping 11 matching lines...) Expand all
361 } 311 }
362 312
363 animations.forEach(function(animation) { 313 animations.forEach(function(animation) {
364 animation.node = this.containedElement; 314 animation.node = this.containedElement;
365 }, this); 315 }, this);
366 316
367 this.animationConfig = animationConfig; 317 this.animationConfig = animationConfig;
368 }, 318 },
369 319
370 /** 320 /**
371 * Prepares the dropdown for opening by updating measured layout
372 * values.
373 */
374 _prepareDropdown: function() {
375 this.sizingTarget = this.containedElement || this.sizingTarget;
376 this._updateAnimationConfig();
377 this._updateOverlayPosition();
378 },
379
380 /**
381 * Updates the overlay position based on configured horizontal 321 * Updates the overlay position based on configured horizontal
382 * and vertical alignment, and re-memoizes these values for the sake 322 * and vertical alignment.
383 * of behavior in `IronFitBehavior`.
384 */ 323 */
385 _updateOverlayPosition: function() { 324 _updateOverlayPosition: function() {
386 this._positionRectMemo = null; 325 if (this.isAttached) {
387 326 // This triggers iron-resize, and iron-overlay-behavior will call re fit if needed.
388 if (!this.positionTarget) { 327 this.notifyResize();
389 return;
390 }
391
392 this.style[this._localeHorizontalAlign] =
393 this._horizontalAlignTargetValue + 'px';
394
395 this.style[this.verticalAlign] =
396 this._verticalAlignTargetValue + 'px';
397
398 // NOTE(cdata): We re-memoize inline styles here, otherwise
399 // calling `refit` from `IronFitBehavior` will reset inline styles
400 // to whatever they were when the dropdown first opened.
401 if (this._fitInfo) {
402 this._fitInfo.inlineStyle[this.horizontalAlign] =
403 this.style[this.horizontalAlign];
404
405 this._fitInfo.inlineStyle[this.verticalAlign] =
406 this.style[this.verticalAlign];
407 } 328 }
408 }, 329 },
409 330
410 /** 331 /**
332 * Useful to call this after the element, the window, or the `fitInfo`
333 * element has been resized. Will maintain the scroll position.
334 */
335 refit: function () {
336 if (!this.opened) {
337 return
338 }
339 var containedElement = this.containedElement;
340 var scrollTop;
341 var scrollLeft;
342
343 if (containedElement) {
344 scrollTop = containedElement.scrollTop;
345 scrollLeft = containedElement.scrollLeft;
346 }
347 Polymer.IronFitBehavior.refit.apply(this, arguments);
348
349 if (containedElement) {
350 containedElement.scrollTop = scrollTop;
351 containedElement.scrollLeft = scrollLeft;
352 }
353 },
354
355 /**
356 * Resets the target element's position and size constraints, and clear
357 * the memoized data.
358 */
359 resetFit: function() {
360 Polymer.IronFitBehavior.resetFit.apply(this, arguments);
361
362 var hAlign = this._localeHorizontalAlign;
363 var vAlign = this.verticalAlign;
364 // Set to 0, 0 in order to discover any offset caused by parent stacki ng contexts.
365 this.style[hAlign] = this.style[vAlign] = '0px';
366
367 var dropdownRect = this.getBoundingClientRect();
368 var positionRect = this.positionTarget.getBoundingClientRect();
369 var horizontalValue = this._horizontalAlignTargetValue(dropdownRect, p ositionRect, hAlign === 'right');
370 var verticalValue = this._verticalAlignTargetValue(dropdownRect, posit ionRect, vAlign === 'bottom');
371
372 this.style[hAlign] = horizontalValue + 'px';
373 this.style[vAlign] = verticalValue + 'px';
374 },
375
376 /**
377 * Overridden from `IronFitBehavior`.
378 * Ensure positionedBy has correct values for horizontally & vertically.
379 */
380 _discoverInfo: function() {
381 Polymer.IronFitBehavior._discoverInfo.apply(this, arguments);
382 // Note(valdrin): in Firefox, an element with style `position: fixed; bottom: 90vh; height: 20vh`
383 // would have `getComputedStyle(element).top < 0` (instead of being `a uto`) http://jsbin.com/cofired/3/edit?html,output
384 // This would cause IronFitBehavior's `constrain` to wrongly calculate sizes
385 // (it would use `top` instead of `bottom`), so we ensure we give the correct values.
386 this._fitInfo.positionedBy.horizontally = this._localeHorizontalAlign;
387 this._fitInfo.positionedBy.vertically = this.verticalAlign;
388 },
389
390 /**
411 * Apply focus to focusTarget or containedElement 391 * Apply focus to focusTarget or containedElement
412 */ 392 */
413 _applyFocus: function () { 393 _applyFocus: function () {
414 var focusTarget = this.focusTarget || this.containedElement; 394 var focusTarget = this.focusTarget || this.containedElement;
415 if (focusTarget && this.opened && !this.noAutoFocus) { 395 if (focusTarget && this.opened && !this.noAutoFocus) {
416 focusTarget.focus(); 396 focusTarget.focus();
417 } else { 397 } else {
418 Polymer.IronOverlayBehaviorImpl._applyFocus.apply(this, arguments); 398 Polymer.IronOverlayBehaviorImpl._applyFocus.apply(this, arguments);
419 } 399 }
420 } 400 }
421 }); 401 });
422 })(); 402 })();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698