44* https://github.com/sdecima/javascript-detect-element-resize
55* Sebastian Decima
66*
7- * version: 0.2
7+ * version: 0.3
88**/
99
10- function addFlowListener ( element , type , fn ) {
11- var flow = type == 'over' ;
12- element . addEventListener ( 'OverflowEvent' in window ? 'overflowchanged' : type + 'flow' , function ( e ) {
13- if ( e . type == ( type + 'flow' ) ||
14- ( ( e . orient == 0 && e . horizontalOverflow == flow ) ||
15- ( e . orient == 1 && e . verticalOverflow == flow ) ||
16- ( e . orient == 2 && e . horizontalOverflow == flow && e . verticalOverflow == flow ) ) ) {
17- e . flow = type ;
18- return fn . call ( this , e ) ;
10+ ( function ( $ ) {
11+ function addFlowListener ( element , type , fn ) {
12+ var flow = type == 'over' ;
13+ element . addEventListener ( 'OverflowEvent' in window ? 'overflowchanged' : type + 'flow' , function ( e ) {
14+ if ( e . type == ( type + 'flow' ) ||
15+ ( ( e . orient == 0 && e . horizontalOverflow == flow ) ||
16+ ( e . orient == 1 && e . verticalOverflow == flow ) ||
17+ ( e . orient == 2 && e . horizontalOverflow == flow && e . verticalOverflow == flow ) ) ) {
18+ e . flow = type ;
19+ return fn . call ( this , e ) ;
20+ }
21+ } , false ) ;
22+ } ;
23+
24+ function newResizeMutationObserverCallback ( element , fn ) {
25+ var oldWidth = element . clientWidth ,
26+ oldHeight = element . clientHeight ;
27+ return function ( ) {
28+ if ( oldWidth != element . clientWidth || oldHeight != element . clientHeight ) {
29+ oldWidth = element . clientWidth ;
30+ oldHeight = element . clientHeight ;
31+ fn . call ( element ) ;
32+ }
1933 }
20- } , false ) ;
21- } ;
34+ }
35+
36+ function addResizeMutationObserver ( element , fn ) {
37+ var observer = new MutationObserver ( newResizeMutationObserverCallback ( element , fn ) ) ;
38+ observer . observe ( element , {
39+ attributes : true ,
40+ subtree : true ,
41+ attributeFilter : [ 'style' ]
42+ } ) ;
43+ return observer ;
44+ } ;
2245
23- function fireEvent ( element , type , data , options ) {
24- var options = options || { } ,
25- event = document . createEvent ( 'Event' ) ;
26- event . initEvent ( type , 'bubbles' in options ? options . bubbles : true , 'cancelable' in options ? options . cancelable : true ) ;
27- for ( var z in data ) event [ z ] = data [ z ] ;
28- element . dispatchEvent ( event ) ;
29- } ;
46+ function fireEvent ( element , type , data , options ) {
47+ var options = options || { } ,
48+ event = document . createEvent ( 'Event' ) ;
49+ event . initEvent ( type , 'bubbles' in options ? options . bubbles : true , 'cancelable' in options ? options . cancelable : true ) ;
50+ for ( var z in data ) event [ z ] = data [ z ] ;
51+ element . dispatchEvent ( event ) ;
52+ } ;
3053
31- function addResizeListener ( element , fn ) {
32- var resize = 'onresize' in element ;
33- if ( ! resize && ! element . _resizeSensor ) {
34- var sensor_style = 'position: absolute; top: 0; left: 0; width: 100%; height: 100%; overflow: hidden; z-index: -1;' ;
35- var sensor = element . _resizeSensor = document . createElement ( 'div' ) ;
36- sensor . className = 'resize-sensor' ;
37- //sensor.style = ;
38- sensor . innerHTML = '<div class="resize-overflow" style="' + sensor_style
39- + '"><div></div></div><div class="resize-underflow" style="' + sensor_style
40- + '"><div></div></div>' ;
41-
42- var x = 0 , y = 0 ,
43- first = sensor . firstElementChild . firstChild ,
44- last = sensor . lastElementChild . firstChild ,
45- matchFlow = function ( event ) {
46- var change = false ,
47- width = element . offsetWidth ;
48- if ( x != width ) {
49- first . style . width = width - 1 + 'px' ;
50- last . style . width = width + 1 + 'px' ;
51- change = true ;
52- x = width ;
53- }
54- var height = element . offsetHeight ;
55- if ( y != height ) {
56- first . style . height = height - 1 + 'px' ;
57- last . style . height = height + 1 + 'px' ;
58- change = true ;
59- y = height ;
54+ function addResizeListener ( element , fn ) {
55+ if ( 'MutationObserver' in window ) {
56+ fn . _mutationObserver = addResizeMutationObserver ( element , fn ) ;
57+ var events = element . _mutationObservers || ( element . _mutationObservers = [ ] ) ;
58+ if ( indexOf . call ( events , fn ) == - 1 ) events . push ( fn ) ;
59+ } else {
60+ var resize = 'onresize' in element ;
61+ if ( ! resize && ! element . _resizeSensor ) {
62+ var sensor_style = 'position: absolute; top: 0; left: 0; width: 100%; height: 100%; overflow: hidden; z-index: -1;' ;
63+ var sensor = element . _resizeSensor = document . createElement ( 'div' ) ;
64+ sensor . className = 'resize-sensor' ;
65+ sensor . innerHTML = '<div class="resize-overflow" style="' + sensor_style
66+ + '"><div></div></div><div class="resize-underflow" style="' + sensor_style
67+ + '"><div></div></div>' ;
68+
69+ var x = 0 , y = 0 ,
70+ first = sensor . firstElementChild . firstChild ,
71+ last = sensor . lastElementChild . firstChild ,
72+ matchFlow = function ( event ) {
73+ var change = false ,
74+ width = element . offsetWidth ;
75+ if ( x != width ) {
76+ first . style . width = width - 1 + 'px' ;
77+ last . style . width = width + 1 + 'px' ;
78+ change = true ;
79+ x = width ;
80+ }
81+ var height = element . offsetHeight ;
82+ if ( y != height ) {
83+ first . style . height = height - 1 + 'px' ;
84+ last . style . height = height + 1 + 'px' ;
85+ change = true ;
86+ y = height ;
87+ }
88+ if ( change && event . currentTarget != element ) fireEvent ( element , 'resize' ) ;
89+ } ;
90+
91+ if ( getComputedStyle ( element ) . position == 'static' ) {
92+ element . style . position = 'relative' ;
93+ element . _resizeSensor . _resetPosition = true ;
6094 }
61- if ( change && event . currentTarget != element ) fireEvent ( element , 'resize' ) ;
95+ addFlowListener ( sensor , 'over' , matchFlow ) ;
96+ addFlowListener ( sensor , 'under' , matchFlow ) ;
97+ addFlowListener ( sensor . firstElementChild , 'over' , matchFlow ) ;
98+ addFlowListener ( sensor . lastElementChild , 'under' , matchFlow ) ;
99+ element . appendChild ( sensor ) ;
100+ matchFlow ( { } ) ;
101+ }
102+ var events = element . _flowEvents || ( element . _flowEvents = [ ] ) ;
103+ if ( indexOf . call ( events , fn ) == - 1 ) events . push ( fn ) ;
104+ if ( ! resize ) element . addEventListener ( 'resize' , fn , false ) ;
105+ element . onresize = function ( e ) {
106+ forEach . call ( events , function ( fn ) {
107+ fn . call ( element , e ) ;
108+ } ) ;
62109 } ;
63-
64- if ( getComputedStyle ( element ) . position == 'static' ) {
65- element . style . position = 'relative' ;
66- element . _resizeSensor . _resetPosition = true ;
67110 }
68- addFlowListener ( sensor , 'over' , matchFlow ) ;
69- addFlowListener ( sensor , 'under' , matchFlow ) ;
70- addFlowListener ( sensor . firstElementChild , 'over' , matchFlow ) ;
71- addFlowListener ( sensor . lastElementChild , 'under' , matchFlow ) ;
72- element . appendChild ( sensor ) ;
73- matchFlow ( { } ) ;
74- }
75- var events = element . _flowEvents || ( element . _flowEvents = [ ] ) ;
76- if ( indexOf . call ( events , fn ) == - 1 ) events . push ( fn ) ;
77- if ( ! resize ) element . addEventListener ( 'resize' , fn , false ) ;
78- element . onresize = function ( e ) {
79- forEach . call ( events , function ( fn ) {
80- fn . call ( element , e ) ;
81- } ) ;
82111 } ;
83- } ;
84112
85- function removeResizeListener ( element , fn ) {
86- var index = indexOf . call ( element . _flowEvents , fn ) ;
87- if ( index > - 1 ) element . _flowEvents . splice ( index , 1 ) ;
88- if ( ! element . _flowEvents . length ) {
89- var sensor = element . _resizeSensor ;
90- if ( sensor ) {
91- element . removeChild ( sensor ) ;
92- if ( sensor . _resetPosition ) element . style . position = 'static' ;
93- delete element . _resizeSensor ;
113+ function removeResizeListener ( element , fn ) {
114+ if ( 'MutationObserver' in window ) {
115+ var index = indexOf . call ( element . _mutationObservers , fn ) ;
116+ if ( index > - 1 ) {
117+ var observer = element . _mutationObservers [ index ] . _mutationObserver ;
118+ element . _mutationObservers . splice ( index , 1 ) ;
119+ observer . disconnect ( ) ;
120+ }
121+ } else {
122+ var resize = 'onresize' in element ;
123+ var index = indexOf . call ( element . _flowEvents , fn ) ;
124+ if ( index > - 1 ) element . _flowEvents . splice ( index , 1 ) ;
125+ if ( ! element . _flowEvents . length ) {
126+ var sensor = element . _resizeSensor ;
127+ if ( sensor ) {
128+ element . removeChild ( sensor ) ;
129+ if ( sensor . _resetPosition ) element . style . position = 'static' ;
130+ try { delete element . _resizeSensor ; } catch ( e ) { /* delete arrays not supported on IE 7 and below */ }
131+ }
132+ if ( resize ) element . onresize = null ;
133+ try { delete element . _flowEvents ; } catch ( e ) { /* delete arrays not supported on IE 7 and below */ }
134+ }
135+ if ( ! resize ) element . removeEventListener ( 'resize' , fn ) ;
94136 }
95- if ( 'onresize' in element ) element . onresize = null ;
96- delete element . _flowEvents ;
97- }
98- element . removeEventListener ( 'resize' , fn ) ;
99- } ;
137+ } ;
100138
101- /* Array.indexOf for IE < 9 */
102- var indexOf = function ( needle ) {
103- if ( typeof Array . prototype . indexOf === 'function' ) {
104- indexOf = Array . prototype . indexOf ;
105- } else {
106- indexOf = function ( needle ) {
107- var i = - 1 , index = - 1 ;
139+ /* Array.indexOf for IE < 9 */
140+ var indexOf = function ( needle ) {
141+ if ( typeof Array . prototype . indexOf === 'function' ) {
142+ indexOf = Array . prototype . indexOf ;
143+ } else {
144+ indexOf = function ( needle ) {
145+ var i = - 1 , index = - 1 ;
108146
109- for ( i = 0 ; i < this . length ; i ++ ) {
110- if ( this [ i ] === needle ) {
111- index = i ;
112- break ;
113- }
114- }
147+ for ( i = 0 ; i < this . length ; i ++ ) {
148+ if ( this [ i ] === needle ) {
149+ index = i ;
150+ break ;
151+ }
152+ }
115153
116- return index ;
117- } ;
118- }
154+ return index ;
155+ } ;
156+ }
119157
120- return indexOf . call ( this , needle ) ;
121- } ;
158+ return indexOf . call ( this , needle ) ;
159+ } ;
122160
123- /* Array.forEach for IE < 9 */
124- var forEach = function ( action , that ) {
125- if ( typeof Array . prototype . forEach === 'function' ) {
126- forEach = Array . prototype . forEach ;
127- } else {
128- forEach = function ( action , that ) {
129- for ( var i = 0 , n = this . length ; i < n ; i ++ )
130- if ( i in this )
131- action . call ( that , this [ i ] , i , this ) ;
132- } ;
133- }
161+ /* Array.forEach for IE < 9 */
162+ var forEach = function ( action , that ) {
163+ if ( typeof Array . prototype . forEach === 'function' ) {
164+ forEach = Array . prototype . forEach ;
165+ } else {
166+ forEach = function ( action , that ) {
167+ for ( var i = 0 , n = this . length ; i < n ; i ++ )
168+ if ( i in this )
169+ action . call ( that , this [ i ] , i , this ) ;
170+ } ;
171+ }
134172
135- return forEach . call ( this , action , that ) ;
136- } ;
173+ return forEach . call ( this , action , that ) ;
174+ } ;
175+
176+ window . addResizeListener = addResizeListener ;
177+ window . removeResizeListener = removeResizeListener ;
178+ } ( ) ) ;
0 commit comments