Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
YUI.add('dom-screen', function (Y, NAME) {
2
 
3
(function(Y) {
4
 
5
/**
6
 * Adds position and region management functionality to DOM.
7
 * @module dom
8
 * @submodule dom-screen
9
 * @for DOM
10
 */
11
 
12
var DOCUMENT_ELEMENT = 'documentElement',
13
    COMPAT_MODE = 'compatMode',
14
    POSITION = 'position',
15
    FIXED = 'fixed',
16
    RELATIVE = 'relative',
17
    LEFT = 'left',
18
    TOP = 'top',
19
    _BACK_COMPAT = 'BackCompat',
20
    MEDIUM = 'medium',
21
    BORDER_LEFT_WIDTH = 'borderLeftWidth',
22
    BORDER_TOP_WIDTH = 'borderTopWidth',
23
    GET_BOUNDING_CLIENT_RECT = 'getBoundingClientRect',
24
    GET_COMPUTED_STYLE = 'getComputedStyle',
25
 
26
    Y_DOM = Y.DOM,
27
 
28
    // TODO: how about thead/tbody/tfoot/tr?
29
    // TODO: does caption matter?
30
    RE_TABLE = /^t(?:able|d|h)$/i,
31
 
32
    SCROLL_NODE;
33
 
34
if (Y.UA.ie) {
35
    if (Y.config.doc[COMPAT_MODE] !== 'BackCompat') {
36
        SCROLL_NODE = DOCUMENT_ELEMENT;
37
    } else {
38
        SCROLL_NODE = 'body';
39
    }
40
}
41
 
42
Y.mix(Y_DOM, {
43
    /**
44
     * Returns the inner height of the viewport (exludes scrollbar).
45
     * @method winHeight
46
     * @return {Number} The current height of the viewport.
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
     * @return {Number} The current width of the viewport.
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
     * @return {Number} The current height of the document.
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
     * @return {Number} The current width of the document.
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 horizontally
85
     * @method docScrollX
86
     * @return {Number} The current amount the screen is scrolled horizontally.
87
     */
88
    docScrollX: function(node, doc) {
89
        doc = doc || (node) ? Y_DOM._getDoc(node) : Y.config.doc; // perf optimization
90
        var dv = doc.defaultView,
91
            pageOffset = (dv) ? dv.pageXOffset : 0;
92
        return Math.max(doc[DOCUMENT_ELEMENT].scrollLeft, doc.body.scrollLeft, pageOffset);
93
    },
94
 
95
    /**
96
     * Amount page has been scroll vertically
97
     * @method docScrollY
98
     * @return {Number} The current amount the screen is scrolled vertically.
99
     */
100
    docScrollY:  function(node, doc) {
101
        doc = doc || (node) ? Y_DOM._getDoc(node) : Y.config.doc; // perf optimization
102
        var dv = doc.defaultView,
103
            pageOffset = (dv) ? dv.pageYOffset : 0;
104
        return Math.max(doc[DOCUMENT_ELEMENT].scrollTop, doc.body.scrollTop, pageOffset);
105
    },
106
 
107
    /**
108
     * Gets the current position of an element based on page coordinates.
109
     * Element must be part of the DOM tree to have page coordinates
110
     * (display:none or elements not appended return false).
111
     * @method getXY
112
     * @param element The target element
113
     * @return {Array} The XY position of the element
114
 
115
     TODO: test inDocument/display?
116
     */
117
    getXY: function() {
118
        if (Y.config.doc[DOCUMENT_ELEMENT][GET_BOUNDING_CLIENT_RECT]) {
119
            return function(node) {
120
                var xy = null,
121
                    scrollLeft,
122
                    scrollTop,
123
                    mode,
124
                    box,
125
                    offX,
126
                    offY,
127
                    doc,
128
                    win,
129
                    inDoc,
130
                    rootNode;
131
 
132
                if (node && node.tagName) {
133
                    doc = node.ownerDocument;
134
                    mode = doc[COMPAT_MODE];
135
 
136
                    if (mode !== _BACK_COMPAT) {
137
                        rootNode = doc[DOCUMENT_ELEMENT];
138
                    } else {
139
                        rootNode = doc.body;
140
                    }
141
 
142
                    // inline inDoc check for perf
143
                    if (rootNode.contains) {
144
                        inDoc = rootNode.contains(node);
145
                    } else {
146
                        inDoc = Y.DOM.contains(rootNode, node);
147
                    }
148
 
149
                    if (inDoc) {
150
                        win = doc.defaultView;
151
 
152
                        // inline scroll calc for perf
153
                        if (win && 'pageXOffset' in win) {
154
                            scrollLeft = win.pageXOffset;
155
                            scrollTop = win.pageYOffset;
156
                        } else {
157
                            scrollLeft = (SCROLL_NODE) ? doc[SCROLL_NODE].scrollLeft : Y_DOM.docScrollX(node, doc);
158
                            scrollTop = (SCROLL_NODE) ? doc[SCROLL_NODE].scrollTop : Y_DOM.docScrollY(node, doc);
159
                        }
160
 
161
                        if (Y.UA.ie) { // IE < 8, quirks, or compatMode
162
                            if (!doc.documentMode || doc.documentMode < 8 || mode === _BACK_COMPAT) {
163
                                offX = rootNode.clientLeft;
164
                                offY = rootNode.clientTop;
165
                            }
166
                        }
167
                        box = node[GET_BOUNDING_CLIENT_RECT]();
168
                        xy = [box.left, box.top];
169
 
170
                        if (offX || offY) {
171
                                xy[0] -= offX;
172
                                xy[1] -= offY;
173
 
174
                        }
175
                        if ((scrollTop || scrollLeft)) {
176
                            if (!Y.UA.ios || (Y.UA.ios >= 4.2)) {
177
                                xy[0] += scrollLeft;
178
                                xy[1] += scrollTop;
179
                            }
180
 
181
                        }
182
                    } else {
183
                        xy = Y_DOM._getOffset(node);
184
                    }
185
                }
186
                return xy;
187
            };
188
        } else {
189
            return function(node) { // manually calculate by crawling up offsetParents
190
                //Calculate the Top and Left border sizes (assumes pixels)
191
                var xy = null,
192
                    doc,
193
                    parentNode,
194
                    bCheck,
195
                    scrollTop,
196
                    scrollLeft;
197
 
198
                if (node) {
199
                    if (Y_DOM.inDoc(node)) {
200
                        xy = [node.offsetLeft, node.offsetTop];
201
                        doc = node.ownerDocument;
202
                        parentNode = node;
203
                        // TODO: refactor with !! or just falsey
204
                        bCheck = ((Y.UA.gecko || Y.UA.webkit > 519) ? true : false);
205
 
206
                        // TODO: worth refactoring for TOP/LEFT only?
207
                        while ((parentNode = parentNode.offsetParent)) {
208
                            xy[0] += parentNode.offsetLeft;
209
                            xy[1] += parentNode.offsetTop;
210
                            if (bCheck) {
211
                                xy = Y_DOM._calcBorders(parentNode, xy);
212
                            }
213
                        }
214
 
215
                        // account for any scrolled ancestors
216
                        if (Y_DOM.getStyle(node, POSITION) != FIXED) {
217
                            parentNode = node;
218
 
219
                            while ((parentNode = parentNode.parentNode)) {
220
                                scrollTop = parentNode.scrollTop;
221
                                scrollLeft = parentNode.scrollLeft;
222
 
223
                                //Firefox does something funky with borders when overflow is not visible.
224
                                if (Y.UA.gecko && (Y_DOM.getStyle(parentNode, 'overflow') !== 'visible')) {
225
                                        xy = Y_DOM._calcBorders(parentNode, xy);
226
                                }
227
 
228
 
229
                                if (scrollTop || scrollLeft) {
230
                                    xy[0] -= scrollLeft;
231
                                    xy[1] -= scrollTop;
232
                                }
233
                            }
234
                            xy[0] += Y_DOM.docScrollX(node, doc);
235
                            xy[1] += Y_DOM.docScrollY(node, doc);
236
 
237
                        } else {
238
                            //Fix FIXED position -- add scrollbars
239
                            xy[0] += Y_DOM.docScrollX(node, doc);
240
                            xy[1] += Y_DOM.docScrollY(node, doc);
241
                        }
242
                    } else {
243
                        xy = Y_DOM._getOffset(node);
244
                    }
245
                }
246
 
247
                return xy;
248
            };
249
        }
250
    }(),// NOTE: Executing for loadtime branching
251
 
252
    /**
253
    Gets the width of vertical scrollbars on overflowed containers in the body
254
    content.
255
 
256
    @method getScrollbarWidth
257
    @return {Number} Pixel width of a scrollbar in the current browser
258
    **/
259
    getScrollbarWidth: Y.cached(function () {
260
        var doc      = Y.config.doc,
261
            testNode = doc.createElement('div'),
262
            body     = doc.getElementsByTagName('body')[0],
263
            // 0.1 because cached doesn't support falsy refetch values
264
            width    = 0.1;
265
 
266
        if (body) {
267
            testNode.style.cssText = "position:absolute;visibility:hidden;overflow:scroll;width:20px;";
268
            testNode.appendChild(doc.createElement('p')).style.height = '1px';
269
            body.insertBefore(testNode, body.firstChild);
270
            width = testNode.offsetWidth - testNode.clientWidth;
271
 
272
            body.removeChild(testNode);
273
        }
274
 
275
        return width;
276
    }, null, 0.1),
277
 
278
    /**
279
     * Gets the current X position of an element based on page coordinates.
280
     * Element must be part of the DOM tree to have page coordinates
281
     * (display:none or elements not appended return false).
282
     * @method getX
283
     * @param element The target element
284
     * @return {Number} The X position of the element
285
     */
286
 
287
    getX: function(node) {
288
        return Y_DOM.getXY(node)[0];
289
    },
290
 
291
    /**
292
     * Gets the current Y position of an element based on page coordinates.
293
     * Element must be part of the DOM tree to have page coordinates
294
     * (display:none or elements not appended return false).
295
     * @method getY
296
     * @param element The target element
297
     * @return {Number} The Y position of the element
298
     */
299
 
300
    getY: function(node) {
301
        return Y_DOM.getXY(node)[1];
302
    },
303
 
304
    /**
305
     * Set the position of an html element in page coordinates.
306
     * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
307
     * @method setXY
308
     * @param element The target element
309
     * @param {Array} xy Contains X & Y values for new position (coordinates are page-based)
310
     * @param {Boolean} noRetry By default we try and set the position a second time if the first fails
311
     */
312
    setXY: function(node, xy, noRetry) {
313
        var setStyle = Y_DOM.setStyle,
314
            pos,
315
            delta,
316
            newXY,
317
            currentXY;
318
 
319
        if (node && xy) {
320
            pos = Y_DOM.getStyle(node, POSITION);
321
 
322
            delta = Y_DOM._getOffset(node);
323
            if (pos == 'static') { // default to relative
324
                pos = RELATIVE;
325
                setStyle(node, POSITION, pos);
326
            }
327
            currentXY = Y_DOM.getXY(node);
328
 
329
            if (xy[0] !== null) {
330
                setStyle(node, LEFT, xy[0] - currentXY[0] + delta[0] + 'px');
331
            }
332
 
333
            if (xy[1] !== null) {
334
                setStyle(node, TOP, xy[1] - currentXY[1] + delta[1] + 'px');
335
            }
336
 
337
            if (!noRetry) {
338
                newXY = Y_DOM.getXY(node);
339
                if (newXY[0] !== xy[0] || newXY[1] !== xy[1]) {
340
                    Y_DOM.setXY(node, xy, true);
341
                }
342
            }
343
 
344
        } else {
345
        }
346
    },
347
 
348
    /**
349
     * Set the X position of an html element in page coordinates, regardless of how the element is positioned.
350
     * The element(s) must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
351
     * @method setX
352
     * @param element The target element
353
     * @param {Number} x The X values for new position (coordinates are page-based)
354
     */
355
    setX: function(node, x) {
356
        return Y_DOM.setXY(node, [x, null]);
357
    },
358
 
359
    /**
360
     * Set the Y position of an html element in page coordinates, regardless of how the element is positioned.
361
     * The element(s) must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
362
     * @method setY
363
     * @param element The target element
364
     * @param {Number} y The Y values for new position (coordinates are page-based)
365
     */
366
    setY: function(node, y) {
367
        return Y_DOM.setXY(node, [null, y]);
368
    },
369
 
370
    /**
371
     * @method swapXY
372
     * @description Swap the xy position with another node
373
     * @param {Node} node The node to swap with
374
     * @param {Node} otherNode The other node to swap with
375
     * @return {Node}
376
     */
377
    swapXY: function(node, otherNode) {
378
        var xy = Y_DOM.getXY(node);
379
        Y_DOM.setXY(node, Y_DOM.getXY(otherNode));
380
        Y_DOM.setXY(otherNode, xy);
381
    },
382
 
383
    _calcBorders: function(node, xy2) {
384
        var t = parseInt(Y_DOM[GET_COMPUTED_STYLE](node, BORDER_TOP_WIDTH), 10) || 0,
385
            l = parseInt(Y_DOM[GET_COMPUTED_STYLE](node, BORDER_LEFT_WIDTH), 10) || 0;
386
        if (Y.UA.gecko) {
387
            if (RE_TABLE.test(node.tagName)) {
388
                t = 0;
389
                l = 0;
390
            }
391
        }
392
        xy2[0] += l;
393
        xy2[1] += t;
394
        return xy2;
395
    },
396
 
397
    _getWinSize: function(node, doc) {
398
        doc  = doc || (node) ? Y_DOM._getDoc(node) : Y.config.doc;
399
        var win = doc.defaultView || doc.parentWindow,
400
            mode = doc[COMPAT_MODE],
401
            h = win.innerHeight,
402
            w = win.innerWidth,
403
            root = doc[DOCUMENT_ELEMENT];
404
 
405
        if ( mode && !Y.UA.opera ) { // IE, Gecko
406
            if (mode != 'CSS1Compat') { // Quirks
407
                root = doc.body;
408
            }
409
            h = root.clientHeight;
410
            w = root.clientWidth;
411
        }
412
        return { height: h, width: w };
413
    },
414
 
415
    _getDocSize: function(node) {
416
        var doc = (node) ? Y_DOM._getDoc(node) : Y.config.doc,
417
            root = doc[DOCUMENT_ELEMENT];
418
 
419
        if (doc[COMPAT_MODE] != 'CSS1Compat') {
420
            root = doc.body;
421
        }
422
 
423
        return { height: root.scrollHeight, width: root.scrollWidth };
424
    }
425
});
426
 
427
})(Y);
428
(function(Y) {
429
var TOP = 'top',
430
    RIGHT = 'right',
431
    BOTTOM = 'bottom',
432
    LEFT = 'left',
433
 
434
    getOffsets = function(r1, r2) {
435
        var t = Math.max(r1[TOP], r2[TOP]),
436
            r = Math.min(r1[RIGHT], r2[RIGHT]),
437
            b = Math.min(r1[BOTTOM], r2[BOTTOM]),
438
            l = Math.max(r1[LEFT], r2[LEFT]),
439
            ret = {};
440
 
441
        ret[TOP] = t;
442
        ret[RIGHT] = r;
443
        ret[BOTTOM] = b;
444
        ret[LEFT] = l;
445
        return ret;
446
    },
447
 
448
    DOM = Y.DOM;
449
 
450
Y.mix(DOM, {
451
    /**
452
     * Returns an Object literal containing the following about this element: (top, right, bottom, left)
453
     * @for DOM
454
     * @method region
455
     * @param {HTMLElement} element The DOM element.
456
     * @return {Object} Object literal containing the following about this element: (top, right, bottom, left)
457
     */
458
    region: function(node) {
459
        var xy = DOM.getXY(node),
460
            ret = false;
461
 
462
        if (node && xy) {
463
            ret = DOM._getRegion(
464
                xy[1], // top
465
                xy[0] + node.offsetWidth, // right
466
                xy[1] + node.offsetHeight, // bottom
467
                xy[0] // left
468
            );
469
        }
470
 
471
        return ret;
472
    },
473
 
474
    /**
475
     * Find the intersect information for the passed nodes.
476
     * @method intersect
477
     * @for DOM
478
     * @param {HTMLElement} element The first element
479
     * @param {HTMLElement | Object} element2 The element or region to check the interect with
480
     * @param {Object} altRegion An object literal containing the region for the first element if we already have the data (for performance e.g. DragDrop)
481
     * @return {Object} Object literal containing the following intersection data: (top, right, bottom, left, area, yoff, xoff, inRegion)
482
     */
483
    intersect: function(node, node2, altRegion) {
484
        var r = altRegion || DOM.region(node), region = {},
485
            n = node2,
486
            off;
487
 
488
        if (n.tagName) {
489
            region = DOM.region(n);
490
        } else if (Y.Lang.isObject(node2)) {
491
            region = node2;
492
        } else {
493
            return false;
494
        }
495
 
496
        off = getOffsets(region, r);
497
        return {
498
            top: off[TOP],
499
            right: off[RIGHT],
500
            bottom: off[BOTTOM],
501
            left: off[LEFT],
502
            area: ((off[BOTTOM] - off[TOP]) * (off[RIGHT] - off[LEFT])),
503
            yoff: ((off[BOTTOM] - off[TOP])),
504
            xoff: (off[RIGHT] - off[LEFT]),
505
            inRegion: DOM.inRegion(node, node2, false, altRegion)
506
        };
507
 
508
    },
509
    /**
510
     * Check if any part of this node is in the passed region
511
     * @method inRegion
512
     * @for DOM
513
     * @param {Object} node The node to get the region from
514
     * @param {Object} node2 The second node to get the region from or an Object literal of the region
515
     * @param {Boolean} all Should all of the node be inside the region
516
     * @param {Object} altRegion An object literal containing the region for this node if we already have the data (for performance e.g. DragDrop)
517
     * @return {Boolean} True if in region, false if not.
518
     */
519
    inRegion: function(node, node2, all, altRegion) {
520
        var region = {},
521
            r = altRegion || DOM.region(node),
522
            n = node2,
523
            off;
524
 
525
        if (n.tagName) {
526
            region = DOM.region(n);
527
        } else if (Y.Lang.isObject(node2)) {
528
            region = node2;
529
        } else {
530
            return false;
531
        }
532
 
533
        if (all) {
534
            return (
535
                r[LEFT]   >= region[LEFT]   &&
536
                r[RIGHT]  <= region[RIGHT]  &&
537
                r[TOP]    >= region[TOP]    &&
538
                r[BOTTOM] <= region[BOTTOM]  );
539
        } else {
540
            off = getOffsets(region, r);
541
            if (off[BOTTOM] >= off[TOP] && off[RIGHT] >= off[LEFT]) {
542
                return true;
543
            } else {
544
                return false;
545
            }
546
 
547
        }
548
    },
549
 
550
    /**
551
     * Check if any part of this element is in the viewport
552
     * @method inViewportRegion
553
     * @for DOM
554
     * @param {HTMLElement} element The DOM element.
555
     * @param {Boolean} all Should all of the node be inside the region
556
     * @param {Object} altRegion An object literal containing the region for this node if we already have the data (for performance e.g. DragDrop)
557
     * @return {Boolean} True if in region, false if not.
558
     */
559
    inViewportRegion: function(node, all, altRegion) {
560
        return DOM.inRegion(node, DOM.viewportRegion(node), all, altRegion);
561
 
562
    },
563
 
564
    _getRegion: function(t, r, b, l) {
565
        var region = {};
566
 
567
        region[TOP] = region[1] = t;
568
        region[LEFT] = region[0] = l;
569
        region[BOTTOM] = b;
570
        region[RIGHT] = r;
571
        region.width = region[RIGHT] - region[LEFT];
572
        region.height = region[BOTTOM] - region[TOP];
573
 
574
        return region;
575
    },
576
 
577
    /**
578
     * Returns an Object literal containing the following about the visible region of viewport: (top, right, bottom, left)
579
     * @method viewportRegion
580
     * @for DOM
581
     * @return {Object} Object literal containing the following about the visible region of the viewport: (top, right, bottom, left)
582
     */
583
    viewportRegion: function(node) {
584
        node = node || Y.config.doc.documentElement;
585
        var ret = false,
586
            scrollX,
587
            scrollY;
588
 
589
        if (node) {
590
            scrollX = DOM.docScrollX(node);
591
            scrollY = DOM.docScrollY(node);
592
 
593
            ret = DOM._getRegion(scrollY, // top
594
                DOM.winWidth(node) + scrollX, // right
595
                scrollY + DOM.winHeight(node), // bottom
596
                scrollX); // left
597
        }
598
 
599
        return ret;
600
    }
601
});
602
})(Y);
603
 
604
 
605
}, '3.18.1', {"requires": ["dom-base", "dom-style"]});