您好,欢迎访问一九零五行业门户网

Prototype1.5 rc2版指南最后一篇之Position_prototype

position是prototype中定义的一个对象,提供了操作dom中与位置相关的方法,要很好的理解元素在页面中的位置,可以参考这篇文章:relatively absolute
具体代码如下,按照代码说说,其中英文是作者的注释,中文红色的才是偶的说明或翻译英文的注释,采用顶式注释法(注释在要说明的代码的上面)说明
  // set to true if needed, warning: firefox performance problems
  // not neeeded for page scrolling, only if draggable contained in
  // scrollable elements
  //只有在使用拖动的时候元素包含在有滚动条的元素中才需要设置为true
  includescrolloffsets: false,
  // must be called before calling withinincludingscrolloffset, every time the
  // page is scrolled
  //当页面被scrolled后,使用withinincludingscrolloffset的时候需要先调用这个方法
  prepare: function() {
    //横向滚动条滚动的距离
    this.deltax =  window.pagexoffset
                || document.documentelement.scrollleft
                || document.body.scrollleft
                || 0;
    //纵向滚动条滚动的距离
    this.deltay =  window.pageyoffset
                || document.documentelement.scrolltop
                || document.body.scrolltop
                || 0;
  },
//元素由于滚动条偏移的总距离 
realoffset: function(element) {
    var valuet = 0, valuel = 0;
    do {
      valuet += element.scrolltop  || 0;
      valuel += element.scrollleft || 0;
      element = element.parentnode;
    } while (element);
    return [valuel, valuet];
  },
//元素在页面中由offsetparent累积的offset,当offsetparent都没有滚动条时,就是元素在页面中的位置
cumulativeoffset: function(element) {
    var valuet = 0, valuel = 0;
    do {
      valuet += element.offsettop  || 0;
      valuel += element.offsetleft || 0;
      element = element.offsetparent;
    } while (element);
    return [valuel, valuet];
  },
//元素相对于containing block(nearest positioned ancestor)的位置,也就是相对于最近的一个position设置为relative或者absolute的祖先节点的位置,如果没有就是相对于body的位置,跟style.top,style.left一样?
positionedoffset: function(element) {
    var valuet = 0, valuel = 0;
    do {
      valuet += element.offsettop  || 0;
      valuel += element.offsetleft || 0;
      element = element.offsetparent;
      if (element) {
        if(element.tagname=='body') break;
        var p = element.getstyle(element, 'position');
        if (p == 'relative' || p == 'absolute') break;
      }
    } while (element);
    return [valuel, valuet];
  },
//offsetparent
  offsetparent: function(element) {
    if (element.offsetparent) return element.offsetparent;
    if (element == document.body) return element;
    while ((element = element.parentnode) && element != document.body)
      if (element.getstyle(element, 'position') != 'static')
        return element;
    return document.body;
  },
// caches x/y coordinate pair to use with overlap
  //判断指定的位置是否在元素内
  within: function(element, x, y) {
    if (this.includescrolloffsets)
      return this.withinincludingscrolloffsets(element, x, y);
    this.xcomp = x;
    this.ycomp = y;
    this.offset = this.cumulativeoffset(element);
    return (y >= this.offset[1] &&
            y             x >= this.offset[0] &&
            x   },
//跟within差不多,不过考虑到滚动条,也许是在元素上面,但不是直接在上面,因为滚动条也许已经使元素不可见了 
withinincludingscrolloffsets: function(element, x, y) {
    var offsetcache = this.realoffset(element);
    this.xcomp = x + offsetcache[0] - this.deltax;
    this.ycomp = y + offsetcache[1] - this.deltay;
    this.offset = this.cumulativeoffset(element);
    return (this.ycomp >= this.offset[1] &&
            this.ycomp             this.xcomp >= this.offset[0] &&
            this.xcomp   },
  // within must be called directly before
  //在调用这个方法前,必须先调用within,返回在with指定的位置在水平或者垂直方向上占用的百分比
  overlap: function(mode, element) { 
    if (!mode) return 0; 
    if (mode == 'vertical')
      return ((this.offset[1] + element.offsetheight) - this.ycomp) /
        element.offsetheight;
    if (mode == 'horizontal')
      return ((this.offset[0] + element.offsetwidth) - this.xcomp) /
        element.offsetwidth;
  },
//返回元素相对页面的真实位置 
page: function(forelement) {
    var valuet = 0, valuel = 0;
    var element = forelement;
    do {
      valuet += element.offsettop  || 0;
      valuel += element.offsetleft || 0;
      // safari fix
      if (element.offsetparent==document.body)
        if (element.getstyle(element,'position')=='absolute') break;
    } while (element = element.offsetparent);
    element = forelement;
    do {
      if (!window.opera || element.tagname=='body') {
        valuet -= element.scrolltop  || 0;
        valuel -= element.scrollleft || 0;
      }
    } while (element = element.parentnode);
    return [valuel, valuet];
  },
//设置target为source的位置,大小 
clone: function(source, target) {
    var options = object.extend({
      setleft:    true,
      settop:     true,
      setwidth:   true,
      setheight:  true,
      offsettop:  0,
      offsetleft: 0
    }, arguments[2] || {})
    // find page position of source
    source = $(source);
    var p = position.page(source);
    // find coordinate system to use
    target = $(target);
    var delta = [0, 0];
    var parent = null;
    // delta [0,0] will do fine with position: fixed elements,
    // position:absolute needs offsetparent deltas
    if (element.getstyle(target,'position') == 'absolute') {
      parent = position.offsetparent(target);
      delta = position.page(parent);
    }
    // correct by body offsets (fixes safari)
    if (parent == document.body) {
      delta[0] -= document.body.offsetleft;
      delta[1] -= document.body.offsettop;
    }
    // set position
    if(options.setleft)   target.style.left  = (p[0] - delta[0] + options.offsetleft) + 'px';
    if(options.settop)    target.style.top   = (p[1] - delta[1] + options.offsettop) + 'px';
    if(options.setwidth)  target.style.width = source.offsetwidth + 'px';
    if(options.setheight) target.style.height = source.offsetheight + 'px';
  },
//将element的position设置为absolute的模式 
absolutize: function(element) {
    element = $(element);
    if (element.style.position == 'absolute') return;
    position.prepare();
    var offsets = position.positionedoffset(element);
    var top     = offsets[1];
    var left    = offsets[0];
    var width   = element.clientwidth;
    var height  = element.clientheight;
    element._originalleft   = left - parsefloat(element.style.left  || 0);
    element._originaltop    = top  - parsefloat(element.style.top || 0);
    element._originalwidth  = element.style.width;
    element._originalheight = element.style.height;
    element.style.position = 'absolute';
    element.style.top    = top + 'px';;
    element.style.left   = left + 'px';;
    element.style.width  = width + 'px';;
    element.style.height = height + 'px';;
  },
//将element的position设置为absolute的模式 
relativize: function(element) {
    element = $(element);
    if (element.style.position == 'relative') return;
    position.prepare();
    element.style.position = 'relative';
    var top  = parsefloat(element.style.top  || 0) - (element._originaltop || 0);
    var left = parsefloat(element.style.left || 0) - (element._originalleft || 0);
    element.style.top    = top + 'px';
    element.style.left   = left + 'px';
    element.style.height = element._originalheight;
    element.style.width  = element._originalwidth;
  }
}
// safari returns margins on body which is incorrect if the child is absolutely
// positioned.  for performance reasons, redefine position.cumulativeoffset for
// khtml/webkit only.
if (/konqueror|safari|khtml/.test(navigator.useragent)) {
  position.cumulativeoffset = function(element) {
    var valuet = 0, valuel = 0;
    do {
      valuet += element.offsettop  || 0;
      valuel += element.offsetleft || 0;
      if (element.offsetparent == document.body)
        if (element.getstyle(element, 'position') == 'absolute') break;
element = element.offsetparent;
    } while (element);
return [valuel, valuet];
  }
}
终于把prototype的所有部分都写完了,哈哈,越来越佩服自己的耐力了
下一步决定写写scriptaculous这个超级流行的效果库
其它类似信息

推荐信息