1'use strict'; 2 3/** 4 * Copyright Marc J. Schmidt. See the LICENSE file at the top-level 5 * directory of this distribution and at 6 * https://github.com/marcj/css-element-queries/blob/master/LICENSE. 7 */ 8(function (root, factory) { 9 if (typeof define === "function" && define.amd) { 10 define(factory); 11 } else if (typeof exports === "object") { 12 module.exports = factory(); 13 } else { 14 root.ResizeSensor = factory(); 15 } 16}(typeof window !== 'undefined' ? window : this, function () { 17 18 // Make sure it does not throw in a SSR (Server Side Rendering) situation 19 if (typeof window === "undefined") { 20 return null; 21 } 22 // https://github.com/Semantic-Org/Semantic-UI/issues/3855 23 // https://github.com/marcj/css-element-queries/issues/257 24 var globalWindow = typeof window != 'undefined' && window.Math == Math 25 ? window 26 : typeof self != 'undefined' && self.Math == Math 27 ? self 28 : Function('return this')(); 29 // Only used for the dirty checking, so the event callback count is limited to max 1 call per fps per sensor. 30 // In combination with the event based resize sensor this saves cpu time, because the sensor is too fast and 31 // would generate too many unnecessary events. 32 var requestAnimationFrame = globalWindow.requestAnimationFrame || 33 globalWindow.mozRequestAnimationFrame || 34 globalWindow.webkitRequestAnimationFrame || 35 function (fn) { 36 return globalWindow.setTimeout(fn, 20); 37 }; 38 39 /** 40 * Iterate over each of the provided element(s). 41 * 42 * @param {HTMLElement|HTMLElement[]} elements 43 * @param {Function} callback 44 */ 45 function forEachElement(elements, callback){ 46 var elementsType = Object.prototype.toString.call(elements); 47 var isCollectionTyped = ('[object Array]' === elementsType 48 || ('[object NodeList]' === elementsType) 49 || ('[object HTMLCollection]' === elementsType) 50 || ('[object Object]' === elementsType) 51 || ('undefined' !== typeof jQuery && elements instanceof jQuery) //jquery 52 || ('undefined' !== typeof Elements && elements instanceof Elements) //mootools 53 ); 54 var i = 0, j = elements.length; 55 if (isCollectionTyped) { 56 for (; i < j; i++) { 57 callback(elements[i]); 58 } 59 } else { 60 callback(elements); 61 } 62 } 63 64 /** 65 * Get element size 66 * @param {HTMLElement} element 67 * @returns {Object} {width, height} 68 */ 69 function getElementSize(element) { 70 if (!element.getBoundingClientRect) { 71 return { 72 width: element.offsetWidth, 73 height: element.offsetHeight 74 } 75 } 76 77 var rect = element.getBoundingClientRect(); 78 return { 79 width: Math.round(rect.width), 80 height: Math.round(rect.height) 81 } 82 } 83 84 /** 85 * Apply CSS styles to element. 86 * 87 * @param {HTMLElement} element 88 * @param {Object} style 89 */ 90 function setStyle(element, style) { 91 Object.keys(style).forEach(function(key) { 92 element.style[key] = style[key]; 93 }); 94 } 95 96 /** 97 * Class for dimension change detection. 98 * 99 * @param {Element|Element[]|Elements|jQuery} element 100 * @param {Function} callback 101 * 102 * @constructor 103 */ 104 var ResizeSensor = function(element, callback) { 105 /** 106 * 107 * @constructor 108 */ 109 function EventQueue() { 110 var q = []; 111 this.add = function(ev) { 112 q.push(ev); 113 }; 114 115 var i, j; 116 this.call = function(sizeInfo) { 117 for (i = 0, j = q.length; i < j; i++) { 118 q[i].call(this, sizeInfo); 119 } 120 }; 121 122 this.remove = function(ev) { 123 var newQueue = []; 124 for(i = 0, j = q.length; i < j; i++) { 125 if(q[i] !== ev) newQueue.push(q[i]); 126 } 127 q = newQueue; 128 }; 129 130 this.length = function() { 131 return q.length; 132 } 133 } 134 135 /** 136 * 137 * @param {HTMLElement} element 138 * @param {Function} resized 139 */ 140 function attachResizeEvent(element, resized) { 141 if (!element) return; 142 if (element.resizedAttached) { 143 element.resizedAttached.add(resized); 144 return; 145 } 146 147 element.resizedAttached = new EventQueue(); 148 element.resizedAttached.add(resized); 149 150 element.resizeSensor = document.createElement('div'); 151 element.resizeSensor.dir = 'ltr'; 152 element.resizeSensor.className = 'resize-sensor'; 153 154 var style = { 155 pointerEvents: 'none', 156 position: 'absolute', 157 left: '0px', 158 top: '0px', 159 right: '0px', 160 bottom: '0px', 161 overflow: 'hidden', 162 zIndex: '-1', 163 visibility: 'hidden', 164 maxWidth: '100%' 165 }; 166 var styleChild = { 167 position: 'absolute', 168 left: '0px', 169 top: '0px', 170 transition: '0s', 171 }; 172 173 setStyle(element.resizeSensor, style); 174 175 var expand = document.createElement('div'); 176 expand.className = 'resize-sensor-expand'; 177 setStyle(expand, style); 178 179 var expandChild = document.createElement('div'); 180 setStyle(expandChild, styleChild); 181 expand.appendChild(expandChild); 182 183 var shrink = document.createElement('div'); 184 shrink.className = 'resize-sensor-shrink'; 185 setStyle(shrink, style); 186 187 var shrinkChild = document.createElement('div'); 188 setStyle(shrinkChild, styleChild); 189 setStyle(shrinkChild, { width: '200%', height: '200%' }); 190 shrink.appendChild(shrinkChild); 191 192 element.resizeSensor.appendChild(expand); 193 element.resizeSensor.appendChild(shrink); 194 element.appendChild(element.resizeSensor); 195 196 var computedStyle = window.getComputedStyle(element); 197 var position = computedStyle ? computedStyle.getPropertyValue('position') : null; 198 if ('absolute' !== position && 'relative' !== position && 'fixed' !== position) { 199 element.style.position = 'relative'; 200 } 201 202 var dirty, rafId; 203 var size = getElementSize(element); 204 var lastWidth = 0; 205 var lastHeight = 0; 206 var initialHiddenCheck = true; 207 var lastAnimationFrame = 0; 208 209 var resetExpandShrink = function () { 210 var width = element.offsetWidth; 211 var height = element.offsetHeight; 212 213 expandChild.style.width = (width + 10) + 'px'; 214 expandChild.style.height = (height + 10) + 'px'; 215 216 expand.scrollLeft = width + 10; 217 expand.scrollTop = height + 10; 218 219 shrink.scrollLeft = width + 10; 220 shrink.scrollTop = height + 10; 221 }; 222 223 var reset = function() { 224 // Check if element is hidden 225 if (initialHiddenCheck) { 226 var invisible = element.offsetWidth === 0 && element.offsetHeight === 0; 227 if (invisible) { 228 // Check in next frame 229 if (!lastAnimationFrame){ 230 lastAnimationFrame = requestAnimationFrame(function(){ 231 lastAnimationFrame = 0; 232 233 reset(); 234 }); 235 } 236 237 return; 238 } else { 239 // Stop checking 240 initialHiddenCheck = false; 241 } 242 } 243 244 resetExpandShrink(); 245 }; 246 element.resizeSensor.resetSensor = reset; 247 248 var onResized = function() { 249 rafId = 0; 250 251 if (!dirty) return; 252 253 lastWidth = size.width; 254 lastHeight = size.height; 255 256 if (element.resizedAttached) { 257 element.resizedAttached.call(size); 258 } 259 }; 260 261 var onScroll = function() { 262 size = getElementSize(element); 263 dirty = size.width !== lastWidth || size.height !== lastHeight; 264
265 if (dirty && !rafId) { 266 rafId = requestAnimationFrame(onResized); 267 } 268 269 reset(); 270 }; 271 272 var addEvent = function(el, name, cb) { 273 if (el.attachEvent) { 274 el.attachEvent('on' + name, cb); 275 } else { 276 el.addEventListener(name, cb); 277 } 278 }; 279 280 addEvent(expand, 'scroll', onScroll); 281 addEvent(shrink, 'scroll', onScroll); 282 283 // Fix for custom Elements 284 requestAnimationFrame(reset); 285 } 286 287 forEachElement(element, function(elem){ 288 attachResizeEvent(elem, callback); 289 }); 290 291 this.detach = function(ev) { 292 ResizeSensor.detach(element, ev); 293 }; 294 295 this.reset = function() { 296 element.resizeSensor.resetSensor(); 297 }; 298 }; 299 300 ResizeSensor.reset = function(element) { 301 forEachElement(element, function(elem){ 302 elem.resizeSensor.resetSensor(); 303 }); 304 }; 305 306 ResizeSensor.detach = function(element, ev) { 307 forEachElement(element, function(elem){ 308 if (!elem) return; 309 if(elem.resizedAttached && typeof ev === "function"){ 310 elem.resizedAttached.remove(ev); 311 if(elem.resizedAttached.length()) return; 312 } 313 if (elem.resizeSensor) { 314 if (elem.contains(elem.resizeSensor)) { 315 elem.removeChild(elem.resizeSensor); 316 } 317 delete elem.resizeSensor; 318 delete elem.resizedAttached; 319 } 320 }); 321 }; 322 323 if (typeof MutationObserver !== "undefined") { 324 var observer = new MutationObserver(function (mutations) { 325 for (var i in mutations) { 326 if (mutations.hasOwnProperty(i)) { 327 var items = mutations[i].addedNodes; 328 for (var j = 0; j < items.length; j++) { 329 if (items[j].resizeSensor) { 330 ResizeSensor.reset(items[j]); 331 } 332 } 333 } 334 } 335 }); 336 337 document.addEventListener("DOMContentLoaded", function (event) { 338 observer.observe(document.body, { 339 childList: true, 340 subtree: true, 341 }); 342 }); 343 } 344 345 return ResizeSensor; 346 347}));
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.