fixed offset(coordinates) returns null when no matching elements in jQuery object...
[jquery.git] / test / unit / offset.js
1 module("offset");
2
3 testoffset("absolute", function( jQuery ) {
4         expect(144);
5         
6         // get offset tests
7         var tests = [
8                 { id: '#absolute-1',     top:  1, left:  1 }, 
9                 { id: '#absolute-1-1',   top:  5, left:  5 },
10                 { id: '#absolute-1-1-1', top:  9, left:  9 },
11                 { id: '#absolute-2',     top: 20, left: 20 }
12         ];
13         jQuery.each( tests, function() {
14                 equals( jQuery( this.id ).offset().top,  this.top,  "jQuery('" + this.id + "').offset().top" );
15                 equals( jQuery( this.id ).offset().left, this.left, "jQuery('" + this.id + "').offset().left" );
16         });
17         
18         
19         // get position
20         tests = [
21                 { id: '#absolute-1',     top:  0, left:  0 },
22                 { id: '#absolute-1-1',   top:  1, left:  1 },
23                 { id: '#absolute-1-1-1', top:  1, left:  1 },
24                 { id: '#absolute-2',     top: 19, left: 19 }
25         ];
26         jQuery.each( tests, function() {
27                 equals( jQuery( this.id ).position().top,  this.top,  "jQuery('" + this.id + "').position().top" );
28                 equals( jQuery( this.id ).position().left, this.left, "jQuery('" + this.id + "').position().left" );
29         });
30         
31         
32         // set offset
33         tests = [
34                 { id: '#absolute-2',     top: 30, left: 30 },
35                 { id: '#absolute-2',     top: 10, left: 10 },
36                 { id: '#absolute-2',     top: -1, left: -1 },
37                 { id: '#absolute-2',     top: 19, left: 19 },
38                 { id: '#absolute-1-1-1', top: 15, left: 15 },
39                 { id: '#absolute-1-1-1', top:  5, left:  5 },
40                 { id: '#absolute-1-1-1', top: -1, left: -1 },
41                 { id: '#absolute-1-1-1', top:  9, left:  9 },
42                 { id: '#absolute-1-1',   top: 10, left: 10 },
43                 { id: '#absolute-1-1',   top:  0, left:  0 },
44                 { id: '#absolute-1-1',   top: -1, left: -1 },
45                 { id: '#absolute-1-1',   top:  5, left:  5 },
46                 { id: '#absolute-1',     top:  2, left:  2 },
47                 { id: '#absolute-1',     top:  0, left:  0 },
48                 { id: '#absolute-1',     top: -1, left: -1 },
49                 { id: '#absolute-1',     top:  1, left:  1 }
50         ];
51         jQuery.each( tests, function() {
52                 jQuery( this.id ).offset({ top: this.top, left: this.left });
53                 equals( jQuery( this.id ).offset().top,  this.top,  "jQuery('" + this.id + "').offset({ top: "  + this.top  + " })" );
54                 equals( jQuery( this.id ).offset().left, this.left, "jQuery('" + this.id + "').offset({ left: " + this.left + " })" );
55                 
56                 var top = this.top, left = this.left;
57                 
58                 jQuery( this.id ).offset(function(i, val){
59                         equals( val.top, top, "Verify incoming top position." );
60                         equals( val.left, left, "Verify incoming top position." );
61                         return { top: top + 1, left: left + 1 };
62                 });
63                 equals( jQuery( this.id ).offset().top,  this.top + 1,  "jQuery('" + this.id + "').offset({ top: "  + this.top  + " })" );
64                 equals( jQuery( this.id ).offset().left, this.left + 1, "jQuery('" + this.id + "').offset({ left: " + this.left + " })" );
65                 
66                 jQuery( this.id ).offset({ top: this.top, left: this.left, using: function( props ) {
67                         jQuery( this ).css({
68                                 top:  props.top  + 1,
69                                 left: props.left + 1
70                         });
71                 }});
72                 equals( jQuery( this.id ).offset().top,  this.top  + 1, "jQuery('" + this.id + "').offset({ top: "  + (this.top  + 1) + ", using: fn })" );
73                 equals( jQuery( this.id ).offset().left, this.left + 1, "jQuery('" + this.id + "').offset({ left: " + (this.left + 1) + ", using: fn })" );
74         });
75 });
76
77 testoffset("relative", function( jQuery ) {
78         expect(60);
79         
80         // IE is collapsing the top margin of 1px
81         var ie = jQuery.browser.msie && parseInt( jQuery.browser.version ) < 8;
82         
83         // get offset
84         var tests = [
85                 { id: '#relative-1',   top: ie ?   6 :   7, left:  7 },
86                 { id: '#relative-1-1', top: ie ?  13 :  15, left: 15 },
87                 { id: '#relative-2',   top: ie ? 141 : 142, left: 27 }
88         ];
89         jQuery.each( tests, function() {
90                 equals( jQuery( this.id ).offset().top,  this.top,  "jQuery('" + this.id + "').offset().top" );
91                 equals( jQuery( this.id ).offset().left, this.left, "jQuery('" + this.id + "').offset().left" );
92         });
93         
94         
95         // get position
96         tests = [
97                 { id: '#relative-1',   top: ie ?   5 :   6, left:  6 },
98                 { id: '#relative-1-1', top: ie ?   4 :   5, left:  5 },
99                 { id: '#relative-2',   top: ie ? 140 : 141, left: 26 }
100         ];
101         jQuery.each( tests, function() {
102                 equals( jQuery( this.id ).position().top,  this.top,  "jQuery('" + this.id + "').position().top" );
103                 equals( jQuery( this.id ).position().left, this.left, "jQuery('" + this.id + "').position().left" );
104         });
105         
106         
107         // set offset
108         tests = [
109                 { id: '#relative-2',   top: 200, left:  50 },
110                 { id: '#relative-2',   top: 100, left:  10 },
111                 { id: '#relative-2',   top:  -5, left:  -5 },
112                 { id: '#relative-2',   top: 142, left:  27 },
113                 { id: '#relative-1-1', top: 100, left: 100 },
114                 { id: '#relative-1-1', top:   5, left:   5 },
115                 { id: '#relative-1-1', top:  -1, left:  -1 },
116                 { id: '#relative-1-1', top:  15, left:  15 },
117                 { id: '#relative-1',   top: 100, left: 100 },
118                 { id: '#relative-1',   top:   0, left:   0 },
119                 { id: '#relative-1',   top:  -1, left:  -1 },
120                 { id: '#relative-1',   top:   7, left:   7 }
121         ];
122         jQuery.each( tests, function() {
123                 jQuery( this.id ).offset({ top: this.top, left: this.left });
124                 equals( jQuery( this.id ).offset().top,  this.top,  "jQuery('" + this.id + "').offset({ top: "  + this.top  + " })" );
125                 equals( jQuery( this.id ).offset().left, this.left, "jQuery('" + this.id + "').offset({ left: " + this.left + " })" );
126                 
127                 jQuery( this.id ).offset({ top: this.top, left: this.left, using: function( props ) {
128                         jQuery( this ).css({
129                                 top:  props.top  + 1,
130                                 left: props.left + 1
131                         });
132                 }});
133                 equals( jQuery( this.id ).offset().top,  this.top  + 1, "jQuery('" + this.id + "').offset({ top: "  + (this.top  + 1) + ", using: fn })" );
134                 equals( jQuery( this.id ).offset().left, this.left + 1, "jQuery('" + this.id + "').offset({ left: " + (this.left + 1) + ", using: fn })" );
135         });
136 });
137
138 testoffset("static", function( jQuery ) {
139         expect(80);
140         
141         // IE is collapsing the top margin of 1px
142         var ie = jQuery.browser.msie && parseInt( jQuery.browser.version ) < 8;
143         
144         // get offset
145         var tests = [
146                 { id: '#static-1',     top: ie ?   6 :   7, left:  7 },
147                 { id: '#static-1-1',   top: ie ?  13 :  15, left: 15 },
148                 { id: '#static-1-1-1', top: ie ?  20 :  23, left: 23 },
149                 { id: '#static-2',     top: ie ? 121 : 122, left:  7 }
150         ];
151         jQuery.each( tests, function() {
152                 equals( jQuery( this.id ).offset().top,  this.top,  "jQuery('" + this.id + "').offset().top" );
153                 equals( jQuery( this.id ).offset().left, this.left, "jQuery('" + this.id + "').offset().left" );
154         });
155         
156         
157         // get position
158         tests = [
159                 { id: '#static-1',     top: ie ?   5 :   6, left:  6 },
160                 { id: '#static-1-1',   top: ie ?  12 :  14, left: 14 },
161                 { id: '#static-1-1-1', top: ie ?  19 :  22, left: 22 },
162                 { id: '#static-2',     top: ie ? 120 : 121, left:  6 }
163         ];
164         jQuery.each( tests, function() {
165                 equals( jQuery( this.id ).position().top,  this.top,  "jQuery('" + this.top  + "').position().top" );
166                 equals( jQuery( this.id ).position().left, this.left, "jQuery('" + this.left +"').position().left" );
167         });
168         
169         
170         // set offset
171         tests = [
172                 { id: '#static-2',     top: 200, left: 200 },
173                 { id: '#static-2',     top: 100, left: 100 },
174                 { id: '#static-2',     top:  -2, left:  -2 },
175                 { id: '#static-2',     top: 121, left:   6 },
176                 { id: '#static-1-1-1', top:  50, left:  50 },
177                 { id: '#static-1-1-1', top:  10, left:  10 },
178                 { id: '#static-1-1-1', top:  -1, left:  -1 },
179                 { id: '#static-1-1-1', top:  22, left:  22 },
180                 { id: '#static-1-1',   top:  25, left:  25 },
181                 { id: '#static-1-1',   top:  10, left:  10 },
182                 { id: '#static-1-1',   top:  -3, left:  -3 },
183                 { id: '#static-1-1',   top:  14, left:  14 },
184                 { id: '#static-1',     top:  30, left:  30 },
185                 { id: '#static-1',     top:   2, left:   2 },
186                 { id: '#static-1',     top:  -2, left:  -2 },
187                 { id: '#static-1',     top:   7, left:   7 }
188         ];
189         jQuery.each( tests, function() {
190                 jQuery( this.id ).offset({ top: this.top, left: this.left });
191                 equals( jQuery( this.id ).offset().top,  this.top,  "jQuery('" + this.id + "').offset({ top: "  + this.top  + " })" );
192                 equals( jQuery( this.id ).offset().left, this.left, "jQuery('" + this.id + "').offset({ left: " + this.left + " })" );
193                 
194                 jQuery( this.id ).offset({ top: this.top, left: this.left, using: function( props ) {
195                         jQuery( this ).css({
196                                 top:  props.top  + 1,
197                                 left: props.left + 1
198                         });
199                 }});
200                 equals( jQuery( this.id ).offset().top,  this.top  + 1, "jQuery('" + this.id + "').offset({ top: "  + (this.top  + 1) + ", using: fn })" );
201                 equals( jQuery( this.id ).offset().left, this.left + 1, "jQuery('" + this.id + "').offset({ left: " + (this.left + 1) + ", using: fn })" );
202         });
203 });
204
205 testoffset("fixed", function( jQuery ) {
206         expect(28);
207         
208         jQuery.offset.initialize();
209         
210         var tests = [
211                 { id: '#fixed-1', top: 1001, left: 1001 },
212                 { id: '#fixed-2', top: 1021, left: 1021 }
213         ];
214         jQuery.each( tests, function() {
215                 if ( jQuery.offset.supportsFixedPosition ) {
216                         equals( jQuery( this.id ).offset().top,  this.top,  "jQuery('" + this.id + "').offset().top" );
217                         equals( jQuery( this.id ).offset().left, this.left, "jQuery('" + this.id + "').offset().left" );
218                 } else {
219                         // need to have same number of assertions
220                         ok( true, 'Fixed position is not supported' );
221                         ok( true, 'Fixed position is not supported' );
222                 }
223         });
224         
225         tests = [
226                 { id: '#fixed-1', top: 100, left: 100 },
227                 { id: '#fixed-1', top:   0, left:   0 },
228                 { id: '#fixed-1', top:  -4, left:  -4 },
229                 { id: '#fixed-2', top: 200, left: 200 },
230                 { id: '#fixed-2', top:   0, left:   0 },
231                 { id: '#fixed-2', top:  -5, left:  -5 }
232         ];
233         
234         jQuery.each( tests, function() {
235                 if ( jQuery.offset.supportsFixedPosition ) {
236                         jQuery( this.id ).offset({ top: this.top, left: this.left });
237                         equals( jQuery( this.id ).offset().top,  this.top,  "jQuery('" + this.id + "').offset({ top: "  + this.top  + " })" );
238                         equals( jQuery( this.id ).offset().left, this.left, "jQuery('" + this.id + "').offset({ left: " + this.left + " })" );
239                 
240                         jQuery( this.id ).offset({ top: this.top, left: this.left, using: function( props ) {
241                                 jQuery( this ).css({
242                                         top:  props.top  + 1,
243                                         left: props.left + 1
244                                 });
245                         }});
246                         equals( jQuery( this.id ).offset().top,  this.top  + 1, "jQuery('" + this.id + "').offset({ top: "  + (this.top  + 1) + ", using: fn })" );
247                         equals( jQuery( this.id ).offset().left, this.left + 1, "jQuery('" + this.id + "').offset({ left: " + (this.left + 1) + ", using: fn })" );
248                 } else {
249                         // need to have same number of assertions
250                         ok( true, 'Fixed position is not supported' );
251                         ok( true, 'Fixed position is not supported' );
252                         ok( true, 'Fixed position is not supported' );
253                         ok( true, 'Fixed position is not supported' );
254                 }
255         });
256 });
257
258 testoffset("table", function( jQuery ) {
259         expect(4);
260         
261         equals( jQuery('#table-1').offset().top, 6, "jQuery('#table-1').offset().top" );
262         equals( jQuery('#table-1').offset().left, 6, "jQuery('#table-1').offset().left" );
263         
264         equals( jQuery('#th-1').offset().top, 10, "jQuery('#th-1').offset().top" );
265         equals( jQuery('#th-1').offset().left, 10, "jQuery('#th-1').offset().left" );
266 });
267
268 testoffset("scroll", function( jQuery, win ) {
269         expect(12);
270         
271         var ie = jQuery.browser.msie && parseInt( jQuery.browser.version ) < 8;
272         
273         // IE is collapsing the top margin of 1px
274         equals( jQuery('#scroll-1').offset().top, ie ? 6 : 7, "jQuery('#scroll-1').offset().top" );
275         equals( jQuery('#scroll-1').offset().left, 7, "jQuery('#scroll-1').offset().left" );
276         
277         // IE is collapsing the top margin of 1px
278         equals( jQuery('#scroll-1-1').offset().top, ie ? 9 : 11, "jQuery('#scroll-1-1').offset().top" );
279         equals( jQuery('#scroll-1-1').offset().left, 11, "jQuery('#scroll-1-1').offset().left" );
280         
281         
282         // scroll offset tests .scrollTop/Left
283         equals( jQuery('#scroll-1').scrollTop(), 5, "jQuery('#scroll-1').scrollTop()" );
284         equals( jQuery('#scroll-1').scrollLeft(), 5, "jQuery('#scroll-1').scrollLeft()" );
285         
286         equals( jQuery('#scroll-1-1').scrollTop(), 0, "jQuery('#scroll-1-1').scrollTop()" );
287         equals( jQuery('#scroll-1-1').scrollLeft(), 0, "jQuery('#scroll-1-1').scrollLeft()" );
288         
289         // equals( jQuery('body').scrollTop(), 0, "jQuery('body').scrollTop()" );
290         // equals( jQuery('body').scrollLeft(), 0, "jQuery('body').scrollTop()" );
291         
292         win.name = "test";
293         
294         equals( jQuery(win).scrollTop(), 1000, "jQuery(window).scrollTop()" );
295         equals( jQuery(win).scrollLeft(), 1000, "jQuery(window).scrollLeft()" );
296         
297         equals( jQuery(win.document).scrollTop(), 1000, "jQuery(document).scrollTop()" );
298         equals( jQuery(win.document).scrollLeft(), 1000, "jQuery(document).scrollLeft()" );
299 });
300
301 testoffset("body", function( jQuery ) {
302         expect(2);
303         
304         equals( jQuery('body').offset().top, 1, "jQuery('#body').offset().top" );
305         equals( jQuery('body').offset().left, 1, "jQuery('#body').offset().left" );
306 });
307
308 test("Chaining offset(coords) returns jQuery object", function() {
309   expect(2);
310   var coords = { top:  1, left:  1 };
311         equals( jQuery("#absolute-1").offset(coords).selector, "#absolute-1", "offset(coords) returns jQuery object" );
312         equals( jQuery("#non-existent").offset(coords).selector, "#non-existent", "offset(coords) with empty jQuery set returns jQuery object" );
313 });
314
315 test("offsetParent", function(){
316         expect(11);
317
318         var body = jQuery("body").offsetParent();
319         equals( body.length, 1, "Only one offsetParent found." );
320         equals( body[0], document.body, "The body is its own offsetParent." );
321
322         var header = jQuery("#qunit-header").offsetParent();
323         equals( header.length, 1, "Only one offsetParent found." );
324         equals( header[0], document.body, "The body is the offsetParent." );
325
326         var div = jQuery("#nothiddendivchild").offsetParent();
327         equals( div.length, 1, "Only one offsetParent found." );
328         equals( div[0], document.body, "The body is the offsetParent." );
329
330         jQuery("#nothiddendiv").css("position", "relative");
331
332         div = jQuery("#nothiddendivchild").offsetParent();
333         equals( div.length, 1, "Only one offsetParent found." );
334         equals( div[0], jQuery("#nothiddendiv")[0], "The div is the offsetParent." );
335
336         div = jQuery("body, #nothiddendivchild").offsetParent();
337         equals( div.length, 2, "Two offsetParent found." );
338         equals( div[0], document.body, "The body is the offsetParent." );
339         equals( div[1], jQuery("#nothiddendiv")[0], "The div is the offsetParent." );
340 });
341
342 function testoffset(name, fn) {
343         
344         test(name, function() {
345                 // pause execution for now
346                 stop();
347                 
348                 // load fixture in iframe
349                 var iframe = loadFixture(),
350                         win = iframe.contentWindow,
351                         interval = setInterval( function() {
352                                 if ( win && win.jQuery && win.jQuery.isReady ) {
353                                         clearInterval( interval );
354                                         // continue
355                                         start();
356                                         // call actual tests passing the correct jQuery isntance to use
357                                         fn.call( this, win.jQuery, win );
358                                         document.body.removeChild( iframe );
359                                         iframe = null;
360                                 }
361                         }, 15 );
362         });
363         
364         function loadFixture() {
365                 var src = './data/offset/' + name + '.html?' + parseInt( Math.random()*1000 ),
366                         iframe = jQuery('<iframe />').css({
367                                 width: 500, height: 500, position: 'absolute', top: -600, left: -600, visiblity: 'hidden'
368                         }).appendTo('body')[0];
369                 iframe.contentWindow.location = src;
370                 return iframe;
371         }
372 }