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