MediaWiki:ResizeSensor.js

/** * Copyright Marc J. Schmidt. See the LICENSE file at the top-level * directory of this distribution and at * https://github.com/marcj/css-element-queries/blob/master/LICENSE. */ (function {

/**    * Class for dimension change detection. *    * @param {Element|Element[]|Elements|jQuery} element * @param {Function} callback *    * @constructor */   this.ResizeSensor = function(element, callback) { /**        *         * @constructor */       function EventQueue { this.q = []; this.add = function(ev) { this.q.push(ev); };

var i, j;           this.call = function { for (i = 0, j = this.q.length; i < j; i++) { this.q[i].call; }           };        }

/**        * @param {HTMLElement} element * @param {String}     prop * @returns {String|Number} */       function getComputedStyle(element, prop) { if (element.currentStyle) { return element.currentStyle[prop]; } else if (window.getComputedStyle) { return window.getComputedStyle(element, null).getPropertyValue(prop); } else { return element.style[prop]; }       }

/**        *         * @param {HTMLElement} element * @param {Function}   resized */       function attachResizeEvent(element, resized) { if (!element.resizedAttached) { element.resizedAttached = new EventQueue; element.resizedAttached.add(resized); } else if (element.resizedAttached) { element.resizedAttached.add(resized); return; }

element.resizeSensor = document.createElement('div'); element.resizeSensor.className = 'resize-sensor'; var style = 'position: absolute; left: 0; top: 0; right: 0; bottom: 0; overflow: scroll; z-index: -1; visibility: hidden;'; var styleChild = 'position: absolute; left: 0; top: 0;';

element.resizeSensor.style.cssText = style; element.resizeSensor.innerHTML = '' + ' ' + ' ' +               '' + ' ' + ' ';           element.appendChild(element.resizeSensor);

if (!{fixed: 1, absolute: 1}[getComputedStyle(element, 'position')]) { element.style.position = 'relative'; }

var expand = element.resizeSensor.childNodes[0]; var expandChild = expand.childNodes[0]; var shrink = element.resizeSensor.childNodes[1]; var shrinkChild = shrink.childNodes[0];

var lastWidth, lastHeight;

var reset = function { expandChild.style.width = expand.offsetWidth + 10 + 'px'; expandChild.style.height = expand.offsetHeight + 10 + 'px'; expand.scrollLeft = expand.scrollWidth; expand.scrollTop = expand.scrollHeight; shrink.scrollLeft = shrink.scrollWidth; shrink.scrollTop = shrink.scrollHeight; lastWidth = element.offsetWidth; lastHeight = element.offsetHeight; };

reset;

var changed = function { if (element.resizedAttached) { element.resizedAttached.call; }           };

var addEvent = function(el, name, cb) { if (el.attachEvent) { el.attachEvent('on' + name, cb); } else { el.addEventListener(name, cb); }           };            var onScroll = function { if (element.offsetWidth != lastWidth || element.offsetHeight != lastHeight) { changed; }             reset; }

addEvent(expand, 'scroll', onScroll); addEvent(shrink, 'scroll', onScroll); }

var elementType = Object.prototype.toString.call(element); var isCollectionTyped = ('[object Array]' === elementType           || ('[object NodeList]' === elementType)            || ('[object HTMLCollection]' === elementType)            || ('undefined' !== typeof jQuery && element instanceof jQuery) //jquery            || ('undefined' !== typeof Elements && element instanceof Elements) //mootools        );

if (isCollectionTyped) { var i = 0, j = element.length; for (i < j; i++) { attachResizeEvent(element[i], callback); }       } else { attachResizeEvent(element, callback); }

this.detach = function { if (isCollectionTyped) { var i = 0, j = element.length; for (i < j; i++) { ResizeSensor.detach(element[i]); }           } else { ResizeSensor.detach(element); }       };    };

this.ResizeSensor.detach = function(element) { if (element.resizeSensor) { element.removeChild(element.resizeSensor); delete element.resizeSensor; delete element.resizedAttached; }   };

});