[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/yuilib/3.17.2/dom-screen/ -> dom-screen.js (source)

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


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1