1 /*! |
|
2 * jQuery resize event - v1.1 - 3/14/2010 |
|
3 * http://benalman.com/projects/jquery-resize-plugin/ |
|
4 * |
|
5 * Copyright (c) 2010 "Cowboy" Ben Alman |
|
6 * Dual licensed under the MIT and GPL licenses. |
|
7 * http://benalman.com/about/license/ |
|
8 */ |
|
9 |
|
10 // Script: jQuery resize event |
|
11 // |
|
12 // *Version: 1.1, Last updated: 3/14/2010* |
|
13 // |
|
14 // Project Home - http://benalman.com/projects/jquery-resize-plugin/ |
|
15 // GitHub - http://github.com/cowboy/jquery-resize/ |
|
16 // Source - http://github.com/cowboy/jquery-resize/raw/master/jquery.ba-resize.js |
|
17 // (Minified) - http://github.com/cowboy/jquery-resize/raw/master/jquery.ba-resize.min.js (1.0kb) |
|
18 // |
|
19 // About: License |
|
20 // |
|
21 // Copyright (c) 2010 "Cowboy" Ben Alman, |
|
22 // Dual licensed under the MIT and GPL licenses. |
|
23 // http://benalman.com/about/license/ |
|
24 // |
|
25 // About: Examples |
|
26 // |
|
27 // This working example, complete with fully commented code, illustrates a few |
|
28 // ways in which this plugin can be used. |
|
29 // |
|
30 // resize event - http://benalman.com/code/projects/jquery-resize/examples/resize/ |
|
31 // |
|
32 // About: Support and Testing |
|
33 // |
|
34 // Information about what version or versions of jQuery this plugin has been |
|
35 // tested with, what browsers it has been tested in, and where the unit tests |
|
36 // reside (so you can test it yourself). |
|
37 // |
|
38 // jQuery Versions - 1.3.2, 1.4.1, 1.4.2 |
|
39 // Browsers Tested - Internet Explorer 6-8, Firefox 2-3.6, Safari 3-4, Chrome, Opera 9.6-10.1. |
|
40 // Unit Tests - http://benalman.com/code/projects/jquery-resize/unit/ |
|
41 // |
|
42 // About: Release History |
|
43 // |
|
44 // 1.1 - (3/14/2010) Fixed a minor bug that was causing the event to trigger |
|
45 // immediately after bind in some circumstances. Also changed $.fn.data |
|
46 // to $.data to improve performance. |
|
47 // 1.0 - (2/10/2010) Initial release |
|
48 |
|
49 (function ($, window, undefined) { |
|
50 '$:nomunge'; // Used by YUI compressor. |
|
51 |
|
52 // A jQuery object containing all non-window elements to which the resize |
|
53 // event is bound. |
|
54 var elems = $([]), |
|
55 |
|
56 // Extend $.resize if it already exists, otherwise create it. |
|
57 jq_resize = $.resize = $.extend($.resize, {}), |
|
58 |
|
59 timeout_id, |
|
60 |
|
61 // Reused strings. |
|
62 str_setTimeout = 'setTimeout', |
|
63 str_resize = 'resize', |
|
64 str_data = str_resize + '-special-event', |
|
65 str_delay = 'delay', |
|
66 str_throttle = 'throttleWindow'; |
|
67 |
|
68 // Property: jQuery.resize.delay |
|
69 // |
|
70 // The numeric interval (in milliseconds) at which the resize event polling |
|
71 // loop executes. Defaults to 250. |
|
72 |
|
73 jq_resize[ str_delay ] = 250; |
|
74 |
|
75 // Property: jQuery.resize.throttleWindow |
|
76 // |
|
77 // Throttle the native window object resize event to fire no more than once |
|
78 // every <jQuery.resize.delay> milliseconds. Defaults to true. |
|
79 // |
|
80 // Because the window object has its own resize event, it doesn't need to be |
|
81 // provided by this plugin, and its execution can be left entirely up to the |
|
82 // browser. However, since certain browsers fire the resize event continuously |
|
83 // while others do not, enabling this will throttle the window resize event, |
|
84 // making event behavior consistent across all elements in all browsers. |
|
85 // |
|
86 // While setting this property to false will disable window object resize |
|
87 // event throttling, please note that this property must be changed before any |
|
88 // window object resize event callbacks are bound. |
|
89 |
|
90 jq_resize[ str_throttle ] = true; |
|
91 |
|
92 // Event: resize event |
|
93 // |
|
94 // Fired when an element's width or height changes. Because browsers only |
|
95 // provide this event for the window element, for other elements a polling |
|
96 // loop is initialized, running every <jQuery.resize.delay> milliseconds |
|
97 // to see if elements' dimensions have changed. You may bind with either |
|
98 // .resize( fn ) or .bind( "resize", fn ), and unbind with .unbind( "resize" ). |
|
99 // |
|
100 // Usage: |
|
101 // |
|
102 // > jQuery('selector').bind( 'resize', function(e) { |
|
103 // > // element's width or height has changed! |
|
104 // > ... |
|
105 // > }); |
|
106 // |
|
107 // Additional Notes: |
|
108 // |
|
109 // * The polling loop is not created until at least one callback is actually |
|
110 // bound to the 'resize' event, and this single polling loop is shared |
|
111 // across all elements. |
|
112 // |
|
113 // Double firing issue in jQuery 1.3.2: |
|
114 // |
|
115 // While this plugin works in jQuery 1.3.2, if an element's event callbacks |
|
116 // are manually triggered via .trigger( 'resize' ) or .resize() those |
|
117 // callbacks may double-fire, due to limitations in the jQuery 1.3.2 special |
|
118 // events system. This is not an issue when using jQuery 1.4+. |
|
119 // |
|
120 // > // While this works in jQuery 1.4+ |
|
121 // > $(elem).css({ width: new_w, height: new_h }).resize(); |
|
122 // > |
|
123 // > // In jQuery 1.3.2, you need to do this: |
|
124 // > var elem = $(elem); |
|
125 // > elem.css({ width: new_w, height: new_h }); |
|
126 // > elem.data( 'resize-special-event', { width: elem.width(), height: elem.height() } ); |
|
127 // > elem.resize(); |
|
128 |
|
129 $.event.special[ str_resize ] = { |
|
130 |
|
131 // Called only when the first 'resize' event callback is bound per element. |
|
132 setup: function () { |
|
133 // Since window has its own native 'resize' event, return false so that |
|
134 // jQuery will bind the event using DOM methods. Since only 'window' |
|
135 // objects have a .setTimeout method, this should be a sufficient test. |
|
136 // Unless, of course, we're throttling the 'resize' event for window. |
|
137 if (!jq_resize[ str_throttle ] && this[ str_setTimeout ]) { |
|
138 return false; |
|
139 } |
|
140 |
|
141 var elem = $(this); |
|
142 |
|
143 // Add this element to the list of internal elements to monitor. |
|
144 elems = elems.add(elem); |
|
145 |
|
146 // Initialize data store on the element. |
|
147 $.data(this, str_data, { w: elem.width(), h: elem.height() }); |
|
148 |
|
149 // If this is the first element added, start the polling loop. |
|
150 if (elems.length === 1) { |
|
151 loopy(); |
|
152 } |
|
153 }, |
|
154 |
|
155 // Called only when the last 'resize' event callback is unbound per element. |
|
156 teardown: function () { |
|
157 // Since window has its own native 'resize' event, return false so that |
|
158 // jQuery will unbind the event using DOM methods. Since only 'window' |
|
159 // objects have a .setTimeout method, this should be a sufficient test. |
|
160 // Unless, of course, we're throttling the 'resize' event for window. |
|
161 if (!jq_resize[ str_throttle ] && this[ str_setTimeout ]) { |
|
162 return false; |
|
163 } |
|
164 |
|
165 var elem = $(this); |
|
166 |
|
167 // Remove this element from the list of internal elements to monitor. |
|
168 elems = elems.not(elem); |
|
169 |
|
170 // Remove any data stored on the element. |
|
171 elem.removeData(str_data); |
|
172 |
|
173 // If this is the last element removed, stop the polling loop. |
|
174 if (!elems.length) { |
|
175 clearTimeout(timeout_id); |
|
176 } |
|
177 }, |
|
178 |
|
179 // Called every time a 'resize' event callback is bound per element (new in |
|
180 // jQuery 1.4). |
|
181 add: function (handleObj) { |
|
182 // Since window has its own native 'resize' event, return false so that |
|
183 // jQuery doesn't modify the event object. Unless, of course, we're |
|
184 // throttling the 'resize' event for window. |
|
185 if (!jq_resize[ str_throttle ] && this[ str_setTimeout ]) { |
|
186 return false; |
|
187 } |
|
188 |
|
189 var old_handler; |
|
190 |
|
191 // The new_handler function is executed every time the event is triggered. |
|
192 // This is used to update the internal element data store with the width |
|
193 // and height when the event is triggered manually, to avoid double-firing |
|
194 // of the event callback. See the "Double firing issue in jQuery 1.3.2" |
|
195 // comments above for more information. |
|
196 |
|
197 function new_handler(e, w, h) { |
|
198 var elem = $(this), |
|
199 data = $.data(this, str_data); |
|
200 |
|
201 // If called from the polling loop, w and h will be passed in as |
|
202 // arguments. If called manually, via .trigger( 'resize' ) or .resize(), |
|
203 // those values will need to be computed. |
|
204 data.w = w !== undefined ? w : elem.width(); |
|
205 data.h = h !== undefined ? h : elem.height(); |
|
206 |
|
207 old_handler.apply(this, arguments); |
|
208 }; |
|
209 |
|
210 // This may seem a little complicated, but it normalizes the special event |
|
211 // .add method between jQuery 1.4/1.4.1 and 1.4.2+ |
|
212 if ($.isFunction(handleObj)) { |
|
213 // 1.4, 1.4.1 |
|
214 old_handler = handleObj; |
|
215 return new_handler; |
|
216 } else { |
|
217 // 1.4.2+ |
|
218 old_handler = handleObj.handler; |
|
219 handleObj.handler = new_handler; |
|
220 } |
|
221 } |
|
222 |
|
223 }; |
|
224 |
|
225 function loopy() { |
|
226 |
|
227 // Start the polling loop, asynchronously. |
|
228 timeout_id = window[ str_setTimeout ](function () { |
|
229 |
|
230 // Iterate over all elements to which the 'resize' event is bound. |
|
231 elems.each(function () { |
|
232 var elem = $(this), |
|
233 width = elem.width(), |
|
234 height = elem.height(), |
|
235 data = $.data(this, str_data); |
|
236 |
|
237 // If element size has changed since the last time, update the element |
|
238 // data store and trigger the 'resize' event. |
|
239 if (width !== data.w || height !== data.h) { |
|
240 elem.trigger(str_resize, [ data.w = width, data.h = height ]); |
|
241 } |
|
242 |
|
243 }); |
|
244 |
|
245 // Loop. |
|
246 loopy(); |
|
247 |
|
248 }, jq_resize[ str_delay ]); |
|
249 |
|
250 }; |
|
251 |
|
252 })(jQuery, this); |
|