ba42a800581efb0c4f61ca41596ce2f76ea5f4aa
[usecase-ui.git] /
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 = '<div class="expand-trigger"><div></div></div>' +
139                                                                                                                                                                                 '<div class="contract-trigger"></div>';
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 ));