element-resize-detector
Advanced tools
Comparing version 0.4.0 to 1.0.0
/*! | ||
* element-resize-detector 0.4.0 (2015-10-14, 13:20) | ||
* element-resize-detector 1.0.0 | ||
* https://github.com/wnr/element-resize-detector | ||
@@ -249,60 +249,84 @@ * Licensed under MIT | ||
function onObjectLoad() { | ||
/*jshint validthis: true */ | ||
//The target element needs to be positioned (everything except static) so the absolute positioned object will be positioned relative to the target element. | ||
function getDocument(element, callback) { | ||
//Opera 12 seem to call the object.onload before the actual document has been created. | ||
//So if it is not present, poll it with an timeout until it is present. | ||
//TODO: Could maybe be handled better with object.onreadystatechange or similar. | ||
if(!element.contentDocument) { | ||
setTimeout(function checkForObjectDocument() { | ||
getDocument(element, callback); | ||
}, 100); | ||
// Position altering may be performed directly or on object load, depending on if style resolution is possible directly or not. | ||
var positionCheckPerformed = false; | ||
return; | ||
} | ||
// The element may not yet be attached to the DOM, and therefore the style object may be empty in some browsers. | ||
// Since the style object is a reference, it will be updated as soon as the element is attached to the DOM. | ||
var style = getComputedStyle(element); | ||
callback(element.contentDocument); | ||
} | ||
getState(element).startSizeStyle = { | ||
width: style.width, | ||
height: style.height | ||
}; | ||
//Mutating the object element here seems to fire another load event. | ||
//Mutating the inner document of the object element is fine though. | ||
var objectElement = this; | ||
function mutateDom() { | ||
function alterPositionStyles() { | ||
if(style.position === "static") { | ||
element.style.position = "relative"; | ||
//Create the style element to be added to the object. | ||
getDocument(objectElement, function onObjectDocumentReady(objectDocument) { | ||
//Notify that the element is ready to be listened to. | ||
callback(element); | ||
}); | ||
} | ||
var removeRelativeStyles = function(reporter, element, style, property) { | ||
function getNumericalValue(value) { | ||
return value.replace(/[^-\d\.]/g, ""); | ||
} | ||
//The target element needs to be positioned (everything except static) so the absolute positioned object will be positioned relative to the target element. | ||
var style = getComputedStyle(element); | ||
var position = style.position; | ||
var value = style[property]; | ||
function mutateDom() { | ||
if(position === "static") { | ||
element.style.position = "relative"; | ||
if(value !== "auto" && getNumericalValue(value) !== "0") { | ||
reporter.warn("An element that is positioned static has style." + property + "=" + value + " which is ignored due to the static positioning. The element will need to be positioned relative, so the style." + property + " will be set to 0. Element: ", element); | ||
element.style[property] = 0; | ||
} | ||
}; | ||
var removeRelativeStyles = function(reporter, element, style, property) { | ||
function getNumericalValue(value) { | ||
return value.replace(/[^-\d\.]/g, ""); | ||
} | ||
//Check so that there are no accidental styles that will make the element styled differently now that is is relative. | ||
//If there are any, set them to 0 (this should be okay with the user since the style properties did nothing before [since the element was positioned static] anyway). | ||
removeRelativeStyles(reporter, element, style, "top"); | ||
removeRelativeStyles(reporter, element, style, "right"); | ||
removeRelativeStyles(reporter, element, style, "bottom"); | ||
removeRelativeStyles(reporter, element, style, "left"); | ||
} | ||
} | ||
var value = style[property]; | ||
function onObjectLoad() { | ||
// The object has been loaded, which means that the element now is guaranteed to be attached to the DOM. | ||
if (!positionCheckPerformed) { | ||
alterPositionStyles(); | ||
} | ||
if(value !== "auto" && getNumericalValue(value) !== "0") { | ||
reporter.warn("An element that is positioned static has style." + property + "=" + value + " which is ignored due to the static positioning. The element will need to be positioned relative, so the style." + property + " will be set to 0. Element: ", element); | ||
element.style[property] = 0; | ||
/*jshint validthis: true */ | ||
function getDocument(element, callback) { | ||
//Opera 12 seem to call the object.onload before the actual document has been created. | ||
//So if it is not present, poll it with an timeout until it is present. | ||
//TODO: Could maybe be handled better with object.onreadystatechange or similar. | ||
if(!element.contentDocument) { | ||
setTimeout(function checkForObjectDocument() { | ||
getDocument(element, callback); | ||
}, 100); | ||
return; | ||
} | ||
}; | ||
//Check so that there are no accidental styles that will make the element styled differently now that is is relative. | ||
//If there are any, set them to 0 (this should be okay with the user since the style properties did nothing before [since the element was positioned static] anyway). | ||
removeRelativeStyles(reporter, element, style, "top"); | ||
removeRelativeStyles(reporter, element, style, "right"); | ||
removeRelativeStyles(reporter, element, style, "bottom"); | ||
removeRelativeStyles(reporter, element, style, "left"); | ||
callback(element.contentDocument); | ||
} | ||
//Mutating the object element here seems to fire another load event. | ||
//Mutating the inner document of the object element is fine though. | ||
var objectElement = this; | ||
//Create the style element to be added to the object. | ||
getDocument(objectElement, function onObjectDocumentReady(objectDocument) { | ||
//Notify that the element is ready to be listened to. | ||
callback(element); | ||
}); | ||
} | ||
// The element may be detached from the DOM, and some browsers does not support style resolving of detached elements. | ||
// The alterPositionStyles needs to be delayed until we know the element has been attached to the DOM (which we are sure of when the onObjectLoad has been fired), if style resolution is not possible. | ||
if (style.position !== "") { | ||
alterPositionStyles(style); | ||
positionCheckPerformed = true; | ||
} | ||
//Add an object element as a child to the target element that will be listened to for resize events. | ||
@@ -443,106 +467,153 @@ var object = document.createElement("object"); | ||
function makeDetectable(element, callback) { | ||
// Reading properties of elementStyle will result in a forced getComputedStyle for some browsers, so read all values and store them as primitives here. | ||
var elementStyle = getComputedStyle(element); | ||
var position = elementStyle.position; | ||
var width = parseSize(elementStyle.width); | ||
var height = parseSize(elementStyle.height); | ||
var top = elementStyle.top; | ||
var right = elementStyle.right; | ||
var bottom = elementStyle.bottom; | ||
var left = elementStyle.left; | ||
var readyExpandScroll = false; | ||
var readyShrinkScroll = false; | ||
var readyOverall = false; | ||
function isStyleResolved() { | ||
function isPxValue(length) { | ||
return length.indexOf("px") !== -1; | ||
} | ||
function ready() { | ||
if(readyExpandScroll && readyShrinkScroll && readyOverall) { | ||
callback(element); | ||
} | ||
var style = getComputedStyle(element); | ||
return style.position && isPxValue(style.width) && isPxValue(style.height); | ||
} | ||
function mutateDom() { | ||
if(position === "static") { | ||
element.style.position = "relative"; | ||
function install() { | ||
function getStyle() { | ||
// Some browsers only force layouts when actually reading the style properties of the style object, so make sure that they are all read here, | ||
// so that the user of the function can be sure that it will perform the layout here, instead of later (important for batching). | ||
var style = {}; | ||
var elementStyle = getComputedStyle(element); | ||
style.position = elementStyle.position; | ||
style.width = parseSize(elementStyle.width); | ||
style.height = parseSize(elementStyle.height); | ||
style.top = elementStyle.top; | ||
style.right = elementStyle.right; | ||
style.bottom = elementStyle.bottom; | ||
style.left = elementStyle.left; | ||
style.widthStyle = elementStyle.width; | ||
style.heightStyle = elementStyle.height; | ||
return style; | ||
} | ||
var removeRelativeStyles = function(reporter, element, value, property) { | ||
function getNumericalValue(value) { | ||
return value.replace(/[^-\d\.]/g, ""); | ||
} | ||
// Style is to be retrieved in the first level (before mutating the DOM) so that a forced layout is avoided later. | ||
var style = getStyle(); | ||
if(value !== "auto" && getNumericalValue(value) !== "0") { | ||
reporter.warn("An element that is positioned static has style." + property + "=" + value + " which is ignored due to the static positioning. The element will need to be positioned relative, so the style." + property + " will be set to 0. Element: ", element); | ||
element.style[property] = 0; | ||
} | ||
}; | ||
getState(element).startSizeStyle = { | ||
width: style.widthStyle, | ||
height: style.heightStyle | ||
}; | ||
//Check so that there are no accidental styles that will make the element styled differently now that is is relative. | ||
//If there are any, set them to 0 (this should be okay with the user since the style properties did nothing before [since the element was positioned static] anyway). | ||
removeRelativeStyles(reporter, element, top, "top"); | ||
removeRelativeStyles(reporter, element, right, "right"); | ||
removeRelativeStyles(reporter, element, bottom, "bottom"); | ||
removeRelativeStyles(reporter, element, left, "left"); | ||
var readyExpandScroll = false; | ||
var readyShrinkScroll = false; | ||
var readyOverall = false; | ||
function ready() { | ||
if(readyExpandScroll && readyShrinkScroll && readyOverall) { | ||
callback(element); | ||
} | ||
} | ||
function getContainerCssText(left, top, bottom, right) { | ||
left = (!left ? "0" : (left + "px")); | ||
top = (!top ? "0" : (top + "px")); | ||
bottom = (!bottom ? "0" : (bottom + "px")); | ||
right = (!right ? "0" : (right + "px")); | ||
function mutateDom() { | ||
function alterPositionStyles() { | ||
if(style.position === "static") { | ||
element.style.position = "relative"; | ||
return "position: absolute; left: " + left + "; top: " + top + "; right: " + right + "; bottom: " + bottom + "; overflow: scroll; z-index: -1; visibility: hidden;"; | ||
} | ||
var removeRelativeStyles = function(reporter, element, style, property) { | ||
function getNumericalValue(value) { | ||
return value.replace(/[^-\d\.]/g, ""); | ||
} | ||
var scrollbarWidth = scrollbarSizes.width; | ||
var scrollbarHeight = scrollbarSizes.height; | ||
var containerStyle = getContainerCssText(-1, -1, -scrollbarHeight, -scrollbarWidth); | ||
var shrinkExpandstyle = getContainerCssText(0, 0, -scrollbarHeight, -scrollbarWidth); | ||
var shrinkExpandChildStyle = "position: absolute; left: 0; top: 0;"; | ||
var value = style[property]; | ||
var container = document.createElement("div"); | ||
var expand = document.createElement("div"); | ||
var expandChild = document.createElement("div"); | ||
var shrink = document.createElement("div"); | ||
var shrinkChild = document.createElement("div"); | ||
if(value !== "auto" && getNumericalValue(value) !== "0") { | ||
reporter.warn("An element that is positioned static has style." + property + "=" + value + " which is ignored due to the static positioning. The element will need to be positioned relative, so the style." + property + " will be set to 0. Element: ", element); | ||
element.style[property] = 0; | ||
} | ||
}; | ||
container.style.cssText = containerStyle; | ||
expand.style.cssText = shrinkExpandstyle; | ||
expandChild.style.cssText = shrinkExpandChildStyle; | ||
shrink.style.cssText = shrinkExpandstyle; | ||
shrinkChild.style.cssText = shrinkExpandChildStyle + " width: 200%; height: 200%;"; | ||
//Check so that there are no accidental styles that will make the element styled differently now that is is relative. | ||
//If there are any, set them to 0 (this should be okay with the user since the style properties did nothing before [since the element was positioned static] anyway). | ||
removeRelativeStyles(reporter, element, style, "top"); | ||
removeRelativeStyles(reporter, element, style, "right"); | ||
removeRelativeStyles(reporter, element, style, "bottom"); | ||
removeRelativeStyles(reporter, element, style, "left"); | ||
} | ||
} | ||
expand.appendChild(expandChild); | ||
shrink.appendChild(shrinkChild); | ||
container.appendChild(expand); | ||
container.appendChild(shrink); | ||
element.appendChild(container); | ||
getState(element).element = container; | ||
function getContainerCssText(left, top, bottom, right) { | ||
left = (!left ? "0" : (left + "px")); | ||
top = (!top ? "0" : (top + "px")); | ||
bottom = (!bottom ? "0" : (bottom + "px")); | ||
right = (!right ? "0" : (right + "px")); | ||
addEvent(expand, "scroll", function onFirstExpandScroll() { | ||
removeEvent(expand, "scroll", onFirstExpandScroll); | ||
readyExpandScroll = true; | ||
ready(); | ||
}); | ||
return "position: absolute; left: " + left + "; top: " + top + "; right: " + right + "; bottom: " + bottom + "; overflow: scroll; z-index: -1; visibility: hidden;"; | ||
} | ||
addEvent(shrink, "scroll", function onFirstShrinkScroll() { | ||
removeEvent(shrink, "scroll", onFirstShrinkScroll); | ||
readyShrinkScroll = true; | ||
alterPositionStyles(style); | ||
var scrollbarWidth = scrollbarSizes.width; | ||
var scrollbarHeight = scrollbarSizes.height; | ||
var containerStyle = getContainerCssText(-1, -1, -scrollbarHeight, -scrollbarWidth); | ||
var shrinkExpandstyle = getContainerCssText(0, 0, -scrollbarHeight, -scrollbarWidth); | ||
var shrinkExpandChildStyle = "position: absolute; left: 0; top: 0;"; | ||
var container = document.createElement("div"); | ||
var expand = document.createElement("div"); | ||
var expandChild = document.createElement("div"); | ||
var shrink = document.createElement("div"); | ||
var shrinkChild = document.createElement("div"); | ||
container.style.cssText = containerStyle; | ||
expand.style.cssText = shrinkExpandstyle; | ||
expandChild.style.cssText = shrinkExpandChildStyle; | ||
shrink.style.cssText = shrinkExpandstyle; | ||
shrinkChild.style.cssText = shrinkExpandChildStyle + " width: 200%; height: 200%;"; | ||
expand.appendChild(expandChild); | ||
shrink.appendChild(shrinkChild); | ||
container.appendChild(expand); | ||
container.appendChild(shrink); | ||
element.appendChild(container); | ||
getState(element).element = container; | ||
addEvent(expand, "scroll", function onFirstExpandScroll() { | ||
removeEvent(expand, "scroll", onFirstExpandScroll); | ||
readyExpandScroll = true; | ||
ready(); | ||
}); | ||
addEvent(shrink, "scroll", function onFirstShrinkScroll() { | ||
removeEvent(shrink, "scroll", onFirstShrinkScroll); | ||
readyShrinkScroll = true; | ||
ready(); | ||
}); | ||
updateChildSizes(element, style.width, style.height); | ||
} | ||
function finalizeDomMutation() { | ||
storeCurrentSize(element, style.width, style.height); | ||
positionScrollbars(element, style.width, style.height); | ||
readyOverall = true; | ||
ready(); | ||
}); | ||
} | ||
updateChildSizes(element, width, height); | ||
if(batchProcessor) { | ||
batchProcessor.add(mutateDom); | ||
batchProcessor.add(1, finalizeDomMutation); | ||
} else { | ||
mutateDom(); | ||
finalizeDomMutation(); | ||
} | ||
} | ||
function finalizeDomMutation() { | ||
storeCurrentSize(element, width, height); | ||
positionScrollbars(element, width, height); | ||
readyOverall = true; | ||
ready(); | ||
} | ||
if(batchProcessor) { | ||
batchProcessor.add(mutateDom); | ||
batchProcessor.add(1, finalizeDomMutation); | ||
// Only install the strategy if the style has been resolved (this does not always mean that the element is attached). | ||
if (isStyleResolved()) { | ||
install(); | ||
} else { | ||
mutateDom(); | ||
finalizeDomMutation(); | ||
// Need to perform polling in order to detect when the element has been attached to the DOM. | ||
var timeout = setInterval(function () { | ||
if (isStyleResolved()) { | ||
install(); | ||
clearTimeout(timeout); | ||
} | ||
}, 50); | ||
} | ||
@@ -785,2 +856,22 @@ } | ||
function isCollection(obj) { | ||
return Array.isArray(obj) || obj.length !== undefined; | ||
} | ||
function toArray(collection) { | ||
if (!Array.isArray(collection)) { | ||
var array = []; | ||
forEach(elements, function (element) { | ||
array.push(element); | ||
}); | ||
return array; | ||
} else { | ||
return collection; | ||
} | ||
} | ||
function isElement(obj) { | ||
return obj && obj.nodeType === 1; | ||
} | ||
//Options object may be omitted. | ||
@@ -801,4 +892,10 @@ if(!listener) { | ||
if(elements.length === undefined) { | ||
if (isElement(elements)) { | ||
// A single element has been passed in. | ||
elements = [elements]; | ||
} else if (isCollection(elements)) { | ||
// Convert collection to array for plugins. | ||
elements = toArray(elements); | ||
} else { | ||
return reporter.error("Invalid arguments. Must be a DOM element or a collection of DOM elements."); | ||
} | ||
@@ -838,2 +935,9 @@ | ||
// Since the element size might have changed since the call to "listenTo", we need to check for this change, | ||
// so that a resize event may be emitted. | ||
var style = getComputedStyle(element); | ||
if (stateHandler.getState(element).startSizeStyle.width !== style.width || stateHandler.getState(element).startSizeStyle.height !== style.height) { | ||
onResizeCallback(element); | ||
} | ||
elementsReady++; | ||
@@ -840,0 +944,0 @@ if(elementsReady === elements.length) { |
/*! | ||
* element-resize-detector 0.4.0 (2015-10-14, 13:20) | ||
* element-resize-detector 1.0.0 | ||
* https://github.com/wnr/element-resize-detector | ||
@@ -7,2 +7,2 @@ * Licensed under MIT | ||
!function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;b="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,b.elementResizeDetectorMaker=a()}}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);var j=new Error("Cannot find module '"+g+"'");throw j.code="MODULE_NOT_FOUND",j}var k=c[g]={exports:{}};b[g][0].call(k.exports,function(a){var c=b[g][1][a];return e(c?c:a)},k,k.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g<d.length;g++)e(d[g]);return e}({1:[function(a,b,c){"use strict";var d=a("./utils");b.exports=function(a){function b(a,b){b||(b=a,a=0),a>o?o=a:p>a&&(p=a),m[a]||(m[a]=[]),l&&k&&0===n&&f(),m[a].push(b),n++}function c(a){void 0===a&&(a=k),q&&(h(q),q=null),a?f():e()}function e(){for(var a=p;o>=a;a++)for(var b=m[a],c=0;c<b.length;c++){var d=b[c];d()}g()}function f(){q=i(e)}function g(){m={},n=0,o=0,p=0}function h(a){var b=window.clearTimeout;return b(a)}function i(a){var b=function(a){return window.setTimeout(a,0)};return b(a)}a=a||{};var j=a.reporter,k=d.getOption(a,"async",!0),l=d.getOption(a,"auto",!0);l&&!k&&(j&&j.warn("Invalid options combination. auto=true and async=false is invalid. Setting async=true."),k=!0);var m,n,o,p;g();var q;return{add:b,force:c}}},{"./utils":2}],2:[function(a,b,c){"use strict";function d(a,b,c){var d=a[b];return void 0!==d&&null!==d||void 0===c?d:c}var e=b.exports={};e.getOption=d},{}],3:[function(a,b,c){"use strict";var d=b.exports={};d.isIE=function(a){function b(){var a=navigator.userAgent.toLowerCase();return-1!==a.indexOf("msie")||-1!==a.indexOf("trident")||-1!==a.indexOf(" edge/")}if(!b())return!1;if(!a)return!0;var c=function(){var a,b=3,c=document.createElement("div"),d=c.getElementsByTagName("i");do c.innerHTML="<!--[if gt IE "+ ++b+"]><i></i><![endif]-->";while(d[0]);return b>4?b:a}();return a===c},d.isLegacyOpera=function(){return!!window.opera}},{}],4:[function(a,b,c){"use strict";var d=b.exports={};d.forEach=function(a,b){for(var c=0;c<a.length;c++){var d=b(a[c]);if(d)return d}}},{}],5:[function(a,b,c){"use strict";var d=a("../browser-detector");b.exports=function(a){function b(a,b){function c(){b(a)}if(!e(a))throw new Error("Element is not detectable by this strategy.");if(d.isIE(8))i(a).object={proxy:c},a.attachEvent("onresize",c);else{var f=e(a);f.contentDocument.defaultView.addEventListener("resize",c)}}function c(a,b){function c(a,b){function c(){function c(a,b){return a.contentDocument?void b(a.contentDocument):void setTimeout(function(){c(a,b)},100)}var d=this;c(d,function(c){b(a)})}function e(){if("static"===k){a.style.position="relative";var b=function(a,b,c,d){function e(a){return a.replace(/[^-\d\.]/g,"")}var f=c[d];"auto"!==f&&"0"!==e(f)&&(a.warn("An element that is positioned static has style."+d+"="+f+" which is ignored due to the static positioning. The element will need to be positioned relative, so the style."+d+" will be set to 0. Element: ",b),b.style[d]=0)};b(g,a,j,"top"),b(g,a,j,"right"),b(g,a,j,"bottom"),b(g,a,j,"left")}var e=document.createElement("object");e.style.cssText=f,e.type="text/html",e.onload=c,d.isIE()||(e.data="about:blank"),a.appendChild(e),i(a).object=e,d.isIE()&&(e.data="about:blank")}var f="display: block; position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: none; padding: 0; margin: 0; opacity: 0; z-index: -1000; pointer-events: none;",j=getComputedStyle(a),k=j.position;h?h.add(e):e()}d.isIE(8)?b(a):c(a,b)}function e(a){return i(a).object}function f(a){d.isIE(8)?a.detachEvent("onresize",i(a).object.proxy):a.removeChild(e(a)),delete i(a).object}a=a||{};var g=a.reporter,h=a.batchProcessor,i=a.stateHandler.getState;if(!g)throw new Error("Missing required dependency: reporter.");return{makeDetectable:c,addListener:b,uninstall:f}}},{"../browser-detector":3}],6:[function(a,b,c){"use strict";b.exports=function(a){function b(a,b){function c(){var b=getComputedStyle(a),c=n(b.width),d=n(b.height);(c!==a.lastWidth||d!==a.lastHeight)&&e()}var e=function(){var c=getComputedStyle(a),d=n(c.width),e=n(c.height);j(a,d,e),r.add(function(){i(a,d,e)}),r.add(1,function(){k(a,d,e),b(a)})},g=d(a),h=f(a);l(g,"scroll",c),l(h,"scroll",c)}function c(a,b){function c(){x&&y&&z&&b(a)}function d(){function b(a,b,c,d){return a=a?a+"px":"0",b=b?b+"px":"0",c=c?c+"px":"0",d=d?d+"px":"0","position: absolute; left: "+a+"; top: "+b+"; right: "+d+"; bottom: "+c+"; overflow: scroll; z-index: -1; visibility: hidden;"}if("static"===g){a.style.position="relative";var d=function(a,b,c,d){function e(a){return a.replace(/[^-\d\.]/g,"")}"auto"!==c&&"0"!==e(c)&&(a.warn("An element that is positioned static has style."+d+"="+c+" which is ignored due to the static positioning. The element will need to be positioned relative, so the style."+d+" will be set to 0. Element: ",b),b.style[d]=0)};d(q,a,p,"top"),d(q,a,u,"right"),d(q,a,v,"bottom"),d(q,a,w,"left")}var e=t.width,f=t.height,j=b(-1,-1,-f,-e),k=b(0,0,-f,-e),n="position: absolute; left: 0; top: 0;",r=document.createElement("div"),z=document.createElement("div"),A=document.createElement("div"),B=document.createElement("div"),C=document.createElement("div");r.style.cssText=j,z.style.cssText=k,A.style.cssText=n,B.style.cssText=k,C.style.cssText=n+" width: 200%; height: 200%;",z.appendChild(A),B.appendChild(C),r.appendChild(z),r.appendChild(B),a.appendChild(r),s(a).element=r,l(z,"scroll",function D(){m(z,"scroll",D),x=!0,c()}),l(B,"scroll",function E(){m(B,"scroll",E),y=!0,c()}),i(a,h,o)}function e(){j(a,h,o),k(a,h,o),z=!0,c()}var f=getComputedStyle(a),g=f.position,h=n(f.width),o=n(f.height),p=f.top,u=f.right,v=f.bottom,w=f.left,x=!1,y=!1,z=!1;r?(r.add(d),r.add(1,e)):(d(),e())}function d(a){return s(a).element.childNodes[0]}function e(a){return d(a).childNodes[0]}function f(a){return s(a).element.childNodes[1]}function g(a){return a+10}function h(a){return 2*a}function i(a,b,c){var d=e(a),f=g(b),h=g(c);d.style.width=f+"px",d.style.height=h+"px"}function j(a,b,c){a.lastWidth=b,a.lastHeight=c}function k(a,b,c){var e=d(a),i=f(a),j=g(b),k=g(c),l=h(b),m=h(c);e.scrollLeft=j,e.scrollTop=k,i.scrollLeft=l,i.scrollTop=m}function l(a,b,c){a.attachEvent?a.attachEvent("on"+b,c):a.addEventListener(b,c)}function m(a,b,c){a.attachEvent?a.detachEvent("on"+b,c):a.removeEventListener(b,c)}function n(a){return parseFloat(a.replace(/px/,""))}function o(){var a=500,b=500,c=document.createElement("div");c.style.cssText="position: absolute; width: "+2*a+"px; height: "+2*b+"px; visibility: hidden;";var d=document.createElement("div");d.style.cssText="position: absolute; width: "+a+"px; height: "+b+"px; overflow: scroll; visibility: none; top: "+3*-a+"px; left: "+3*-b+"px; visibility: hidden;",d.appendChild(c),document.body.insertBefore(d,document.body.firstChild);var e=a-d.clientWidth,f=b-d.clientHeight;return document.body.removeChild(d),{width:e,height:f}}function p(a){var b=s(a);a.removeChild(b.element),delete b.element}a=a||{};var q=a.reporter,r=a.batchProcessor,s=a.stateHandler.getState;if(!q)throw new Error("Missing required dependency: reporter.");var t=o();return{makeDetectable:c,addListener:b,uninstall:p}}},{}],7:[function(a,b,c){"use strict";function d(a,b,c){var d=a[b];return void 0!==d&&null!==d||void 0===c?d:c}var e=a("./collection-utils").forEach,f=a("./element-utils"),g=a("./listener-handler"),h=a("./id-generator"),i=a("./id-handler"),j=a("./reporter"),k=a("./browser-detector"),l=a("batch-processor"),m=a("./state-handler"),n=a("./detection-strategy/object.js"),o=a("./detection-strategy/scroll.js");b.exports=function(a){function b(a,b,c){function f(a){var b=x.get(a);e(b,function(b){b(a)})}function g(a,b,c){x.add(b,c),a&&c(b)}if(c||(c=b,b=a,a={}),!b)throw new Error("At least one element required.");if(!c)throw new Error("Listener required.");void 0===b.length&&(b=[b]);var h=0,i=d(a,"callOnAdd",v.callOnAdd),j=d(a,"onReady",function(){});e(b,function(a){var d=p.get(a);return y.isDetectable(a)?(g(i,a,c),void h++):y.isBusy(a)?(g(i,a,c),B[d]=B[d]||[],void B[d].push(function(){h++,h===b.length&&j()})):(y.markBusy(a,!0),w.makeDetectable(a,function(a){y.markAsDetectable(a),y.markBusy(a,!1),w.addListener(a,f),g(i,a,c),h++,h===b.length&&j(),B[d]&&(e(B[d],function(a){a()}),delete B[d])}))}),h===b.length&&j()}function c(a){x.removeAllListeners(a),w.uninstall(a),m.cleanState(a)}a=a||{};var p=a.idHandler;if(!p){var q=h(),r=i({idGenerator:q,stateHandler:m});p=r}var s=a.reporter;if(!s){var t=s===!1;s=j(t)}var u=d(a,"batchProcessor",l({reporter:s})),v={};v.callOnAdd=!!d(a,"callOnAdd",!0);var w,x=g(p),y=f({stateHandler:m}),z=d(a,"strategy","object"),A={reporter:s,batchProcessor:u,stateHandler:m};if("scroll"===z&&k.isLegacyOpera()&&(s.warn("Scroll strategy is not supported on legacy Opera. Changing to object strategy."),z="object"),"scroll"===z)w=o(A);else{if("object"!==z)throw new Error("Invalid strategy name: "+z);w=n(A)}var B={};return{listenTo:b,removeListener:x.removeListener,removeAllListeners:x.removeAllListeners,uninstall:c}}},{"./browser-detector":3,"./collection-utils":4,"./detection-strategy/object.js":5,"./detection-strategy/scroll.js":6,"./element-utils":8,"./id-generator":9,"./id-handler":10,"./listener-handler":11,"./reporter":12,"./state-handler":13,"batch-processor":1}],8:[function(a,b,c){"use strict";b.exports=function(a){function b(a){return!!f(a).isDetectable}function c(a){f(a).isDetectable=!0}function d(a){return!!f(a).busy}function e(a,b){f(a).busy=!!b}var f=a.stateHandler.getState;return{isDetectable:b,markAsDetectable:c,isBusy:d,markBusy:e}}},{}],9:[function(a,b,c){"use strict";b.exports=function(){function a(){return b++}var b=1;return{generate:a}}},{}],10:[function(a,b,c){"use strict";b.exports=function(a){function b(a,b){return b||d(a)||c(a),g(a).id}function c(a){var b=f.generate();return g(a).id=b,b}function d(a){return void 0!==g(a).id}function e(a){delete g(a).id}var f=a.idGenerator,g=a.stateHandler.getState;return{get:b,remove:e}}},{}],11:[function(a,b,c){"use strict";b.exports=function(a){function b(b){return f[a.get(b)]||[]}function c(b,c){var d=a.get(b);f[d]||(f[d]=[]),f[d].push(c)}function d(a,c){for(var d=b(a),e=0,f=d.length;f>e;++e)if(d[e]===c){d.splice(e,1);break}}function e(b){var c=f[a.get(b)];c&&(c.length=0)}var f={};return{get:b,add:c,removeListener:d,removeAllListeners:e}}},{}],12:[function(a,b,c){"use strict";b.exports=function(a){function b(){}var c={log:b,warn:b,error:b};if(!a&&window.console){var d=function(a,b){a[b]=function(){console[b].apply(console,arguments)}};d(c,"log"),d(c,"warn"),d(c,"error")}return c}},{}],13:[function(a,b,c){"use strict";function d(a){return a[g]={},e(a)}function e(a){return a[g]||d(a)}function f(a){delete a[g]}var g="_erd";b.exports={initState:d,getState:e,cleanState:f}},{}]},{},[7])(7)}); | ||
!function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;b="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,b.elementResizeDetectorMaker=a()}}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);var j=new Error("Cannot find module '"+g+"'");throw j.code="MODULE_NOT_FOUND",j}var k=c[g]={exports:{}};b[g][0].call(k.exports,function(a){var c=b[g][1][a];return e(c?c:a)},k,k.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g<d.length;g++)e(d[g]);return e}({1:[function(a,b,c){"use strict";var d=a("./utils");b.exports=function(a){function b(a,b){b||(b=a,a=0),a>o?o=a:p>a&&(p=a),m[a]||(m[a]=[]),l&&k&&0===n&&f(),m[a].push(b),n++}function c(a){void 0===a&&(a=k),q&&(h(q),q=null),a?f():e()}function e(){for(var a=p;o>=a;a++)for(var b=m[a],c=0;c<b.length;c++){var d=b[c];d()}g()}function f(){q=i(e)}function g(){m={},n=0,o=0,p=0}function h(a){var b=window.clearTimeout;return b(a)}function i(a){var b=function(a){return window.setTimeout(a,0)};return b(a)}a=a||{};var j=a.reporter,k=d.getOption(a,"async",!0),l=d.getOption(a,"auto",!0);l&&!k&&(j&&j.warn("Invalid options combination. auto=true and async=false is invalid. Setting async=true."),k=!0);var m,n,o,p;g();var q;return{add:b,force:c}}},{"./utils":2}],2:[function(a,b,c){"use strict";function d(a,b,c){var d=a[b];return void 0!==d&&null!==d||void 0===c?d:c}var e=b.exports={};e.getOption=d},{}],3:[function(a,b,c){"use strict";var d=b.exports={};d.isIE=function(a){function b(){var a=navigator.userAgent.toLowerCase();return-1!==a.indexOf("msie")||-1!==a.indexOf("trident")||-1!==a.indexOf(" edge/")}if(!b())return!1;if(!a)return!0;var c=function(){var a,b=3,c=document.createElement("div"),d=c.getElementsByTagName("i");do c.innerHTML="<!--[if gt IE "+ ++b+"]><i></i><![endif]-->";while(d[0]);return b>4?b:a}();return a===c},d.isLegacyOpera=function(){return!!window.opera}},{}],4:[function(a,b,c){"use strict";var d=b.exports={};d.forEach=function(a,b){for(var c=0;c<a.length;c++){var d=b(a[c]);if(d)return d}}},{}],5:[function(a,b,c){"use strict";var d=a("../browser-detector");b.exports=function(a){function b(a,b){function c(){b(a)}if(!e(a))throw new Error("Element is not detectable by this strategy.");if(d.isIE(8))i(a).object={proxy:c},a.attachEvent("onresize",c);else{var f=e(a);f.contentDocument.defaultView.addEventListener("resize",c)}}function c(a,b){function c(a,b){function c(){function c(){if("static"===j.position){a.style.position="relative";var b=function(a,b,c,d){function e(a){return a.replace(/[^-\d\.]/g,"")}var f=c[d];"auto"!==f&&"0"!==e(f)&&(a.warn("An element that is positioned static has style."+d+"="+f+" which is ignored due to the static positioning. The element will need to be positioned relative, so the style."+d+" will be set to 0. Element: ",b),b.style[d]=0)};b(g,a,j,"top"),b(g,a,j,"right"),b(g,a,j,"bottom"),b(g,a,j,"left")}}function h(){function d(a,b){return a.contentDocument?void b(a.contentDocument):void setTimeout(function(){d(a,b)},100)}f||c();var e=this;d(e,function(c){b(a)})}""!==j.position&&(c(j),f=!0);var k=document.createElement("object");k.style.cssText=e,k.type="text/html",k.onload=h,d.isIE()||(k.data="about:blank"),a.appendChild(k),i(a).object=k,d.isIE()&&(k.data="about:blank")}var e="display: block; position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: none; padding: 0; margin: 0; opacity: 0; z-index: -1000; pointer-events: none;",f=!1,j=getComputedStyle(a);i(a).startSizeStyle={width:j.width,height:j.height},h?h.add(c):c()}d.isIE(8)?b(a):c(a,b)}function e(a){return i(a).object}function f(a){d.isIE(8)?a.detachEvent("onresize",i(a).object.proxy):a.removeChild(e(a)),delete i(a).object}a=a||{};var g=a.reporter,h=a.batchProcessor,i=a.stateHandler.getState;if(!g)throw new Error("Missing required dependency: reporter.");return{makeDetectable:c,addListener:b,uninstall:f}}},{"../browser-detector":3}],6:[function(a,b,c){"use strict";b.exports=function(a){function b(a,b){function c(){var b=getComputedStyle(a),c=n(b.width),d=n(b.height);(c!==a.lastWidth||d!==a.lastHeight)&&e()}var e=function(){var c=getComputedStyle(a),d=n(c.width),e=n(c.height);j(a,d,e),r.add(function(){i(a,d,e)}),r.add(1,function(){k(a,d,e),b(a)})},g=d(a),h=f(a);l(g,"scroll",c),l(h,"scroll",c)}function c(a,b){function c(){function b(a){return-1!==a.indexOf("px")}var c=getComputedStyle(a);return c.position&&b(c.width)&&b(c.height)}function d(){function c(){var b={},c=getComputedStyle(a);return b.position=c.position,b.width=n(c.width),b.height=n(c.height),b.top=c.top,b.right=c.right,b.bottom=c.bottom,b.left=c.left,b.widthStyle=c.width,b.heightStyle=c.height,b}function d(){h&&o&&p&&b(a)}function e(){function b(){if("static"===g.position){a.style.position="relative";var b=function(a,b,c,d){function e(a){return a.replace(/[^-\d\.]/g,"")}var f=c[d];"auto"!==f&&"0"!==e(f)&&(a.warn("An element that is positioned static has style."+d+"="+f+" which is ignored due to the static positioning. The element will need to be positioned relative, so the style."+d+" will be set to 0. Element: ",b),b.style[d]=0)};b(q,a,g,"top"),b(q,a,g,"right"),b(q,a,g,"bottom"),b(q,a,g,"left")}}function c(a,b,c,d){return a=a?a+"px":"0",b=b?b+"px":"0",c=c?c+"px":"0",d=d?d+"px":"0","position: absolute; left: "+a+"; top: "+b+"; right: "+d+"; bottom: "+c+"; overflow: scroll; z-index: -1; visibility: hidden;"}b(g);var e=t.width,f=t.height,j=c(-1,-1,-f,-e),k=c(0,0,-f,-e),n="position: absolute; left: 0; top: 0;",p=document.createElement("div"),r=document.createElement("div"),u=document.createElement("div"),v=document.createElement("div"),w=document.createElement("div");p.style.cssText=j,r.style.cssText=k,u.style.cssText=n,v.style.cssText=k,w.style.cssText=n+" width: 200%; height: 200%;",r.appendChild(u),v.appendChild(w),p.appendChild(r),p.appendChild(v),a.appendChild(p),s(a).element=p,l(r,"scroll",function x(){m(r,"scroll",x),h=!0,d()}),l(v,"scroll",function y(){m(v,"scroll",y),o=!0,d()}),i(a,g.width,g.height)}function f(){j(a,g.width,g.height),k(a,g.width,g.height),p=!0,d()}var g=c();s(a).startSizeStyle={width:g.widthStyle,height:g.heightStyle};var h=!1,o=!1,p=!1;r?(r.add(e),r.add(1,f)):(e(),f())}if(c())d();else var e=setInterval(function(){c()&&(d(),clearTimeout(e))},50)}function d(a){return s(a).element.childNodes[0]}function e(a){return d(a).childNodes[0]}function f(a){return s(a).element.childNodes[1]}function g(a){return a+10}function h(a){return 2*a}function i(a,b,c){var d=e(a),f=g(b),h=g(c);d.style.width=f+"px",d.style.height=h+"px"}function j(a,b,c){a.lastWidth=b,a.lastHeight=c}function k(a,b,c){var e=d(a),i=f(a),j=g(b),k=g(c),l=h(b),m=h(c);e.scrollLeft=j,e.scrollTop=k,i.scrollLeft=l,i.scrollTop=m}function l(a,b,c){a.attachEvent?a.attachEvent("on"+b,c):a.addEventListener(b,c)}function m(a,b,c){a.attachEvent?a.detachEvent("on"+b,c):a.removeEventListener(b,c)}function n(a){return parseFloat(a.replace(/px/,""))}function o(){var a=500,b=500,c=document.createElement("div");c.style.cssText="position: absolute; width: "+2*a+"px; height: "+2*b+"px; visibility: hidden;";var d=document.createElement("div");d.style.cssText="position: absolute; width: "+a+"px; height: "+b+"px; overflow: scroll; visibility: none; top: "+3*-a+"px; left: "+3*-b+"px; visibility: hidden;",d.appendChild(c),document.body.insertBefore(d,document.body.firstChild);var e=a-d.clientWidth,f=b-d.clientHeight;return document.body.removeChild(d),{width:e,height:f}}function p(a){var b=s(a);a.removeChild(b.element),delete b.element}a=a||{};var q=a.reporter,r=a.batchProcessor,s=a.stateHandler.getState;if(!q)throw new Error("Missing required dependency: reporter.");var t=o();return{makeDetectable:c,addListener:b,uninstall:p}}},{}],7:[function(a,b,c){"use strict";function d(a,b,c){var d=a[b];return void 0!==d&&null!==d||void 0===c?d:c}var e=a("./collection-utils").forEach,f=a("./element-utils"),g=a("./listener-handler"),h=a("./id-generator"),i=a("./id-handler"),j=a("./reporter"),k=a("./browser-detector"),l=a("batch-processor"),m=a("./state-handler"),n=a("./detection-strategy/object.js"),o=a("./detection-strategy/scroll.js");b.exports=function(a){function b(a,b,c){function f(a){var b=x.get(a);e(b,function(b){b(a)})}function g(a,b,c){x.add(b,c),a&&c(b)}function h(a){return Array.isArray(a)||void 0!==a.length}function i(a){if(Array.isArray(a))return a;var c=[];return e(b,function(a){c.push(a)}),c}function j(a){return a&&1===a.nodeType}if(c||(c=b,b=a,a={}),!b)throw new Error("At least one element required.");if(!c)throw new Error("Listener required.");if(j(b))b=[b];else{if(!h(b))return s.error("Invalid arguments. Must be a DOM element or a collection of DOM elements.");b=i(b)}var k=0,l=d(a,"callOnAdd",v.callOnAdd),n=d(a,"onReady",function(){});e(b,function(a){var d=p.get(a);return y.isDetectable(a)?(g(l,a,c),void k++):y.isBusy(a)?(g(l,a,c),B[d]=B[d]||[],void B[d].push(function(){k++,k===b.length&&n()})):(y.markBusy(a,!0),w.makeDetectable(a,function(a){y.markAsDetectable(a),y.markBusy(a,!1),w.addListener(a,f),g(l,a,c);var h=getComputedStyle(a);(m.getState(a).startSizeStyle.width!==h.width||m.getState(a).startSizeStyle.height!==h.height)&&f(a),k++,k===b.length&&n(),B[d]&&(e(B[d],function(a){a()}),delete B[d])}))}),k===b.length&&n()}function c(a){x.removeAllListeners(a),w.uninstall(a),m.cleanState(a)}a=a||{};var p=a.idHandler;if(!p){var q=h(),r=i({idGenerator:q,stateHandler:m});p=r}var s=a.reporter;if(!s){var t=s===!1;s=j(t)}var u=d(a,"batchProcessor",l({reporter:s})),v={};v.callOnAdd=!!d(a,"callOnAdd",!0);var w,x=g(p),y=f({stateHandler:m}),z=d(a,"strategy","object"),A={reporter:s,batchProcessor:u,stateHandler:m};if("scroll"===z&&k.isLegacyOpera()&&(s.warn("Scroll strategy is not supported on legacy Opera. Changing to object strategy."),z="object"),"scroll"===z)w=o(A);else{if("object"!==z)throw new Error("Invalid strategy name: "+z);w=n(A)}var B={};return{listenTo:b,removeListener:x.removeListener,removeAllListeners:x.removeAllListeners,uninstall:c}}},{"./browser-detector":3,"./collection-utils":4,"./detection-strategy/object.js":5,"./detection-strategy/scroll.js":6,"./element-utils":8,"./id-generator":9,"./id-handler":10,"./listener-handler":11,"./reporter":12,"./state-handler":13,"batch-processor":1}],8:[function(a,b,c){"use strict";b.exports=function(a){function b(a){return!!f(a).isDetectable}function c(a){f(a).isDetectable=!0}function d(a){return!!f(a).busy}function e(a,b){f(a).busy=!!b}var f=a.stateHandler.getState;return{isDetectable:b,markAsDetectable:c,isBusy:d,markBusy:e}}},{}],9:[function(a,b,c){"use strict";b.exports=function(){function a(){return b++}var b=1;return{generate:a}}},{}],10:[function(a,b,c){"use strict";b.exports=function(a){function b(a,b){return b||d(a)||c(a),g(a).id}function c(a){var b=f.generate();return g(a).id=b,b}function d(a){return void 0!==g(a).id}function e(a){delete g(a).id}var f=a.idGenerator,g=a.stateHandler.getState;return{get:b,remove:e}}},{}],11:[function(a,b,c){"use strict";b.exports=function(a){function b(b){return f[a.get(b)]||[]}function c(b,c){var d=a.get(b);f[d]||(f[d]=[]),f[d].push(c)}function d(a,c){for(var d=b(a),e=0,f=d.length;f>e;++e)if(d[e]===c){d.splice(e,1);break}}function e(b){var c=f[a.get(b)];c&&(c.length=0)}var f={};return{get:b,add:c,removeListener:d,removeAllListeners:e}}},{}],12:[function(a,b,c){"use strict";b.exports=function(a){function b(){}var c={log:b,warn:b,error:b};if(!a&&window.console){var d=function(a,b){a[b]=function(){console[b].apply(console,arguments)}};d(c,"log"),d(c,"warn"),d(c,"error")}return c}},{}],13:[function(a,b,c){"use strict";function d(a){return a[g]={},e(a)}function e(a){return a[g]||d(a)}function f(a){delete a[g]}var g="_erd";b.exports={initState:d,getState:e,cleanState:f}},{}]},{},[7])(7)}); |
@@ -52,3 +52,3 @@ /* global process:false */ | ||
banner: "/*!\n" + | ||
" * element-resize-detector <%= pkg.version %> (<%= grunt.template.today('yyyy-mm-dd, HH:MM') %>)\n" + | ||
" * element-resize-detector <%= pkg.version %>\n" + | ||
" * <%= pkg.homepage %>\n" + | ||
@@ -55,0 +55,0 @@ " * Licensed under <%= pkg.license %>\n" + |
{ | ||
"name": "element-resize-detector", | ||
"version": "0.4.0", | ||
"description": "resize event emitter for elements.", | ||
"version": "1.0.0", | ||
"description": "Resize event emitter for elements.", | ||
"homepage": "https://github.com/wnr/element-resize-detector", | ||
@@ -6,0 +6,0 @@ "repository": { |
@@ -17,3 +17,3 @@ # element-resize-detector | ||
``` | ||
This will create a global function ```elementResieDetectorMaker```, which is the maker function that makes an element resize detector instance. | ||
This will create a global function ```elementResizeDetectorMaker```, which is the maker function that makes an element resize detector instance. | ||
@@ -20,0 +20,0 @@ You can also ```require``` it like so: |
@@ -57,60 +57,84 @@ /** | ||
function onObjectLoad() { | ||
/*jshint validthis: true */ | ||
//The target element needs to be positioned (everything except static) so the absolute positioned object will be positioned relative to the target element. | ||
function getDocument(element, callback) { | ||
//Opera 12 seem to call the object.onload before the actual document has been created. | ||
//So if it is not present, poll it with an timeout until it is present. | ||
//TODO: Could maybe be handled better with object.onreadystatechange or similar. | ||
if(!element.contentDocument) { | ||
setTimeout(function checkForObjectDocument() { | ||
getDocument(element, callback); | ||
}, 100); | ||
// Position altering may be performed directly or on object load, depending on if style resolution is possible directly or not. | ||
var positionCheckPerformed = false; | ||
return; | ||
} | ||
// The element may not yet be attached to the DOM, and therefore the style object may be empty in some browsers. | ||
// Since the style object is a reference, it will be updated as soon as the element is attached to the DOM. | ||
var style = getComputedStyle(element); | ||
callback(element.contentDocument); | ||
} | ||
getState(element).startSizeStyle = { | ||
width: style.width, | ||
height: style.height | ||
}; | ||
//Mutating the object element here seems to fire another load event. | ||
//Mutating the inner document of the object element is fine though. | ||
var objectElement = this; | ||
function mutateDom() { | ||
function alterPositionStyles() { | ||
if(style.position === "static") { | ||
element.style.position = "relative"; | ||
//Create the style element to be added to the object. | ||
getDocument(objectElement, function onObjectDocumentReady(objectDocument) { | ||
//Notify that the element is ready to be listened to. | ||
callback(element); | ||
}); | ||
} | ||
var removeRelativeStyles = function(reporter, element, style, property) { | ||
function getNumericalValue(value) { | ||
return value.replace(/[^-\d\.]/g, ""); | ||
} | ||
//The target element needs to be positioned (everything except static) so the absolute positioned object will be positioned relative to the target element. | ||
var style = getComputedStyle(element); | ||
var position = style.position; | ||
var value = style[property]; | ||
function mutateDom() { | ||
if(position === "static") { | ||
element.style.position = "relative"; | ||
if(value !== "auto" && getNumericalValue(value) !== "0") { | ||
reporter.warn("An element that is positioned static has style." + property + "=" + value + " which is ignored due to the static positioning. The element will need to be positioned relative, so the style." + property + " will be set to 0. Element: ", element); | ||
element.style[property] = 0; | ||
} | ||
}; | ||
var removeRelativeStyles = function(reporter, element, style, property) { | ||
function getNumericalValue(value) { | ||
return value.replace(/[^-\d\.]/g, ""); | ||
} | ||
//Check so that there are no accidental styles that will make the element styled differently now that is is relative. | ||
//If there are any, set them to 0 (this should be okay with the user since the style properties did nothing before [since the element was positioned static] anyway). | ||
removeRelativeStyles(reporter, element, style, "top"); | ||
removeRelativeStyles(reporter, element, style, "right"); | ||
removeRelativeStyles(reporter, element, style, "bottom"); | ||
removeRelativeStyles(reporter, element, style, "left"); | ||
} | ||
} | ||
var value = style[property]; | ||
function onObjectLoad() { | ||
// The object has been loaded, which means that the element now is guaranteed to be attached to the DOM. | ||
if (!positionCheckPerformed) { | ||
alterPositionStyles(); | ||
} | ||
if(value !== "auto" && getNumericalValue(value) !== "0") { | ||
reporter.warn("An element that is positioned static has style." + property + "=" + value + " which is ignored due to the static positioning. The element will need to be positioned relative, so the style." + property + " will be set to 0. Element: ", element); | ||
element.style[property] = 0; | ||
/*jshint validthis: true */ | ||
function getDocument(element, callback) { | ||
//Opera 12 seem to call the object.onload before the actual document has been created. | ||
//So if it is not present, poll it with an timeout until it is present. | ||
//TODO: Could maybe be handled better with object.onreadystatechange or similar. | ||
if(!element.contentDocument) { | ||
setTimeout(function checkForObjectDocument() { | ||
getDocument(element, callback); | ||
}, 100); | ||
return; | ||
} | ||
}; | ||
//Check so that there are no accidental styles that will make the element styled differently now that is is relative. | ||
//If there are any, set them to 0 (this should be okay with the user since the style properties did nothing before [since the element was positioned static] anyway). | ||
removeRelativeStyles(reporter, element, style, "top"); | ||
removeRelativeStyles(reporter, element, style, "right"); | ||
removeRelativeStyles(reporter, element, style, "bottom"); | ||
removeRelativeStyles(reporter, element, style, "left"); | ||
callback(element.contentDocument); | ||
} | ||
//Mutating the object element here seems to fire another load event. | ||
//Mutating the inner document of the object element is fine though. | ||
var objectElement = this; | ||
//Create the style element to be added to the object. | ||
getDocument(objectElement, function onObjectDocumentReady(objectDocument) { | ||
//Notify that the element is ready to be listened to. | ||
callback(element); | ||
}); | ||
} | ||
// The element may be detached from the DOM, and some browsers does not support style resolving of detached elements. | ||
// The alterPositionStyles needs to be delayed until we know the element has been attached to the DOM (which we are sure of when the onObjectLoad has been fired), if style resolution is not possible. | ||
if (style.position !== "") { | ||
alterPositionStyles(style); | ||
positionCheckPerformed = true; | ||
} | ||
//Add an object element as a child to the target element that will be listened to for resize events. | ||
@@ -117,0 +141,0 @@ var object = document.createElement("object"); |
@@ -71,106 +71,153 @@ /** | ||
function makeDetectable(element, callback) { | ||
// Reading properties of elementStyle will result in a forced getComputedStyle for some browsers, so read all values and store them as primitives here. | ||
var elementStyle = getComputedStyle(element); | ||
var position = elementStyle.position; | ||
var width = parseSize(elementStyle.width); | ||
var height = parseSize(elementStyle.height); | ||
var top = elementStyle.top; | ||
var right = elementStyle.right; | ||
var bottom = elementStyle.bottom; | ||
var left = elementStyle.left; | ||
var readyExpandScroll = false; | ||
var readyShrinkScroll = false; | ||
var readyOverall = false; | ||
function isStyleResolved() { | ||
function isPxValue(length) { | ||
return length.indexOf("px") !== -1; | ||
} | ||
function ready() { | ||
if(readyExpandScroll && readyShrinkScroll && readyOverall) { | ||
callback(element); | ||
} | ||
var style = getComputedStyle(element); | ||
return style.position && isPxValue(style.width) && isPxValue(style.height); | ||
} | ||
function mutateDom() { | ||
if(position === "static") { | ||
element.style.position = "relative"; | ||
function install() { | ||
function getStyle() { | ||
// Some browsers only force layouts when actually reading the style properties of the style object, so make sure that they are all read here, | ||
// so that the user of the function can be sure that it will perform the layout here, instead of later (important for batching). | ||
var style = {}; | ||
var elementStyle = getComputedStyle(element); | ||
style.position = elementStyle.position; | ||
style.width = parseSize(elementStyle.width); | ||
style.height = parseSize(elementStyle.height); | ||
style.top = elementStyle.top; | ||
style.right = elementStyle.right; | ||
style.bottom = elementStyle.bottom; | ||
style.left = elementStyle.left; | ||
style.widthStyle = elementStyle.width; | ||
style.heightStyle = elementStyle.height; | ||
return style; | ||
} | ||
var removeRelativeStyles = function(reporter, element, value, property) { | ||
function getNumericalValue(value) { | ||
return value.replace(/[^-\d\.]/g, ""); | ||
} | ||
// Style is to be retrieved in the first level (before mutating the DOM) so that a forced layout is avoided later. | ||
var style = getStyle(); | ||
if(value !== "auto" && getNumericalValue(value) !== "0") { | ||
reporter.warn("An element that is positioned static has style." + property + "=" + value + " which is ignored due to the static positioning. The element will need to be positioned relative, so the style." + property + " will be set to 0. Element: ", element); | ||
element.style[property] = 0; | ||
} | ||
}; | ||
getState(element).startSizeStyle = { | ||
width: style.widthStyle, | ||
height: style.heightStyle | ||
}; | ||
//Check so that there are no accidental styles that will make the element styled differently now that is is relative. | ||
//If there are any, set them to 0 (this should be okay with the user since the style properties did nothing before [since the element was positioned static] anyway). | ||
removeRelativeStyles(reporter, element, top, "top"); | ||
removeRelativeStyles(reporter, element, right, "right"); | ||
removeRelativeStyles(reporter, element, bottom, "bottom"); | ||
removeRelativeStyles(reporter, element, left, "left"); | ||
var readyExpandScroll = false; | ||
var readyShrinkScroll = false; | ||
var readyOverall = false; | ||
function ready() { | ||
if(readyExpandScroll && readyShrinkScroll && readyOverall) { | ||
callback(element); | ||
} | ||
} | ||
function getContainerCssText(left, top, bottom, right) { | ||
left = (!left ? "0" : (left + "px")); | ||
top = (!top ? "0" : (top + "px")); | ||
bottom = (!bottom ? "0" : (bottom + "px")); | ||
right = (!right ? "0" : (right + "px")); | ||
function mutateDom() { | ||
function alterPositionStyles() { | ||
if(style.position === "static") { | ||
element.style.position = "relative"; | ||
return "position: absolute; left: " + left + "; top: " + top + "; right: " + right + "; bottom: " + bottom + "; overflow: scroll; z-index: -1; visibility: hidden;"; | ||
} | ||
var removeRelativeStyles = function(reporter, element, style, property) { | ||
function getNumericalValue(value) { | ||
return value.replace(/[^-\d\.]/g, ""); | ||
} | ||
var scrollbarWidth = scrollbarSizes.width; | ||
var scrollbarHeight = scrollbarSizes.height; | ||
var containerStyle = getContainerCssText(-1, -1, -scrollbarHeight, -scrollbarWidth); | ||
var shrinkExpandstyle = getContainerCssText(0, 0, -scrollbarHeight, -scrollbarWidth); | ||
var shrinkExpandChildStyle = "position: absolute; left: 0; top: 0;"; | ||
var value = style[property]; | ||
var container = document.createElement("div"); | ||
var expand = document.createElement("div"); | ||
var expandChild = document.createElement("div"); | ||
var shrink = document.createElement("div"); | ||
var shrinkChild = document.createElement("div"); | ||
if(value !== "auto" && getNumericalValue(value) !== "0") { | ||
reporter.warn("An element that is positioned static has style." + property + "=" + value + " which is ignored due to the static positioning. The element will need to be positioned relative, so the style." + property + " will be set to 0. Element: ", element); | ||
element.style[property] = 0; | ||
} | ||
}; | ||
container.style.cssText = containerStyle; | ||
expand.style.cssText = shrinkExpandstyle; | ||
expandChild.style.cssText = shrinkExpandChildStyle; | ||
shrink.style.cssText = shrinkExpandstyle; | ||
shrinkChild.style.cssText = shrinkExpandChildStyle + " width: 200%; height: 200%;"; | ||
//Check so that there are no accidental styles that will make the element styled differently now that is is relative. | ||
//If there are any, set them to 0 (this should be okay with the user since the style properties did nothing before [since the element was positioned static] anyway). | ||
removeRelativeStyles(reporter, element, style, "top"); | ||
removeRelativeStyles(reporter, element, style, "right"); | ||
removeRelativeStyles(reporter, element, style, "bottom"); | ||
removeRelativeStyles(reporter, element, style, "left"); | ||
} | ||
} | ||
expand.appendChild(expandChild); | ||
shrink.appendChild(shrinkChild); | ||
container.appendChild(expand); | ||
container.appendChild(shrink); | ||
element.appendChild(container); | ||
getState(element).element = container; | ||
function getContainerCssText(left, top, bottom, right) { | ||
left = (!left ? "0" : (left + "px")); | ||
top = (!top ? "0" : (top + "px")); | ||
bottom = (!bottom ? "0" : (bottom + "px")); | ||
right = (!right ? "0" : (right + "px")); | ||
addEvent(expand, "scroll", function onFirstExpandScroll() { | ||
removeEvent(expand, "scroll", onFirstExpandScroll); | ||
readyExpandScroll = true; | ||
ready(); | ||
}); | ||
return "position: absolute; left: " + left + "; top: " + top + "; right: " + right + "; bottom: " + bottom + "; overflow: scroll; z-index: -1; visibility: hidden;"; | ||
} | ||
addEvent(shrink, "scroll", function onFirstShrinkScroll() { | ||
removeEvent(shrink, "scroll", onFirstShrinkScroll); | ||
readyShrinkScroll = true; | ||
alterPositionStyles(style); | ||
var scrollbarWidth = scrollbarSizes.width; | ||
var scrollbarHeight = scrollbarSizes.height; | ||
var containerStyle = getContainerCssText(-1, -1, -scrollbarHeight, -scrollbarWidth); | ||
var shrinkExpandstyle = getContainerCssText(0, 0, -scrollbarHeight, -scrollbarWidth); | ||
var shrinkExpandChildStyle = "position: absolute; left: 0; top: 0;"; | ||
var container = document.createElement("div"); | ||
var expand = document.createElement("div"); | ||
var expandChild = document.createElement("div"); | ||
var shrink = document.createElement("div"); | ||
var shrinkChild = document.createElement("div"); | ||
container.style.cssText = containerStyle; | ||
expand.style.cssText = shrinkExpandstyle; | ||
expandChild.style.cssText = shrinkExpandChildStyle; | ||
shrink.style.cssText = shrinkExpandstyle; | ||
shrinkChild.style.cssText = shrinkExpandChildStyle + " width: 200%; height: 200%;"; | ||
expand.appendChild(expandChild); | ||
shrink.appendChild(shrinkChild); | ||
container.appendChild(expand); | ||
container.appendChild(shrink); | ||
element.appendChild(container); | ||
getState(element).element = container; | ||
addEvent(expand, "scroll", function onFirstExpandScroll() { | ||
removeEvent(expand, "scroll", onFirstExpandScroll); | ||
readyExpandScroll = true; | ||
ready(); | ||
}); | ||
addEvent(shrink, "scroll", function onFirstShrinkScroll() { | ||
removeEvent(shrink, "scroll", onFirstShrinkScroll); | ||
readyShrinkScroll = true; | ||
ready(); | ||
}); | ||
updateChildSizes(element, style.width, style.height); | ||
} | ||
function finalizeDomMutation() { | ||
storeCurrentSize(element, style.width, style.height); | ||
positionScrollbars(element, style.width, style.height); | ||
readyOverall = true; | ||
ready(); | ||
}); | ||
} | ||
updateChildSizes(element, width, height); | ||
if(batchProcessor) { | ||
batchProcessor.add(mutateDom); | ||
batchProcessor.add(1, finalizeDomMutation); | ||
} else { | ||
mutateDom(); | ||
finalizeDomMutation(); | ||
} | ||
} | ||
function finalizeDomMutation() { | ||
storeCurrentSize(element, width, height); | ||
positionScrollbars(element, width, height); | ||
readyOverall = true; | ||
ready(); | ||
} | ||
if(batchProcessor) { | ||
batchProcessor.add(mutateDom); | ||
batchProcessor.add(1, finalizeDomMutation); | ||
// Only install the strategy if the style has been resolved (this does not always mean that the element is attached). | ||
if (isStyleResolved()) { | ||
install(); | ||
} else { | ||
mutateDom(); | ||
finalizeDomMutation(); | ||
// Need to perform polling in order to detect when the element has been attached to the DOM. | ||
var timeout = setInterval(function () { | ||
if (isStyleResolved()) { | ||
install(); | ||
clearTimeout(timeout); | ||
} | ||
}, 50); | ||
} | ||
@@ -177,0 +224,0 @@ } |
@@ -130,2 +130,22 @@ "use strict"; | ||
function isCollection(obj) { | ||
return Array.isArray(obj) || obj.length !== undefined; | ||
} | ||
function toArray(collection) { | ||
if (!Array.isArray(collection)) { | ||
var array = []; | ||
forEach(elements, function (element) { | ||
array.push(element); | ||
}); | ||
return array; | ||
} else { | ||
return collection; | ||
} | ||
} | ||
function isElement(obj) { | ||
return obj && obj.nodeType === 1; | ||
} | ||
//Options object may be omitted. | ||
@@ -146,4 +166,10 @@ if(!listener) { | ||
if(elements.length === undefined) { | ||
if (isElement(elements)) { | ||
// A single element has been passed in. | ||
elements = [elements]; | ||
} else if (isCollection(elements)) { | ||
// Convert collection to array for plugins. | ||
elements = toArray(elements); | ||
} else { | ||
return reporter.error("Invalid arguments. Must be a DOM element or a collection of DOM elements."); | ||
} | ||
@@ -183,2 +209,9 @@ | ||
// Since the element size might have changed since the call to "listenTo", we need to check for this change, | ||
// so that a resize event may be emitted. | ||
var style = getComputedStyle(element); | ||
if (stateHandler.getState(element).startSizeStyle.width !== style.width || stateHandler.getState(element).startSizeStyle.height !== style.height) { | ||
onResizeCallback(element); | ||
} | ||
elementsReady++; | ||
@@ -185,0 +218,0 @@ if(elementsReady === elements.length) { |
@@ -306,3 +306,3 @@ /* global describe:false, it:false, beforeEach:false, expect:false, elementResizeDetectorMaker:false, _:false, $:false, jasmine:false */ | ||
it("should call listener if the element is changed synchronously after listenTo", function(done) { | ||
it("should call listener on add if options is set to true", function(done) { | ||
var erd = elementResizeDetectorMaker({ | ||
@@ -324,2 +324,46 @@ callOnAdd: true, | ||
it("should call listener if the element is changed synchronously after listenTo", function(done) { | ||
var erd = elementResizeDetectorMaker({ | ||
callOnAdd: false, | ||
reporter: reporter, | ||
strategy: strategy | ||
}); | ||
var listener1 = jasmine.createSpy("listener1"); | ||
erd.listenTo($("#test"), listener1); | ||
$("#test").width(200); | ||
setTimeout(function() { | ||
expect(listener1).toHaveBeenCalledWith($("#test")[0]); | ||
done(); | ||
}, 100); | ||
}); | ||
it("should be able to install into elements that are detached from the DOM", function(done) { | ||
var erd = elementResizeDetectorMaker({ | ||
callOnAdd: false, | ||
reporter: reporter, | ||
strategy: strategy | ||
}); | ||
var listener1 = jasmine.createSpy("listener1"); | ||
var div = document.createElement("div"); | ||
div.style.width = "100%"; | ||
div.style.height = "100%"; | ||
erd.listenTo(div, listener1); | ||
setTimeout(function () { | ||
$("#test")[0].appendChild(div); | ||
}, 100); | ||
setTimeout(function () { | ||
$("#test").width(200); | ||
}, 200); | ||
setTimeout(function() { | ||
expect(listener1).toHaveBeenCalledWith(div); | ||
done(); | ||
}, 300); | ||
}); | ||
it("should use the option.idHandler if present", function(done) { | ||
@@ -491,2 +535,8 @@ var ID_ATTR = "some-fancy-id-attr"; | ||
}); | ||
it("should work for elements that don't have the detector installed", function() { | ||
var erd = elementResizeDetectorMaker(); | ||
var $testElem = $("#test"); | ||
expect(erd.removeAllListeners.bind(erd, $testElem[0])).not.toThrow(); | ||
}); | ||
}); | ||
@@ -550,3 +600,3 @@ | ||
//Scroll only supported on non-opera browsers. | ||
//Scroll only supported on non-opera browsers. | ||
if(!window.opera) { | ||
@@ -553,0 +603,0 @@ listenToTest("scroll"); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
157835
3037
1