Mailing List Archive

[interchange] Switch jQuery "equal heights" plugins
commit a9f9a979cad896ac0e80fc1af3051423f56434df
Author: Josh Lavin <digory@cpan.com>
Date: Mon Aug 22 16:29:36 2016 -0700

Switch jQuery "equal heights" plugins

- former plugin wasn't working in real-life use cases, for results pages
with multiple categories -- it would leave an orphan right-aligned as
the last item.
- the "matchHeights" plugin can group all blocks, so in results.html, we
are grouping by the block in each category.
- make results page wider by omitting right-hand component and column.
Adjust block widths afterwards.

.../strap/html/js/jquery.equalheightcolumns.min.js | 2 -
dist/strap/html/js/jquery.matchHeight.js | 385 ++++++++++++++++++++
dist/strap/pages/results.html | 12 +-
dist/strap/templates/components/cross | 4 +-
dist/strap/variables/JS | 8 +-
5 files changed, 392 insertions(+), 19 deletions(-)
---
diff --git a/dist/strap/html/js/jquery.matchHeight.js b/dist/strap/html/js/jquery.matchHeight.js
new file mode 100644
index 0000000..ab24d45
--- /dev/null
+++ b/dist/strap/html/js/jquery.matchHeight.js
@@ -0,0 +1,385 @@
+/**
+* jquery-match-height master by @liabru
+* http://brm.io/jquery-match-height/
+* License: MIT
+*/
+
+;(function(factory) { // eslint-disable-line no-extra-semi
+ 'use strict';
+ if (typeof define === 'function' && define.amd) {
+ // AMD
+ define(['jquery'], factory);
+ } else if (typeof module !== 'undefined' && module.exports) {
+ // CommonJS
+ module.exports = factory(require('jquery'));
+ } else {
+ // Global
+ factory(jQuery);
+ }
+})(function($) {
+ /*
+ * internal
+ */
+
+ var _previousResizeWidth = -1,
+ _updateTimeout = -1;
+
+ /*
+ * _parse
+ * value parse utility function
+ */
+
+ var _parse = function(value) {
+ // parse value and convert NaN to 0
+ return parseFloat(value) || 0;
+ };
+
+ /*
+ * _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 - _parse($that.css('margin-top')),
+ 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;
+ };
+
+ /*
+ * _parseOptions
+ * handle plugin options
+ */
+
+ var _parseOptions = function(options) {
+ var opts = {
+ byRow: true,
+ property: 'height',
+ target: null,
+ remove: false
+ };
+
+ if (typeof options === 'object') {
+ return $.extend(opts, options);
+ }
+
+ if (typeof options === 'boolean') {
+ opts.byRow = options;
+ } else if (options === 'remove') {
+ opts.remove = true;
+ }
+
+ return opts;
+ };
+
+ /*
+ * matchHeight
+ * plugin definition
+ */
+
+ var matchHeight = $.fn.matchHeight = function(options) {
+ var opts = _parseOptions(options);
+
+ // handle remove
+ if (opts.remove) {
+ var that = this;
+
+ // remove fixed height from all selected elements
+ this.css(opts.property, '');
+
+ // remove selected elements from all groups
+ $.each(matchHeight._groups, function(key, group) {
+ group.elements = group.elements.not(that);
+ });
+
+ // TODO: cleanup empty groups
+
+ return this;
+ }
+
+ if (this.length <= 1 && !opts.target) {
+ return this;
+ }
+
+ // keep track of this group so we can re-apply later on load and resize events
+ matchHeight._groups.push({
+ elements: this,
+ options: opts
+ });
+
+ // match each element's height to the tallest element in the selection
+ matchHeight._apply(this, opts);
+
+ return this;
+ };
+
+ /*
+ * plugin global options
+ */
+
+ matchHeight.version = 'master';
+ matchHeight._groups = [];
+ matchHeight._throttle = 80;
+ matchHeight._maintainScroll = false;
+ matchHeight._beforeUpdate = null;
+ matchHeight._afterUpdate = null;
+ matchHeight._rows = _rows;
+ matchHeight._parse = _parse;
+ matchHeight._parseOptions = _parseOptions;
+
+ /*
+ * matchHeight._apply
+ * apply matchHeight to given elements
+ */
+
+ matchHeight._apply = function(elements, options) {
+ var opts = _parseOptions(options),
+ $elements = $(elements),
+ rows = [$elements];
+
+ // take note of scroll position
+ var scrollTop = $(window).scrollTop(),
+ htmlHeight = $('html').outerHeight(true);
+
+ // get hidden parents
+ var $hiddenParents = $elements.parents().filter(':hidden');
+
+ // cache the original inline style
+ $hiddenParents.each(function() {
+ var $that = $(this);
+ $that.data('style-cache', $that.attr('style'));
+ });
+
+ // temporarily must force hidden parents visible
+ $hiddenParents.css('display', 'block');
+
+ // get rows if using byRow, otherwise assume one row
+ if (opts.byRow && !opts.target) {
+
+ // must first force an arbitrary equal height so floating elements break evenly
+ $elements.each(function() {
+ var $that = $(this),
+ display = $that.css('display');
+
+ // temporarily force a usable display value
+ if (display !== 'inline-block' && display !== 'flex' && display !== 'inline-flex') {
+ display = 'block';
+ }
+
+ // cache the original inline style
+ $that.data('style-cache', $that.attr('style'));
+
+ $that.css({
+ 'display': display,
+ 'padding-top': '0',
+ 'padding-bottom': '0',
+ 'margin-top': '0',
+ 'margin-bottom': '0',
+ 'border-top-width': '0',
+ 'border-bottom-width': '0',
+ 'height': '100px',
+ 'overflow': 'hidden'
+ });
+ });
+
+ // get the array of rows (based on element top position)
+ rows = _rows($elements);
+
+ // revert original inline styles
+ $elements.each(function() {
+ var $that = $(this);
+ $that.attr('style', $that.data('style-cache') || '');
+ });
+ }
+
+ $.each(rows, function(key, row) {
+ var $row = $(row),
+ targetHeight = 0;
+
+ if (!opts.target) {
+ // skip apply to rows with only one item
+ if (opts.byRow && $row.length <= 1) {
+ $row.css(opts.property, '');
+ return;
+ }
+
+ // iterate the row and find the max height
+ $row.each(function(){
+ var $that = $(this),
+ style = $that.attr('style'),
+ display = $that.css('display');
+
+ // temporarily force a usable display value
+ if (display !== 'inline-block' && display !== 'flex' && display !== 'inline-flex') {
+ display = 'block';
+ }
+
+ // ensure we get the correct actual height (and not a previously set height value)
+ var css = { 'display': display };
+ css[opts.property] = '';
+ $that.css(css);
+
+ // find the max height (including padding, but not margin)
+ if ($that.outerHeight(false) > targetHeight) {
+ targetHeight = $that.outerHeight(false);
+ }
+
+ // revert styles
+ if (style) {
+ $that.attr('style', style);
+ } else {
+ $that.css('display', '');
+ }
+ });
+ } else {
+ // if target set, use the height of the target element
+ targetHeight = opts.target.outerHeight(false);
+ }
+
+ // iterate the row and apply the height to all elements
+ $row.each(function(){
+ var $that = $(this),
+ verticalPadding = 0;
+
+ // don't apply to a target
+ if (opts.target && $that.is(opts.target)) {
+ return;
+ }
+
+ // handle padding and border correctly (required when not using border-box)
+ if ($that.css('box-sizing') !== 'border-box') {
+ verticalPadding += _parse($that.css('border-top-width')) + _parse($that.css('border-bottom-width'));
+ verticalPadding += _parse($that.css('padding-top')) + _parse($that.css('padding-bottom'));
+ }
+
+ // set the height (accounting for padding and border)
+ $that.css(opts.property, (targetHeight - verticalPadding) + 'px');
+ });
+ });
+
+ // revert hidden parents
+ $hiddenParents.each(function() {
+ var $that = $(this);
+ $that.attr('style', $that.data('style-cache') || null);
+ });
+
+ // restore scroll position if enabled
+ if (matchHeight._maintainScroll) {
+ $(window).scrollTop((scrollTop / htmlHeight) * $('html').outerHeight(true));
+ }
+
+ return this;
+ };
+
+ /*
+ * matchHeight._applyDataApi
+ * applies matchHeight to all elements with a data-match-height attribute
+ */
+
+ 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-mh') || $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);
+ });
+ };
+
+ /*
+ * matchHeight._update
+ * updates matchHeight on all current groups with their correct options
+ */
+
+ var _update = function(event) {
+ if (matchHeight._beforeUpdate) {
+ matchHeight._beforeUpdate(event, matchHeight._groups);
+ }
+
+ $.each(matchHeight._groups, function() {
+ matchHeight._apply(this.elements, this.options);
+ });
+
+ if (matchHeight._afterUpdate) {
+ matchHeight._afterUpdate(event, matchHeight._groups);
+ }
+ };
+
+ matchHeight._update = function(throttle, event) {
+ // prevent update if fired from a resize event
+ // where the viewport width hasn't actually changed
+ // fixes an event looping bug in IE8
+ if (event && event.type === 'resize') {
+ var windowWidth = $(window).width();
+ if (windowWidth === _previousResizeWidth) {
+ return;
+ }
+ _previousResizeWidth = windowWidth;
+ }
+
+ // throttle updates
+ if (!throttle) {
+ _update(event);
+ } else if (_updateTimeout === -1) {
+ _updateTimeout = setTimeout(function() {
+ _update(event);
+ _updateTimeout = -1;
+ }, matchHeight._throttle);
+ }
+ };
+
+ /*
+ * bind events
+ */
+
+ // apply on DOM ready event
+ $(matchHeight._applyDataApi);
+
+ // update heights on load and resize events
+ $(window).bind('load', function(event) {
+ matchHeight._update(false, event);
+ });
+
+ // throttled update heights on resize events
+ $(window).bind('resize orientationchange', function(event) {
+ matchHeight._update(true, event);
+ });
+
+});
diff --git a/dist/strap/pages/results.html b/dist/strap/pages/results.html
index 243da5d..6ff4950 100644
--- a/dist/strap/pages/results.html
+++ b/dist/strap/pages/results.html
@@ -4,6 +4,7 @@
return;
[/calc]
[tmp page_title]__COMPANY__ -- [L]Search Results[/L][/tmp]
+[tmpn display_class]leftonly[/tmpn]
[if value more_link]
[tmp page_title]__COMPANY__ -- [either][value-extended name=mv_searchspec joiner=" / "][or][value name=more_link filter=uri2string keep=1][/either][/tmp]
[/if]
@@ -13,13 +14,6 @@
[component]product_tree[/component]
[output]left[/output]
[/control-set]
-[control-set]
- [component]random[/component]
- [banner][L]Specials[/L][/banner]
- [cols]col-xs-6 col-sm-3 col-md-12[/cols]
- [size]3[/size]
- [output]right[/output]
-[/control-set]
[control reset=1]

@_TOP_@
@@ -113,10 +107,10 @@
[if-item-field category]
<h3>[either][value banner_text][or][item-field category][/either]</h3>
[/if-item-field]
- <div class="row">
+ <div class="row equal-height-container">
[/item-change 1]

- <div class="col-xs-6 col-sm-4 col-md-6 col-lg-3">
+ <div class="col-xs-6 col-sm-4 col-md-3 col-lg-2" data-mh="[item-filter word][item-field category][/item-filter]">
<div class="thumbnail">
<a href="[area [item-code]]">[image sku="[item-code]" default="../thumb.gif" imagesubdir=items makesize="120x150>"]</a>
<div class="caption">
diff --git a/dist/strap/templates/components/cross b/dist/strap/templates/components/cross
index e1e22c1..6877f43 100644
--- a/dist/strap/templates/components/cross
+++ b/dist/strap/templates/components/cross
@@ -79,8 +79,8 @@ buttons:
<h4 class="text-muted">[control name=banner default="[L]See also...[/L]"]</h4>
[div-organize embed=lc pretty=1 cols="12" filler_class="[control cols col-sm-3]" row_attr='class="row equal-height-container"']
[loop random="[scratch random]" list="[strip interpolate=1][scratch cross_codes][/strip]"]
- <div class="[control cols col-sm-3] equal-height-column">
- <DIV class="thumbnail equal-height-column">
+ <div class="[control cols col-sm-3]">
+ <DIV class="thumbnail">
<a href="[area [loop-code]]">[image src="thumb/[loop-field thumb]" default="thumb.gif"]</a>
<DIV class="caption text-center">
<h5><a href="[area [loop-code]]">[loop-description]</a></h5>
diff --git a/dist/strap/variables/JS b/dist/strap/variables/JS
index d354f74..dbe5bf6 100644
--- a/dist/strap/variables/JS
+++ b/dist/strap/variables/JS
@@ -1,13 +1,9 @@
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
-<script src="[var WWW_DIR]/js/jquery.equalheightcolumns.min.js"></script>
+<script src="[var WWW_DIR]/js/jquery.matchHeight.js"></script>
<script>
$(document).ready(function() {
- $(".equal-height-container .equal-height-column").equalHeightColumns({
- maxWidth: 1199,
- checkHeight: 'innerHeight'
- });
-});
+ $('.equal-height-container').matchHeight();
</script>

[if var GOOGLE_ANL_ID]

_______________________________________________
interchange-cvs mailing list
interchange-cvs@icdevgroup.org
http://www.icdevgroup.org/mailman/listinfo/interchange-cvs