javascript YUI 读码日记之 YAHOO.util.Dom - Part.4

  var getXY = function() {

  // 判断是否是 IE

  if (document.documentElement.getBoundingClientRect) {

  // 注1

  return function(el) {

  var box = el.getBoundingClientRect();

  var rootNode = el.ownerDocument;

  return [box.left +

  Y.Dom.getDocumentScrollLeft(rootNode), box.top +

  Y.Dom.getDocumentScrollTop(rootNode)];

  };

  } else {

  return function(el) {

  var pos = [el.offsetLeft, el.offsetTop];

  var parentNode = el.offsetParent;

  // 判断是否在 Safari 下,节点是否为 absolute ,

  // 并且父元素是否为 body

  // 注2.

  var accountForBody = (isSafari &&

  Y.Dom.getStyle(el, 'position') == 'absolute' &&

  el.offsetParent == el.ownerDocument.body);

  // 如果父元素不是自身

  if (parentNode != el) {

  while (parentNode) {

  pos[0] += parentNode.offsetLeft;

  pos[1] += parentNode.offsetTop;

  if (!accountForBody && isSafari &&

  Y.Dom.getStyle(parentNode,'position')

  == 'absolute' ) {

  accountForBody = true;

  }

  parentNode = parentNode.offsetParent;

  }

  }

  // 还是针对 Safari 的

  if (accountForBody) { //safari doubles in this case

  pos[0] -= el.ownerDocument.body.offsetLeft;

  pos[1] -= el.ownerDocument.body.offsetTop;

  }

  parentNode = el.parentNode;

  // account for any scrolled ancestors

  while ( parentNode.tagName &&

  !patterns.ROOT_TAG.test(parentNode.tagName) )

  {

  // work around opera inline/table scrollLeft/Top bug

  // 注3.

  if (Y.Dom.getStyle(parentNode, 'display')

  .search(/^inline|table-row.*$/i)) {

  pos[0] -= parentNode.scrollLeft;

  pos[1] -= parentNode.scrollTop;

  }

  parentNode = parentNode.parentNode;

  }

  return pos;

  };

  }

  }() // NOTE: Executing for loadtime branching注. 有关 IE 的 getBoundingClientRect 方法,可以参考这里。

  注. Safari 的 BUG,详细情况参见这里。

  注. 参见老外的原话(出处):

  "- Remove parent scroll UNLESS that parent is inline or a table

  to work around Opera inline/table scrollLeft/Top bug"

  Fixed in Opera 9.5. (also, Opera 9.5 supports getBoundingClientRect

  and getClientRects.)最后,有关更多 DOM 的兼容性,可以参看 PPK 的总结(怎么又是他)。