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