2012-02-14 79 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