1/** 2 * @file 3 * Masonry script. 4 * 5 * Sponsored by: www.freelance-drupal.com 6 */ 7 8(function ($, Drupal, drupalSettings) { 9 'use strict'; 10 11 Drupal.behaviors.masonry = { 12 attach: function (context) { 13 14 /** 15 * (internal) Sub-function for code factoring: actually build masonry. 16 */ 17 function _buildMasonry($container, options) { 18 const masonryExists = $container.hasClass('masonry'); 19 20 // If no masonry find in container: init it... 21 if (!masonryExists) { 22 $container.addClass('masonry').addClass('masonry-layout').masonry(options); 23 $(window).resize(function () { 24 $container.masonry('bindResize'); 25 }); 26 } else { 27 // ...otherwise, simply rebuild the layout. 28 $container.masonry('reloadItems').masonry('layout'); 29 } 30 31 // Hack to support lazysizes lazy loading. 32 if (options.imagesLazyLoad) { 33 let lastClassState = false; 34 const observer = new MutationObserver(function(mutationsList) { 35 mutationsList.forEach(function(mutation) { 36 if (mutation.type === 'attributes' && mutation.attributeName === 'class') { 37 let currentClassState = mutation.target.classList.contains(options.lazyloadedSelector); 38 39 if (lastClassState !== currentClassState) { 40 lastClassState = currentClassState; 41 42 if (currentClassState) { 43 if (options.imagesFirst) { 44 $container.imagesLoaded(function () { 45 $container.masonry('reloadItems').masonry('layout'); 46 }); 47 } else { 48 $container.masonry('reloadItems').masonry('layout'); 49 } 50 } 51 } 52 } 53 }); 54 }); 55 56 $('img.' + options.lazyloadSelector, $container).each(function() { 57 if (!$(this).hasClass('imgloaded')) { 58 $(this).addClass('imgloaded'); 59 observer.observe(this, {attributes: true}); 60 } 61 }); 62 } 63 } 64 65 /** 66 * Apply Masonry. 67 */ 68 function applyMasonry() { 69 70 // Iterate through all Masonry instances. 71 $.each(drupalSettings.masonry, function (container, settings) { 72 73 // Set container. 74 settings.lazyload_selector = undefined; 75 const $container = $(container); 76 77 // Set options. 78 const options = {}; 79 80 // Apply column width units accordingly. 81 if (settings.column_width) { 82 if (settings.column_width_units === 'px') { 83 options.columnWidth = parseInt(settings.column_width); 84 } 85 else if (settings.column_width_units === '%') { 86 const column_width = parseInt(settings.column_width); 87 options.columnWidth = ($container.width() * (column_width / 100)) - column_width; 88 } 89 else { 90 settings.force_width = false; // Can't force width on CSS selector. 91 options.columnWidth = settings.column_width; 92 } 93 } 94 95 // Apply gutter width units accordingly. 96 if (settings.gutter_width) { 97 if (settings.gutter_width_units === 'px') { 98 options.gutter = parseInt(settings.gutter_width); 99 } 100 else if (settings.gutter_width_units === '%') { 101 const gutter = parseInt(settings.gutter_width); 102 options.gutter = ($container.width() * (gutter / 100)) - gutter; 103 } 104 else { 105 options.gutter = settings.gutter_width; 106 } 107 } 108 109 // Sets the item selector and size force. 110 if (settings.item_selector) { 111 options.itemSelector = settings.item_selector; 112 // Add custom class to all items. 113 const $items = $(settings.item_selector, $container) 114 $items.addClass('masonry-item'); 115 // Force the column size. 116 if (settings.force_width) { 117 $items.css('width', settings.column_width); 118 } 119 } 120 121 // Add stamped selector. 122 if (settings.stamp) { 123 options.stamp = settings.stamp; 124 } 125 126 // Add the various options. 127 options.isResizeBound = settings.resizable; 128 options.isFitWidth = settings.fit_width; 129 options.imagesFirst = settings.images_first; 130 options.imagesLazyLoad = settings.images_lazyload; 131 options.lazyloadSelector = settings.lazyload_selector; 132 options.lazyloadedSelector = settings.lazyloaded_selector; 133 if (settings.rtl) { 134 options.isOriginLeft = false;
135 } 136 if (settings.animated) { 137 options.transitionDuration = settings.animation_duration + 'ms'; 138 } 139 else { 140 options.transitionDuration = 0; 141 } 142 if (settings.percent_position) { 143 options.percentPosition = true; 144 } 145 146 // Include the extra options. 147 $.each(settings.extra_options, function (option, value) { 148 options[option] = value; 149 }); 150 151 /** 152 * Apply Masonry to container. 153 */ 154 155 // Load images first if necessary. 156 if (settings.images_first) { 157 $container.imagesLoaded(function () { 158 _buildMasonry($container, options); 159 }); 160 } 161 162 // Apply without loading images first otherwise. 163 else { 164 _buildMasonry($container, options); 165 } 166 }); 167 } 168 169 // Apply Masonry on the page. 170 applyMasonry(); 171 172 // Hack for tabs: when the tab is open, it takes to reload Masonry. 173 $('a[data-toggle="tab"]', context).on('shown.bs.tab', function () { 174 applyMasonry(); 175 }); 176 177 } 178 }; 179})(jQuery, Drupal, drupalSettings);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.