不好意思,说反了:是当标签处于另一个标签中时,如果这个标签有滚动(auto),那它的坐标定位怎么改也是绝对定位,而无法使用相对定位处理我用的是prototype中的Postion的两个方法:relativize和absolutize。
先absolutize后,移动拖动对象,然后再relativize回去时,如果没有滚动条,则能正确显示在我放置的位置,当有滚动条时,则会是:放置的位置-滚动条的那个层与页面top和left的偏移量

解决方案 »

  1.   

    谢谢两位,问题已经解决了,可能是prototype本身的bug吧。我查了一下HTML文档,当取绝对坐标"absolute "时,其解释如下:
    absolute :Object is positioned relative to parent element's position—or to the body object if its parent element is not positioned—using the top and left properties. 
    经过测试,如果标签的所有祖先节点中,有任何一个是可滚动的(overflow,overflow-y,overflow-x其中一个属性的值为auto或scroll),那标签的绝对定位就是在此标签中的坐标位置,而不是对于BODY的。而prototype1.4在实现Position.absolutize方法时是这样写的:
    Position.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';
    };
    其中Position.positionedOffset就是取当前标签到body的偏移量,然后将信息存入_original*的相关属性中,等到调用Position.relativize时,再从这些_original*属性中从新计算出当前标签的相对位置。再看一下Position.positionedOffset的实现:
    Position.positionedOffset = function (element) {
    var valueT = 0, valueL = 0;

    do {
    valueT += element.offsetTop || 0;
    valueL += element.offsetLeft || 0;
    element = element.offsetParent;
    if (element) {
    p = Element.getStyle(element, "position");
    if (p == "relative" || p == "absolute") {
    break;
    }
    }
    } while (element);
    return [valueL, valueT];
    };
    更改中间判断中断的部分为:
    if (element) {
        var scrollable = [element.style.overflow, element.style.overflowX, element.style.overflowY];
        p = Element.getStyle(element, "position");
        if (p == "relative" || p == "absolute" || scrollable.contains( "auto" ) || scrollable.contains( "scroll" )) {
            break;
        }
    }
    更改后位置处理的问题的解决了,下面的用于测试的HTML:
    <div style="width:500px;overflow-y:auto;height:300px">
    <div style="height:200px">
    </div>
    <div style="height:300px">
    <div id="test" style="height:20px">test</div>
        <input type="button" value="abs" onclick="Position.absolutize(${'test'});">
        <input type="button" value="rel" onclick="Position.relativize(${'test'});">
        </div>
    </div>
    <div style="width:500px;overflow-y:auto;height:300px">
        <div id="test1" style="height:20px">test</div>
        <input type="button" value="abs" onclick="Position.absolutize(${'test1'});">
        <input type="button" value="rel" onclick="Position.relativize(${'test1'});">
    </div>
    此问题还有待进一步测试,如果没问题了就来结贴
      

  2.   

    说明一下,原来出的问题其实就是因为在变为绝对坐标时的位置就已经错了,而拖动的代码是通过鼠标位置进行处理而不存在拖动时的错位,当鼠标释放时,此时的位置已与存在_original*中的位置有所偏差(这部分偏差就是第一个可滚动的祖先节点到BODY的偏移量),再次使用Position.relativize变回相对位置时,就会加上位置的偏差,导致看起来像绝对定位的位置。