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 var cancelAnimationFrame = globalWindow.cancelAnimationFrame || 40 globalWindow.mozCancelAnimationFrame || 41 globalWindow.webkitCancelAnimationFrame || 42 function (timer) { 43 globalWindow.clearTimeout(timer); 44 }; 45 46 /** 47 * Iterate over each of the provided element(s). 48 * 49 * @param {HTMLElement|HTMLElement[]} elements 50 * @param {Function} callback 51 */ 52 function forEachElement(elements, callback){ 53 var elementsType = Object.prototype.toString.call(elements); 54 var isCollectionTyped = ('[object Array]' === elementsType 55 || ('[object NodeList]' === elementsType) 56 || ('[object HTMLCollection]' === elementsType) 57 || ('[object Object]' === elementsType) 58 || ('undefined' !== typeof jQuery && elements instanceof jQuery) //jquery 59 || ('undefined' !== typeof Elements && elements instanceof Elements) //mootools 60 ); 61 var i = 0, j = elements.length; 62 if (isCollectionTyped) { 63 for (; i < j; i++) { 64 callback(elements[i]); 65 } 66 } else { 67 callback(elements); 68 } 69 } 70 71 /** 72 * Get element size 73 * @param {HTMLElement} element 74 * @returns {Object} {width, height} 75 */ 76 function getElementSize(element) { 77 if (!element.getBoundingClientRect) { 78 return { 79 width: element.offsetWidth, 80 height: element.offsetHeight 81 } 82 } 83 84 var rect = element.getBoundingClientRect(); 85 return { 86 width: Math.round(rect.width), 87 height: Math.round(rect.height) 88 } 89 } 90 91 /** 92 * Apply CSS styles to element. 93 * 94 * @param {HTMLElement} element 95 * @param {Object} style 96 */ 97 function setStyle(element, style) { 98 Object.keys(style).forEach(function(key) { 99 element.style[key] = style[key]; 100 }); 101 } 102 103 /** 104 * Class for dimension change detection. 105 * 106 * @param {Element|Element[]|Elements|jQuery} element 107 * @param {Function} callback 108 * 109 * @constructor 110 */ 111 var ResizeSensor = function(element, callback) { 112 //Is used when checking in reset() only for invisible elements 113 var lastAnimationFrameForInvisibleCheck = 0; 114 115 /** 116 * 117 * @constructor 118 */ 119 function EventQueue() { 120 var q = []; 121 this.add = function(ev) { 122 q.push(ev); 123 }; 124 125 var i, j; 126 this.call = function(sizeInfo) { 127 for (i = 0, j = q.length; i < j; i++) { 128 q[i].call(this, sizeInfo); 129 } 130 }; 131 132 this.remove = function(ev) { 133 var newQueue = []; 134 for(i = 0, j = q.length; i < j; i++) { 135 if(q[i] !== ev) newQueue.push(q[i]); 136 } 137 q = newQueue; 138 }; 139 140 this.length = function() { 141 return q.length; 142 } 143 } 144 145 /** 146 * 147 * @param {HTMLElement} element 148 * @param {Function} resized 149 */ 150 function attachResizeEvent(element, resized) { 151 if (!element) return; 152 if (element.resizedAttached) { 153 element.resizedAttached.add(resized); 154 return; 155 } 156 157 element.resizedAttached = new EventQueue(); 158 element.resizedAttached.add(resized); 159 160 element.resizeSensor = document.createElement('div'); 161 element.resizeSensor.dir = 'ltr'; 162 element.resizeSensor.className = 'resize-sensor'; 163 164 var style = { 165 pointerEvents: 'none', 166 position: 'absolute', 167 left: '0px', 168 top: '0px', 169 right: '0px', 170 bottom: '0px', 171 overflow: 'hidden', 172 zIndex: '-1', 173 visibility: 'hidden', 174 maxWidth: '100%' 175 }; 176 var styleChild = { 177 position: 'absolute', 178 left: '0px', 179 top: '0px', 180 transition: '0s', 181 }; 182 183 setStyle(element.resizeSensor, style); 184 185 var expand = document.createElement('div'); 186 expand.className = 'resize-sensor-expand'; 187 setStyle(expand, style); 188 189 var expandChild = document.createElement('div'); 190 setStyle(expandChild, styleChild); 191 expand.appendChild(expandChild); 192 193 var shrink = document.createElement('div'); 194 shrink.className = 'resize-sensor-shrink'; 195 setStyle(shrink, style); 196 197 var shrinkChild = document.createElement('div'); 198 setStyle(shrinkChild, styleChild); 199 setStyle(shrinkChild, { width: '200%', height: '200%' }); 200 shrink.appendChild(shrinkChild); 201 202 element.resizeSensor.appendChild(expand); 203 element.resizeSensor.appendChild(shrink); 204 element.appendChild(element.resizeSensor); 205 206 var computedStyle = window.getComputedStyle(element); 207 var position = computedStyle ? computedStyle.getPropertyValue('position') : null; 208 if ('absolute' !== position && 'relative' !== position && 'fixed' !== position && 'sticky' !== position) { 209 element.style.position = 'relative'; 210 } 211 212 var dirty = false; 213 214 //last request animation frame id used in onscroll event 215 var rafId = 0; 216 var size = getElementSize(element); 217 var lastWidth = 0; 218 var lastHeight = 0; 219 var initialHiddenCheck = true; 220 lastAnimationFrameForInvisibleCheck = 0; 221 222 var resetExpandShrink = function () { 223 var width = element.offsetWidth; 224 var height = element.offsetHeight; 225 226 expandChild.style.width = (width + 10) + 'px'; 227 expandChild.style.height = (height + 10) + 'px'; 228 229 expand.scrollLeft = width + 10; 230 expand.scrollTop = height + 10; 231 232 shrink.scrollLeft = width + 10; 233 shrink.scrollTop = height + 10; 234 }; 235 236 var reset = function() { 237 // Check if element is hidden 238 if (initialHiddenCheck) { 239 var invisible = element.offsetWidth === 0 && element.offsetHeight === 0; 240 if (invisible) { 241 // Check in next frame 242 if (!lastAnimationFrameForInvisibleCheck){ 243 lastAnimationFrameForInvisibleCheck = requestAnimationFrame(function(){ 244 lastAnimationFrameForInvisibleCheck = 0; 245 reset(); 246 }); 247 } 248 249 return; 250 } else { 251 // Stop checking 252 initialHiddenCheck = false; 253 } 254 } 255 256 resetExpandShrink(); 257 }; 258 element.resizeSensor.resetSensor = reset; 259 260 var onResized = function() { 261 rafId = 0; 262 263 if (!dirty) return; 264 265 lastWidth = size.width; 266 lastHeight = size.height; 267 268 if (element.resizedAttached) { 269 element.resizedAttached.call(size); 270 } 271 }; 272 273 var onScroll = function() { 274 size = getElementSize(element); 275 dirty = size.width !== lastWidth || size.height !== lastHeight; 276
277 if (dirty && !rafId) { 278 rafId = requestAnimationFrame(onResized); 279 } 280 281 reset(); 282 }; 283 284 var addEvent = function(el, name, cb) { 285 if (el.attachEvent) { 286 el.attachEvent('on' + name, cb); 287 } else { 288 el.addEventListener(name, cb); 289 } 290 }; 291 292 addEvent(expand, 'scroll', onScroll); 293 addEvent(shrink, 'scroll', onScroll); 294 295 // Fix for custom Elements and invisible elements 296 lastAnimationFrameForInvisibleCheck = requestAnimationFrame(function(){ 297 lastAnimationFrameForInvisibleCheck = 0; 298 reset(); 299 }); 300 } 301 302 forEachElement(element, function(elem){ 303 attachResizeEvent(elem, callback); 304 }); 305 306 this.detach = function(ev) { 307 // clean up the unfinished animation frame to prevent a potential endless requestAnimationFrame of reset 308 if (lastAnimationFrameForInvisibleCheck) { 309 cancelAnimationFrame(lastAnimationFrameForInvisibleCheck); 310 lastAnimationFrameForInvisibleCheck = 0; 311 } 312 ResizeSensor.detach(element, ev); 313 }; 314 315 this.reset = function() { 316 //To prevent invoking element.resizeSensor.resetSensor if it's undefined 317 if (element.resizeSensor.resetSensor) { 318 element.resizeSensor.resetSensor(); 319 } 320 }; 321 }; 322 323 ResizeSensor.reset = function(element) { 324 forEachElement(element, function(elem){ 325 //To prevent invoking element.resizeSensor.resetSensor if it's undefined 326 if (element.resizeSensor.resetSensor) { 327 elem.resizeSensor.resetSensor(); 328 } 329 }); 330 }; 331 332 ResizeSensor.detach = function(element, ev) { 333 forEachElement(element, function(elem){ 334 if (!elem) return; 335 if(elem.resizedAttached && typeof ev === "function"){ 336 elem.resizedAttached.remove(ev); 337 if(elem.resizedAttached.length()) return; 338 } 339 if (elem.resizeSensor) { 340 if (elem.contains(elem.resizeSensor)) { 341 elem.removeChild(elem.resizeSensor); 342 } 343 delete elem.resizeSensor; 344 delete elem.resizedAttached; 345 } 346 }); 347 }; 348 349 if (typeof MutationObserver !== "undefined") { 350 var observer = new MutationObserver(function (mutations) { 351 for (var i in mutations) { 352 if (mutations.hasOwnProperty(i)) { 353 var items = mutations[i].addedNodes; 354 for (var j = 0; j < items.length; j++) { 355 if (items[j].resizeSensor) { 356 ResizeSensor.reset(items[j]); 357 } 358 } 359 } 360 } 361 }); 362 363 document.addEventListener("DOMContentLoaded", function (event) { 364 observer.observe(document.body, { 365 childList: true, 366 subtree: true, 367 }); 368 }); 369 } 370 return ResizeSensor; 371}));
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.