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