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 < 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]; },
//设置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的所有部分都写完了,哈哈,越来越佩服自己的耐力了![](shades_smile.gif)
下一步决定写写Scriptaculous这个超级流行的效果库 |