PageSourceSearch

https://choosewindmill.com/wp-content/plugins/ut-portfolio/assets/…ry.isotope.perfectmasonry.min.js?ver=5.1.19

js choosewindmill.com collected 2026-10-04 06:37:26 UTC 10,392 bytes, 271 lines download raw bytes

1/*!
2 * PerfectMasonry extension for Isotope
3 *
4 * Does similar things as the Isotopes "masonry" layoutmode, except that this one will actually go back and plug the holes
5 * left by bigger elements, thus making a perfect brick wall. Profit!
6 * 
7 * Usage:
8 * 	$('#grid').isotope({
9 * 		layoutMode: 'perfectMasonry',
10 *		perfectMasonry: {
11 *			layout: 'horizontal',		// Set layout as vertical/horizontal (default: vertical)
12 *			columnWidth: 200,			// Set/Prefer columns to x wide (default: width of first tile)
13 *			rowHeight: 200,				// Set/Prefer rows to y high (default: height of first tile)
14 * 
15 *			liquid: true,				// Set layout as liquid (default: false)
16 *			cols: 3,					// Force to have x columns (default: null)
17 *			rows: 3,					// Force to have y rows (default: null)
18 *			minCols: 3,					// Set min col count (default: 1)
19 *			minRows: 3,					// Set min row count (default: 1)
20 *			maxCols: 5,					// Set max col count (default: 9999)
21 *			maxRows: 4					// Set max row count (default: 9999)
22 * 		}
23 * 	});
24 *
25 * 
26 * @author Mikko Tikkanen, Zonear Ltd. <[email protected]>
27 */
28;(function($, undefined) {
29	var version = '1.2.1';
30	var isotope = null,
31		$context = null,
32		$container = null,
33		isFirstRun = true;
34	
35	$.extend($.Isotope.prototype, {
36
37		/**
38		 * Reset layout properties
39		 *
40		 * Runs before any layout change
41		 * -------------------------------------------------------------------------------------------------------- */
42		_perfectMasonryReset: function() {
43			var isVertical = this.options.perfectMasonry.layout != 'horizontal',
44				isLiquid = this.options.perfectMasonry.liquid == true;
45			
46			// Do things on a first run
47			if(isFirstRun) {
48				isFirstRun = false;
49				isotope = this;
50				$context = $(this.element.context);
51				$container = $context.parent();
52				
53				// Make sure we have min/maxCols & rows
54				this.options.perfectMasonry.minCols = this.options.perfectMasonry.minCols || 1; 
55				this.options.perfectMasonry.minRows = this.options.perfectMasonry.minRows || 1;
56				this.options.perfectMasonry.maxCols = this.options.perfectMasonry.maxCols || 9999; 
57				this.options.perfectMasonry.maxRows = this.options.perfectMasonry.maxRows || 9999;
58			}
59			
60			// For liquid layout, replace default resize handler with forced relayout (outside firstRun as Isotope grid can be destroyed and created on the fly)
61			if(isLiquid && $._data(window, 'events').smartresize) {
62				$(window).off('smartresize.isotope');
63				$(window).on('resize.isotope.perfectmasonry', function() {
64					if(!$context.hasClass('isotope')) { return; }
65					$context.isotope('reLayout');
66				});
67			}
68			
69			// Setup layout properties ---------------------------------------------------
70			var properties = this.perfectMasonry = {};
71			
72			// Fill properties with columnWidth and rowHeight (true argument)
73			this._getSegments();
74      		this._getSegments(true);
75      		
76      		// ...and with cols & rows
77			this._perfectMasonryGetSegments();
78      		
79			// Handle liquid layout (cols, rows & sizes must be calculated on the fly)
80			if(isLiquid) {
81				var width = $container.width(),
82					height = $container.height();
83					
84				// Make sure we have colwidth & rowheight (get it from the calculated )
85				this.options.perfectMasonry.columnWidth = this.options.perfectMasonry.columnWidth || properties.columnWidth;
86				this.options.perfectMasonry.rowHeight = this.options.perfectMasonry.rowHeight || properties.rowHeight;
87				
88				// Figure out how many cols & rows either have been set or can be fit into the container (also make sure we're still between min/max)
89				properties.cols = this.options.perfectMasonry.cols || Math.floor(width / this.options.perfectMasonry.columnWidth);
90				properties.rows = this.options.perfectMasonry.rows || Math.floor(height / this.options.perfectMasonry.rowHeight);
91				properties.cols = Math.min(Math.max(properties.cols, this.options.perfectMasonry.minCols), this.options.perfectMasonry.maxCols);
92				properties.rows = Math.min(Math.max(properties.rows, this.options.perfectMasonry.minRows), this.options.perfectMasonry.maxRows);
93								
94				// Recalculate accurate width/height so that the whole available space is used
95				var diff = (isVertical ? properties.columnWidth / (width / properties.cols) : properties.rowHeight / (height / properties.rows));
96				properties.columnWidth = Math.floor(properties.columnWidth / diff);
97				properties.rowHeight = Math.floor(properties.rowHeight / diff);
98			}
99			
100			// Create top row of the grid
101			properties.grid = new Array(this.perfectMasonry.cols);
102
103			// Set container dimensions to 0
104			properties.containerHeight = 0;
105			properties.containerWidth = 0;
106	    },
107
108
109
110	    /**
111		 * Create layout
112		 * -------------------------------------------------------------------------------------------------------- */
113		_perfectMasonryLayout: function($elems) {
114			var instance = this,
115				properties = this.perfectMasonry,
116				isVertical = instance.options.perfectMasonry.layout != 'horizontal',
117				isLiquid = instance.options.perfectMasonry.liquid == true;
118			
119			// Create first set of the grid
120			properties.grid = new Array(properties[(isVertical ? 'cols' : 'rows')]);
121			
122			// Loop each element
123			$elems.each(function() {
124				var $this  = $(this);
125				
126				// Calculate col & row spans (with liquid layouts, store desired width as element data)
127				var colSpan = (isLiquid ? $this.data('colSpan') : Math.ceil($this.outerWidth() / (properties.columnWidth + 1))),
128					rowSpan = (isLiquid ? $this.data('rowSpan') : Math.ceil($this.outerHeight() / (properties.rowHeight + 1)));
129				
130				// For the first run with liquid layout, calculate sizes
131				if(!colSpan) {
132					colSpan = Math.ceil($this.outerWidth(true) / (properties.columnWidth + 1));
133					rowSpan = Math.ceil($this.outerHeight(true) / (properties.rowHeight + 1));
134					$this.data('colSpan', colSpan);
135					$this.data('rowSpan', rowSpan);
136				}
137				
138				
139				/* Do the layout
140				 * -------------------------------------------------------------------------------- */
141				
142				// Set spans
143				var aSpan = (isVertical ? colSpan : rowSpan);
144				var bSpan = (isVertical ? rowSpan : colSpan);
145				
146				// Bigger tiles can't fit into the last primary (though keep it still at least as 1)
147				var max = Math.max((isVertical ? properties.cols - colSpan : properties.rows - rowSpan) + 1, 1);
148								
149				// Loop through/create primaries (set hard limit of 10.000 to prevent endless loop)
150				var a = -1, x = 0, y = 0;
151				while(++a < 10000) {
152					properties.grid[a] = properties.grid[a] || [];
153					
154					// Go through the secondaries in the primary, set secondary and tile
155					for (var b = 0; b < max; b++) {
156						var tile = properties.grid[a][b];
157							
158						// If the tile is not free, move to the next one immediately
159						if(tile) { continue; }
160
161						// Tiles spanning to multiple rows/columns - Check if it'll fit
162						var doesFit = true;
163						if(colSpan > 1 || rowSpan > 1) {
164							for (var i = 0; i < aSpan; i++) {
165								for (var j = 0; j < bSpan; j++) {
166									properties.grid[a+j] = properties.grid[a+j] || [];
167									if(properties.grid[a+j][b+i]) { doesFit = false; break; }
168								}
169
170								// If it doesn't fit, don't waste our time looping
171								if(!doesFit) { break; }
172							}
173						}
174						if(!doesFit) { continue }
175						
176
177						// Set all the cells as occupied
178						for (var i = 0; i < aSpan; i++) {
179							for (var j = 0; j < bSpan; j++) {
180								properties.grid[a+j][b+i] = true;
181							}
182						}
183						
184						// Set x & y values
185						var x = a, y = b;
186						if(isVertical) { var x = b, y = a; }
187						
188						// Update container dimensions
189						properties.containerWidth = Math.max(properties.containerWidth, (x + aSpan) * properties.columnWidth);
190						properties.containerHeight = Math.max(properties.containerHeight, (y + bSpan) * properties.rowHeight);
191						
192						// In case of liquid layout, set element size full width/height
193						if(instance.options.perfectMasonry.liquid == true) {
194							$this.css({
195								width: properties.columnWidth * colSpan,
196								height: properties.rowHeight * rowSpan
197							});
198						}
199
200						// Set the element location and GTFO
201						instance._pushPosition($this, x*properties.columnWidth, y*properties.rowHeight);
202						return;
203					}
204				}
205				
206
207				// If we got all the way down to here, the element doesn't fit - Hide it
208				instance._pushPosition($this, -9999, -9999);
209			});
210		},
211		
212		
213		
214	    /**
215		 * Get container size
216		 *
217		 * For resizing the container
218		 * -------------------------------------------------------------------------------------------------------- */
219	    _perfectMasonryGetContainerSize: function() {
220			return {
221				width: this.perfectMasonry.containerWidth,
222				height: this.perfectMasonry.containerHeight
223			};
224	    },
225		
226		
227		
228	    /**
229		 * Resize changed
230		 *
231		 * Figure out if layout changed
232		 * -------------------------------------------------------------------------------------------------------- */
233	    _perfectMasonryResizeChanged: function() {
234	    	var properties = this.perfectMasonry;
235
236	    	// Store old values and calculate new numbers
237	    	var oldCols = properties.cols,
238	    		oldRows = properties.rows;
239	    	this._perfectMasonryGetSegments();
240			
241			// If new count was different, force layout change
242			if(this.options.perfectMasonry.layout == 'horizontal' && oldRows !== properties.rows) { return true; }
243			if(oldCols !== properties.cols) { return true; }
244			
245	    	return false;
246	    },
247		
248		
249		
250		
251	    /**
252		 * Private
253		 * Do segment calculations by hand
254		 * -------------------------------------------------------------------------------------------------------- */
255		_perfectMasonryGetSegments: function() {
256			var properties = this.perfectMasonry;
257			var parent = this.options.perfectMasonry.parent || this.element.parent();
258			
259			// Calculate columns
260			var parentWidth = parent.width();
261			properties.cols = Math.floor(parentWidth / properties.columnWidth) || 1;
262
263			// Calculate rows
264			var parentHeight = parent.height();
265			properties.rows = Math.floor(parentHeight / properties.rowHeight) || 1;
266		}
267	});
268	
269	
270})(jQuery);
271

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.