/loggerhead/trunk

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/loggerhead/trunk

« back to all changes in this revision

Viewing changes to loggerhead/static/javascript/yui/build/dom/dom-screen.js

  • Committer: Colin Watson
  • Date: 2020-06-08 09:55:03 UTC
  • mfrom: (498.2.2 jquery)
  • Revision ID: cjwatson@canonical.com-20200608095503-n387xggxud2khqsw
[r=cjwatson] Port loggerhead from YUI to jQuery.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
Copyright (c) 2008, Yahoo! Inc. All rights reserved.
3
 
Code licensed under the BSD License:
4
 
http://developer.yahoo.net/yui/license.txt
5
 
version: 3.0.0pr2
6
 
*/
7
 
YUI.add('dom-screen', function(Y) {
8
 
 
9
 
 
10
 
/**
11
 
 * Adds position and region management functionality to DOM.
12
 
 * @module dom
13
 
 * @submodule dom-screen
14
 
 * @for DOM
15
 
 */
16
 
 
17
 
var OFFSET_TOP = 'offsetTop',
18
 
 
19
 
    DOCUMENT_ELEMENT = 'documentElement',
20
 
    COMPAT_MODE = 'compatMode',
21
 
    OFFSET_LEFT = 'offsetLeft',
22
 
    OFFSET_PARENT = 'offsetParent',
23
 
    POSITION = 'position',
24
 
    FIXED = 'fixed',
25
 
    RELATIVE = 'relative',
26
 
    LEFT = 'left',
27
 
    TOP = 'top',
28
 
    SCROLL_LEFT = 'scrollLeft',
29
 
    SCROLL_TOP = 'scrollTop',
30
 
    _BACK_COMPAT = 'BackCompat',
31
 
    MEDIUM = 'medium',
32
 
    HEIGHT = 'height',
33
 
    WIDTH = 'width',
34
 
    BORDER_LEFT_WIDTH = 'borderLeftWidth',
35
 
    BORDER_TOP_WIDTH = 'borderTopWidth',
36
 
    GET_BOUNDING_CLIENT_RECT = 'getBoundingClientRect',
37
 
    GET_COMPUTED_STYLE = 'getComputedStyle',
38
 
    RE_TABLE = /^t(?:able|d|h)$/i;
39
 
 
40
 
Y.mix(Y.DOM, {
41
 
 
42
 
 
43
 
    /**
44
 
     * Returns the inner height of the viewport (exludes scrollbar). 
45
 
     * @method winHeight
46
 
 
47
 
     */
48
 
    winHeight: function(node) {
49
 
        var h = Y.DOM._getWinSize(node)[HEIGHT];
50
 
        return h;
51
 
    },
52
 
 
53
 
    /**
54
 
     * Returns the inner width of the viewport (exludes scrollbar). 
55
 
     * @method winWidth
56
 
 
57
 
     */
58
 
    winWidth: function(node) {
59
 
        var w = Y.DOM._getWinSize(node)[WIDTH];
60
 
        return w;
61
 
    },
62
 
 
63
 
    /**
64
 
     * Document height 
65
 
     * @method docHeight
66
 
 
67
 
     */
68
 
    docHeight:  function(node) {
69
 
        var h = Y.DOM._getDocSize(node)[HEIGHT];
70
 
        return Math.max(h, Y.DOM._getWinSize(node)[HEIGHT]);
71
 
    },
72
 
 
73
 
    /**
74
 
     * Document width 
75
 
     * @method docWidth
76
 
 
77
 
     */
78
 
    docWidth:  function(node) {
79
 
        var w = Y.DOM._getDocSize(node)[WIDTH];
80
 
        return Math.max(w, Y.DOM._getWinSize(node)[WIDTH]);
81
 
    },
82
 
 
83
 
    /**
84
 
     * Amount page has been scroll vertically 
85
 
     * @method docScrollX
86
 
 
87
 
     */
88
 
    docScrollX: function(node) {
89
 
        var doc = Y.DOM._getDoc();
90
 
        return Math.max(doc[DOCUMENT_ELEMENT][SCROLL_LEFT], doc.body[SCROLL_LEFT]);
91
 
    },
92
 
 
93
 
    /**
94
 
     * Amount page has been scroll horizontally 
95
 
     * @method docScrollY
96
 
 
97
 
     */
98
 
    docScrollY:  function(node) {
99
 
        var doc = Y.DOM._getDoc();
100
 
        return Math.max(doc[DOCUMENT_ELEMENT][SCROLL_TOP], doc.body[SCROLL_TOP]);
101
 
    },
102
 
 
103
 
    /**
104
 
     * Gets the current position of an element based on page coordinates. 
105
 
     * Element must be part of the DOM tree to have page coordinates
106
 
     * (display:none or elements not appended return false).
107
 
     * @method getXY
108
 
     * @param element The target element
109
 
     * @return {Array} The XY position of the element
110
 
 
111
 
     TODO: test inDocument/display
112
 
     */
113
 
    getXY: function() {
114
 
 
115
 
 
116
 
 
117
 
 
118
 
        if (document[DOCUMENT_ELEMENT][GET_BOUNDING_CLIENT_RECT]) {
119
 
            return function(node) {
120
 
                if (!node) {
121
 
                    return false;
122
 
                }
123
 
                var scrollLeft = Y.DOM.docScrollX(node),
124
 
                    scrollTop = Y.DOM.docScrollY(node),
125
 
                    box = node[GET_BOUNDING_CLIENT_RECT](),
126
 
                    doc = Y.DOM._getDoc(node),
127
 
                    //Round the numbers so we get sane data back
128
 
                    xy = [Math.floor(box[LEFT]), Math.floor(box[TOP])];
129
 
 
130
 
                    if (Y.UA.ie) {
131
 
                        var off1 = 2, off2 = 2,
132
 
                        mode = doc[COMPAT_MODE],
133
 
                        bLeft = Y.DOM[GET_COMPUTED_STYLE](doc[DOCUMENT_ELEMENT], BORDER_LEFT_WIDTH),
134
 
                        bTop = Y.DOM[GET_COMPUTED_STYLE](doc[DOCUMENT_ELEMENT], BORDER_TOP_WIDTH);
135
 
 
136
 
                        if (Y.UA.ie === 6) {
137
 
                            if (mode !== _BACK_COMPAT) {
138
 
                                off1 = 0;
139
 
                                off2 = 0;
140
 
                            }
141
 
                        }
142
 
                        
143
 
                        if ((mode == _BACK_COMPAT)) {
144
 
                            if (bLeft !== MEDIUM) {
145
 
                                off1 = parseInt(bLeft, 10);
146
 
                            }
147
 
                            if (bTop !== MEDIUM) {
148
 
                                off2 = parseInt(bTop, 10);
149
 
                            }
150
 
 
151
 
 
152
 
 
153
 
                        }
154
 
                        
155
 
                        xy[0] -= off1;
156
 
                        xy[1] -= off2;
157
 
 
158
 
                    }
159
 
 
160
 
                if ((scrollTop || scrollLeft)) {
161
 
                    xy[0] += scrollLeft;
162
 
                    xy[1] += scrollTop;
163
 
                }
164
 
 
165
 
                // gecko may return sub-pixel (non-int) values
166
 
                xy[0] = Math.floor(xy[0]);
167
 
                xy[1] = Math.floor(xy[1]);
168
 
 
169
 
                return xy;                   
170
 
            };
171
 
        } else {
172
 
            return function(node) { // manually calculate by crawling up offsetParents
173
 
                //Calculate the Top and Left border sizes (assumes pixels)
174
 
                var xy = [node[OFFSET_LEFT], node[OFFSET_TOP]],
175
 
                    parentNode = node,
176
 
                    bCheck = ((Y.UA.gecko || (Y.UA.webkit > 519)) ? true : false);
177
 
 
178
 
                while ((parentNode = parentNode[OFFSET_PARENT])) {
179
 
                    xy[0] += parentNode[OFFSET_LEFT];
180
 
                    xy[1] += parentNode[OFFSET_TOP];
181
 
                    if (bCheck) {
182
 
                        xy = Y.DOM._calcBorders(parentNode, xy);
183
 
                    }
184
 
                }
185
 
 
186
 
                // account for any scrolled ancestors
187
 
                if (Y.DOM.getStyle(node, POSITION) != FIXED) {
188
 
                    parentNode = node;
189
 
                    var scrollTop, scrollLeft;
190
 
 
191
 
                    while ((parentNode = parentNode.parentNode)) {
192
 
                        scrollTop = parentNode[SCROLL_TOP];
193
 
                        scrollLeft = parentNode[SCROLL_LEFT];
194
 
 
195
 
                        //Firefox does something funky with borders when overflow is not visible.
196
 
                        if (Y.UA.gecko && (Y.DOM.getStyle(parentNode, 'overflow') !== 'visible')) {
197
 
                                xy = Y.DOM._calcBorders(parentNode, xy);
198
 
                        }
199
 
                        
200
 
 
201
 
                        if (scrollTop || scrollLeft) {
202
 
                            xy[0] -= scrollLeft;
203
 
                            xy[1] -= scrollTop;
204
 
                        }
205
 
                    }
206
 
                    xy[0] += Y.DOM.docScrollX(node);
207
 
                    xy[1] += Y.DOM.docScrollY(node);
208
 
 
209
 
                } else {
210
 
                    //Fix FIXED position -- add scrollbars
211
 
                    if (Y.UA.opera) {
212
 
                        xy[0] -= Y.DOM.docScrollX(node);
213
 
                        xy[1] -= Y.DOM.docScrollY(node);
214
 
                    } else if (Y.UA.webkit || Y.UA.gecko) {
215
 
                        xy[0] += Y.DOM.docScrollX(node);
216
 
                        xy[1] += Y.DOM.docScrollY(node);
217
 
                    }
218
 
                }
219
 
                //Round the numbers so we get sane data back
220
 
                xy[0] = Math.floor(xy[0]);
221
 
                xy[1] = Math.floor(xy[1]);
222
 
 
223
 
                return xy;                
224
 
            };
225
 
        }
226
 
    }(),// NOTE: Executing for loadtime branching
227
 
 
228
 
    /**
229
 
     * Gets the current X position of an element based on page coordinates. 
230
 
     * Element must be part of the DOM tree to have page coordinates
231
 
     * (display:none or elements not appended return false).
232
 
     * @method getX
233
 
     * @param element The target element
234
 
     * @return {Int} The X position of the element
235
 
     */
236
 
 
237
 
    getX: function(node) {
238
 
        return Y.DOM.getXY(node)[0];
239
 
    },
240
 
 
241
 
    /**
242
 
     * Gets the current Y position of an element based on page coordinates. 
243
 
     * Element must be part of the DOM tree to have page coordinates
244
 
     * (display:none or elements not appended return false).
245
 
     * @method getY
246
 
     * @param element The target element
247
 
     * @return {Int} The Y position of the element
248
 
     */
249
 
 
250
 
    getY: function(node) {
251
 
        return Y.DOM.getXY(node)[1];
252
 
    },
253
 
 
254
 
    /**
255
 
     * Set the position of an html element in page coordinates.
256
 
     * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
257
 
     * @method setXY
258
 
     * @param element The target element
259
 
     * @param {Array} xy Contains X & Y values for new position (coordinates are page-based)
260
 
     * @param {Boolean} noRetry By default we try and set the position a second time if the first fails
261
 
     */
262
 
    setXY: function(node, xy, noRetry) {
263
 
        var pos = Y.DOM.getStyle(node, POSITION),
264
 
            setStyle = Y.DOM.setStyle,
265
 
 
266
 
            delta = [ // assuming pixels; if not we will have to retry
267
 
                parseInt( Y.DOM[GET_COMPUTED_STYLE](node, LEFT), 10 ),
268
 
                parseInt( Y.DOM[GET_COMPUTED_STYLE](node, TOP), 10 )
269
 
            ];
270
 
    
271
 
        if (pos == 'static') { // default to relative
272
 
            pos = RELATIVE;
273
 
            setStyle(node, POSITION, pos);
274
 
        }
275
 
 
276
 
        var currentXY = Y.DOM.getXY(node);
277
 
 
278
 
 
279
 
 
280
 
 
281
 
        if (currentXY === false) { // has to be part of doc to have xy
282
 
 
283
 
 
284
 
 
285
 
 
286
 
 
287
 
            return false; 
288
 
        }
289
 
        
290
 
        if ( isNaN(delta[0]) ) {// in case of 'auto'
291
 
            delta[0] = (pos == RELATIVE) ? 0 : node[OFFSET_LEFT];
292
 
        } 
293
 
        if ( isNaN(delta[1]) ) { // in case of 'auto'
294
 
            delta[1] = (pos == RELATIVE) ? 0 : node[OFFSET_TOP];
295
 
        } 
296
 
 
297
 
        if (xy[0] !== null) {
298
 
            setStyle(node, LEFT, xy[0] - currentXY[0] + delta[0] + 'px');
299
 
        }
300
 
 
301
 
        if (xy[1] !== null) {
302
 
            setStyle(node, TOP, xy[1] - currentXY[1] + delta[1] + 'px');
303
 
        }
304
 
      
305
 
        if (!noRetry) {
306
 
            var newXY = Y.DOM.getXY(node);
307
 
 
308
 
            // if retry is true, try one more time if we miss 
309
 
           if ( (xy[0] !== null && newXY[0] != xy[0]) || 
310
 
                (xy[1] !== null && newXY[1] != xy[1]) ) {
311
 
               Y.DOM.setXY(node, xy, true);
312
 
           }
313
 
        }        
314
 
 
315
 
    },
316
 
 
317
 
    /**
318
 
     * Set the X position of an html element in page coordinates, regardless of how the element is positioned.
319
 
     * The element(s) must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
320
 
     * @method setX
321
 
     * @param element The target element
322
 
     * @param {Int} x The X values for new position (coordinates are page-based)
323
 
     */
324
 
    setX: function(node, x) {
325
 
        return Y.DOM.setXY(node, [x, null]);
326
 
    },
327
 
 
328
 
    /**
329
 
     * Set the Y position of an html element in page coordinates, regardless of how the element is positioned.
330
 
     * The element(s) must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
331
 
     * @method setY
332
 
     * @param element The target element
333
 
     * @param {Int} y The Y values for new position (coordinates are page-based)
334
 
     */
335
 
    setY: function(node, y) {
336
 
        return Y.DOM.setXY(node, [null, y]);
337
 
    },
338
 
 
339
 
    _calcBorders: function(node, xy2) {
340
 
        var t = parseInt(Y.DOM[GET_COMPUTED_STYLE](node, BORDER_TOP_WIDTH), 10) || 0,
341
 
            l = parseInt(Y.DOM[GET_COMPUTED_STYLE](node, BORDER_LEFT_WIDTH), 10) || 0;
342
 
        if (Y.UA.gecko) {
343
 
            if (RE_TABLE.test(node.tagName)) {
344
 
                t = 0;
345
 
                l = 0;
346
 
            }
347
 
        }
348
 
        xy2[0] += l;
349
 
        xy2[1] += t;
350
 
        return xy2;
351
 
    },
352
 
 
353
 
    _getWinSize: function(node) {
354
 
        var doc = Y.DOM._getDoc(),
355
 
            win = doc.defaultView || doc.parentWindow,
356
 
            mode = doc[COMPAT_MODE],
357
 
            h = win.innerHeight,
358
 
            w = win.innerWidth,
359
 
            root = doc[DOCUMENT_ELEMENT];
360
 
 
361
 
        if ( mode && !Y.UA.opera ) { // IE, Gecko
362
 
            if (mode != 'CSS1Compat') { // Quirks
363
 
                root = doc.body; 
364
 
            }
365
 
            h = root.clientHeight;
366
 
            w = root.clientWidth;
367
 
        }
368
 
        return { height: h, width: w }; 
369
 
    },
370
 
 
371
 
    _getDocSize: function(node) {
372
 
        var doc = Y.DOM._getDoc(),
373
 
            root = doc[DOCUMENT_ELEMENT];
374
 
 
375
 
        if (doc[COMPAT_MODE] != 'CSS1Compat') {
376
 
            root = doc.body;
377
 
        }
378
 
 
379
 
        return { height: root.scrollHeight, width: root.scrollWidth };
380
 
    }
381
 
});
382
 
 
383
 
 
384
 
 
385
 
/**
386
 
 * Adds position and region management functionality to DOM.
387
 
 * @module dom
388
 
 * @submodule dom-screen
389
 
 * @for DOM
390
 
 */
391
 
 
392
 
var OFFSET_WIDTH = 'offsetWidth',
393
 
    OFFSET_HEIGHT = 'offsetHeight',
394
 
    TOP = 'top',
395
 
    RIGHT = 'right',
396
 
    BOTTOM = 'bottom',
397
 
    LEFT = 'left',
398
 
    TAG_NAME = 'tagName';
399
 
 
400
 
var getOffsets = function(r1, r2) {
401
 
    var t = Math.max(r1[TOP], r2[TOP]),
402
 
        r = Math.min(r1[RIGHT], r2[RIGHT]),
403
 
        b = Math.min(r1[BOTTOM], r2[BOTTOM]),
404
 
        l = Math.max(r1[LEFT], r2[LEFT]),
405
 
        ret = {};
406
 
    
407
 
    ret[TOP] = t;
408
 
    ret[RIGHT] = r;
409
 
    ret[BOTTOM] = b;
410
 
    ret[LEFT] = l;
411
 
    return ret;
412
 
};
413
 
 
414
 
var DOM = DOM || Y.DOM;
415
 
Y.mix(DOM, {
416
 
    /**
417
 
     * Returns an Object literal containing the following about this element: (top, right, bottom, left)
418
 
     * @method region
419
 
     * @param {HTMLElement} element The DOM element. 
420
 
     @return {Object} Object literal containing the following about this element: (top, right, bottom, left)
421
 
     */
422
 
    region: function(node) {
423
 
        var x = DOM.getXY(node),
424
 
            ret = false;
425
 
        
426
 
        if (x) {
427
 
            ret = {
428
 
                '0': x[0],
429
 
                '1': x[1],
430
 
                top: x[1],
431
 
                right: x[0] + node[OFFSET_WIDTH],
432
 
                bottom: x[1] + node[OFFSET_HEIGHT],
433
 
                left: x[0],
434
 
                height: node[OFFSET_HEIGHT],
435
 
                width: node[OFFSET_WIDTH]
436
 
            };
437
 
        }
438
 
 
439
 
        return ret;
440
 
    },
441
 
 
442
 
    /**
443
 
     * Find the intersect information for the passes nodes.
444
 
     * @method intersect
445
 
     * @param {HTMLElement} element The first element 
446
 
     * @param {HTMLElement | Object} element2 The element or region to check the interect with
447
 
     * @param {Object} altRegion An object literal containing the region for the first element if we already have the data (for performance i.e. DragDrop)
448
 
     @return {Object} Object literal containing the following intersection data: (top, right, bottom, left, area, yoff, xoff, inRegion)
449
 
     */
450
 
    intersect: function(node, node2, altRegion) {
451
 
        var r = altRegion || DOM.region(node), region = {};
452
 
 
453
 
        var n = node2;
454
 
        if (n[TAG_NAME]) {
455
 
            region = DOM.region(n);
456
 
        } else if (Y.Lang.isObject(node2)) {
457
 
            region = node2;
458
 
        } else {
459
 
            return false;
460
 
        }
461
 
        
462
 
        var off = getOffsets(region, r);
463
 
        return {
464
 
            top: off[TOP],
465
 
            right: off[RIGHT],
466
 
            bottom: off[BOTTOM],
467
 
            left: off[LEFT],
468
 
            area: ((off[BOTTOM] - off[TOP]) * (off[RIGHT] - off[LEFT])),
469
 
            yoff: ((off[BOTTOM] - off[TOP])),
470
 
            xoff: (off[RIGHT] - off[LEFT]),
471
 
            inRegion: DOM.inRegion(node, node2, false, altRegion)
472
 
        };
473
 
        
474
 
    },
475
 
    /**
476
 
     * Check if any part of this node is in the passed region
477
 
     * @method inRegion
478
 
     * @param {Object} node2 The node to get the region from or an Object literal of the region
479
 
     * $param {Boolean} all Should all of the node be inside the region
480
 
     * @param {Object} altRegion An object literal containing the region for this node if we already have the data (for performance i.e. DragDrop)
481
 
     * @return {Boolean} True if in region, false if not.
482
 
     */
483
 
    inRegion: function(node, node2, all, altRegion) {
484
 
        var region = {},
485
 
            r = altRegion || DOM.region(node);
486
 
 
487
 
        var n = node2;
488
 
        if (n[TAG_NAME]) {
489
 
            region = DOM.region(n);
490
 
        } else if (Y.Lang.isObject(node2)) {
491
 
            region = node2;
492
 
        } else {
493
 
            return false;
494
 
        }
495
 
            
496
 
        if (all) {
497
 
            return (
498
 
                r[LEFT]   >= region[LEFT]   &&
499
 
                r[RIGHT]  <= region[RIGHT]  && 
500
 
                r[TOP]    >= region[TOP]    && 
501
 
                r[BOTTOM] <= region[BOTTOM]  );
502
 
        } else {
503
 
            var off = getOffsets(region, r);
504
 
            if (off[BOTTOM] >= off[TOP] && off[RIGHT] >= off[LEFT]) {
505
 
                return true;
506
 
            } else {
507
 
                return false;
508
 
            }
509
 
            
510
 
        }
511
 
    },
512
 
 
513
 
    /**
514
 
     * Check if any part of this element is in the viewport
515
 
     * @method inViewportRegion
516
 
     * @param {HTMLElement} element The DOM element. 
517
 
     * @param {Boolean} all Should all of the node be inside the region
518
 
     * @param {Object} altRegion An object literal containing the region for this node if we already have the data (for performance i.e. DragDrop)
519
 
     * @return {Boolean} True if in region, false if not.
520
 
     */
521
 
    inViewportRegion: function(node, all, altRegion) {
522
 
        return DOM.inRegion(node, DOM.viewportRegion(node), all, altRegion);
523
 
            
524
 
    },
525
 
 
526
 
    /**
527
 
     * Returns an Object literal containing the following about the visible region of viewport: (top, right, bottom, left)
528
 
     * @method viewportRegion
529
 
     @return {Object} Object literal containing the following about the visible region of the viewport: (top, right, bottom, left)
530
 
     */
531
 
    viewportRegion: function(node) {
532
 
        node = node || Y.config.doc.documentElement;
533
 
        var r = {};
534
 
        r[TOP] = DOM.docScrollY(node);
535
 
        r[RIGHT] = DOM.winWidth(node) + DOM.docScrollX(node);
536
 
        r[BOTTOM] = (DOM.docScrollY(node) + DOM.winHeight(node));
537
 
        r[LEFT] = DOM.docScrollX(node);
538
 
 
539
 
        return r;
540
 
    }
541
 
});
542
 
 
543
 
 
544
 
 
545
 
}, '3.0.0pr2' ,{skinnable:false, requires:['dom-base', 'dom-style']});