1/*! 2 * Right-Height v4.1.0: Dynamically set content areas of different lengths to the same height 3 * (c) 2015 Chris Ferdinandi 4 * MIT License 5 * http://github.com/cferdinandi/right-height 6 */ 7 8(function (root, factory) { 9 if ( typeof define === 'function' && define.amd ) { 10 define([], factory(root)); 11 } else if ( typeof exports === 'object' ) { 12 module.exports = factory(root); 13 } else { 14 root.rightHeight = factory(root); 15 } 16})(typeof global !== "undefined" ? global : this.window || this.global, function (root) { 17 18 'use strict'; 19 20 // 21 // Variables 22 // 23 24 var rightHeight = {}; // Object for public APIs 25 var supports = 'querySelector' in document && 'addEventListener' in root; // Feature test 26 var settings, containers, eventTimeout; 27 28 // Default settings 29 var defaults = { 30 selector: '[data-right-height]', 31 selectorContent: '[data-right-height-content]', 32 callback: function () {} 33 }; 34 35 36 // 37 // Methods 38 // 39 40 /** 41 * A simple forEach() implementation for Arrays, Objects and NodeLists. 42 * @private 43 * @author Todd Motto 44 * @link https://github.com/toddmotto/foreach 45 * @param {Array|Object|NodeList} collection Collection of items to iterate 46 * @param {Function} callback Callback function for each iteration 47 * @param {Array|Object|NodeList} scope Object/NodeList/Array that forEach is iterating over (aka `this`) 48 */
49 var forEach = function ( collection, callback, scope ) { 50 if ( Object.prototype.toString.call( collection ) === '[object Object]' ) { 51 for ( var prop in collection ) { 52 if ( Object.prototype.hasOwnProperty.call( collection, prop ) ) { 53 callback.call( scope, collection[prop], prop, collection ); 54 } 55 } 56 } else { 57 for ( var i = 0, len = collection.length; i < len; i++ ) { 58 callback.call( scope, collection[i], i, collection ); 59 } 60 } 61 }; 62 63 /** 64 * Merge two or more objects. Returns a new object. 65 * @private 66 * @param {Boolean} deep If true, do a deep (or recursive) merge [optional] 67 * @param {Object} objects The objects to merge together 68 * @returns {Object} Merged values of defaults and options 69 */ 70 var extend = function () { 71 72 // Variables 73 var extended = {}; 74 var deep = false; 75 var i = 0; 76 var length = arguments.length; 77 78 // Check if a deep merge 79 if ( Object.prototype.toString.call( arguments[0] ) === '[object Boolean]' ) { 80 deep = arguments[0]; 81 i++; 82 } 83 84 // Merge the object into the extended object 85 var merge = function (obj) { 86 for ( var prop in obj ) { 87 if ( Object.prototype.hasOwnProperty.call( obj, prop ) ) { 88 // If deep merge and property is an object, merge properties 89 if ( deep && Object.prototype.toString.call(obj[prop]) === '[object Object]' ) { 90 extended[prop] = extend( true, extended[prop], obj[prop] ); 91 } else { 92 extended[prop] = obj[prop]; 93 } 94 } 95 } 96 }; 97 98 // Loop through each object and conduct a merge 99 for ( ; i < length; i++ ) { 100 var obj = arguments[i]; 101 merge(obj); 102 } 103 104 return extended; 105 106 }; 107 108 /** 109 * Get an element's distance from the top of the Document. 110 * @private 111 * @param {Node} elem The element 112 * @return {Number} Distance from the top in pixels 113 */ 114 var getOffsetTop = function ( elem ) { 115 var location = 0; 116 if (elem.offsetParent) { 117 do { 118 location += elem.offsetTop; 119 elem = elem.offsetParent; 120 } while (elem); 121 } 122 return location >= 0 ? location : 0; 123 }; 124 125 /** 126 * Check if a group of content areas are stacked 127 * @private 128 * @param {NodeList} contents A collection of content areas to compare 129 * @return {Boolean} Returns true if elements are stacked 130 */ 131 var checkIfStacked = function ( contents ) { 132 133 // Selectors and variables 134 var contentFirst = contents.item(0); 135 var contentSecond = contents.item(1); 136 137 // Determine if content containers are stacked 138 if ( contentFirst && contentSecond ) { 139 if ( getOffsetTop(contentFirst) - getOffsetTop(contentSecond) === 0 ) { 140 return false; 141 } else { 142 return true; 143 } 144 } else { 145 return false; 146 } 147 148 }; 149 150 /** 151 * Reset the content height to 'auto' 152 * @private 153 * @param {Element} content The content area to set to height: auto 154 */ 155 var resetHeight = function ( content ) { 156 content.style.height = ''; 157 content.style.minHeight = ''; 158 }; 159 160 /** 161 * Get the natural height of each content area, and 162 * record the tallest height to set for all other elements. 163 * @private 164 * @param {Element} content A content area 165 * @param {Number} height The current tallest height 166 * @return {Number} The updated tallest height 167 */ 168 var getHeight = function ( content, height ) { 169 if ( content.offsetHeight > height ) { 170 height = content.offsetHeight; 171 } 172 return height; 173 }; 174 175 /** 176 * Set the height of each content area 177 * @private 178 * @param {Element} content The content area to set a height for 179 * @param {Number} height The height of the tallest content area 180 */ 181 var setHeight = function ( content, height ) { 182 content.style.height = height + 'px'; 183 }; 184 185 /** 186 * Get all content areas within a group 187 * @public 188 * @param {Element} container The wrapper that contains a set of content areas 189 * @param {Object} options 190 */ 191 rightHeight.adjustContainerHeight = function ( container, options ) { 192 193 // Selectors and variables 194 var settings = extend( settings || defaults, options || {} ); // Merge user options with defaults 195 var contents = container.querySelectorAll( settings.selectorContent ); 196 var isStacked = checkIfStacked(contents); 197 var height = '0'; 198 199 // Reset each content area to its natural height 200 forEach(contents, function (content) { 201 resetHeight( content ); 202 }); 203 204 // If content areas are not stacked, give them equal heights 205 if ( !isStacked ) {
206 forEach(contents, function (content) { 207 height = getHeight( content, height ); 208 }); 209 forEach(contents, function (content) { 210 setHeight( content, height ); 211 }); 212 } 213 214 settings.callback( container ); // Run callbacks after adjust content 215 216 }; 217 218 /** 219 * For each group of content, adjust the content area heights 220 * @private 221 * @param {NodeList} containers A collection of content wrappers 222 * @param {Object} settings 223 */ 224 var runRightHeight = function () { 225 forEach(containers, function (container) { 226 rightHeight.adjustContainerHeight( container, settings ); 227 }); 228 }; 229 230 /** 231 * On window resize, only run 'runRightHeight' at a rate of 15fps for better performance 232 * @private 233 * @param {Function} eventTimeout Timeout function 234 * @param {NodeList} containers A collection of content wrappers 235 * @param {Object} settings 236 */ 237 var eventThrottler = function () { 238 if ( !eventTimeout ) { 239 eventTimeout = setTimeout(function() { 240 eventTimeout = null; 241 runRightHeight( containers, settings ); 242 }, 66); 243 } 244 }; 245 246 /** 247 * Destroy the current initialization. 248 * @public 249 */ 250 rightHeight.destroy = function () { 251 252 if (!settings) return; 253 254 // Reset content and remove event listeners 255 forEach(containers, function (container) { 256 var contents = container.querySelectorAll( settings.selectorContent ); 257 forEach(contents, function (content) { 258 resetHeight( content ); 259 }); 260 }); 261 root.removeEventListener('resize', eventThrottler, false); 262 263 // Reset variables 264 settings = null; 265 containers = null; 266 eventTimeout = null; 267 268 }; 269 270 /** 271 * Initialize Right Height 272 * @public 273 * @param {Object} options User settings 274 */ 275 rightHeight.init = function ( options ) { 276 277 // feature test 278 if ( !supports ) return; 279 280 // Destroy any existing initializations 281 rightHeight.destroy(); 282 283 // Selectors and variables 284 settings = extend( defaults, options || {} ); // Merge user options with defaults 285 containers = document.querySelectorAll( settings.selector ); // Groups of content 286 287 // Events and listeners 288 runRightHeight( containers, options ); // Run Right Height on load 289 root.addEventListener('load', runRightHeight, false); 290 root.addEventListener('resize', eventThrottler, false); // Run Right Height on window resize 291 292 }; 293 294 295 // 296 // Public APIs 297 // 298 299 return rightHeight; 300 301});
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.