140f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik/**
240f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik * Copyright Marc J. Schmidt. See the LICENSE file at the top-level
340f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik * directory of this distribution and at
440f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik * https://github.com/marcj/css-element-queries/blob/master/LICENSE.
540f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik */
640f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik;
740f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik(function() {
840f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik
940f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik    /**
1040f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik     * Class for dimension change detection.
1140f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik     *
1240f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik     * @param {Element|Element[]|Elements|jQuery} element
1340f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik     * @param {Function} callback
1440f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik     *
1540f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik     * @constructor
1640f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik     */
1740f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik    this.ResizeSensor = function(element, callback) {
1840f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik        /**
1940f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik         *
2040f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik         * @constructor
2140f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik         */
2240f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik        function EventQueue() {
2340f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            this.q = [];
2440f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            this.add = function(ev) {
2540f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik                this.q.push(ev);
2640f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            };
2740f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik
2840f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            var i, j;
2940f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            this.call = function() {
3040f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik                for (i = 0, j = this.q.length; i < j; i++) {
3140f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik                    this.q[i].call();
3240f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik                }
3340f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            };
3440f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik        }
3540f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik
3640f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik        /**
3740f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik         * @param {HTMLElement} element
3840f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik         * @param {String}      prop
3940f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik         * @returns {String|Number}
4040f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik         */
4140f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik        function getComputedStyle(element, prop) {
4240f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            if (element.currentStyle) {
4340f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik                return element.currentStyle[prop];
4440f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            } else if (window.getComputedStyle) {
4540f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik                return window.getComputedStyle(element, null).getPropertyValue(prop);
4640f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            } else {
4740f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik                return element.style[prop];
4840f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            }
4940f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik        }
5040f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik
5140f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik        /**
5240f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik         *
5340f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik         * @param {HTMLElement} element
5440f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik         * @param {Function}    resized
5540f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik         */
5640f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik        function attachResizeEvent(element, resized) {
5740f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            if (!element.resizedAttached) {
5840f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik                element.resizedAttached = new EventQueue();
5940f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik                element.resizedAttached.add(resized);
6040f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            } else if (element.resizedAttached) {
6140f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik                element.resizedAttached.add(resized);
6240f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik                return;
6340f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            }
6440f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik
6540f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            element.resizeSensor = document.createElement('div');
6640f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            element.resizeSensor.className = 'resize-sensor';
6740f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            var style = 'position: absolute; left: 0; top: 0; right: 0; bottom: 0; overflow: scroll; z-index: -1; visibility: hidden;';
6840f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            var styleChild = 'position: absolute; left: 0; top: 0;';
6940f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik
7040f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            element.resizeSensor.style.cssText = style;
7140f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            element.resizeSensor.innerHTML =
7240f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik                '<div class="resize-sensor-expand" style="' + style + '">' +
7340f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik                    '<div style="' + styleChild + '"></div>' +
7440f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik                '</div>' +
7540f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik                '<div class="resize-sensor-shrink" style="' + style + '">' +
7640f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik                    '<div style="' + styleChild + ' width: 200%; height: 200%"></div>' +
7740f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik                '</div>';
7840f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            element.appendChild(element.resizeSensor);
7940f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik
8040f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            if (!{fixed: 1, absolute: 1}[getComputedStyle(element, 'position')]) {
8140f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik                element.style.position = 'relative';
8240f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            }
8340f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik
8440f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            var expand = element.resizeSensor.childNodes[0];
8540f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            var expandChild = expand.childNodes[0];
8640f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            var shrink = element.resizeSensor.childNodes[1];
8740f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            var shrinkChild = shrink.childNodes[0];
8840f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik
8940f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            var lastWidth, lastHeight;
9040f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik
9140f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            var reset = function() {
9240f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik                expandChild.style.width = expand.offsetWidth + 10 + 'px';
9340f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik                expandChild.style.height = expand.offsetHeight + 10 + 'px';
9440f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik                expand.scrollLeft = expand.scrollWidth;
9540f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik                expand.scrollTop = expand.scrollHeight;
9640f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik                shrink.scrollLeft = shrink.scrollWidth;
9740f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik                shrink.scrollTop = shrink.scrollHeight;
9840f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik                lastWidth = element.offsetWidth;
9940f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik                lastHeight = element.offsetHeight;
10040f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            };
10140f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik
10240f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            reset();
10340f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik
10440f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            var changed = function() {
10540f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik                if (element.resizedAttached) {
10640f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik                    element.resizedAttached.call();
10740f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik                }
10840f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            };
10940f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik
11040f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            var addEvent = function(el, name, cb) {
11140f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik                if (el.attachEvent) {
11240f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik                    el.attachEvent('on' + name, cb);
11340f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik                } else {
11440f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik                    el.addEventListener(name, cb);
11540f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik                }
11640f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            };
11740f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik
11840f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            addEvent(expand, 'scroll', function() {
11940f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik                if (element.offsetWidth > lastWidth || element.offsetHeight > lastHeight) {
12040f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik                    changed();
12140f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik                }
12240f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik                reset();
12340f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            });
12440f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik
12540f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            addEvent(shrink, 'scroll',function() {
12640f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik                if (element.offsetWidth < lastWidth || element.offsetHeight < lastHeight) {
12740f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik                    changed();
12840f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik                }
12940f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik                reset();
13040f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            });
13140f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik        }
13240f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik
13340f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik        if ("[object Array]" === Object.prototype.toString.call(element)
13440f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            || ('undefined' !== typeof jQuery && element instanceof jQuery) //jquery
13540f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            || ('undefined' !== typeof Elements && element instanceof Elements) //mootools
13640f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            ) {
13740f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            var i = 0, j = element.length;
13840f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            for (; i < j; i++) {
13940f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik                attachResizeEvent(element[i], callback);
14040f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            }
14140f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik        } else {
14240f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            attachResizeEvent(element, callback);
14340f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik        }
14440f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik
14540f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik        this.detach = function() {
14640f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            ResizeSensor.detach(element);
14740f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik        };
14840f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik    };
14940f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik
15040f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik    this.ResizeSensor.detach = function(element) {
15140f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik        if (element.resizeSensor) {
15240f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            element.removeChild(element.resizeSensor);
15340f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            delete element.resizeSensor;
15440f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik            delete element.resizedAttached;
15540f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik        }
15640f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik    };
15740f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik
15840f8da8088c9cd699f672242d0cdc3d677353bf8Chris Craik})();