Projet

Général

Profil

Paste
Télécharger (15,3 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / jquery_update / replace / ui / ui / jquery.ui.position.js @ 503b3f7b

1
/*!
2
 * jQuery UI Position 1.10.2
3
 * http://jqueryui.com
4
 *
5
 * Copyright 2013 jQuery Foundation and other contributors
6
 * Released under the MIT license.
7
 * http://jquery.org/license
8
 *
9
 * http://api.jqueryui.com/position/
10
 */
11
(function( $, undefined ) {
12

    
13
$.ui = $.ui || {};
14

    
15
var cachedScrollbarWidth,
16
        max = Math.max,
17
        abs = Math.abs,
18
        round = Math.round,
19
        rhorizontal = /left|center|right/,
20
        rvertical = /top|center|bottom/,
21
        roffset = /[\+\-]\d+(\.[\d]+)?%?/,
22
        rposition = /^\w+/,
23
        rpercent = /%$/,
24
        _position = $.fn.position;
25

    
26
function getOffsets( offsets, width, height ) {
27
        return [
28
                parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
29
                parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
30
        ];
31
}
32

    
33
function parseCss( element, property ) {
34
        return parseInt( $.css( element, property ), 10 ) || 0;
35
}
36

    
37
function getDimensions( elem ) {
38
        var raw = elem[0];
39
        if ( raw.nodeType === 9 ) {
40
                return {
41
                        width: elem.width(),
42
                        height: elem.height(),
43
                        offset: { top: 0, left: 0 }
44
                };
45
        }
46
        if ( $.isWindow( raw ) ) {
47
                return {
48
                        width: elem.width(),
49
                        height: elem.height(),
50
                        offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
51
                };
52
        }
53
        if ( raw.preventDefault ) {
54
                return {
55
                        width: 0,
56
                        height: 0,
57
                        offset: { top: raw.pageY, left: raw.pageX }
58
                };
59
        }
60
        return {
61
                width: elem.outerWidth(),
62
                height: elem.outerHeight(),
63
                offset: elem.offset()
64
        };
65
}
66

    
67
$.position = {
68
        scrollbarWidth: function() {
69
                if ( cachedScrollbarWidth !== undefined ) {
70
                        return cachedScrollbarWidth;
71
                }
72
                var w1, w2,
73
                        div = $( "<div style='display:block;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>" ),
74
                        innerDiv = div.children()[0];
75

    
76
                $( "body" ).append( div );
77
                w1 = innerDiv.offsetWidth;
78
                div.css( "overflow", "scroll" );
79

    
80
                w2 = innerDiv.offsetWidth;
81

    
82
                if ( w1 === w2 ) {
83
                        w2 = div[0].clientWidth;
84
                }
85

    
86
                div.remove();
87

    
88
                return (cachedScrollbarWidth = w1 - w2);
89
        },
90
        getScrollInfo: function( within ) {
91
                var overflowX = within.isWindow ? "" : within.element.css( "overflow-x" ),
92
                        overflowY = within.isWindow ? "" : within.element.css( "overflow-y" ),
93
                        hasOverflowX = overflowX === "scroll" ||
94
                                ( overflowX === "auto" && within.width < within.element[0].scrollWidth ),
95
                        hasOverflowY = overflowY === "scroll" ||
96
                                ( overflowY === "auto" && within.height < within.element[0].scrollHeight );
97
                return {
98
                        width: hasOverflowY ? $.position.scrollbarWidth() : 0,
99
                        height: hasOverflowX ? $.position.scrollbarWidth() : 0
100
                };
101
        },
102
        getWithinInfo: function( element ) {
103
                var withinElement = $( element || window ),
104
                        isWindow = $.isWindow( withinElement[0] );
105
                return {
106
                        element: withinElement,
107
                        isWindow: isWindow,
108
                        offset: withinElement.offset() || { left: 0, top: 0 },
109
                        scrollLeft: withinElement.scrollLeft(),
110
                        scrollTop: withinElement.scrollTop(),
111
                        width: isWindow ? withinElement.width() : withinElement.outerWidth(),
112
                        height: isWindow ? withinElement.height() : withinElement.outerHeight()
113
                };
114
        }
115
};
116

    
117
$.fn.position = function( options ) {
118
        if ( !options || !options.of ) {
119
                return _position.apply( this, arguments );
120
        }
121

    
122
        // make a copy, we don't want to modify arguments
123
        options = $.extend( {}, options );
124

    
125
        var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
126
                target = $( options.of ),
127
                within = $.position.getWithinInfo( options.within ),
128
                scrollInfo = $.position.getScrollInfo( within ),
129
                collision = ( options.collision || "flip" ).split( " " ),
130
                offsets = {};
131

    
132
        dimensions = getDimensions( target );
133
        if ( target[0].preventDefault ) {
134
                // force left top to allow flipping
135
                options.at = "left top";
136
        }
137
        targetWidth = dimensions.width;
138
        targetHeight = dimensions.height;
139
        targetOffset = dimensions.offset;
140
        // clone to reuse original targetOffset later
141
        basePosition = $.extend( {}, targetOffset );
142

    
143
        // force my and at to have valid horizontal and vertical positions
144
        // if a value is missing or invalid, it will be converted to center
145
        $.each( [ "my", "at" ], function() {
146
                var pos = ( options[ this ] || "" ).split( " " ),
147
                        horizontalOffset,
148
                        verticalOffset;
149

    
150
                if ( pos.length === 1) {
151
                        pos = rhorizontal.test( pos[ 0 ] ) ?
152
                                pos.concat( [ "center" ] ) :
153
                                rvertical.test( pos[ 0 ] ) ?
154
                                        [ "center" ].concat( pos ) :
155
                                        [ "center", "center" ];
156
                }
157
                pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
158
                pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
159

    
160
                // calculate offsets
161
                horizontalOffset = roffset.exec( pos[ 0 ] );
162
                verticalOffset = roffset.exec( pos[ 1 ] );
163
                offsets[ this ] = [
164
                        horizontalOffset ? horizontalOffset[ 0 ] : 0,
165
                        verticalOffset ? verticalOffset[ 0 ] : 0
166
                ];
167

    
168
                // reduce to just the positions without the offsets
169
                options[ this ] = [
170
                        rposition.exec( pos[ 0 ] )[ 0 ],
171
                        rposition.exec( pos[ 1 ] )[ 0 ]
172
                ];
173
        });
174

    
175
        // normalize collision option
176
        if ( collision.length === 1 ) {
177
                collision[ 1 ] = collision[ 0 ];
178
        }
179

    
180
        if ( options.at[ 0 ] === "right" ) {
181
                basePosition.left += targetWidth;
182
        } else if ( options.at[ 0 ] === "center" ) {
183
                basePosition.left += targetWidth / 2;
184
        }
185

    
186
        if ( options.at[ 1 ] === "bottom" ) {
187
                basePosition.top += targetHeight;
188
        } else if ( options.at[ 1 ] === "center" ) {
189
                basePosition.top += targetHeight / 2;
190
        }
191

    
192
        atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
193
        basePosition.left += atOffset[ 0 ];
194
        basePosition.top += atOffset[ 1 ];
195

    
196
        return this.each(function() {
197
                var collisionPosition, using,
198
                        elem = $( this ),
199
                        elemWidth = elem.outerWidth(),
200
                        elemHeight = elem.outerHeight(),
201
                        marginLeft = parseCss( this, "marginLeft" ),
202
                        marginTop = parseCss( this, "marginTop" ),
203
                        collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width,
204
                        collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height,
205
                        position = $.extend( {}, basePosition ),
206
                        myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
207

    
208
                if ( options.my[ 0 ] === "right" ) {
209
                        position.left -= elemWidth;
210
                } else if ( options.my[ 0 ] === "center" ) {
211
                        position.left -= elemWidth / 2;
212
                }
213

    
214
                if ( options.my[ 1 ] === "bottom" ) {
215
                        position.top -= elemHeight;
216
                } else if ( options.my[ 1 ] === "center" ) {
217
                        position.top -= elemHeight / 2;
218
                }
219

    
220
                position.left += myOffset[ 0 ];
221
                position.top += myOffset[ 1 ];
222

    
223
                // if the browser doesn't support fractions, then round for consistent results
224
                if ( !$.support.offsetFractions ) {
225
                        position.left = round( position.left );
226
                        position.top = round( position.top );
227
                }
228

    
229
                collisionPosition = {
230
                        marginLeft: marginLeft,
231
                        marginTop: marginTop
232
                };
233

    
234
                $.each( [ "left", "top" ], function( i, dir ) {
235
                        if ( $.ui.position[ collision[ i ] ] ) {
236
                                $.ui.position[ collision[ i ] ][ dir ]( position, {
237
                                        targetWidth: targetWidth,
238
                                        targetHeight: targetHeight,
239
                                        elemWidth: elemWidth,
240
                                        elemHeight: elemHeight,
241
                                        collisionPosition: collisionPosition,
242
                                        collisionWidth: collisionWidth,
243
                                        collisionHeight: collisionHeight,
244
                                        offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
245
                                        my: options.my,
246
                                        at: options.at,
247
                                        within: within,
248
                                        elem : elem
249
                                });
250
                        }
251
                });
252

    
253
                if ( options.using ) {
254
                        // adds feedback as second argument to using callback, if present
255
                        using = function( props ) {
256
                                var left = targetOffset.left - position.left,
257
                                        right = left + targetWidth - elemWidth,
258
                                        top = targetOffset.top - position.top,
259
                                        bottom = top + targetHeight - elemHeight,
260
                                        feedback = {
261
                                                target: {
262
                                                        element: target,
263
                                                        left: targetOffset.left,
264
                                                        top: targetOffset.top,
265
                                                        width: targetWidth,
266
                                                        height: targetHeight
267
                                                },
268
                                                element: {
269
                                                        element: elem,
270
                                                        left: position.left,
271
                                                        top: position.top,
272
                                                        width: elemWidth,
273
                                                        height: elemHeight
274
                                                },
275
                                                horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
276
                                                vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
277
                                        };
278
                                if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
279
                                        feedback.horizontal = "center";
280
                                }
281
                                if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
282
                                        feedback.vertical = "middle";
283
                                }
284
                                if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
285
                                        feedback.important = "horizontal";
286
                                } else {
287
                                        feedback.important = "vertical";
288
                                }
289
                                options.using.call( this, props, feedback );
290
                        };
291
                }
292

    
293
                elem.offset( $.extend( position, { using: using } ) );
294
        });
295
};
296

    
297
$.ui.position = {
298
        fit: {
299
                left: function( position, data ) {
300
                        var within = data.within,
301
                                withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
302
                                outerWidth = within.width,
303
                                collisionPosLeft = position.left - data.collisionPosition.marginLeft,
304
                                overLeft = withinOffset - collisionPosLeft,
305
                                overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
306
                                newOverRight;
307

    
308
                        // element is wider than within
309
                        if ( data.collisionWidth > outerWidth ) {
310
                                // element is initially over the left side of within
311
                                if ( overLeft > 0 && overRight <= 0 ) {
312
                                        newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset;
313
                                        position.left += overLeft - newOverRight;
314
                                // element is initially over right side of within
315
                                } else if ( overRight > 0 && overLeft <= 0 ) {
316
                                        position.left = withinOffset;
317
                                // element is initially over both left and right sides of within
318
                                } else {
319
                                        if ( overLeft > overRight ) {
320
                                                position.left = withinOffset + outerWidth - data.collisionWidth;
321
                                        } else {
322
                                                position.left = withinOffset;
323
                                        }
324
                                }
325
                        // too far left -> align with left edge
326
                        } else if ( overLeft > 0 ) {
327
                                position.left += overLeft;
328
                        // too far right -> align with right edge
329
                        } else if ( overRight > 0 ) {
330
                                position.left -= overRight;
331
                        // adjust based on position and margin
332
                        } else {
333
                                position.left = max( position.left - collisionPosLeft, position.left );
334
                        }
335
                },
336
                top: function( position, data ) {
337
                        var within = data.within,
338
                                withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
339
                                outerHeight = data.within.height,
340
                                collisionPosTop = position.top - data.collisionPosition.marginTop,
341
                                overTop = withinOffset - collisionPosTop,
342
                                overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
343
                                newOverBottom;
344

    
345
                        // element is taller than within
346
                        if ( data.collisionHeight > outerHeight ) {
347
                                // element is initially over the top of within
348
                                if ( overTop > 0 && overBottom <= 0 ) {
349
                                        newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset;
350
                                        position.top += overTop - newOverBottom;
351
                                // element is initially over bottom of within
352
                                } else if ( overBottom > 0 && overTop <= 0 ) {
353
                                        position.top = withinOffset;
354
                                // element is initially over both top and bottom of within
355
                                } else {
356
                                        if ( overTop > overBottom ) {
357
                                                position.top = withinOffset + outerHeight - data.collisionHeight;
358
                                        } else {
359
                                                position.top = withinOffset;
360
                                        }
361
                                }
362
                        // too far up -> align with top
363
                        } else if ( overTop > 0 ) {
364
                                position.top += overTop;
365
                        // too far down -> align with bottom edge
366
                        } else if ( overBottom > 0 ) {
367
                                position.top -= overBottom;
368
                        // adjust based on position and margin
369
                        } else {
370
                                position.top = max( position.top - collisionPosTop, position.top );
371
                        }
372
                }
373
        },
374
        flip: {
375
                left: function( position, data ) {
376
                        var within = data.within,
377
                                withinOffset = within.offset.left + within.scrollLeft,
378
                                outerWidth = within.width,
379
                                offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
380
                                collisionPosLeft = position.left - data.collisionPosition.marginLeft,
381
                                overLeft = collisionPosLeft - offsetLeft,
382
                                overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
383
                                myOffset = data.my[ 0 ] === "left" ?
384
                                        -data.elemWidth :
385
                                        data.my[ 0 ] === "right" ?
386
                                                data.elemWidth :
387
                                                0,
388
                                atOffset = data.at[ 0 ] === "left" ?
389
                                        data.targetWidth :
390
                                        data.at[ 0 ] === "right" ?
391
                                                -data.targetWidth :
392
                                                0,
393
                                offset = -2 * data.offset[ 0 ],
394
                                newOverRight,
395
                                newOverLeft;
396

    
397
                        if ( overLeft < 0 ) {
398
                                newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset;
399
                                if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
400
                                        position.left += myOffset + atOffset + offset;
401
                                }
402
                        }
403
                        else if ( overRight > 0 ) {
404
                                newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft;
405
                                if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
406
                                        position.left += myOffset + atOffset + offset;
407
                                }
408
                        }
409
                },
410
                top: function( position, data ) {
411
                        var within = data.within,
412
                                withinOffset = within.offset.top + within.scrollTop,
413
                                outerHeight = within.height,
414
                                offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
415
                                collisionPosTop = position.top - data.collisionPosition.marginTop,
416
                                overTop = collisionPosTop - offsetTop,
417
                                overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
418
                                top = data.my[ 1 ] === "top",
419
                                myOffset = top ?
420
                                        -data.elemHeight :
421
                                        data.my[ 1 ] === "bottom" ?
422
                                                data.elemHeight :
423
                                                0,
424
                                atOffset = data.at[ 1 ] === "top" ?
425
                                        data.targetHeight :
426
                                        data.at[ 1 ] === "bottom" ?
427
                                                -data.targetHeight :
428
                                                0,
429
                                offset = -2 * data.offset[ 1 ],
430
                                newOverTop,
431
                                newOverBottom;
432
                        if ( overTop < 0 ) {
433
                                newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset;
434
                                if ( ( position.top + myOffset + atOffset + offset) > overTop && ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) ) {
435
                                        position.top += myOffset + atOffset + offset;
436
                                }
437
                        }
438
                        else if ( overBottom > 0 ) {
439
                                newOverTop = position.top -  data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop;
440
                                if ( ( position.top + myOffset + atOffset + offset) > overBottom && ( newOverTop > 0 || abs( newOverTop ) < overBottom ) ) {
441
                                        position.top += myOffset + atOffset + offset;
442
                                }
443
                        }
444
                }
445
        },
446
        flipfit: {
447
                left: function() {
448
                        $.ui.position.flip.left.apply( this, arguments );
449
                        $.ui.position.fit.left.apply( this, arguments );
450
                },
451
                top: function() {
452
                        $.ui.position.flip.top.apply( this, arguments );
453
                        $.ui.position.fit.top.apply( this, arguments );
454
                }
455
        }
456
};
457

    
458
// fraction support test
459
(function () {
460
        var testElement, testElementParent, testElementStyle, offsetLeft, i,
461
                body = document.getElementsByTagName( "body" )[ 0 ],
462
                div = document.createElement( "div" );
463

    
464
        //Create a "fake body" for testing based on method used in jQuery.support
465
        testElement = document.createElement( body ? "div" : "body" );
466
        testElementStyle = {
467
                visibility: "hidden",
468
                width: 0,
469
                height: 0,
470
                border: 0,
471
                margin: 0,
472
                background: "none"
473
        };
474
        if ( body ) {
475
                $.extend( testElementStyle, {
476
                        position: "absolute",
477
                        left: "-1000px",
478
                        top: "-1000px"
479
                });
480
        }
481
        for ( i in testElementStyle ) {
482
                testElement.style[ i ] = testElementStyle[ i ];
483
        }
484
        testElement.appendChild( div );
485
        testElementParent = body || document.documentElement;
486
        testElementParent.insertBefore( testElement, testElementParent.firstChild );
487

    
488
        div.style.cssText = "position: absolute; left: 10.7432222px;";
489

    
490
        offsetLeft = $( div ).offset().left;
491
        $.support.offsetFractions = offsetLeft > 10 && offsetLeft < 11;
492

    
493
        testElement.innerHTML = "";
494
        testElementParent.removeChild( testElement );
495
})();
496

    
497
}( jQuery ) );