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