1/** 2* Copyright Marc J. Schmidt. See the LICENSE file at the top-level 3* directory of this distribution and at 4* https://github.com/marcj/css-element-queries/blob/master/LICENSE. 5*/ 6; 7(function (root, factory) { 8 if (typeof define === "function" && define.amd) { 9 define(factory); 10 } else if (typeof exports === "object") { 11 module.exports = factory(); 12 } else { 13 root.ResizeSensor = factory(); 14 } 15}(typeof window !== 'undefined' ? window : this, function () { 16 17 // Make sure it does not throw in a SSR (Server Side Rendering) situation 18 if (typeof window === "undefined") { 19 return null; 20 } 21 // Only used for the dirty checking, so the event callback count is limited to max 1 call per fps per sensor. 22 // In combination with the event based resize sensor this saves cpu time, because the sensor is too fast and 23 // would generate too many unnecessary events. 24 var requestAnimationFrame = window.requestAnimationFrame || 25 window.mozRequestAnimationFrame || 26 window.webkitRequestAnimationFrame || 27 function (fn) { 28 return window.setTimeout(fn, 20); 29 }; 30 31 /** 32 * Iterate over each of the provided element(s). 33 * 34 * @param {HTMLElement|HTMLElement[]} elements 35 * @param {Function} callback 36 */ 37 function forEachElement(elements, callback){ 38 var elementsType = Object.prototype.toString.call(elements); 39 var isCollectionTyped = ('[object Array]' === elementsType 40 || ('[object NodeList]' === elementsType) 41 || ('[object HTMLCollection]' === elementsType) 42 || ('[object Object]' === elementsType) 43 || ('undefined' !== typeof jQuery && elements instanceof jQuery) //jquery 44 || ('undefined' !== typeof Elements && elements instanceof Elements) //mootools 45 ); 46 var i = 0, j = elements.length; 47 if (isCollectionTyped) { 48 for (; i < j; i++) { 49 callback(elements[i]); 50 } 51 } else { 52 callback(elements); 53 } 54 } 55 56 /** 57 * Class for dimension change detection. 58 * 59 * @param {Element|Element[]|Elements|jQuery} element 60 * @param {Function} callback 61 * 62 * @constructor 63 */ 64 var ResizeSensor = function(element, callback) { 65 /** 66 * 67 * @constructor 68 */ 69 function EventQueue() { 70 var q = []; 71 this.add = function(ev) { 72 q.push(ev); 73 }; 74 75 var i, j; 76 this.call = function() { 77 for (i = 0, j = q.length; i < j; i++) { 78 q[i].call(); 79 } 80 }; 81 82 this.remove = function(ev) { 83 var newQueue = []; 84 for(i = 0, j = q.length; i < j; i++) { 85 if(q[i] !== ev) newQueue.push(q[i]); 86 } 87 q = newQueue; 88 } 89 90 this.length = function() { 91 return q.length; 92 } 93 } 94 95 /** 96 * 97 * @param {HTMLElement} element 98 * @param {Function} resized 99 */ 100 function attachResizeEvent(element, resized) { 101 if (!element) return; 102 if (element.resizedAttached) { 103 element.resizedAttached.add(resized); 104 return; 105 } 106 107 element.resizedAttached = new EventQueue(); 108 element.resizedAttached.add(resized); 109 110 element.resizeSensor = document.createElement('div'); 111 element.resizeSensor.className = 'resize-sensor'; 112 var style = 'position: absolute; left: 0; top: 0; right: 0; bottom: 0; overflow: hidden; z-index: -1; visibility: hidden;'; 113 var styleChild = 'position: absolute; left: 0; top: 0; transition: 0s;'; 114 115 element.resizeSensor.style.cssText = style; 116 element.resizeSensor.innerHTML = 117 '<div class="resize-sensor-expand" style="' + style + '">' + 118 '<div style="' + styleChild + '"></div>' + 119 '</div>' + 120 '<div class="resize-sensor-shrink" style="' + style + '">' + 121 '<div style="' + styleChild + ' width: 200%; height: 200%"></div>' + 122 '</div>'; 123 element.appendChild(element.resizeSensor); 124 125 if (element.resizeSensor.offsetParent !== element) { 126 element.style.position = 'relative'; 127 } 128 129 var expand = element.resizeSensor.childNodes[0]; 130 var expandChild = expand.childNodes[0]; 131 var shrink = element.resizeSensor.childNodes[1]; 132 var dirty, rafId, newWidth, newHeight; 133 var lastWidth = element.offsetWidth; 134 var lastHeight = element.offsetHeight; 135 136 var reset = function() { 137 expandChild.style.width = '100000px'; 138 expandChild.style.height = '100000px'; 139 140 expand.scrollLeft = 100000; 141 expand.scrollTop = 100000; 142 143 shrink.scrollLeft = 100000; 144 shrink.scrollTop = 100000; 145 }; 146 147 reset(); 148 149 var onResized = function() { 150 rafId = 0; 151 152 if (!dirty) return; 153 154 lastWidth = newWidth; 155 lastHeight = newHeight; 156 157 if (element.resizedAttached) { 158 element.resizedAttached.call(); 159 } 160 }; 161 162 var onScroll = function() { 163 newWidth = element.offsetWidth; 164 newHeight = element.offsetHeight; 165 dirty = newWidth != lastWidth || newHeight != lastHeight; 166
167 if (dirty && !rafId) { 168 rafId = requestAnimationFrame(onResized); 169 } 170 171 reset(); 172 }; 173 174 var addEvent = function(el, name, cb) { 175 if (el.attachEvent) { 176 el.attachEvent('on' + name, cb); 177 } else { 178 el.addEventListener(name, cb); 179 } 180 }; 181 182 addEvent(expand, 'scroll', onScroll); 183 addEvent(shrink, 'scroll', onScroll); 184 } 185 186 forEachElement(element, function(elem){ 187 attachResizeEvent(elem, callback); 188 }); 189 190 this.detach = function(ev) { 191 ResizeSensor.detach(element, ev); 192 }; 193 }; 194 195 ResizeSensor.detach = function(element, ev) { 196 forEachElement(element, function(elem){ 197 if (!elem) return 198 if(elem.resizedAttached && typeof ev == "function"){ 199 elem.resizedAttached.remove(ev); 200 if(elem.resizedAttached.length()) return; 201 } 202 if (elem.resizeSensor) { 203 if (elem.contains(elem.resizeSensor)) { 204 elem.removeChild(elem.resizeSensor); 205 } 206 delete elem.resizeSensor; 207 delete elem.resizedAttached; 208 } 209 }); 210 }; 211 212 return ResizeSensor; 213 214}));
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.