vendor: 10,928 bytes, lines 1-364
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 matchHeight._rows = _rows; 140 141 /* 142 * matchHeight._apply 143 * apply matchHeight to given elements 144 */ 145 146 matchHeight._apply = function(elements, options) { 147 var opts = _parseOptions(options), 148 $elements = $(elements), 149 rows = [$elements]; 150 151 // take note of scroll position 152 var scrollTop = $(window).scrollTop(), 153 htmlHeight = $('html').outerHeight(true); 154 155 // get hidden parents 156 var $hiddenParents = $elements.parents().filter(':hidden'); 157 158 // cache the original inline style 159 $hiddenParents.each(function() { 160 var $that = $(this); 161 $that.data('style-cache', $that.attr('style')); 162 }); 163 164 // temporarily must force hidden parents visible 165 $hiddenParents.css('display', 'block'); 166 167 // get rows if using byRow, otherwise assume one row 168 if (opts.byRow && !opts.target) { 169 170 // must first force an arbitrary equal height so floating elements break evenly 171 $elements.each(function() { 172 var $that = $(this), 173 display = $that.css('display'); 174 175 // temporarily force a usable display value 176 if (display !== 'inline-block' && display !== 'inline-flex') { 177 display = 'block'; 178 } 179 180 // cache the original inline style 181 $that.data('style-cache', $that.attr('style')); 182 183 $that.css({ 184 'display': display, 185 'padding-top': '0', 186 'padding-bottom': '0', 187 'margin-top': '0', 188 'margin-bottom': '0', 189 'border-top-width': '0', 190 'border-bottom-width': '0', 191 'height': '100px' 192 }); 193 }); 194 195 // get the array of rows (based on element top position) 196 rows = _rows($elements); 197 198 // revert original inline styles 199 $elements.each(function() { 200 var $that = $(this); 201 $that.attr('style', $that.data('style-cache') || ''); 202 }); 203 } 204 205 $.each(rows, function(key, row) { 206 var $row = $(row), 207 targetHeight = 0; 208 209 if (!opts.target) { 210 // skip apply to rows with only one item 211 if (opts.byRow && $row.length <= 1) { 212 $row.css(opts.property, ''); 213 return; 214 } 215 216 // iterate the row and find the max height 217 $row.each(function(){ 218 var $that = $(this), 219 display = $that.css('display'); 220 221 // temporarily force a usable display value 222 if (display !== 'inline-block' && display !== 'inline-flex') { 223 display = 'block'; 224 } 225 226 // ensure we get the correct actual height (and not a previously set height value) 227 var css = { 'display': display }; 228 css[opts.property] = ''; 229 $that.css(css); 230 231 // find the max height (including padding, but not margin) 232 if ($that.outerHeight(false) > targetHeight) { 233 targetHeight = $that.outerHeight(false); 234 } 235 236 // revert display block 237 $that.css('display', ''); 238 }); 239 } else { 240 // if target set, use the height of the target element 241 targetHeight = opts.target.outerHeight(false); 242 } 243 244 // iterate the row and apply the height to all elements 245 $row.each(function(){ 246 var $that = $(this), 247 verticalPadding = 0; 248 249 // don't apply to a target 250 if (opts.target && $that.is(opts.target)) { 251 return; 252 } 253 254 // handle padding and border correctly (required when not using border-box) 255 if ($that.css('box-sizing') !== 'border-box') { 256 verticalPadding += _parse($that.css('border-top-width')) + _parse($that.css('border-bottom-width')); 257 verticalPadding += _parse($that.css('padding-top')) + _parse($that.css('padding-bottom')); 258 } 259 260 // set the height (accounting for padding and border) 261 $that.css(opts.property, (targetHeight - verticalPadding) + 'px'); 262 }); 263 }); 264 265 // revert hidden parents 266 $hiddenParents.each(function() { 267 var $that = $(this); 268 $that.attr('style', $that.data('style-cache') || null); 269 }); 270 271 // restore scroll position if enabled 272 if (matchHeight._maintainScroll) { 273 $(window).scrollTop((scrollTop / htmlHeight) * $('html').outerHeight(true)); 274 } 275 276 return this; 277 }; 278 279 /* 280 * matchHeight._applyDataApi 281 * applies matchHeight to all elements with a data-match-height attribute 282 */ 283 284 matchHeight._applyDataApi = function() { 285 var groups = {}; 286 287 // generate groups by their groupId set by elements using data-match-height 288 $('[data-match-height], [data-mh]').each(function() { 289 var $this = $(this), 290 groupId = $this.attr('data-mh') || $this.attr('data-match-height'); 291 292 if (groupId in groups) { 293 groups[groupId] = groups[groupId].add($this); 294 } else { 295 groups[groupId] = $this; 296 } 297 }); 298 299 // apply matchHeight to each group 300 $.each(groups, function() { 301 this.matchHeight(true); 302 }); 303 }; 304 305 /* 306 * matchHeight._update 307 * updates matchHeight on all current groups with their correct options 308 */ 309 310 var _update = function(event) { 311 if (matchHeight._beforeUpdate) { 312 matchHeight._beforeUpdate(event, matchHeight._groups); 313 } 314 315 $.each(matchHeight._groups, function() { 316 matchHeight._apply(this.elements, this.options); 317 }); 318 319 if (matchHeight._afterUpdate) { 320 matchHeight._afterUpdate(event, matchHeight._groups); 321 } 322 }; 323 324 matchHeight._update = function(throttle, event) { 325 // prevent update if fired from a resize event 326 // where the viewport width hasn't actually changed 327 // fixes an event looping bug in IE8 328 if (event && event.type === 'resize') { 329 var windowWidth = $(window).width(); 330 if (windowWidth === _previousResizeWidth) { 331 return; 332 } 333 _previousResizeWidth = windowWidth; 334 } 335 336 // throttle updates 337 if (!throttle) { 338 _update(event); 339 } else if (_updateTimeout === -1) { 340 _updateTimeout = setTimeout(function() { 341 _update(event); 342 _updateTimeout = -1; 343 }, matchHeight._throttle); 344 } 345 }; 346 347 /* 348 * bind events 349 */ 350 351 // apply on DOM ready event 352 $(matchHeight._applyDataApi); 353 354 // update heights on load and resize events 355 $(window).bind('load', function(event) { 356 matchHeight._update(false, event); 357 }); 358 359 // throttled update heights on resize events 360 $(window).bind('resize orientationchange', function(event) { 361 matchHeight._update(true, event); 362 }); 363 364})(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.