diff --git a/README.md b/README.md index 73278b4..70f0b47 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,12 @@ TODO Release Notes ============= + +v0.6.0 +------ + +- CSP support added + v0.5.3 ------ diff --git a/detect-element-resize.js b/detect-element-resize.js index cbb3c02..7169b1d 100644 --- a/detect-element-resize.js +++ b/detect-element-resize.js @@ -1,147 +1,189 @@ /** * Detect Element Resize * -* https://github.com/sdecima/javascript-detect-element-resize +* https://github.com/tedaford/javascript-detect-element-resize * Sebastian Decima +* Rewritten by Ted Ford * -* version: 0.5.3 +* version: 0.6.0 **/ (function () { - var attachEvent = document.attachEvent, - stylesCreated = false; - + var attachEvent = document.attachEvent; + var stylesCreated = false; + if (!attachEvent) { - var requestFrame = (function(){ - var raf = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || - function(fn){ return window.setTimeout(fn, 20); }; - return function(fn){ return raf(fn); }; + var requestFrame = (function () { + var raf = + window.requestAnimationFrame || + window.mozRequestAnimationFrame || + window.webkitRequestAnimationFrame || + function (fn) { + return window.setTimeout(fn, 20); + }; + return function (fn) { + return raf(fn); + }; })(); - - var cancelFrame = (function(){ - var cancel = window.cancelAnimationFrame || window.mozCancelAnimationFrame || window.webkitCancelAnimationFrame || - window.clearTimeout; - return function(id){ return cancel(id); }; + + var cancelFrame = (function () { + var cancel = + window.cancelAnimationFrame || + window.mozCancelAnimationFrame || + window.webkitCancelAnimationFrame || + window.clearTimeout; + return function (id) { + return cancel(id); + }; })(); - function resetTriggers(element){ + function resetTriggers(element) { var triggers = element.__resizeTriggers__, expand = triggers.firstElementChild, contract = triggers.lastElementChild, expandChild = expand.firstElementChild; + contract.scrollLeft = contract.scrollWidth; contract.scrollTop = contract.scrollHeight; - expandChild.style.width = expand.offsetWidth + 1 + 'px'; - expandChild.style.height = expand.offsetHeight + 1 + 'px'; + expandChild.style.width = expand.offsetWidth + 1 + "px"; + expandChild.style.height = expand.offsetHeight + 1 + "px"; expand.scrollLeft = expand.scrollWidth; expand.scrollTop = expand.scrollHeight; - }; + } - function checkTriggers(element){ - return element.offsetWidth != element.__resizeLast__.width || - element.offsetHeight != element.__resizeLast__.height; + function checkTriggers(element) { + return ( + element.offsetWidth != element.__resizeLast__.width || + element.offsetHeight != element.__resizeLast__.height + ); } - - function scrollListener(e){ + + function scrollListener(e) { var element = this; resetTriggers(this); if (this.__resizeRAF__) cancelFrame(this.__resizeRAF__); - this.__resizeRAF__ = requestFrame(function(){ + this.__resizeRAF__ = requestFrame(function () { if (checkTriggers(element)) { element.__resizeLast__.width = element.offsetWidth; element.__resizeLast__.height = element.offsetHeight; - element.__resizeListeners__.forEach(function(fn){ + element.__resizeListeners__.forEach(function (fn) { fn.call(element, e); }); } }); - }; - - /* Detect CSS Animations support to detect element display/re-attach */ + } + + // Detect CSS animation support var animation = false, - animationstring = 'animation', - keyframeprefix = '', - animationstartevent = 'animationstart', - domPrefixes = 'Webkit Moz O ms'.split(' '), - startEvents = 'webkitAnimationStart animationstart oAnimationStart MSAnimationStart'.split(' '), - pfx = ''; + animationstring = "animation", + keyframeprefix = "", + animationstartevent = "animationstart", + domPrefixes = "Webkit Moz O ms".split(" "), + startEvents = "webkitAnimationStart animationstart oAnimationStart MSAnimationStart".split(" "), + pfx = ""; + { - var elm = document.createElement('fakeelement'); - if( elm.style.animationName !== undefined ) { animation = true; } - - if( animation === false ) { - for( var i = 0; i < domPrefixes.length; i++ ) { - if( elm.style[ domPrefixes[i] + 'AnimationName' ] !== undefined ) { - pfx = domPrefixes[ i ]; - animationstring = pfx + 'Animation'; - keyframeprefix = '-' + pfx.toLowerCase() + '-'; - animationstartevent = startEvents[ i ]; + var elm = document.createElement("fakeelement"); + if (elm.style.animationName !== undefined) { + animation = true; + } + + if (animation === false) { + for (var i = 0; i < domPrefixes.length; i++) { + if (elm.style[domPrefixes[i] + "AnimationName"] !== undefined) { + pfx = domPrefixes[i]; + animationstring = pfx + "Animation"; + keyframeprefix = "-" + pfx.toLowerCase() + "-"; + animationstartevent = startEvents[i]; animation = true; break; } } } } - - var animationName = 'resizeanim'; - var animationKeyframes = '@' + keyframeprefix + 'keyframes ' + animationName + ' { from { opacity: 0; } to { opacity: 0; } } '; - var animationStyle = keyframeprefix + 'animation: 1ms ' + animationName + '; '; - } - - function createStyles() { - if (!stylesCreated) { - //opacity:0 works around a chrome bug https://code.google.com/p/chromium/issues/detail?id=286360 - var css = (animationKeyframes ? animationKeyframes : '') + - '.resize-triggers { ' + (animationStyle ? animationStyle : '') + 'visibility: hidden; opacity: 0; } ' + - '.resize-triggers, .resize-triggers > div, .contract-trigger:before { content: \" \"; display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden; } .resize-triggers > div { background: #eee; overflow: auto; } .contract-trigger:before { width: 200%; height: 200%; }', - head = document.head || document.getElementsByTagName('head')[0], - style = document.createElement('style'); - - style.type = 'text/css'; - if (style.styleSheet) { - style.styleSheet.cssText = css; - } else { + + var animationName = "resizeanim"; + var animationKeyframes = + "@" + + keyframeprefix + + "keyframes " + + animationName + + " { from { opacity: 0; } to { opacity: 0; } } "; + var animationStyle = keyframeprefix + "animation: 1ms " + animationName + ";"; + + function createStyles() { + if (!stylesCreated) { + var css = + (animationKeyframes ? animationKeyframes : "") + + ".resize-triggers { " + + (animationStyle ? animationStyle : "") + + "visibility: hidden; opacity: 0; } " + + ".resize-triggers, .resize-triggers > div, .contract-trigger:before { content: ' '; display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden; } " + + ".resize-triggers > div { background: #eee; overflow: auto; } " + + ".contract-trigger:before { width: 200%; height: 200%; }"; + + var head = document.head || document.getElementsByTagName("head")[0]; + var style = document.createElement("style"); + + // Set the nonce from the + var meta = document.querySelector('meta[name="csp-nonce"]'); + if (meta) { + style.setAttribute("nonce", meta.getAttribute("content")); + } + + style.type = "text/css"; style.appendChild(document.createTextNode(css)); + head.appendChild(style); + stylesCreated = true; } - - head.appendChild(style); - stylesCreated = true; } - } - - window.addResizeListener = function(element, fn){ - if (attachEvent) element.attachEvent('onresize', fn); - else { - if (!element.__resizeTriggers__) { - if (getComputedStyle(element).position == 'static') element.style.position = 'relative'; - createStyles(); - element.__resizeLast__ = {}; - element.__resizeListeners__ = []; - (element.__resizeTriggers__ = document.createElement('div')).className = 'resize-triggers'; - element.__resizeTriggers__.innerHTML = '
' + - ''; - element.appendChild(element.__resizeTriggers__); - resetTriggers(element); - element.addEventListener('scroll', scrollListener, true); - - /* Listen for a css animation to detect element display/re-attach */ - animationstartevent && element.__resizeTriggers__.addEventListener(animationstartevent, function(e) { - if(e.animationName == animationName) - resetTriggers(element); - }); + + window.addResizeListener = function (element, fn) { + if (attachEvent) element.attachEvent("onresize", fn); + else { + if (!element.__resizeTriggers__) { + if (getComputedStyle(element).position === "static") { + element.style.position = "relative"; + } + createStyles(); + element.__resizeLast__ = {}; + element.__resizeListeners__ = []; + var wrapper = document.createElement("div"); + wrapper.className = "resize-triggers"; + + var expand = document.createElement("div"); + expand.className = "expand-trigger"; + expand.appendChild(document.createElement("div")); + + var contract = document.createElement("div"); + contract.className = "contract-trigger"; + + wrapper.appendChild(expand); + wrapper.appendChild(contract); + element.appendChild(wrapper); + element.__resizeTriggers__ = wrapper; + + resetTriggers(element); + element.addEventListener("scroll", scrollListener, true); + + animationstartevent && + element.__resizeTriggers__.addEventListener(animationstartevent, function (e) { + if (e.animationName === animationName) resetTriggers(element); + }); + } + element.__resizeListeners__.push(fn); } - element.__resizeListeners__.push(fn); - } - }; - - window.removeResizeListener = function(element, fn){ - if (attachEvent) element.detachEvent('onresize', fn); - else { - element.__resizeListeners__.splice(element.__resizeListeners__.indexOf(fn), 1); - if (!element.__resizeListeners__.length) { - element.removeEventListener('scroll', scrollListener); + }; + + window.removeResizeListener = function (element, fn) { + if (attachEvent) element.detachEvent("onresize", fn); + else { + element.__resizeListeners__.splice(element.__resizeListeners__.indexOf(fn), 1); + if (!element.__resizeListeners__.length) { + element.removeEventListener("scroll", scrollListener); element.__resizeTriggers__ = !element.removeChild(element.__resizeTriggers__); + } } - } + }; } -})(); \ No newline at end of file +})();