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