Javascript / jQuery - 为什么这个endDrag事件无法正常启动?

时间:2012-02-14 20:30:48

标签: javascript jquery drag-and-drop mouseevent

在下面的丰富编辑器控件(CLEditor,available here)中,框底部的拖动抓手让我向下拖动并释放好,向下和向上拖动并释放正常,但向上拖动会导致它永远不会触发endDrag事件,我必须实现超时kludge。你知道我在jQuery / Javascript中可能做错了吗?

注意:我在jsFiddle here上创建了一个示例。

<script type="text/javascript">
var textarea, staticOffset;
var iLastMousePos = 0;
var iMin = 160;
var prevTimeout = null;

function startDrag(e) {
    console.log('startDrag() event fired');
    textarea = $(e.data.el);
    textarea.blur();
    iLastMousePos = mousePosition(e).y;
    staticOffset = textarea.height() - iLastMousePos;
    textarea.css('opacity', 0.25);
    $(document).mousemove(performDrag).mouseup(endDrag);
    return false;
}

function performDrag(e) {
    console.log('performDrag() event fired');
    var iThisMousePos = mousePosition(e).y;
    var iMousePos = staticOffset + iThisMousePos;

    // kludge start
    // Try implementing without this and the endDrag event won't fire
    // if you immediately start dragging upwards
    if (iLastMousePos >= (iThisMousePos)) {
        console.log('kludge implemented');
        iMousePos -= 60;
        if (iMousePos < iMin) {
            endDrag();
            return false;
        }
        if (!prevTimeout) {
            prevTimeout = setTimeout('endDrag();clearTimeout();',600);
        }
    }
    // end kludge

    iLastMousePos = iThisMousePos;
    iMousePos = Math.max(iMin, iMousePos);
    textarea.height(iMousePos + 'px');
    if (iMousePos < iMin) {
        endDrag();
    }
    return false;
}

function endDrag() {
    console.log('endDrag() event fired');
    prevTimeout = null;
    $(document).unbind('mousemove', performDrag).unbind('mouseup', endDrag);
    textarea = $('.cleditorMain:first'); // got a better selector?
    textarea.css('opacity', 1);
    textarea.focus();
    textarea = null;
    staticOffset = null;
    iLastMousePos = 0;
    var editor = $("#fldMessage").cleditor()[0];
    editor.refresh();
    if (!$.browser.msie) { // there's a quirk in IE
        editor.focus();
    }   
}

function mousePosition(e) {
    return { x: e.clientX + document.documentElement.scrollLeft, y: e.clientY + document.documentElement.scrollTop };
};

$(document).ready(function(){

    $('#fldMessage').cleditor({
        width:'100%',
        height:'100%',
        useCSS:true,
        styles:[["Paragraph", "<p>"], ["Header 1", "<h1>"], ["Header 2", "<h2>"],
               ["Header 3", "<h3>"],  ["Header 4","<h4>"],  ["Header 5","<h5>"],
               ["Header 6","<h6>"],  ["Code","<pre>"]],
        docCSSFile:"js/jquery.cleditor/jquery.cleditor.doc.css"
    }).focus(); 

    // BTW, if you have a more efficient selector than .cleditorMain:first, please let me know
    $('.cleditorMain:first').after('<div class="gripper" />');
    $('.cleditorMain:first').next('.gripper').css({
                'background':'transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABsAAAAFCAMAAACD1meMAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAAGUExURbu7u////3iwjPUAAAACdFJOU/8A5bcwSgAAABRJREFUeNpiYMADGHEDBhroAwgwAA9QADeT0qnSAAAAAElFTkSuQmCC) no-repeat scroll center 2px',
                'cursor':'s-resize',
                'height':'9px',
                'overflow':'hidden'
    }).bind("mousedown",{el: $('.cleditorMain:first')} , startDrag);

});
</script>

<fieldset style="min-height:160px">
    <textarea id="fldMessage" name="fldMessage" rows="4"></textarea>
</fieldset>

2 个答案:

答案 0 :(得分:0)

我可能会误解这个问题,但是如果问题是向上拖动以使其大小&lt; 160实际上从未导致拖尾;问题是下面的if语句。

iLastMousePos = iThisMousePos;
iMousePos = Math.max(iMin, iMousePos);
textarea.height(iMousePos + 'px');
if (iMousePos < iMin) {
    endDrag();
}

Math.max使iMousePos无法&lt;算我一个。它可能是&lt; =但从不&lt;。

这实际上是一个问题;但这不是您正在寻找的潜在问题。我看到的问题似乎与掩盖事件有关。即使你向下拖动然后再向后移动,也会发生这种情况;你将松开mousemove事件。由于可以在鼠标位置变化超过1px的情况下进行更新,因此当鼠标离开.gripper区域并进入textarea时,mousedown事件可能会丢失。当我得到更多时间并且会更新时,我会看但是有一个解决方案,因为如果您编辑评论,就可以在此处完成。最有可能的事情就是将mousemove事件设置为全局文档,然后使用全局表示是否拖动。然后发生mousedown / mouseup并设置全局拖动变量以使move方法有效。

答案 1 :(得分:0)

我找到了答案,这是时机 - 所有浏览器中的浏览器怪癖。我也使用了修改后的例子:

http://jsfiddle.net/bCBRW/

<script type="text/javascript">
var textarea, staticOffset;
var iLastMousePos = 0;
var iMin = 160;

function startDrag(e) {
    textarea = $(e.data.el);
    textarea.blur();
    iLastMousePos = mousePosition(e).y;
    staticOffset = textarea.height() - iLastMousePos;
    $(document).mousemove(performDrag).mouseup(endDrag);
    return false;
}

function performDrag(e) {
    var iThisMousePos = mousePosition(e).y;
    var iMousePos = staticOffset + iThisMousePos;

    if (iLastMousePos >= (iThisMousePos)) {
        iMousePos -= 4;
    }

    iLastMousePos = iThisMousePos;
    iMousePos = Math.max(iMin, iMousePos);
    textarea.height(iMousePos + 'px');
    if (iMousePos < iMin) {
        endDrag();
    }
    return false;
}

function endDrag() {
    $(document).unbind('mousemove', performDrag).unbind('mouseup', endDrag);
    textarea = $('.cleditorMain:first');
    textarea.focus();
    textarea = null;
    staticOffset = null;
    iLastMousePos = 0;
    var editor = $("#fldMessage").cleditor()[0];
    editor.refresh();
    if (!$.browser.msie) {
        editor.focus();
    }
}

function mousePosition(e) {
    return {
        x: e.clientX + document.documentElement.scrollLeft,
        y: e.clientY + document.documentElement.scrollTop
    };
};

$(document).ready(function() {
    $('#fldMessage').cleditor({
        width: '99%',
        height: '100%',
        useCSS: true,
        styles: [["Paragraph", "<p>"], ["Header 1", "<h1>"], ["Header 2", "<h2>"],
                           ["Header 3", "<h3>"], ["Header 4", "<h4>"], ["Header 5", "<h5>"],
                           ["Header 6", "<h6>"], ["Code", "<pre>"]],
    }).focus();

    $('.cleditorMain:first').after('<div class="gripper" />');
    $('.cleditorMain:first').next('.gripper').css({
        'background': 'transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABsAAAAFCAMAAACD1meMAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAAGUExURbu7u////3iwjPUAAAACdFJOU/8A5bcwSgAAABRJREFUeNpiYMADGHEDBhroAwgwAA9QADeT0qnSAAAAAElFTkSuQmCC) no-repeat scroll center 2px',
        'cursor': 's-resize',
        'height': '9px',
        'overflow': 'hidden'
    }).bind("mousedown", {
        el: $('.cleditorMain:first')
    }, startDrag);
});​

所以,无论如何,这是时机。我尝试了一个完全独立的富编辑器控件,发现当你调整一个richedit控件(基本上使用IFRAME)时,浏览器无法跟上(甚至谷歌Chrome)。如果你足够快地向上调整大小,你的鼠标前进得太快而且endDrag()永远不会触发。这只是一个浏览器怪癖,在浏览器中有拖动事件。

如果您将鼠标移动得更慢,问题就会消失。 问题是,一旦焦点进入IFRAME,mousemove事件就会丢失。