2012-02-14 78 views
0

在以下丰富的编辑器控件(CLEditor,available here)中,盒子底部的拖动抓手可以让我向下拖动并释放,向下和向上拖动并释放好,但向上拖动会导致永远不会触发endDrag事件我不得不实施一个超时kludge。你知道我可能在jQuery/Javascript中做错了吗?Javascript/jQuery - 这个endDrag事件怎么没有正确触发?

注意:我在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> 
+0

你有这个地方的例子吗?此外,执行Drag(e)的final if语句永远不会发生,因为您已确信iMousePos永远不会成为iMin。 – Suroot 2012-02-15 01:21:13

+0

@Suroot我刚刚在jsFiddle上创建了一个演示。请参阅原始问题中的链接。你会看到的是,你可以点击一个拖动抓手向下好,你可以点击然后向上,但如果你点击并立即拖动,它不会让你。注释掉“kludge”块,它仍然会失败。 – Volomike 2012-02-15 13:58:59

回答

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)时,浏览器无法跟上(甚至是谷歌浏览器)。如果你向上调整足够快的速度,你的鼠标速度会很快,endDrag()永远不会触发。这只是浏览器中拖曳事件的浏览器怪癖。

如果您移动鼠标速度更慢,问题就会消失。 问题是一旦焦点移动到IFRAME中,mousemove事件就会丢失。

0

我可能会被误解的问题,但如果问题是向上拖动,使大小< 160从来没有真正导致最终拖累;这个问题将是下面的if语句。

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

Math.max让iMousePos成为不可能的< iMin。它可能是< =但从来没有<。

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

+0

是的,这也是我得出的结论。只要您的鼠标向上移动速度足够快以将鼠标悬停在IFRAME上,您的事件就会丢失。我期待看到你提出的。这就是为什么我现在不把我的答案(列在这里)作为正确的答案。但是,如果缓慢向上拖动,问题不会发生在http:// jsfiddle上。net/bCBRW/example。 – Volomike 2012-02-18 17:08:02

+0

我认为这就是结论,也许我需要编辑整篇文章并重新回答答案。重点是,如果您在IFRAME下创建抓手控件,则所有浏览器都会导致事件丢失,一旦向上移动的鼠标移动速度足够快,以至于事件在IFRAME中丢失。 – Volomike 2012-02-19 22:39:46