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

Side by Side Diff: third_party/polymer/components/iron-fit-behavior/iron-fit-behavior.html

Issue 2113853002: Run bower update (Closed) Base URL: https://github.com/catapult-project/catapult@polymer10-migration
Patch Set: Created 4 years, 5 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 <!-- 1 <!--
2 @license 2 @license
3 Copyright (c) 2015 The Polymer Project Authors. All rights reserved. 3 Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
4 This code may only be used under the BSD style license found at http://polymer.g ithub.io/LICENSE.txt 4 This code may only be used under the BSD style license found at http://polymer.g ithub.io/LICENSE.txt
5 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt 5 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
6 The complete set of contributors may be found at http://polymer.github.io/CONTRI BUTORS.txt 6 The complete set of contributors may be found at http://polymer.github.io/CONTRI BUTORS.txt
7 Code distributed by Google as part of the polymer project is also 7 Code distributed by Google as part of the polymer project is also
8 subject to an additional IP rights grant found at http://polymer.github.io/PATEN TS.txt 8 subject to an additional IP rights grant found at http://polymer.github.io/PATEN TS.txt
9 --> 9 -->
10 10
11 <link rel="import" href="../polymer/polymer.html"> 11 <link rel="import" href="../polymer/polymer.html">
12 12
13 <script> 13 <script>
14
15 /** 14 /**
16 Polymer.IronFitBehavior fits an element in another element using `max-height` an d `max-width`, and 15 `Polymer.IronFitBehavior` fits an element in another element using `max-height` and `max-width`, and
17 optionally centers it in the window or another element. 16 optionally centers it in the window or another element.
18 17
19 The element will only be sized and/or positioned if it has not already been size d and/or positioned 18 The element will only be sized and/or positioned if it has not already been size d and/or positioned
20 by CSS. 19 by CSS.
21 20
22 CSS properties | Action 21 CSS properties | Action
23 -----------------------------|------------------------------------------- 22 -----------------------------|-------------------------------------------
24 `position` set | Element is not centered horizontally or verticall y 23 `position` set | Element is not centered horizontally or verticall y
25 `top` or `bottom` set | Element is not vertically centered 24 `top` or `bottom` set | Element is not vertically centered
26 `left` or `right` set | Element is not horizontally centered 25 `left` or `right` set | Element is not horizontally centered
27 `max-height` or `height` set | Element respects `max-height` or `height` 26 `max-height` set | Element respects `max-height`
28 `max-width` or `width` set | Element respects `max-width` or `width` 27 `max-width` set | Element respects `max-width`
28
29 `Polymer.IronFitBehavior` can position an element into another element using
30 `verticalAlign` and `horizontalAlign`. This will override the element's css posi tion.
31
32 <div class="container">
33 <iron-fit-impl vertical-align="top" horizontal-align="auto">
34 Positioned into the container
35 </iron-fit-impl>
36 </div>
37
38 Use `noOverlap` to position the element around another element without overlappi ng it.
39
40 <div class="container">
41 <iron-fit-impl no-overlap vertical-align="auto" horizontal-align="auto">
42 Positioned around the container
43 </iron-fit-impl>
44 </div>
29 45
30 @demo demo/index.html 46 @demo demo/index.html
31 @polymerBehavior 47 @polymerBehavior
32 */ 48 */
33 49
34 Polymer.IronFitBehavior = { 50 Polymer.IronFitBehavior = {
35 51
36 properties: { 52 properties: {
37 53
38 /** 54 /**
(...skipping 11 matching lines...) Expand all
50 66
51 /** 67 /**
52 * The element to fit `this` into. 68 * The element to fit `this` into.
53 */ 69 */
54 fitInto: { 70 fitInto: {
55 type: Object, 71 type: Object,
56 value: window 72 value: window
57 }, 73 },
58 74
59 /** 75 /**
76 * Will position the element around the positionTarget without overlapping it.
77 */
78 noOverlap: {
79 type: Boolean
80 },
81
82 /**
83 * The element that should be used to position the element. If not set, it will
84 * default to the parent node.
85 * @type {!Element}
86 */
87 positionTarget: {
88 type: Element
89 },
90
91 /**
92 * The orientation against which to align the element horizontally
93 * relative to the `positionTarget`. Possible values are "left", "right", "auto".
94 */
95 horizontalAlign: {
96 type: String
97 },
98
99 /**
100 * The orientation against which to align the element vertically
101 * relative to the `positionTarget`. Possible values are "top", "bottom", "auto".
102 */
103 verticalAlign: {
104 type: String
105 },
106
107 /**
108 * If true, it will use `horizontalAlign` and `verticalAlign` values as pr eferred alignment
109 * and if there's not enough space, it will pick the values which minimize the cropping.
110 */
111 dynamicAlign: {
112 type: Boolean
113 },
114
115 /**
116 * The same as setting margin-left and margin-right css properties.
117 * @deprecated
118 */
119 horizontalOffset: {
120 type: Number,
121 value: 0,
122 notify: true
123 },
124
125 /**
126 * The same as setting margin-top and margin-bottom css properties.
127 * @deprecated
128 */
129 verticalOffset: {
130 type: Number,
131 value: 0,
132 notify: true
133 },
134
135 /**
60 * Set to true to auto-fit on attach. 136 * Set to true to auto-fit on attach.
61 */ 137 */
62 autoFitOnAttach: { 138 autoFitOnAttach: {
63 type: Boolean, 139 type: Boolean,
64 value: false 140 value: false
65 }, 141 },
66 142
67 /** @type {?Object} */ 143 /** @type {?Object} */
68 _fitInfo: { 144 _fitInfo: {
69 type: Object 145 type: Object
70 } 146 }
71
72 }, 147 },
73 148
74 get _fitWidth() { 149 get _fitWidth() {
75 var fitWidth; 150 var fitWidth;
76 if (this.fitInto === window) { 151 if (this.fitInto === window) {
77 fitWidth = this.fitInto.innerWidth; 152 fitWidth = this.fitInto.innerWidth;
78 } else { 153 } else {
79 fitWidth = this.fitInto.getBoundingClientRect().width; 154 fitWidth = this.fitInto.getBoundingClientRect().width;
80 } 155 }
81 return fitWidth; 156 return fitWidth;
(...skipping 22 matching lines...) Expand all
104 get _fitTop() { 179 get _fitTop() {
105 var fitTop; 180 var fitTop;
106 if (this.fitInto === window) { 181 if (this.fitInto === window) {
107 fitTop = 0; 182 fitTop = 0;
108 } else { 183 } else {
109 fitTop = this.fitInto.getBoundingClientRect().top; 184 fitTop = this.fitInto.getBoundingClientRect().top;
110 } 185 }
111 return fitTop; 186 return fitTop;
112 }, 187 },
113 188
189 /**
190 * The element that should be used to position the element,
191 * if no position target is configured.
192 */
193 get _defaultPositionTarget() {
194 var parent = Polymer.dom(this).parentNode;
195
196 if (parent && parent.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
197 parent = parent.host;
198 }
199
200 return parent;
201 },
202
203 /**
204 * The horizontal align value, accounting for the RTL/LTR text direction.
205 */
206 get _localeHorizontalAlign() {
207 if (this._isRTL) {
208 // In RTL, "left" becomes "right".
209 if (this.horizontalAlign === 'right') {
210 return 'left';
211 }
212 if (this.horizontalAlign === 'left') {
213 return 'right';
214 }
215 }
216 return this.horizontalAlign;
217 },
218
114 attached: function() { 219 attached: function() {
220 // Memoize this to avoid expensive calculations & relayouts.
221 this._isRTL = window.getComputedStyle(this).direction == 'rtl';
222 this.positionTarget = this.positionTarget || this._defaultPositionTarget;
115 if (this.autoFitOnAttach) { 223 if (this.autoFitOnAttach) {
116 if (window.getComputedStyle(this).display === 'none') { 224 if (window.getComputedStyle(this).display === 'none') {
117 setTimeout(function() { 225 setTimeout(function() {
118 this.fit(); 226 this.fit();
119 }.bind(this)); 227 }.bind(this));
120 } else { 228 } else {
121 this.fit(); 229 this.fit();
122 } 230 }
123 } 231 }
124 }, 232 },
125 233
126 /** 234 /**
127 * Fits and optionally centers the element into the window, or `fitInfo` if specified. 235 * Positions and fits the element into the `fitInto` element.
128 */ 236 */
129 fit: function() { 237 fit: function() {
130 this._discoverInfo(); 238 this._discoverInfo();
239 this.position();
131 this.constrain(); 240 this.constrain();
132 this.center(); 241 this.center();
133 }, 242 },
134 243
135 /** 244 /**
136 * Memoize information needed to position and size the target element. 245 * Memoize information needed to position and size the target element.
246 * @suppress {deprecated}
137 */ 247 */
138 _discoverInfo: function() { 248 _discoverInfo: function() {
139 if (this._fitInfo) { 249 if (this._fitInfo) {
140 return; 250 return;
141 } 251 }
142 var target = window.getComputedStyle(this); 252 var target = window.getComputedStyle(this);
143 var sizer = window.getComputedStyle(this.sizingTarget); 253 var sizer = window.getComputedStyle(this.sizingTarget);
254
144 this._fitInfo = { 255 this._fitInfo = {
145 inlineStyle: { 256 inlineStyle: {
146 top: this.style.top || '', 257 top: this.style.top || '',
147 left: this.style.left || '' 258 left: this.style.left || '',
259 position: this.style.position || ''
260 },
261 sizerInlineStyle: {
262 maxWidth: this.sizingTarget.style.maxWidth || '',
263 maxHeight: this.sizingTarget.style.maxHeight || '',
264 boxSizing: this.sizingTarget.style.boxSizing || ''
148 }, 265 },
149 positionedBy: { 266 positionedBy: {
150 vertically: target.top !== 'auto' ? 'top' : (target.bottom !== 'auto' ? 267 vertically: target.top !== 'auto' ? 'top' : (target.bottom !== 'auto' ?
151 'bottom' : null), 268 'bottom' : null),
152 horizontally: target.left !== 'auto' ? 'left' : (target.right !== 'aut o' ? 269 horizontally: target.left !== 'auto' ? 'left' : (target.right !== 'aut o' ?
153 'right' : null), 270 'right' : null)
154 css: target.position
155 }, 271 },
156 sizedBy: { 272 sizedBy: {
157 height: sizer.maxHeight !== 'none', 273 height: sizer.maxHeight !== 'none',
158 width: sizer.maxWidth !== 'none' 274 width: sizer.maxWidth !== 'none',
275 minWidth: parseInt(sizer.minWidth, 10) || 0,
276 minHeight: parseInt(sizer.minHeight, 10) || 0
159 }, 277 },
160 margin: { 278 margin: {
161 top: parseInt(target.marginTop, 10) || 0, 279 top: parseInt(target.marginTop, 10) || 0,
162 right: parseInt(target.marginRight, 10) || 0, 280 right: parseInt(target.marginRight, 10) || 0,
163 bottom: parseInt(target.marginBottom, 10) || 0, 281 bottom: parseInt(target.marginBottom, 10) || 0,
164 left: parseInt(target.marginLeft, 10) || 0 282 left: parseInt(target.marginLeft, 10) || 0
165 } 283 }
166 }; 284 };
285
286 // Support these properties until they are removed.
287 if (this.verticalOffset) {
288 this._fitInfo.margin.top = this._fitInfo.margin.bottom = this.verticalOf fset;
289 this._fitInfo.inlineStyle.marginTop = this.style.marginTop || '';
290 this._fitInfo.inlineStyle.marginBottom = this.style.marginBottom || '';
291 this.style.marginTop = this.style.marginBottom = this.verticalOffset + ' px';
292 }
293 if (this.horizontalOffset) {
294 this._fitInfo.margin.left = this._fitInfo.margin.right = this.horizontal Offset;
295 this._fitInfo.inlineStyle.marginLeft = this.style.marginLeft || '';
296 this._fitInfo.inlineStyle.marginRight = this.style.marginRight || '';
297 this.style.marginLeft = this.style.marginRight = this.horizontalOffset + 'px';
298 }
167 }, 299 },
168 300
169 /** 301 /**
170 * Resets the target element's position and size constraints, and clear 302 * Resets the target element's position and size constraints, and clear
171 * the memoized data. 303 * the memoized data.
172 */ 304 */
173 resetFit: function() { 305 resetFit: function() {
174 if (!this._fitInfo || !this._fitInfo.sizedBy.width) { 306 var info = this._fitInfo || {};
175 this.sizingTarget.style.maxWidth = ''; 307 for (var property in info.sizerInlineStyle) {
308 this.sizingTarget.style[property] = info.sizerInlineStyle[property];
176 } 309 }
177 if (!this._fitInfo || !this._fitInfo.sizedBy.height) { 310 for (var property in info.inlineStyle) {
178 this.sizingTarget.style.maxHeight = ''; 311 this.style[property] = info.inlineStyle[property];
179 } 312 }
180 this.style.top = this._fitInfo ? this._fitInfo.inlineStyle.top : ''; 313
181 this.style.left = this._fitInfo ? this._fitInfo.inlineStyle.left : '';
182 if (this._fitInfo) {
183 this.style.position = this._fitInfo.positionedBy.css;
184 }
185 this._fitInfo = null; 314 this._fitInfo = null;
186 }, 315 },
187 316
188 /** 317 /**
189 * Equivalent to calling `resetFit()` and `fit()`. Useful to call this after the element, 318 * Equivalent to calling `resetFit()` and `fit()`. Useful to call this after
190 * the window, or the `fitInfo` element has been resized. 319 * the element or the `fitInto` element has been resized, or if any of the
320 * positioning properties (e.g. `horizontalAlign, verticalAlign`) is updated .
321 * It preserves the scroll position of the sizingTarget.
191 */ 322 */
192 refit: function() { 323 refit: function() {
324 var scrollLeft = this.sizingTarget.scrollLeft;
325 var scrollTop = this.sizingTarget.scrollTop;
193 this.resetFit(); 326 this.resetFit();
194 this.fit(); 327 this.fit();
328 this.sizingTarget.scrollLeft = scrollLeft;
329 this.sizingTarget.scrollTop = scrollTop;
195 }, 330 },
196 331
197 /** 332 /**
198 * Constrains the size of the element to the window or `fitInfo` by setting `max-height` 333 * Positions the element according to `horizontalAlign, verticalAlign`.
334 */
335 position: function() {
336 if (!this.horizontalAlign && !this.verticalAlign) {
337 // needs to be centered, and it is done after constrain.
338 return;
339 }
340
341 this.style.position = 'fixed';
342 // Need border-box for margin/padding.
343 this.sizingTarget.style.boxSizing = 'border-box';
344 // Set to 0, 0 in order to discover any offset caused by parent stacking c ontexts.
345 this.style.left = '0px';
346 this.style.top = '0px';
347
348 var rect = this.getBoundingClientRect();
349 var positionRect = this.__getNormalizedRect(this.positionTarget);
350 var fitRect = this.__getNormalizedRect(this.fitInto);
351
352 var margin = this._fitInfo.margin;
353
354 // Consider the margin as part of the size for position calculations.
355 var size = {
356 width: rect.width + margin.left + margin.right,
357 height: rect.height + margin.top + margin.bottom
358 };
359
360 var position = this.__getPosition(this._localeHorizontalAlign, this.vertic alAlign, size, positionRect, fitRect);
361
362 var left = position.left + margin.left;
363 var top = position.top + margin.top;
364
365 // Use original size (without margin).
366 var right = Math.min(fitRect.right - margin.right, left + rect.width);
367 var bottom = Math.min(fitRect.bottom - margin.bottom, top + rect.height);
368
369 var minWidth = this._fitInfo.sizedBy.minWidth;
370 var minHeight = this._fitInfo.sizedBy.minHeight;
371 if (left < margin.left) {
372 left = margin.left;
373 if (right - left < minWidth) {
374 left = right - minWidth;
375 }
376 }
377 if (top < margin.top) {
378 top = margin.top;
379 if (bottom - top < minHeight) {
380 top = bottom - minHeight;
381 }
382 }
383
384 this.sizingTarget.style.maxWidth = (right - left) + 'px';
385 this.sizingTarget.style.maxHeight = (bottom - top) + 'px';
386
387 // Remove the offset caused by any stacking context.
388 this.style.left = (left - rect.left) + 'px';
389 this.style.top = (top - rect.top) + 'px';
390 },
391
392 /**
393 * Constrains the size of the element to `fitInto` by setting `max-height`
199 * and/or `max-width`. 394 * and/or `max-width`.
200 */ 395 */
201 constrain: function() { 396 constrain: function() {
397 if (this.horizontalAlign || this.verticalAlign) {
398 return;
399 }
202 var info = this._fitInfo; 400 var info = this._fitInfo;
203 // position at (0px, 0px) if not already positioned, so we can measure the natural size. 401 // position at (0px, 0px) if not already positioned, so we can measure the natural size.
204 if (!this._fitInfo.positionedBy.vertically) { 402 if (!info.positionedBy.vertically) {
403 this.style.position = 'fixed';
205 this.style.top = '0px'; 404 this.style.top = '0px';
206 } 405 }
207 if (!this._fitInfo.positionedBy.horizontally) { 406 if (!info.positionedBy.horizontally) {
407 this.style.position = 'fixed';
208 this.style.left = '0px'; 408 this.style.left = '0px';
209 } 409 }
210 if (!this._fitInfo.positionedBy.vertically || !this._fitInfo.positionedBy. horizontally) { 410
211 // need position:fixed to properly size the element
212 this.style.position = 'fixed';
213 }
214 // need border-box for margin/padding 411 // need border-box for margin/padding
215 this.sizingTarget.style.boxSizing = 'border-box'; 412 this.sizingTarget.style.boxSizing = 'border-box';
216 // constrain the width and height if not already set 413 // constrain the width and height if not already set
217 var rect = this.getBoundingClientRect(); 414 var rect = this.getBoundingClientRect();
218 if (!info.sizedBy.height) { 415 if (!info.sizedBy.height) {
219 this._sizeDimension(rect, info.positionedBy.vertically, 'top', 'bottom', 'Height'); 416 this.__sizeDimension(rect, info.positionedBy.vertically, 'top', 'bottom' , 'Height');
220 } 417 }
221 if (!info.sizedBy.width) { 418 if (!info.sizedBy.width) {
222 this._sizeDimension(rect, info.positionedBy.horizontally, 'left', 'right ', 'Width'); 419 this.__sizeDimension(rect, info.positionedBy.horizontally, 'left', 'righ t', 'Width');
223 } 420 }
224 }, 421 },
225 422
423 /**
424 * @protected
425 * @deprecated
426 */
226 _sizeDimension: function(rect, positionedBy, start, end, extent) { 427 _sizeDimension: function(rect, positionedBy, start, end, extent) {
428 this.__sizeDimension(rect, positionedBy, start, end, extent);
429 },
430
431 /**
432 * @private
433 */
434 __sizeDimension: function(rect, positionedBy, start, end, extent) {
227 var info = this._fitInfo; 435 var info = this._fitInfo;
228 var max = extent === 'Width' ? this._fitWidth : this._fitHeight; 436 var fitRect = this.__getNormalizedRect(this.fitInto);
437 var max = extent === 'Width' ? fitRect.width : fitRect.height;
229 var flip = (positionedBy === end); 438 var flip = (positionedBy === end);
230 var offset = flip ? max - rect[end] : rect[start]; 439 var offset = flip ? max - rect[end] : rect[start];
231 var margin = info.margin[flip ? start : end]; 440 var margin = info.margin[flip ? start : end];
232 var offsetExtent = 'offset' + extent; 441 var offsetExtent = 'offset' + extent;
233 var sizingOffset = this[offsetExtent] - this.sizingTarget[offsetExtent]; 442 var sizingOffset = this[offsetExtent] - this.sizingTarget[offsetExtent];
234 this.sizingTarget.style['max' + extent] = (max - margin - offset - sizingO ffset) + 'px'; 443 this.sizingTarget.style['max' + extent] = (max - margin - offset - sizingO ffset) + 'px';
235 }, 444 },
236 445
237 /** 446 /**
238 * Centers horizontally and vertically if not already positioned. This also sets 447 * Centers horizontally and vertically if not already positioned. This also sets
239 * `position:fixed`. 448 * `position:fixed`.
240 */ 449 */
241 center: function() { 450 center: function() {
451 if (this.horizontalAlign || this.verticalAlign) {
452 return;
453 }
242 var positionedBy = this._fitInfo.positionedBy; 454 var positionedBy = this._fitInfo.positionedBy;
243 if (positionedBy.vertically && positionedBy.horizontally) { 455 if (positionedBy.vertically && positionedBy.horizontally) {
244 // Already positioned. 456 // Already positioned.
245 return; 457 return;
246 } 458 }
247 // Need position:fixed to center 459 // Need position:fixed to center
248 this.style.position = 'fixed'; 460 this.style.position = 'fixed';
249 // Take into account the offset caused by parents that create stacking 461 // Take into account the offset caused by parents that create stacking
250 // contexts (e.g. with transform: translate3d). Translate to 0,0 and 462 // contexts (e.g. with transform: translate3d). Translate to 0,0 and
251 // measure the bounding rect. 463 // measure the bounding rect.
252 if (!positionedBy.vertically) { 464 if (!positionedBy.vertically) {
253 this.style.top = '0px'; 465 this.style.top = '0px';
254 } 466 }
255 if (!positionedBy.horizontally) { 467 if (!positionedBy.horizontally) {
256 this.style.left = '0px'; 468 this.style.left = '0px';
257 } 469 }
258 // It will take in consideration margins and transforms 470 // It will take in consideration margins and transforms
259 var rect = this.getBoundingClientRect(); 471 var rect = this.getBoundingClientRect();
472 var fitRect = this.__getNormalizedRect(this.fitInto);
260 if (!positionedBy.vertically) { 473 if (!positionedBy.vertically) {
261 var top = this._fitTop - rect.top + (this._fitHeight - rect.height) / 2; 474 var top = fitRect.top - rect.top + (fitRect.height - rect.height) / 2;
262 this.style.top = top + 'px'; 475 this.style.top = top + 'px';
263 } 476 }
264 if (!positionedBy.horizontally) { 477 if (!positionedBy.horizontally) {
265 var left = this._fitLeft - rect.left + (this._fitWidth - rect.width) / 2 ; 478 var left = fitRect.left - rect.left + (fitRect.width - rect.width) / 2;
266 this.style.left = left + 'px'; 479 this.style.left = left + 'px';
267 } 480 }
481 },
482
483 __getNormalizedRect: function(target) {
484 if (target === document.documentElement || target === window) {
485 return {
486 top: 0,
487 left: 0,
488 width: window.innerWidth,
489 height: window.innerHeight,
490 right: window.innerWidth,
491 bottom: window.innerHeight
492 };
493 }
494 return target.getBoundingClientRect();
495 },
496
497 __getCroppedArea: function(position, size, fitRect) {
498 var verticalCrop = Math.min(0, position.top) + Math.min(0, fitRect.bottom - (position.top + size.height));
499 var horizontalCrop = Math.min(0, position.left) + Math.min(0, fitRect.righ t - (position.left + size.width));
500 return Math.abs(verticalCrop) * size.width + Math.abs(horizontalCrop) * si ze.height;
501 },
502
503
504 __getPosition: function(hAlign, vAlign, size, positionRect, fitRect) {
505 // All the possible configurations.
506 // Ordered as top-left, top-right, bottom-left, bottom-right.
507 var positions = [{
508 verticalAlign: 'top',
509 horizontalAlign: 'left',
510 top: positionRect.top,
511 left: positionRect.left
512 }, {
513 verticalAlign: 'top',
514 horizontalAlign: 'right',
515 top: positionRect.top,
516 left: positionRect.right - size.width
517 }, {
518 verticalAlign: 'bottom',
519 horizontalAlign: 'left',
520 top: positionRect.bottom - size.height,
521 left: positionRect.left
522 }, {
523 verticalAlign: 'bottom',
524 horizontalAlign: 'right',
525 top: positionRect.bottom - size.height,
526 left: positionRect.right - size.width
527 }];
528
529 if (this.noOverlap) {
530 // Duplicate.
531 for (var i = 0, l = positions.length; i < l; i++) {
532 var copy = {};
533 for (var key in positions[i]) {
534 copy[key] = positions[i][key];
535 }
536 positions.push(copy);
537 }
538 // Horizontal overlap only.
539 positions[0].top = positions[1].top += positionRect.height;
540 positions[2].top = positions[3].top -= positionRect.height;
541 // Vertical overlap only.
542 positions[4].left = positions[6].left += positionRect.width;
543 positions[5].left = positions[7].left -= positionRect.width;
544 }
545
546 // Consider auto as null for coding convenience.
547 vAlign = vAlign === 'auto' ? null : vAlign;
548 hAlign = hAlign === 'auto' ? null : hAlign;
549
550 var position;
551 for (var i = 0; i < positions.length; i++) {
552 var pos = positions[i];
553
554 // If both vAlign and hAlign are defined, return exact match.
555 // For dynamicAlign and noOverlap we'll have more than one candidate, so
556 // we'll have to check the croppedArea to make the best choice.
557 if (!this.dynamicAlign && !this.noOverlap &&
558 pos.verticalAlign === vAlign && pos.horizontalAlign === hAlign) {
559 position = pos;
560 break;
561 }
562
563 // Align is ok if alignment preferences are respected. If no preferences ,
564 // it is considered ok.
565 var alignOk = (!vAlign || pos.verticalAlign === vAlign) &&
566 (!hAlign || pos.horizontalAlign === hAlign);
567
568 // Filter out elements that don't match the alignment (if defined).
569 // With dynamicAlign, we need to consider all the positions to find the
570 // one that minimizes the cropped area.
571 if (!this.dynamicAlign && !alignOk) {
572 continue;
573 }
574
575 position = position || pos;
576 pos.croppedArea = this.__getCroppedArea(pos, size, fitRect);
577 var diff = pos.croppedArea - position.croppedArea;
578 // Check which crops less. If it crops equally, check if align is ok.
579 if (diff < 0 || (diff === 0 && alignOk)) {
580 position = pos;
581 }
582 // If not cropped and respects the align requirements, keep it.
583 // This allows to prefer positions overlapping horizontally over the
584 // ones overlapping vertically.
585 if (position.croppedArea === 0 && alignOk) {
586 break;
587 }
588 }
589
590 return position;
268 } 591 }
269 592
270 }; 593 };
271
272 </script> 594 </script>
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698