PluginProbe
Photonic Gallery & Lightbox for Flickr, SmugMug & Others / 2.25
Photonic Gallery & Lightbox for Flickr, SmugMug & Others v2.25
3.37 3.36 3.35 3.34 3.33 2.19 2.20 2.21 2.22 2.23 2.24 2.25 2.26 2.27 2.28 2.29 2.30 2.31 2.32 2.33 2.34 2.40 2.41 2.42 2.43 All 142 releases
photonic / include / scripts / front-end / src / core / layouts.js

layouts.js in Photonic Gallery & Lightbox for Flickr, SmugMug & Others 2.25, at include/scripts/front-end/src/core/layouts.js

640 lines 21.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 $('.photonic-standard-layout.title-display-below').each(function() {
2 var $standard = $(this);
3 $standard.waitForImages(function(){
4 var $block = $(this);
5 $block.find('.photonic-pad-photos').each(function(i, item) {
6 var img = $(item).find('img');
7 img = img[0];
8 var title = $(item).find('.photonic-title-info');
9 title.css({"width": img.width });
10 });
11 });
12 });
13
14 if ($('.title-display-tooltip a, .photonic-slideshow.title-display-tooltip img').length > 0) {
15 if (!$.fn.tooltip) {
16 photonicTooltip('[data-photonic-tooltip]', '.photonic-tooltip-container');
17 }
18 else {
19 $(document).tooltip({
20 items: '.title-display-tooltip a, .photonic-slideshow.title-display-tooltip img',
21 track: true,
22 show: false,
23 selector: '.title-display-tooltip a, .photonic-slideshow.title-display-tooltip img',
24 hide: false
25 });
26 }
27 }
28
29 $(document).on('mouseenter', '.title-display-hover-slideup-show a, .photonic-slideshow.title-display-hover-slideup-show li', function(e) {
30 var title = $(this).find('.photonic-title');
31 title.slideDown();
32 $(this).data('photonic-title', $(this).attr('title'));
33 $(this).attr('title', '');
34 });
35
36 $(document).on('mouseleave', '.title-display-hover-slideup-show a, .photonic-slideshow.title-display-hover-slideup-show li', function(e) {
37 var title = $(this).find('.photonic-title');
38 title.slideUp();
39 $(this).data('photonic-title', $(this).attr('title'));
40 $(this).attr('title', $(this).data('photonic-title'));
41 });
42
43 window.photonicBlankSlideupTitle = function() {
44 $('.title-display-slideup-stick, .photonic-slideshow.title-display-slideup-stick').each(function(i, item){
45 var a = $(item).find('a');
46 $(a).attr('title', '');
47 });
48 };
49 photonicBlankSlideupTitle();
50
51 window.photonicShowSlideupTitle = function() {
52 var titles = document.documentElement.querySelectorAll('.title-display-slideup-stick a .photonic-title');
53 var len = titles.length;
54 for (var i = 0; i < len; i++) {
55 titles[i].style.display = 'block';
56 }
57 };
58
59 $('.auth-button').click(function(){
60 var provider = '';
61 if ($(this).hasClass('auth-button-flickr')) {
62 provider = 'flickr';
63 }
64 else if ($(this).hasClass('auth-button-smug')) {
65 provider = 'smug';
66 }
67 var callbackId = $(this).attr('rel');
68
69 $.post(Photonic_JS.ajaxurl, "action=photonic_authenticate&provider=" + provider + '&callback_id=' + callbackId, function(data) {
70 if (provider === 'flickr') {
71 window.location.replace(data);
72 }
73 else if (provider === 'smug') {
74 window.open(data);
75 }
76 });
77 return false;
78 });
79
80 $('.photonic-login-box-flickr:not(:first)').remove();
81 $('.photonic-login-box-flickr').attr({id: 'photonic-login-box-flickr'});
82 $('.photonic-login-box-smug:not(:first)').remove();
83 $('.photonic-login-box-smug').attr({id: 'photonic-login-box-smug'});
84
85 window.photonicJustifiedGridLayout = function(resized, selector) {
86 if (console !== undefined && Photonic_JS.debug_on !== '0' && Photonic_JS.debug_on !== '') console.time('Justified Grid');
87 if (selector == null || selector === undefined || $(selector).length === 0) {
88 selector = '.photonic-random-layout';
89 }
90
91 if (!resized && $(selector).length > 0) {
92 photonicShowLoading();
93 }
94
95 function linearMin(arr) {
96 var computed, result, x, _i, _len;
97 for (_i = 0, _len = arr.length; _i < _len; _i++) {
98 x = arr[_i];
99 computed = x[0];
100 if (!result || computed < result.computed) {
101 result = {
102 value: x,
103 computed: computed
104 };
105 }
106 }
107 return result.value;
108 }
109
110 function linearPartition(seq, k) {
111 var ans, i, j, m, n, solution, table, x, y, _i, _j, _k, _l;
112 n = seq.length;
113 if (k <= 0) {
114 return [];
115 }
116 if (k > n) {
117 return seq.map(function(x) {
118 return [x];
119 });
120 }
121 table = (function() {
122 var _i, _results;
123 _results = [];
124 for (y = _i = 0; 0 <= n ? _i < n : _i > n; y = 0 <= n ? ++_i : --_i) {
125 _results.push((function() {
126 var _j, _results1;
127 _results1 = [];
128 for (x = _j = 0; 0 <= k ? _j < k : _j > k; x = 0 <= k ? ++_j : --_j) {
129 _results1.push(0);
130 }
131 return _results1;
132 })());
133 }
134 return _results;
135 })();
136 solution = (function() {
137 var _i, _ref, _results;
138 _results = [];
139 for (y = _i = 0, _ref = n - 1; 0 <= _ref ? _i < _ref : _i > _ref; y = 0 <= _ref ? ++_i : --_i) {
140 _results.push((function() {
141 var _j, _ref1, _results1;
142 _results1 = [];
143 for (x = _j = 0, _ref1 = k - 1; 0 <= _ref1 ? _j < _ref1 : _j > _ref1; x = 0 <= _ref1 ? ++_j : --_j) {
144 _results1.push(0);
145 }
146 return _results1;
147 })());
148 }
149 return _results;
150 })();
151 for (i = _i = 0; 0 <= n ? _i < n : _i > n; i = 0 <= n ? ++_i : --_i) {
152 table[i][0] = seq[i] + (i ? table[i - 1][0] : 0);
153 }
154 for (j = _j = 0; 0 <= k ? _j < k : _j > k; j = 0 <= k ? ++_j : --_j) {
155 table[0][j] = seq[0];
156 }
157 for (i = _k = 1; 1 <= n ? _k < n : _k > n; i = 1 <= n ? ++_k : --_k) {
158 for (j = _l = 1; 1 <= k ? _l < k : _l > k; j = 1 <= k ? ++_l : --_l) {
159 m = linearMin((function() {
160 var _m, _results;
161 _results = [];
162 for (x = _m = 0; 0 <= i ? _m < i : _m > i; x = 0 <= i ? ++_m : --_m) {
163 _results.push([Math.max(table[x][j - 1], table[i][0] - table[x][0]), x]);
164 }
165 return _results;
166 })());
167 table[i][j] = m[0];
168 solution[i - 1][j - 1] = m[1];
169 }
170 }
171 n = n - 1;
172 k = k - 2;
173 ans = [];
174 while (k >= 0) {
175 ans = [
176 (function() {
177 var _m, _ref, _ref1, _results;
178 _results = [];
179 for (i = _m = _ref = solution[n - 1][k] + 1, _ref1 = n + 1; _ref <= _ref1 ? _m < _ref1 : _m > _ref1; i = _ref <= _ref1 ? ++_m : --_m) {
180 _results.push(seq[i]);
181 }
182 return _results;
183 })()
184 ].concat(ans);
185 n = solution[n - 1][k];
186 k = k - 1;
187 }
188 return [
189 (function() {
190 var _m, _ref, _results;
191 _results = [];
192 for (i = _m = 0, _ref = n + 1; 0 <= _ref ? _m < _ref : _m > _ref; i = 0 <= _ref ? ++_m : --_m) {
193 _results.push(seq[i]);
194 }
195 return _results;
196 })()
197 ].concat(ans);
198 }
199
200 function part(seq, k) {
201 if (k <= 0) {
202 return [];
203 }
204 while (k) {
205 try {
206 return linearPartition(seq, k--);
207 } catch (_error) {}
208 }
209 }
210
211 $(selector).each(function(idx, obj) {
212 var viewportWidth = Math.floor($(this)[0].getBoundingClientRect().width);
213 var windowHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
214 var idealHeight = Math.max(parseInt(windowHeight / 4), Photonic_JS.tile_min_height);
215
216 var gap = Photonic_JS.tile_spacing * 2;
217
218 $(obj).waitForImages(function() {
219 var container = this;
220 var photos = [];
221 var images = $(container).find('img');
222
223 $(images).each(function() {
224 if ($(this).parents('.photonic-panel').length > 0) {
225 return;
226 }
227
228 var image = $(this)[0];
229 var div = this.parentNode.parentNode;
230
231 if (!(image.naturalHeight === 0 || image.naturalHeight === undefined || image.naturalWidth === undefined)) {
232 photos.push({tile: div, aspect_ratio: (image.naturalWidth) / (image.naturalHeight)});
233 }
234 });
235
236 var summedWidth = photos.reduce((function(sum, p) {
237 return sum += p.aspect_ratio * idealHeight + gap;
238 }), 0);
239
240 var rows = Math.max(Math.round(summedWidth / viewportWidth), 1); // At least 1 row should be shown
241 var weights = photos.map(function(p) {
242 return Math.round(p.aspect_ratio * 100);
243 });
244
245 var partition = part(weights, rows);
246 var index = 0;
247
248 var oLen = partition.length;
249 for (var o = 0; o < oLen; o++) {
250 var onePart = partition[o];
251 var summedRatios;
252 var rowBuffer = photos.slice(index, index + onePart.length);
253 index = index + onePart.length;
254
255 summedRatios = rowBuffer.reduce((function(sum, p) {
256 return sum += p.aspect_ratio;
257 }), 0);
258
259 var rLen = rowBuffer.length;
260 for (var r = 0; r < rLen; r++) {
261 var item = rowBuffer[r];
262 var existing = item.tile;
263 existing.style.width = parseInt(viewportWidth / summedRatios * item.aspect_ratio)+"px";
264 existing.style.height = parseInt(viewportWidth / summedRatios)+"px";
265 }
266 }
267
268 $(container).find('.photonic-thumb, .photonic-thumb img').fadeIn();
269
270 photonicBlankSlideupTitle();
271 photonicShowSlideupTitle();
272
273 if (Photonic_JS.slideshow_library === 'lightcase') {
274 photonicLightbox.initialize('.photonic-random-layout');
275 }
276 else if (Photonic_JS.slideshow_library === 'lightgallery') {
277 photonicLightbox.initialize(container);
278 }
279 else if (Photonic_JS.slideshow_library === 'featherlight') {
280 photonicLightbox.initialize(container);
281 }
282 else if (Photonic_JS.slideshow_library === 'fancybox3') {
283 photonicLightbox.initialize('.photonic-random-layout');
284 }
285 else if (Photonic_JS.slideshow_library === 'photoswipe') {
286 photonicLightbox.initialize();
287 }
288
289 if (!resized) {
290 $('.photonic-loading').hide();
291 }
292 });
293 });
294 if (console !== undefined && Photonic_JS.debug_on !== '0' && Photonic_JS.debug_on !== '') console.timeEnd('Justified Grid');
295 };
296
297 window.photonicMasonryLayout = function(resized, selector) {
298 if (Photonic_JS.is_old_IE === "1") return;
299 if (console !== undefined && Photonic_JS.debug_on !== '0' && Photonic_JS.debug_on !== '') console.time('Masonry');
300
301 if (selector == null || selector === undefined) {
302 selector = '.photonic-masonry-layout';
303 }
304
305 if (!resized && $(selector).length > 0) {
306 photonicShowLoading();
307 }
308
309 var minWidth = (isNaN(Photonic_JS.masonry_min_width) || parseInt(Photonic_JS.masonry_min_width) <= 0) ? 200 : Photonic_JS.masonry_min_width;
310 minWidth = parseInt(minWidth);
311
312 $(selector).each(function(idx, grid) {
313 var $grid = $(grid);
314 $grid.waitForImages(function() {
315 var columns = $grid.attr('data-photonic-gallery-columns');
316 columns = (isNaN(parseInt(columns)) || parseInt(columns) <= 0) ? 3 : parseInt(columns);
317 var viewportWidth = Math.floor($grid[0].getBoundingClientRect().width);
318 var idealColumns = (viewportWidth / columns) > minWidth ? columns : Math.floor(viewportWidth / minWidth);
319 if (idealColumns !== undefined && idealColumns !== null) {
320 $grid.css('column-count', idealColumns.toString());
321 }
322 $grid.find('img').fadeIn().css({"display": "block" });
323 photonicShowSlideupTitle();
324 if (!resized) {
325 $('.photonic-loading').hide();
326 }
327 });
328 });
329 if (console !== undefined && Photonic_JS.debug_on !== '0' && Photonic_JS.debug_on !== '') console.timeEnd('Masonry');
330 };
331
332 window.photonicMosaicLayout = function(resized, selector) {
333 if (console !== undefined && Photonic_JS.debug_on !== '0' && Photonic_JS.debug_on !== '') console.time('Mosaic');
334 if (selector == null || selector === undefined || $(selector).length === 0) {
335 selector = '.photonic-mosaic-layout';
336 }
337
338 if (!resized && $(selector).length > 0) {
339 photonicShowLoading();
340 }
341
342 function getDistribution(setSize, max, min) {
343 var distribution = [];
344 var processed = 0;
345 while (processed < setSize) {
346 if (setSize - processed <= max && processed > 0) {
347 // if (setSize - processed <= 3 && processed > 0) {
348 distribution.push(setSize - processed);
349 processed += setSize - processed;
350 }
351 else {
352 var current = Math.max(Math.floor(Math.random() * max + 1), min);
353 current = Math.min(current, setSize - processed);
354 distribution.push(current);
355 processed += current;
356 }
357 }
358 return distribution;
359 }
360
361 function arrayAlternate(array, remainder) {
362 return array.filter(function(value, index) {
363 return index % 2 === remainder;
364 });
365 }
366
367 function setUniformHeightsForRow(array) {
368 // First, order the array by increasing height
369 array.sort(function(a, b) {
370 return a.height - b.height;
371 });
372
373 array[0].new_height = array[0].height;
374 array[0].new_width = array[0].width;
375
376 for (var i = 1; i < array.length; i++) {
377 array[i].new_height = array[0].height;
378 array[i].new_width = array[i].new_height * array[i].aspect_ratio;
379 }
380 var new_width = array.reduce(function(sum, p) {
381 return sum += p.new_width ;
382 }, 0);
383 return { elements: array, height: array[0].new_height, width: new_width, aspect_ratio: new_width / array[0].new_height };
384 }
385
386 function finalizeTiledLayout(components, containers) {
387 var cLength = components.length;
388 for (var c = 0; c < cLength; c++) {
389 var component = components[c];
390 var rowY = component.y;
391 var otherRowHeight = 0;
392 var container;
393 var ceLen = component.elements.length;
394 for (var e = 0; e < ceLen; e++) {
395 var element = component.elements[e];
396 if (element.photo_position !== undefined) {
397 // Component is a single image
398 container = containers[element.photo_position];
399 container.css('width', (component.new_width));
400 container.css('height', (component.new_height));
401 container.css('top', (component.y));
402 container.css('left', (component.x));
403 }
404 else {
405 // Component is a clique (element is a row). Widths and Heights of cliques have been calculated. But the rows in cliques need to be recalculated
406 element.new_width = component.new_width;
407 if (otherRowHeight === 0) {
408 element.new_height = element.new_width / element.aspect_ratio;
409 otherRowHeight = element.new_height;
410 }
411 else {
412 element.new_height = component.new_height - otherRowHeight;
413 }
414 element.x = component.x;
415 element.y = rowY;
416 rowY += element.new_height;
417 var totalWidth = element.elements.reduce(function(sum, p) {
418 return sum += p.new_width ;
419 }, 0);
420
421 var rowX = 0;
422 var eLength = element.elements.length;
423 for (var i = 0; i < eLength; i++) {
424 var image = element.elements[i];
425 image.new_width = element.new_width * image.new_width / totalWidth;
426 image.new_height = element.new_height; //image.new_width / image.aspect_ratio;
427 image.x = rowX;
428
429 rowX += image.new_width;
430
431 container = containers[image.photo_position];
432 container.css('width', Math.floor(image.new_width));
433 container.css('height', Math.floor(image.new_height));
434 container.css('top', Math.floor(element.y));
435 container.css('left', Math.floor(element.x + image.x));
436 }
437 }
438 }
439 }
440 }
441
442 $(selector).each(function(idx, grid) {
443 var $grid = $(grid);
444 $grid.waitForImages(function() {
445 var viewportWidth = Math.floor($grid[0].getBoundingClientRect().width);
446 var triggerWidth = (isNaN(Photonic_JS.mosaic_trigger_width) || parseInt(Photonic_JS.mosaic_trigger_width) <= 0) ? 200 : parseInt(Photonic_JS.mosaic_trigger_width);
447 var maxInRow = Math.floor(viewportWidth / triggerWidth);
448 var minInRow = viewportWidth >= (triggerWidth * 2) ? 2 : 1;
449 var photos = [];
450 var divs = $grid.children();
451 var setSize = divs.length;
452 if (setSize === 0) {
453 return;
454 }
455
456 var containers = [];
457 var images = $grid.find('img');
458 $(images).each(function(imgIdx) {
459 if ($(this).parents('.photonic-panel').length > 0) {
460 return;
461 }
462
463 var image = $(this)[0];
464 var a = $(this.parentNode);
465 var div = a.parent();
466 div.attr('data-photonic-photo-index', imgIdx);
467 containers[imgIdx] = div;
468
469 if (!(image.naturalHeight === 0 || image.naturalHeight === undefined || image.naturalWidth === undefined)) {
470 var aspectRatio = (image.naturalWidth) / (image.naturalHeight);
471 photos.push({src: image.src, width: image.naturalWidth, height: image.naturalHeight, aspect_ratio: aspectRatio, photo_position: imgIdx});
472 }
473 });
474
475 setSize = photos.length;
476 var distribution = getDistribution(setSize, maxInRow, minInRow);
477
478 // We got our random distribution. Let's divide the photos up according to the distribution.
479 var groups = [], startIdx = 0;
480 $(distribution).each(function(i, size) {
481 groups.push(photos.slice(startIdx, startIdx + size));
482 startIdx += size;
483 });
484
485 var groupY = 0;
486
487 // We now have our groups of photos. We need to find the optimal layout for each group.
488 for (var g = 0; g < groups.length; g++) {
489 var group = groups[g];
490 // First, order the group by aspect ratio
491 group.sort(function(a, b) {
492 return a.aspect_ratio - b.aspect_ratio;
493 });
494
495 // Next, pick a random layout
496 var groupLayout;
497 if (group.length === 1) {
498 groupLayout = [1];
499 }
500 else if (group.length === 2) {
501 groupLayout = [1,1];
502 }
503 else {
504 groupLayout = getDistribution(group.length, group.length - 1, 1);
505 }
506
507 // Now, LAYOUT, BABY!!!
508 var cliqueF = 0, cliqueL = group.length - 1;
509 var cliques = [], indices = [];
510
511 for (var i = 2; i <= maxInRow; i++) {
512 var index = $.inArray(i, groupLayout);
513 while (-1 < index && cliqueF < cliqueL) {
514 // Ideal Layout: one landscape, one portrait. But we will take any 2 with contrasting aspect ratios
515 var clique = [];
516 var j = 0;
517 while (j < i && cliqueF <= cliqueL) {
518 clique.push(group[cliqueF++]); // One with a low aspect ratio
519 j++;
520 if (j < i && cliqueF <= cliqueL) {
521 clique.push(group[cliqueL--]); // One with a high aspect ratio
522 j++;
523 }
524 }
525 // Clique is formed. Add it to the list of cliques.
526 cliques.push(clique);
527 indices.push(index); // Keep track of the position of the clique in the row
528 index = $.inArray(i, groupLayout, index + 1);
529 }
530 }
531
532 // The ones that are not in any clique (i.e. the ones in the middle) will be given their own columns in the row.
533 var remainder = group.slice(cliqueF, cliqueL + 1);
534
535 // Now let's layout the cliques individually. Each clique is its own column.
536 var rowLayout = [];
537 for (var c = 0; c < cliques.length; c++) {
538 var clique = cliques[c];
539 var toss = Math.floor(Math.random() * 2); // 0 --> Groups of smallest and largest, or 1 --> Alternating
540 var oneRow, otherRow;
541 if (toss === 0) {
542 // Group the ones with the lowest aspect ratio together, and the ones with the highest aspect ratio together.
543 // Lay one group at the top and the other at the bottom
544 var wide = Math.max(Math.floor(Math.random() * (clique.length / 2 - 1)), 1);
545 oneRow = clique.slice(0, wide);
546 otherRow = clique.slice(wide);
547 }
548 else {
549 // Group alternates together.
550 // Lay one group at the top and the other at the bottom
551 oneRow = arrayAlternate(clique, 0);
552 otherRow = arrayAlternate(clique, 1);
553 }
554
555 // Make heights consistent within rows:
556 oneRow = setUniformHeightsForRow(oneRow);
557 otherRow = setUniformHeightsForRow(otherRow);
558
559 // Now make widths consistent
560 oneRow.new_width = Math.min(oneRow.width, otherRow.width);
561 oneRow.new_height = oneRow.new_width / oneRow.aspect_ratio;
562 otherRow.new_width = oneRow.new_width;
563 otherRow.new_height = otherRow.new_width / otherRow.aspect_ratio;
564
565 rowLayout.push({elements: [oneRow, otherRow], height: oneRow.new_height + otherRow.new_height, width: oneRow.new_width, aspect_ratio: oneRow.new_width / (oneRow.new_height + otherRow.new_height), element_position: indices[c]});
566 }
567
568 rowLayout.sort(function(a, b) {
569 return a.element_position - b.element_position;
570 });
571
572 var orderedRowLayout = [];
573 for (var position = 0; position < groupLayout.length; position++) {
574 var cliqueExists = indices.indexOf(position) > -1; //$.inArray(position, indices) > -1;
575 if (cliqueExists) {
576 orderedRowLayout.push(rowLayout.shift());
577 }
578 else {
579 var rem = remainder.shift();
580 orderedRowLayout.push({ elements: [rem], height: rem.height, width: rem.width, aspect_ratio: rem.aspect_ratio });
581 }
582 }
583
584 // Main Row layout is fully constructed and ordered. Now we need to balance heights and widths of all cliques with the "remainder"
585 var totalAspect = orderedRowLayout.reduce(function(sum, p) {
586 return sum += p.aspect_ratio ;
587 }, 0);
588
589 var elementX = 0;
590 orderedRowLayout.forEach(function(component) {
591 component.new_width = component.aspect_ratio / totalAspect * viewportWidth;
592 component.new_height = component.new_width / component.aspect_ratio;
593 component.y = groupY;
594 component.x = elementX;
595 elementX += component.new_width;
596 });
597
598 groupY += orderedRowLayout[0].new_height;
599 finalizeTiledLayout(orderedRowLayout, containers);
600 }
601
602 $grid.css('height', groupY);
603 $grid.find('img').fadeIn();
604 photonicShowSlideupTitle();
605 if (!resized) {
606 $('.photonic-loading').hide();
607 }
608 });
609 });
610 if (console !== undefined && Photonic_JS.debug_on !== '0' && Photonic_JS.debug_on !== '') console.timeEnd('Mosaic');
611 };
612
613 photonicJustifiedGridLayout(false);
614 photonicMasonryLayout(false);
615 photonicMosaicLayout(false);
616
617 var currentStreams = document.documentElement.querySelectorAll('.photonic-stream');
618 Array.prototype.forEach.call(currentStreams, function(stream) {
619 var container = stream.querySelector('.photonic-level-1-container');
620 if (container !== null && container.children !== undefined && container.children.length !== undefined && container.children.length === 0) {
621 stream.parentNode.removeChild(stream);
622 }
623 });
624
625 $('.photonic-standard-layout .photonic-level-1, .photonic-standard-layout .photonic-level-2').css({'display': 'inline-block'});
626
627 if (!supportsSVG) {
628 var icon = $('a.photonic-level-3-expand');
629 var bg = icon.css('background-image');
630 bg = bg.replace( 'svg', 'png' );
631 icon.css({'background-image': bg});
632 }
633
634 $(window).on('resize', function() {
635 photonicJustifiedGridLayout(true);
636 photonicMasonryLayout(true);
637 photonicMosaicLayout(true);
638 });
639
640