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

У вас есть пример этого где-нибудь? Кроме того, executeDrag (e) окончательный оператор if никогда не может произойти, поскольку вы уверены, что iMousePos никогда не может быть НИЖЕ iMin. – Suroot

+0

@Suroot Я только что создал демонстрацию на jsFiddle. См. Ссылку в исходном вопросе. То, что вы увидите, это то, что вы можете щелкнуть мышкой вниз, хорошо, вы можете щелкнуть вниз, а затем все в порядке, но если вы нажмете и сразу перетащите, это не позволит вам. Комментируйте блок «kludge», и он все равно потерпит неудачу. – Volomike

ответ

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); 
});​ 

Так, во всяком случае, это сроки. Я попробовал полностью отдельный редактор расширенного редактора и обнаружил, что браузер не может продолжать работу (даже Google Chrome) при изменении размера элемента управления Richedit (который в основном использует IFRAME). Если вы достаточно быстро изменяете размер вверх, ваша мышь слишком быстро продвигается вперед, а endDrag() никогда не срабатывает. Это просто приключение браузера с событиями перетаскивания в браузере.

Если вы двигаете мышь медленнее, проблема исчезнет. Проблема в том, что событие mousemove теряется после того, как фокус переходит в IFRAME.

0

я мог бы быть неправильное понимание вопроса, но если проблема в том, что перетаскивание вверх, чтобы сделать размер < 160 никогда не приводит к конечному сопротивление; вопрос будет приведен ниже.

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

The Math.max сделало невозможным для iMousePos быть < IMIN. Это может быть < = но никогда <.

Это на самом деле одна проблема; но это не основная проблема, которую вы ищете. Проблема, которую я вижу, связана с маскировкой событий. Это происходит, даже если вы перетаскиваете вниз, а затем выполняете резервное копирование; вы потеряете событие mousemove. Так как возможно иметь обновление, в котором положение мыши изменяется более чем на 1px, возможно, что событие mousedown теряется, когда мышь выходит из области .gripper и в текстовое поле. Я посмотрю, когда я получу еще немного времени и буду обновлять; но есть решение, так как это было сделано здесь на SO, если вы отредактируете комментарий. Скорее всего, это будет похоже на установку события mousemove в документ глобально, а затем наличие глобального состояния, указывающего, перетаскиваете ли вы его. Затем происходит mousedown/mouseup и задается глобальная переменная перетаскивания для работы метода перемещения.

+0

Да, это тот вывод, к которому я пришел. Как только ваша мышь движется достаточно быстро, чтобы навести на IFRAME, ваше событие потеряется. Я с нетерпением жду того, что вы придумали. Вот почему я не отмечаю свой ответ (указанный здесь) на данный момент как правильный ответ. Однако если вы медленно поднимаете вверх, проблема не возникает с http: // jsfiddle.net/bCBRW/пример. – Volomike

+0

Я думаю, что это заключение здесь, и, возможно, мне нужно отредактировать весь этот пост и переформулировать ответ. Дело в том, что если вы создадите управление захватом под IFRAME, все браузеры заставляют событие потеряться после того, как верхняя mousemove движется достаточно быстро, чтобы событие потерялось в IFRAME. – Volomike

Смежные вопросы