~mnordhoff/loggerhead/valid-html

« back to all changes in this revision

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

  • Committer: Matt Nordhoff
  • Date: 2008-10-25 21:09:19 UTC
  • mfrom: (229.2.4 trunk)
  • Revision ID: mnordhoff@mattnordhoff.com-20081025210919-cbnlvd2ow5qpnxvh
Merge trunk.

This undoes the whitespace adjustment I made in macros.pt.

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