├── tests
├── tests.css
├── tests-jquery.html
├── tests-javascript.html
├── tests-jquery.js
└── tests-javascript.js
├── bower.json
├── package.json
├── LICENSE
├── README.md
├── detect-element-resize.js
└── jquery.resize.js
/tests/tests.css:
--------------------------------------------------------------------------------
1 | #container {
2 | /*display: none;*/
3 | }
4 |
5 | #resizable-element {
6 | /*display: inline-block;*/
7 | float: left;
8 | }
9 |
10 | #content {
11 | color: red;
12 | width: 20px;
13 | height: 15px;
14 | }
--------------------------------------------------------------------------------
/tests/tests-jquery.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | javascript-detect-element-resize Tests
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/tests/tests-javascript.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | javascript-detect-element-resize Tests
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "javascript-detect-element-resize",
3 | "version": "0.5.3",
4 | "main": "detect-element-resize.js",
5 | "repository": {
6 | "type": "git",
7 | "url": "git@github.com:sdecima/javascript-detect-element-resize.git"
8 | },
9 | "homepage": "https://github.com/sdecima/javascript-detect-element-resize",
10 | "authors": [
11 | "Sebastián Décima (https://github.com/sdecima/)"
12 | ],
13 | "description": "A Cross-Browser, Event-based, Element Resize Detection",
14 | "keywords": [
15 | "resize",
16 | "events",
17 | "javascript",
18 | "ecmascript"
19 | ],
20 | "license": "MIT",
21 | "ignore": [
22 | "**/.*"
23 | ]
24 | }
25 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "javascript-detect-element-resize",
3 | "version": "0.5.3",
4 | "description": "A Cross-Browser, Event-based, Element Resize Detection",
5 | "main": "detect-element-resize.js",
6 | "directories": {
7 | "test": "tests"
8 | },
9 | "scripts": {
10 | "test": "echo \"Error: no test specified\" && exit 1"
11 | },
12 | "repository": {
13 | "type": "git",
14 | "url": "https://github.com/sdecima/javascript-detect-element-resize"
15 | },
16 | "keywords": [
17 | "resize",
18 | "events"
19 | ],
20 | "author": "Sebastián Décima (https://github.com/sdecima/)",
21 | "license": "MIT",
22 | "bugs": {
23 | "url": "https://github.com/sdecima/javascript-detect-element-resize/issues"
24 | },
25 | "homepage": "https://github.com/sdecima/javascript-detect-element-resize",
26 | "devDependencies": {
27 | "browserify": "^6.3.3"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2013 Sebastián Décima
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/tests/tests-jquery.js:
--------------------------------------------------------------------------------
1 | var container, element, content;
2 |
3 | QUnit.module('main', {
4 | setup: function() {
5 | var fixture = '';
6 | $("#qunit-fixture").append(fixture);
7 |
8 | container = document.getElementById('container');
9 | element = document.getElementById('resizable-element');
10 | content = document.getElementById('content');
11 |
12 | $('#container').hide();
13 | $(element).resize(detectCallback);
14 | $('#container').show();
15 | shouldDetect = true;
16 | detected = false;
17 | },
18 | teardown: function() {
19 | $('#styleTest').remove();
20 | try {
21 | $(element).removeResize(detectCallback);
22 | } catch(e) {}
23 | }
24 | });
25 |
26 | var newWidth = 0, newHeight = 0, shouldDetect = true, detected = false;
27 | var detectCallback = function() {
28 | detected = true;
29 | };
30 |
31 | var validateEvent = function(assert) {
32 | setTimeout(function() {
33 | if(shouldDetect) {
34 | assert.ok(shouldDetect === true && detected === true, 'resize event fired OK');
35 | }
36 | assert.ok($(content).width() == newWidth, 'Resize OK');
37 |
38 | QUnit.start();
39 | }, 2000);
40 | };
41 |
42 | QUnit.asyncTest( "JS addResizeListener css resize test", function( assert ) {
43 | expect( 2 );
44 |
45 | newWidth = 100;
46 |
47 | var myCss = '';
48 | $('head').append(myCss);
49 |
50 | validateEvent(assert);
51 | });
52 |
53 | QUnit.asyncTest( "JS addResizeListener script resize test", function( assert ) {
54 | expect( 2 );
55 |
56 | newWidth = 30;
57 |
58 | $(content).width(newWidth);
59 |
60 | validateEvent(assert);
61 | });
62 |
63 | QUnit.asyncTest( "JS addResizeListener script reattach element test", function( assert ) {
64 | expect( 2 );
65 |
66 | var elem = $(content).detach();
67 |
68 | setTimeout(function() {
69 | $(container).append("div").append(elem);
70 | //elem.appendTo(container);
71 | newWidth = 68;
72 | $(content).width(newWidth);
73 | }, 500);
74 |
75 | validateEvent(assert);
76 | });
77 |
78 | QUnit.asyncTest( "JS removeResizeListener test", function( assert ) {
79 | expect( 1 );
80 |
81 | newWidth = 0;
82 | shouldDetect = false;
83 |
84 | $(element).removeResize(detectCallback);
85 |
86 | $(content).width(newWidth);
87 | $(content).height(0);
88 |
89 | validateEvent(assert);
90 | });
--------------------------------------------------------------------------------
/tests/tests-javascript.js:
--------------------------------------------------------------------------------
1 | var container, element, content;
2 |
3 | QUnit.module('main', {
4 | setup: function() {
5 | var fixture = '';
6 | $("#qunit-fixture").append(fixture);
7 |
8 | container = document.getElementById('container');
9 | element = document.getElementById('resizable-element');
10 | content = document.getElementById('content');
11 |
12 | $('#container').hide();
13 | addResizeListener(element, detectCallback);
14 | $('#container').show();
15 | shouldDetect = true;
16 | detected = false;
17 | },
18 | teardown: function() {
19 | $('#styleTest').remove();
20 | try {
21 | removeResizeListener(element, detectCallback);
22 | } catch(e) {}
23 | }
24 | });
25 |
26 | var newWidth = 0, newHeight = 0, shouldDetect = true, detected = false;
27 | var detectCallback = function() {
28 | detected = true;
29 | };
30 |
31 | var validateEvent = function(assert) {
32 | setTimeout(function() {
33 | if(shouldDetect) {
34 | assert.ok(shouldDetect === true && detected === true, 'resize event fired OK');
35 | }
36 | assert.ok($(content).width() == newWidth, 'Resize OK');
37 |
38 | QUnit.start();
39 | }, 2000);
40 | };
41 |
42 | QUnit.asyncTest( "JS addResizeListener css resize test", function( assert ) {
43 | expect( 2 );
44 |
45 | newWidth = 100;
46 |
47 | var myCss = '';
48 | $('head').append(myCss);
49 |
50 | validateEvent(assert);
51 | });
52 |
53 | QUnit.asyncTest( "JS addResizeListener script resize test", function( assert ) {
54 | expect( 2 );
55 |
56 | newWidth = 30;
57 |
58 | $(content).width(newWidth);
59 |
60 | validateEvent(assert);
61 | });
62 |
63 | QUnit.asyncTest( "JS addResizeListener script reattach element test", function( assert ) {
64 | expect( 2 );
65 |
66 | var elem = $(content).detach();
67 |
68 | setTimeout(function() {
69 | $(container).append("div").append(elem);
70 | //elem.appendTo(container);
71 | newWidth = 68;
72 | $(content).width(newWidth);
73 | }, 500);
74 |
75 | validateEvent(assert);
76 | });
77 |
78 | QUnit.asyncTest( "JS removeResizeListener test", function( assert ) {
79 | expect( 1 );
80 |
81 | newWidth = 0;
82 | shouldDetect = false;
83 |
84 | removeResizeListener(element, detectCallback);
85 |
86 | $(content).width(newWidth);
87 | $(content).height(0);
88 |
89 | validateEvent(assert);
90 | });
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | javascript-detect-element-resize
2 | ================================
3 |
4 | A Cross-Browser, Event-based, Element Resize Detection.
5 |
6 | In short, this implementation does NOT use an internal timer to detect size changes (as most implementations I found do).
7 | It uses `scroll` events on most browsers, and the [`onresize` event][5] on IE10 and below.
8 |
9 | The method used not only detects javascript generated resize changes but also changes made from CSS pseudo classes e.g. :hover, CSS animations, etc.
10 |
11 | About the libraries
12 | ===================
13 | I was searching for a library that allowed me to detect when an DOM element changes size, and all solutions I found had two problems:
14 |
15 | 1. only available as jQuery libraries (so no standalone Javascript)
16 | 2. all had terrible performance (because all of them use timers to intermittently poll the size of the elements to detect a change).
17 |
18 | Then I came across this [great post][1] on [Back Alley Coder][3] about using ~~[overflow and underflow events][2]~~ [`scroll` events][2] to do event-based element resize detection; and it works great without consuming resources at all (just like any other browser originated event).
19 |
20 | The libraries on this repository are just a ready-to-use implementation of the above, one pure javascript and the other a jQuery plugin version (just for convenience).
21 |
22 | Libraries
23 | =========
24 |
25 | Pure Javascript library usage
26 | -----------------------------
27 |
28 | ```html
29 |
30 |
38 | ```
39 |
40 | jQuery plugin library usage
41 | ---------------------------
42 | ```html
43 |
44 |
45 |
53 | ```
54 |
55 | Compatibility
56 | -------------
57 | Works great on:
58 |
59 | - Chrome
60 | - Firefox
61 | - IE 11 and below (tested on 11, 10, 9, 8 and 7)
62 |
63 | Known Issues:
64 |
65 | - On IE 10 and below: If you detach the element and re-attach it, you will need to add the resize listener again.
66 |
67 | Doesn't work on:
68 |
69 | - ???
70 |
71 | Please [let me know](https://github.com/sdecima/javascript-detect-element-resize/issues) if you test these libraries on any other browser, of if you run into issues with any of the above browsers.
72 |
73 | TODO
74 | ====
75 |
76 | - Fix detach/re-attach issue on IE 10 and below (IE 9 and below doesn't support CSS animations so we can use those as in the rest of the browsers).
77 | - Create minified version of the libraries.
78 | - Add support for standard jQuery bind method on 'resize' event.
79 |
80 | Release Notes
81 | =============
82 | v0.5.3
83 | ------
84 |
85 | - Fix for when the element is inside a display:none, and for when it is detached and reattached (changed @thomassuckow and @jerjou fixes to properly use CSS animations)
86 | - Adding /tests/ with some general QUnit tests to help test on multiple browsers
87 |
88 | v0.5.2
89 | ------
90 |
91 | - Adding a bower.json file (thanks @adamjcook)
92 | - Fix style being appended to head multiple times (thanks @thomassuckow and @progman32)
93 | - Work around a chrome bug that would show scrollbars in some cases (thanks @thomassuckow)
94 |
95 | v0.5.1
96 | ------
97 |
98 | - Fix for resize event on IE
99 |
100 | v0.5
101 | ----
102 |
103 | - It is now fully compatible with IE11.
104 | - Rework of the libraries using the new scroll-event-based code of [Back Alley Coder][1]. For the pure javascript version I pretty much used the original code from [Back Alley Coder][1] and only had to add code to dynamically insert the styling for the resize-triggers.
105 |
106 | v0.4.1
107 | ----
108 |
109 | - Fix for jQuery 'resize' method overlapping.
110 |
111 | v0.4
112 | ----
113 |
114 | - Adds better cross-browser support, it now uses MutationObservers only on IE11.
115 |
116 | v0.3
117 | ----
118 |
119 | - Adds support for MutationObservers.
120 | - Adds support for IE 11.
121 | - Wrapped the pure javascript version of the library (to hide non-public methods).
122 |
123 | v0.2
124 | ----
125 |
126 | - Adds support for IE 8 and below.
127 |
128 | v0.1
129 | ----
130 |
131 | - Implementation based on the [works][1] of [Back Alley Coder][3].
132 | - Adds jQuery plugin version.
133 |
134 |
135 | References
136 | ==========
137 |
138 | Similar libraries (but they use timers)
139 | ---------------------------------------
140 | [jQuery-mutate](http://www.jqui.net/jquery-projects/jquery-mutate-official/)
141 |
142 | [jQuery-resize-plugin](http://benalman.com/projects/jquery-resize-plugin/)
143 |
144 |
145 | Don't get me wrong, these are great libraries and work as advertised, it's just that they are not easy on browser resources.
146 |
147 | External links
148 | --------------
149 | [Back Alley Coder: Cross-Browser, Event-based, Element Resize Detection][1]
150 | [Back Alley Coder: Overflow and Underflow Events][2]
151 |
152 | [1]: http://www.backalleycoder.com/2013/03/18/cross-browser-event-based-element-resize-detection/
153 | [2]: http://www.backalleycoder.com/2013/03/14/oft-overlooked-overflow-and-underflow-events/
154 | [3]: http://www.backalleycoder.com/
155 | [4]: http://www.w3.org/TR/dom/#mutation-observers
156 | [5]: http://msdn.microsoft.com/en-us/library/ie/ms536959
157 |
158 |
--------------------------------------------------------------------------------
/detect-element-resize.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Detect Element Resize
3 | *
4 | * https://github.com/sdecima/javascript-detect-element-resize
5 | * Sebastian Decima
6 | *
7 | * version: 0.5.3
8 | **/
9 |
10 | (function () {
11 | var attachEvent = document.attachEvent,
12 | stylesCreated = false;
13 |
14 | if (!attachEvent) {
15 | var requestFrame = (function(){
16 | var raf = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame ||
17 | function(fn){ return window.setTimeout(fn, 20); };
18 | return function(fn){ return raf(fn); };
19 | })();
20 |
21 | var cancelFrame = (function(){
22 | var cancel = window.cancelAnimationFrame || window.mozCancelAnimationFrame || window.webkitCancelAnimationFrame ||
23 | window.clearTimeout;
24 | return function(id){ return cancel(id); };
25 | })();
26 |
27 | function resetTriggers(element){
28 | var triggers = element.__resizeTriggers__,
29 | expand = triggers.firstElementChild,
30 | contract = triggers.lastElementChild,
31 | expandChild = expand.firstElementChild;
32 | contract.scrollLeft = contract.scrollWidth;
33 | contract.scrollTop = contract.scrollHeight;
34 | expandChild.style.width = expand.offsetWidth + 1 + 'px';
35 | expandChild.style.height = expand.offsetHeight + 1 + 'px';
36 | expand.scrollLeft = expand.scrollWidth;
37 | expand.scrollTop = expand.scrollHeight;
38 | };
39 |
40 | function checkTriggers(element){
41 | return element.offsetWidth != element.__resizeLast__.width ||
42 | element.offsetHeight != element.__resizeLast__.height;
43 | }
44 |
45 | function scrollListener(e){
46 | var element = this;
47 | resetTriggers(this);
48 | if (this.__resizeRAF__) cancelFrame(this.__resizeRAF__);
49 | this.__resizeRAF__ = requestFrame(function(){
50 | if (checkTriggers(element)) {
51 | element.__resizeLast__.width = element.offsetWidth;
52 | element.__resizeLast__.height = element.offsetHeight;
53 | element.__resizeListeners__.forEach(function(fn){
54 | fn.call(element, e);
55 | });
56 | }
57 | });
58 | };
59 |
60 | /* Detect CSS Animations support to detect element display/re-attach */
61 | var animation = false,
62 | animationstring = 'animation',
63 | keyframeprefix = '',
64 | animationstartevent = 'animationstart',
65 | domPrefixes = 'Webkit Moz O ms'.split(' '),
66 | startEvents = 'webkitAnimationStart animationstart oAnimationStart MSAnimationStart'.split(' '),
67 | pfx = '';
68 | {
69 | var elm = document.createElement('fakeelement');
70 | if( elm.style.animationName !== undefined ) { animation = true; }
71 |
72 | if( animation === false ) {
73 | for( var i = 0; i < domPrefixes.length; i++ ) {
74 | if( elm.style[ domPrefixes[i] + 'AnimationName' ] !== undefined ) {
75 | pfx = domPrefixes[ i ];
76 | animationstring = pfx + 'Animation';
77 | keyframeprefix = '-' + pfx.toLowerCase() + '-';
78 | animationstartevent = startEvents[ i ];
79 | animation = true;
80 | break;
81 | }
82 | }
83 | }
84 | }
85 |
86 | var animationName = 'resizeanim';
87 | var animationKeyframes = '@' + keyframeprefix + 'keyframes ' + animationName + ' { from { opacity: 0; } to { opacity: 0; } } ';
88 | var animationStyle = keyframeprefix + 'animation: 1ms ' + animationName + '; ';
89 | }
90 |
91 | function createStyles() {
92 | if (!stylesCreated) {
93 | //opacity:0 works around a chrome bug https://code.google.com/p/chromium/issues/detail?id=286360
94 | var css = (animationKeyframes ? animationKeyframes : '') +
95 | '.resize-triggers { ' + (animationStyle ? animationStyle : '') + 'visibility: hidden; opacity: 0; } ' +
96 | '.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%; }',
97 | head = document.head || document.getElementsByTagName('head')[0],
98 | style = document.createElement('style');
99 |
100 | style.type = 'text/css';
101 | if (style.styleSheet) {
102 | style.styleSheet.cssText = css;
103 | } else {
104 | style.appendChild(document.createTextNode(css));
105 | }
106 |
107 | head.appendChild(style);
108 | stylesCreated = true;
109 | }
110 | }
111 |
112 | window.addResizeListener = function(element, fn){
113 | if (attachEvent) element.attachEvent('onresize', fn);
114 | else {
115 | if (!element.__resizeTriggers__) {
116 | if (getComputedStyle(element).position == 'static') element.style.position = 'relative';
117 | createStyles();
118 | element.__resizeLast__ = {};
119 | element.__resizeListeners__ = [];
120 | (element.__resizeTriggers__ = document.createElement('div')).className = 'resize-triggers';
121 | element.__resizeTriggers__.innerHTML = '' +
122 | '';
123 | element.appendChild(element.__resizeTriggers__);
124 | resetTriggers(element);
125 | element.addEventListener('scroll', scrollListener, true);
126 |
127 | /* Listen for a css animation to detect element display/re-attach */
128 | animationstartevent && element.__resizeTriggers__.addEventListener(animationstartevent, function(e) {
129 | if(e.animationName == animationName)
130 | resetTriggers(element);
131 | });
132 | }
133 | element.__resizeListeners__.push(fn);
134 | }
135 | };
136 |
137 | window.removeResizeListener = function(element, fn){
138 | if (attachEvent) element.detachEvent('onresize', fn);
139 | else {
140 | element.__resizeListeners__.splice(element.__resizeListeners__.indexOf(fn), 1);
141 | if (!element.__resizeListeners__.length) {
142 | element.removeEventListener('scroll', scrollListener);
143 | element.__resizeTriggers__ = !element.removeChild(element.__resizeTriggers__);
144 | }
145 | }
146 | }
147 | })();
--------------------------------------------------------------------------------
/jquery.resize.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Detect Element Resize Plugin for jQuery
3 | *
4 | * https://github.com/sdecima/javascript-detect-element-resize
5 | * Sebastian Decima
6 | *
7 | * version: 0.5.3
8 | **/
9 |
10 | (function ( $ ) {
11 | var attachEvent = document.attachEvent,
12 | stylesCreated = false;
13 |
14 | var jQuery_resize = $.fn.resize;
15 |
16 | $.fn.resize = function(callback) {
17 | return this.each(function() {
18 | if(this == window)
19 | jQuery_resize.call(jQuery(this), callback);
20 | else
21 | addResizeListener(this, callback);
22 | });
23 | }
24 |
25 | $.fn.removeResize = function(callback) {
26 | return this.each(function() {
27 | removeResizeListener(this, callback);
28 | });
29 | }
30 |
31 | if (!attachEvent) {
32 | var requestFrame = (function(){
33 | var raf = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame ||
34 | function(fn){ return window.setTimeout(fn, 20); };
35 | return function(fn){ return raf(fn); };
36 | })();
37 |
38 | var cancelFrame = (function(){
39 | var cancel = window.cancelAnimationFrame || window.mozCancelAnimationFrame || window.webkitCancelAnimationFrame ||
40 | window.clearTimeout;
41 | return function(id){ return cancel(id); };
42 | })();
43 |
44 | function resetTriggers(element){
45 | var triggers = element.__resizeTriggers__,
46 | expand = triggers.firstElementChild,
47 | contract = triggers.lastElementChild,
48 | expandChild = expand.firstElementChild;
49 | contract.scrollLeft = contract.scrollWidth;
50 | contract.scrollTop = contract.scrollHeight;
51 | expandChild.style.width = expand.offsetWidth + 1 + 'px';
52 | expandChild.style.height = expand.offsetHeight + 1 + 'px';
53 | expand.scrollLeft = expand.scrollWidth;
54 | expand.scrollTop = expand.scrollHeight;
55 | };
56 |
57 | function checkTriggers(element){
58 | return element.offsetWidth != element.__resizeLast__.width ||
59 | element.offsetHeight != element.__resizeLast__.height;
60 | }
61 |
62 | function scrollListener(e){
63 | var element = this;
64 | resetTriggers(this);
65 | if (this.__resizeRAF__) cancelFrame(this.__resizeRAF__);
66 | this.__resizeRAF__ = requestFrame(function(){
67 | if (checkTriggers(element)) {
68 | element.__resizeLast__.width = element.offsetWidth;
69 | element.__resizeLast__.height = element.offsetHeight;
70 | element.__resizeListeners__.forEach(function(fn){
71 | fn.call(element, e);
72 | });
73 | }
74 | });
75 | };
76 |
77 | /* Detect CSS Animations support to detect element display/re-attach */
78 | var animation = false,
79 | animationstring = 'animation',
80 | keyframeprefix = '',
81 | animationstartevent = 'animationstart',
82 | domPrefixes = 'Webkit Moz O ms'.split(' '),
83 | startEvents = 'webkitAnimationStart animationstart oAnimationStart MSAnimationStart'.split(' '),
84 | pfx = '';
85 | {
86 | var elm = document.createElement('fakeelement');
87 | if( elm.style.animationName !== undefined ) { animation = true; }
88 |
89 | if( animation === false ) {
90 | for( var i = 0; i < domPrefixes.length; i++ ) {
91 | if( elm.style[ domPrefixes[i] + 'AnimationName' ] !== undefined ) {
92 | pfx = domPrefixes[ i ];
93 | animationstring = pfx + 'Animation';
94 | keyframeprefix = '-' + pfx.toLowerCase() + '-';
95 | animationstartevent = startEvents[ i ];
96 | animation = true;
97 | break;
98 | }
99 | }
100 | }
101 | }
102 |
103 | var animationName = 'resizeanim';
104 | var animationKeyframes = '@' + keyframeprefix + 'keyframes ' + animationName + ' { from { opacity: 0; } to { opacity: 0; } } ';
105 | var animationStyle = keyframeprefix + 'animation: 1ms ' + animationName + '; ';
106 | }
107 |
108 | function createStyles() {
109 | if (!stylesCreated) {
110 | //opacity:0 works around a chrome bug https://code.google.com/p/chromium/issues/detail?id=286360
111 | var css = (animationKeyframes ? animationKeyframes : '') +
112 | '.resize-triggers { ' + (animationStyle ? animationStyle : '') + 'visibility: hidden; opacity: 0; } ' +
113 | '.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%; }',
114 | head = document.head || document.getElementsByTagName('head')[0],
115 | style = document.createElement('style');
116 |
117 | style.type = 'text/css';
118 | if (style.styleSheet) {
119 | style.styleSheet.cssText = css;
120 | } else {
121 | style.appendChild(document.createTextNode(css));
122 | }
123 |
124 | head.appendChild(style);
125 | stylesCreated = true;
126 | }
127 | }
128 |
129 | window.addResizeListener = function(element, fn){
130 | if (attachEvent) element.attachEvent('onresize', fn);
131 | else {
132 | if (!element.__resizeTriggers__) {
133 | if (getComputedStyle(element).position == 'static') element.style.position = 'relative';
134 | createStyles();
135 | element.__resizeLast__ = {};
136 | element.__resizeListeners__ = [];
137 | (element.__resizeTriggers__ = document.createElement('div')).className = 'resize-triggers';
138 | element.__resizeTriggers__.innerHTML = '' +
139 | '';
140 | element.appendChild(element.__resizeTriggers__);
141 | resetTriggers(element);
142 | element.addEventListener('scroll', scrollListener, true);
143 |
144 | /* Listen for a css animation to detect element display/re-attach */
145 | animationstartevent && element.__resizeTriggers__.addEventListener(animationstartevent, function(e) {
146 | if(e.animationName == animationName)
147 | resetTriggers(element);
148 | });
149 | }
150 | element.__resizeListeners__.push(fn);
151 | }
152 | };
153 |
154 | window.removeResizeListener = function(element, fn){
155 | if (attachEvent) element.detachEvent('onresize', fn);
156 | else {
157 | element.__resizeListeners__.splice(element.__resizeListeners__.indexOf(fn), 1);
158 | if (!element.__resizeListeners__.length) {
159 | element.removeEventListener('scroll', scrollListener);
160 | element.__resizeTriggers__ = !element.removeChild(element.__resizeTriggers__);
161 | }
162 | }
163 | }
164 | }( jQuery ));
--------------------------------------------------------------------------------