Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
liabru committed Mar 2, 2014
0 parents commit 35b8209
Show file tree
Hide file tree
Showing 6 changed files with 717 additions and 0 deletions.
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
The MIT License (MIT)

Copyright (c) 2014 Liam Brummitt

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
104 changes: 104 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# jquery.matchHeight.js #

*matchHeight* makes the height of all selected elements exactly equal.

[brm.io/jquery-match-height](http:https://brm.io/jquery-match-height/)

I needed a more robust version of the common [equal heights](https://www.google.com/search?q=jquery+equal+heights) plugin (that everyone and their grandma has made before).

So matchHeight improves on these by adding features and handling the edge cases where the others tend to fail in practice.

### Demo

See the [jquery.matchHeight.js demo](http:https://brm.io/jquery-match-height-demo).

[![jquery.matchHeight.js screenshot](http:https://brm.io/img/content/jquery-match-height/jquery-match-height.png)](http:https://brm.io/jquery-match-height-demo)

### Features

- row aware, handles floating elements
- responsive, automatically updates on window resize
- handles mixed `padding`, `margin`, `border` values (even if every element has them different)
- accounts for `box-sizing`
- handles images and other media (updates automatically after loading)
- data attributes API
- tested in IE8+, Chrome, Firefox, Chrome Android

### Status

Current version is `v0.5.0`. I've fully tested it and it works well, but if you use it make sure you test fully too.
Please report any [issues](https://github.com/liabru/jquery-match-height/issues) you find.

### Install

[jQuery](http:https://jquery.com/download/) is required, so include it first.
<br>Download [jquery.matchHeight.js](https://github.com/liabru/jquery-match-height/blob/master/jquery.matchHeight.js) and include the script in your HTML file:

<script src="jquery.matchHeight.js" type="text/javascript"></script>

### Usage

$(elements).matchHeight(byRow);

Where `byRow` is a boolean that enables or disables row detection, default is `true`.<br>
You should apply this on the [DOM ready](http:https://api.jquery.com/ready/) event.

See the included [test.html](https://github.com/liabru/jquery-match-height/blob/master/test.html) for a working example.

### Data API

Use the data attribute `data-match-height="group-name"` (or `data-mh` shorthand) where `group-name` is an arbitrary string to denote which elements should be considered as a group.

All elements with the same group name will be set to the same height when the page is loaded, regardless of their position in the DOM, without any extra code required.

Note that `byRow` will be enabled when using the data API, if you don't want this then use the above method.

### Examples

$(function() {
$('.item').matchHeight();
});

Will set all elements with the class `item` to the height of the tallest.<br>
If the items are on multiple rows, the items of each row will be set to the tallest of that row.

<div data-mh="my-group">My text</div>
<div data-mh="my-group">Some other text</div>
<div data-mh="my-other-group">Even more text</div>
<div data-mh="my-other-group">The last bit of text</div>

Will set both elements in `my-group` to the same height, then both elements in `my-other-group` to be the same height respectively.

See the included [test.html](https://github.com/liabru/jquery-match-height/blob/master/test.html) for a working example.

### Advanced Usage

There are a few internal properties and functions you should know about:

$.fn.matchHeight._groups

The array that contains all element groups that have had `matchHeight` applied. Used for automatically updating on resize events.<br>
Search and modify this array if you need to remove any groups or elements, for example if you're deleting elements.

$.fn.matchHeight._update()

If you need to manually trigger an update of all currently set equal heights groups, for example if you've modified some content.


$.fn.matchHeight._apply(elements, byRow)

Use the apply function directly if you wish to avoid the automatic update functionality.

### Why not use CSS?

Making robust, responsive equal height columns for _arbitrary content_ is [difficult or impossible](http:https://filamentgroup.com/lab/setting_equal_heights_with_jquery/) to do with CSS alone (at least without hacks or trickery, in a backwards compatible way).

Note you should probably ensure your layout is still usable if JavaScript is disabled.

### License

jquery.matchHeight.js is licensed under [The MIT License (MIT)](http:https://opensource.org/licenses/MIT)
<br/>Copyright (c) 2014 Liam Brummitt

This license is also supplied with the release and source code.
<br/>As stated in the license, absolutely no warranty is provided.
178 changes: 178 additions & 0 deletions jquery.matchHeight.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
/**
* jquery.matchHeight.js v0.5.0
* http:https://brm.io/jquery-match-height/
* License: MIT
*/

(function($) {

$.fn.matchHeight = function(byRow) {
if (this.length <= 1)
return this;

// byRow default to true
byRow = (typeof byRow !== 'undefined') ? byRow : true;

// keep track of this group so we can re-apply later on load and resize events
$.fn.matchHeight._groups.push({
elements: this,
byRow: byRow
});

// match each element's height to the tallest element in the selection
$.fn.matchHeight._apply(this, byRow);

return this;
};

$.fn.matchHeight._apply = function(elements, byRow) {
var $elements = $(elements),
rows = [$elements];

// get rows if using byRow, otherwise assume one row
if (byRow) {

// must first force an arbitrary equal height so floating elements break evenly
$elements.css({
'display': 'block',
'padding-top': '0',
'padding-bottom': '0',
'border-top': '0',
'border-bottom': '0',
'height': '100px'
});

// get the array of rows (based on element top position)
rows = _rows($elements);

// revert the temporary forced style
$elements.css({
'display': '',
'padding-top': '',
'padding-bottom': '',
'border-top': '',
'border-bottom': '',
'height': ''
});
}

$.each(rows, function(key, row) {
var $row = $(row),
maxHeight = 0;

// iterate the row and find the max height
$row.each(function(){
var $that = $(this);

// ensure we get the correct actual height (and not a previously set height value)
$that.css({ 'display': 'block', 'height': '' });

// find the max height (including padding, but not margin)
if ($that.outerHeight(false) > maxHeight)
maxHeight = $that.outerHeight(false);
});

// iterate the row and apply the height to all elements
$row.each(function(){
var $that = $(this),
verticalPadding = 0;

// handle padding and border correctly (required when not using border-box)
if ($that.css('box-sizing') !== 'border-box') {
verticalPadding += parseInt($that.css('border-top-width'), 10) + parseInt($that.css('border-bottom-width'), 10);
verticalPadding += parseInt($that.css('padding-top'), 10) + parseInt($that.css('padding-bottom'), 10);
}

// set the height (accounting for padding and border)
$that.css('height', maxHeight - verticalPadding);
});
});

return this;
};

/*
* _applyDataApi will apply matchHeight to all elements with a data-match-height attribute
*/

$.fn.matchHeight._applyDataApi = function() {
var groups = {};

// generate groups by their groupId set by elements using data-match-height
$('[data-match-height], [data-mh]').each(function() {
var $this = $(this),
groupId = $this.attr('data-match-height');
if (groupId in groups) {
groups[groupId] = groups[groupId].add($this);
} else {
groups[groupId] = $this;
}
});

// apply matchHeight to each group
$.each(groups, function() {
this.matchHeight(true);
});
};

/*
* _update function will re-apply matchHeight to all groups with the correct options
*/

$.fn.matchHeight._groups = [];

$.fn.matchHeight._update = function() {
$.each($.fn.matchHeight._groups, function() {
$.fn.matchHeight._apply(this.elements, this.byRow);
});
};

/*
* bind events
*/

// apply on DOM ready event
$($.fn.matchHeight._applyDataApi);

// update heights on load and resize events
$(window).on('load resize orientationchange', $.fn.matchHeight._update);

/*
* rows utility function
* returns array of jQuery selections representing each row
* (as displayed after float wrapping applied by browser)
*/

var _rows = function(elements) {
var tolerance = 1,
$elements = $(elements),
lastTop = null,
rows = [];

// group elements by their top position
$elements.each(function(){
var $that = $(this),
top = $that.offset().top - parseInt($that.css('margin-top'), 10),
lastRow = rows.length > 0 ? rows[rows.length - 1] : null;

if (lastRow === null) {
// first item on the row, so just push it
rows.push($that);
} else {
// if the row top is the same, add to the row group
if (Math.floor(Math.abs(lastTop - top)) <= tolerance) {
rows[rows.length - 1] = lastRow.add($that);
} else {
// otherwise start a new row group
rows.push($that);
}
}

// keep track of the last row top
lastTop = top;
});

return rows;
};

})(jQuery);
Loading

0 comments on commit 35b8209

Please sign in to comment.