(十三).Prototype1.5 rc21.5 rc2)版指南最后一篇之Position

Positionprototype中定義的一個對象,提供了操作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的祖先節(jié)點的位置,如果沒有就是相對于 body的位置,跟style.topstyle.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 <  this.offset[1] + element.offsetHeight &&
            x >= this.offset[0] &&
            x <  this.offset[0] + element.offsetWidth);
  },

//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.offset[1] + element.offsetHeight &&
            this.xcomp >= this.offset[0] &&
            this.xcomp <  this.offset[0] + element.offsetWidth);
  },

  // 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];
  },

//設置targetsource的位置,大小 
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’;
  },

//elementposition設置為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’;;
  },

//elementposition設置為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這個超級流行的效果庫

Prototype1.5的下載為什么不簡單點

這幾天在論壇和博客上看到很多人問Prototype1.5怎么下載,為什么下載這么困難呢?
Prototype的官方網站是:http://prototype.conio.net/,如果你一下子找不到,到google上搜索Prototype就找到了
下載當然要到官方網站下載了,但是問題是Prototype官方網站更新太慢,首頁上的下載連接還是prototype1.4的,而且只是一個單獨的js文件
那么怎么下載最新版本的呢?
1,如果你只想得到一個單獨的js文件使用的話,其實官方網站提供了最新版1.5的下載, 下面連接就是下載地址了http://dev.rubyonrails.org/browser/trunk/railties/html/javascripts/prototype.js?format=raw
2,如果你想得到詳細的源文件以及測試代碼,需要通過svn下載:使用下面的命令就可以了:svn co http://dev.rubyonrails.org/svn/rails/spinoffs/prototype
如果你沒有svn的話,我已經下載打包了傳到51js論壇中,查看下面連接的帖子中有下載的:http://bbs.51js.com/viewthread.php?tid=65070&highlight=prototype

想必很多prototype愛好者都一直在等待著prototype1.5的發(fā)布,雖然等待的時間很長,但是這一令人激動的一天終于到來了
因為網友提醒,今天訪問prototype網站,發(fā)現原來的網址已經自動跳轉到新的網站去了,作者使用了一個獨立的域名http://www.prototypejs.org/
剛才在google里搜索prototype,發(fā)現搜索結果中出現的已經是新網站了,google爬蟲也蠻勤快的嘛
更讓人高興的是,一向被人詬病的文檔問題這一版有了非常大的提高,可以說是有了質的飛躍,以前的版本基本上沒有文檔,要使用只有自己理解了,
現在在它的官方網站上有專門的API參考以及一些使用的例子,看來作者真正的關于這個問題來了,prototype愛好者應該高興一把了哈哈,趕快到prototype官方網站下載了Engoy如果感覺閱讀英文是一種折磨的話,可以參考我以前寫的prototype 1.5使用指南系列文章.

--聲明:該使用指南文章為轉載,由于是來源于多次轉載,未找到原出處。再次感謝作者與翻譯人員。



------君臨天下,舍我其誰------