vendor: 10,926 bytes, lines 1-351
1/** 2* jquery.matchHeight.js master 3* http://brm.io/jquery-match-height/ 4* License: MIT 5*/ 6 7;(function($) { 8 /* 9 * internal 10 */ 11 12 var _previousResizeWidth = -1, 13 _updateTimeout = -1; 14 15 /* 16 * _parse 17 * value parse utility function 18 */ 19 20 var _parse = function(value) { 21 // parse value and convert NaN to 0 22 return parseFloat(value) || 0; 23 }; 24 25 /* 26 * _rows 27 * utility function returns array of jQuery selections representing each row 28 * (as displayed after float wrapping applied by browser) 29 */ 30 31 var _rows = function(elements) { 32 var tolerance = 1, 33 $elements = $(elements), 34 lastTop = null, 35 rows = []; 36 37 // group elements by their top position 38 $elements.each(function(){ 39 var $that = $(this), 40 top = $that.offset().top - _parse($that.css('margin-top')), 41 lastRow = rows.length > 0 ? rows[rows.length - 1] : null; 42 43 if (lastRow === null) { 44 // first item on the row, so just push it 45 rows.push($that); 46 } else { 47 // if the row top is the same, add to the row group 48 if (Math.floor(Math.abs(lastTop - top)) <= tolerance) { 49 rows[rows.length - 1] = lastRow.add($that); 50 } else { 51 // otherwise start a new row group 52 rows.push($that); 53 } 54 } 55 56 // keep track of the last row top 57 lastTop = top; 58 }); 59 60 return rows; 61 }; 62 63 /* 64 * _parseOptions 65 * handle plugin options 66 */ 67 68 var _parseOptions = function(options) { 69 var opts = { 70 byRow: true, 71 property: 'height', 72 target: null, 73 remove: false 74 }; 75 76 if (typeof options === 'object') { 77 return $.extend(opts, options); 78 } 79 80 if (typeof options === 'boolean') { 81 opts.byRow = options; 82 } else if (options === 'remove') { 83 opts.remove = true; 84 } 85 86 return opts; 87 }; 88 89 /* 90 * matchHeight 91 * plugin definition 92 */ 93 94 var matchHeight = $.fn.matchHeight = function(options) { 95 var opts = _parseOptions(options); 96 97 // handle remove 98 if (opts.remove) { 99 var that = this; 100 101 // remove fixed height from all selected elements 102 this.css(opts.property, ''); 103 104 // remove selected elements from all groups 105 $.each(matchHeight._groups, function(key, group) { 106 group.elements = group.elements.not(that); 107 }); 108 109 // TODO: cleanup empty groups 110 111 return this; 112 } 113 114 if (this.length <= 1 && !opts.target) { 115 return this; 116 } 117 118 // keep track of this group so we can re-apply later on load and resize events 119 matchHeight._groups.push({ 120 elements: this, 121 options: opts 122 }); 123 124 // match each element's height to the tallest element in the selection 125 matchHeight._apply(this, opts); 126 127 return this; 128 }; 129 130 /* 131 * plugin global options 132 */ 133 134 matchHeight._groups = []; 135 matchHeight._throttle = 80; 136 matchHeight._maintainScroll = false; 137 matchHeight._beforeUpdate = null; 138 matchHeight._afterUpdate = null; 139 140 /* 141 * matchHeight._apply 142 * apply matchHeight to given elements 143 */ 144 145 matchHeight._apply = function(elements, options) { 146 var opts = _parseOptions(options), 147 $elements = $(elements), 148 rows = [$elements]; 149 150 // take note of scroll position 151 var scrollTop = $(window).scrollTop(), 152 htmlHeight = $('html').outerHeight(true); 153 154 // get hidden parents 155 var $hiddenParents = $elements.parents().filter(':hidden'); 156 157 // cache the original inline style 158 $hiddenParents.each(function() { 159 var $that = $(this); 160 $that.data('style-cache', $that.attr('style')); 161 }); 162 163 // temporarily must force hidden parents visible 164 $hiddenParents.css('display', 'block'); 165 166 // get rows if using byRow, otherwise assume one row 167 if (opts.byRow && !opts.target) { 168 169 // must first force an arbitrary equal height so floating elements break evenly 170 $elements.each(function() { 171 var $that = $(this), 172 display = $that.css('display'); 173 174 // temporarily force a usable display value 175 if (display !== 'inline-block' && display !== 'inline-flex') { 176 display = 'block'; 177 } 178 179 // cache the original inline style 180 $that.data('style-cache', $that.attr('style')); 181 182 $that.css({ 183 'display': display, 184 'padding-top': '0', 185 'padding-bottom': '0', 186 'margin-top': '0', 187 'margin-bottom': '0', 188 'border-top-width': '0', 189 'border-bottom-width': '0', 190 'height': '100px' 191 }); 192 }); 193 194 // get the array of rows (based on element top position) 195 rows = _rows($elements); 196 197 // revert original inline styles 198 $elements.each(function() { 199 var $that = $(this); 200 $that.attr('style', $that.data('style-cache') || ''); 201 }); 202 } 203 204 $.each(rows, function(key, row) { 205 var $row = $(row), 206 targetHeight = 0; 207 208 if (!opts.target) { 209 // skip apply to rows with only one item 210 if (opts.byRow && $row.length <= 1) { 211 $row.css(opts.property, ''); 212 return; 213 } 214 215 // iterate the row and find the max height 216 $row.each(function(){ 217 var $that = $(this), 218 display = $that.css('display'); 219 220 // temporarily force a usable display value 221 if (display !== 'inline-block' && display !== 'inline-flex') { 222 display = 'block'; 223 } 224 225 // ensure we get the correct actual height (and not a previously set height value) 226 var css = { 'display': display }; 227 css[opts.property] = ''; 228 $that.css(css); 229 230 // find the max height (including padding, but not margin) 231 if ($that.outerHeight(false) > targetHeight) { 232 targetHeight = $that.outerHeight(false); 233 } 234 235 // revert display block 236 $that.css('display', ''); 237 }); 238 } else { 239 // if target set, use the height of the target element 240 targetHeight = opts.target.outerHeight(false); 241 } 242 243 // iterate the row and apply the height to all elements 244 $row.each(function(){ 245 var $that = $(this), 246 verticalPadding = 0; 247 248 // don't apply to a target 249 if (opts.target && $that.is(opts.target)) { 250 return; 251 } 252 253 // handle padding and border correctly (required when not using border-box) 254 if ($that.css('box-sizing') !== 'border-box') { 255 verticalPadding += _parse($that.css('border-top-width')) + _parse($that.css('border-bottom-width')); 256 verticalPadding += _parse($that.css('padding-top')) + _parse($that.css('padding-bottom')); 257 } 258 259 // set the height (accounting for padding and border) 260 $that.css(opts.property, (targetHeight - verticalPadding) + 'px'); 261 }); 262 }); 263 264 // revert hidden parents 265 $hiddenParents.each(function() { 266 var $that = $(this); 267 $that.attr('style', $that.data('style-cache') || null); 268 }); 269 270 // restore scroll position if enabled 271 if (matchHeight._maintainScroll) { 272 $(window).scrollTop((scrollTop / htmlHeight) * $('html').outerHeight(true)); 273 } 274 275 return this; 276 }; 277 278 /* 279 * matchHeight._applyDataApi 280 * applies matchHeight to all elements with a data-match-height attribute 281 */ 282 283 matchHeight._applyDataApi = function() { 284 var groups = {}; 285 286 // generate groups by their groupId set by elements using data-match-height 287 $('[data-match-height], [data-mh]').each(function() { 288 var $this = $(this), 289 groupId = $this.attr('data-mh') || $this.attr('data-match-height'); 290 291 if (groupId in groups) { 292 groups[groupId] = groups[groupId].add($this); 293 } else { 294 groups[groupId] = $this; 295 } 296 }); 297 298 // apply matchHeight to each group 299 $.each(groups, function() { 300 this.matchHeight(true); 301 }); 302 }; 303 304 /* 305 * matchHeight._update 306 * updates matchHeight on all current groups with their correct options 307 */ 308 309 var _update = function(event) { 310 if (matchHeight._beforeUpdate) { 311 matchHeight._beforeUpdate(event, matchHeight._groups); 312 } 313 314 $.each(matchHeight._groups, function() { 315 matchHeight._apply(this.elements, this.options); 316 }); 317 318 if (matchHeight._afterUpdate) { 319 matchHeight._afterUpdate(event, matchHeight._groups); 320 } 321 }; 322 323 matchHeight._update = function(throttle, event) { 324 // prevent update if fired from a resize event 325 // where the viewport width hasn't actually changed 326 // fixes an event looping bug in IE8 327 if (event && event.type === 'resize') { 328 var windowWidth = $(window).width(); 329 if (windowWidth === _previousResizeWidth) { 330 return; 331 } 332 _previousResizeWidth = windowWidth; 333 } 334 335 // throttle updates 336 if (!throttle) { 337 _update(event); 338 } else if (_updateTimeout === -1) { 339 _updateTimeout = setTimeout(function() { 340 _update(event); 341 _updateTimeout = -1; 342 }, matchHeight._throttle); 343 } 344 }; 345 346 /* 347 * bind events 348 */ 349 350 // apply on DOM ready event 351 $(matchHeight._applyDataApi);
352 353 // update heights on load and resize events 354 $(window).bind('load', function(event) { 355 matchHeight._update(false, event); 356 }); 357 358 // throttled update heights on resize events 359 $(window).bind('resize orientationchange', function(event) { 360 matchHeight._update(true, event); 361 }); 362 363})(jQuery);
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.