Javascript与jQuery:单击并双击相同的元素,不同的效果,一个禁用另一个

我有一个有趣的情况 – 我有一个表格行,当我点击“展开”button时,显示它是隐藏的对应表格。 包含展开button的原始(未隐藏)行也在某个单元格中具有某些内容,点击后该单元格可以编辑。 我想摆脱扩大button,并通过双击行本身的任何地方,包括单击它时可以编辑的字段,启用行的扩展。 你已经可以闻到麻烦了。

当我双击一行时,在发生dblclick之前,首先触发两个点击事件。 这意味着如果我双击该字段,它将变成一个可编辑的,并且该行将展开。 我想阻止这一点。 我想要doubleclick来防止单击发射,并单击执行照常。

使用event.stopPropagation()显然是行不通的,因为它们是两个不同的事件。

有任何想法吗?

编辑(一些半伪代码):

原始版本:

<table> <tbody> <tr> <td><a href="javascript:$('#row_to_expand').toggle();" title="Expand the hidden row">Expand Row</a></td> <td>Some kind of random data</td> <td><?= $editable_cell_which_turns_into_an_input_field_on_single_click[0]->value("First editable value") ?></td> <td><?= $editable_cell_which_turns_into_an_input_field_on_single_click[1]->value("Second editable value") ?></td> <td><?= $editable_cell_which_turns_into_an_input_field_on_single_click[2]->value("Third editable value") ?></td> <!-- ... --> <td><?= $editable_cell_which_turns_into_an_input_field_on_single_click[n]->value("Nth editable value") ?></td> </tr> <tr style="display: none" id="row_to_expand"> <td colspan="n">Some hidden data</td> </tr> </tbody> </table> 

期望的版本:

 <table> <tbody> <tr ondblclick="$('#row_to_expand').toggle()"> <td>Some kind of random data</td> <td><?= $editable_cell_which_turns_into_an_input_field_on_single_click[0]->value("First editable value") ?></td> <td><?= $editable_cell_which_turns_into_an_input_field_on_single_click[1]->value("Second editable value") ?></td> <td><?= $editable_cell_which_turns_into_an_input_field_on_single_click[2]->value("Third editable value") ?></td> <!-- ... --> <td><?= $editable_cell_which_turns_into_an_input_field_on_single_click[n]->value("Nth editable value") ?></td> </tr> <tr style="display: none" id="row_to_expand"> <td colspan="n">Some hidden data</td> </tr> </tbody> </table> 

干杯

总体思路:

  1. 在第一次点击时,不要调用相关的函数(比如说single_click_function())。 而是设置一个定时器一段时间(比如x)。 如果在这段时间内没有再次点击,请进入single_click_function()。 如果我们得到一个,请调用double_click_function()

  2. 一旦收到第二次点击,定时器将被清除。 一旦x毫秒失效,它也将被清除。

顺便说一下,检查保罗的答复: 当检测到双击事件并且当然整个线程需要取消点击/鼠标事件 ! 🙂

更好的回答: https : //stackoverflow.com/a/7845282/260610

工作演示

 $('#alreadyclicked').val('no click'); $('td.dblclickable').on('click',function(){ var $button=$(this); if ($button.data('alreadyclicked')){ $button.data('alreadyclicked', false); // reset $('#alreadyclicked').val('no click'); if ($button.data('alreadyclickedTimeout')){ clearTimeout($button.data('alreadyclickedTimeout')); // prevent this from happening } // do what needs to happen on double click. $('#action').val('Was double clicked'); }else{ $button.data('alreadyclicked', true); $('#alreadyclicked').val('clicked'); var alreadyclickedTimeout=setTimeout(function(){ $button.data('alreadyclicked', false); // reset when it happens $('#alreadyclicked').val('no click'); $('#action').val('Was single clicked'); // do what needs to happen on single click. // use $button instead of $(this) because $(this) is // no longer the element },300); // <-- dblclick tolerance here $button.data('alreadyclickedTimeout', alreadyclickedTimeout); // store this id to clear if necessary } return false; }); 

显然使用<td class="dblclickable">

这个问题只发生在单击可编辑的字段时,所以附加一个常规的click处理程序到该元素将取消传播的事件( 见stopPropagation ),并将设置一个超时( setTimeout(...) )为600ms( 两次点击之间的默认时间为500毫秒[src] )。 如果到那时dblclick还没有发生(你可以在两个事件处理程序中都有一个var作为检测这个标志的标志),那么你可以假设用户想要扩展行并继续这个行为。

国际海事组织,你应该重新考虑这一点。 唉,单击处理程序无法知道用户是否要双击。

我build议让这两个动作单击,并且不要单击时从可编辑字段传播。

重写user822711的答案重用:

  $.singleDoubleClick = function(singleClk, doubleClk) { return (function() { var alreadyclicked = false; var alreadyclickedTimeout; return function(e) { if (alreadyclicked) { // double alreadyclicked = false; alreadyclickedTimeout && clearTimeout(alreadyclickedTimeout); doubleClk && doubleClk(e); } else { // single alreadyclicked = true; alreadyclickedTimeout = setTimeout(function() { alreadyclicked = false; singleClk && singleClk(e); }, 300); } } })(); } 

调用函数。

 $('td.dblclickable').bind('click', $.singleDoubleClick(function(e){ //click. }, function(e){ //double click. }); 

我写了一个简单的jQuery插件,让您使用自定义的“singleclick”事件来区分单击和双击。 这使您可以构build一个界面,在该界面中,通过单击可以使input变为可编辑状态,而双击将其展开。 很像Windows / OSX文件系统重命名/打开用户界面。

https://github.com/omriyariv/jquery-singleclick

 $('#someInput').on('singleclick', function(e) { // The event will be fired with a small delay but will not fire upon a double-click. makeEditable(e.target); } $('#container').on('dblclick', function(e) { // Expand the row... } 
 window.UI = { MIN_LAPS_FOR_DBL_CLICK: 200, // msecs evt_down:null, timer_down:null, mousedown:function(evt){ if( this.evt_down && evt.timeStamp < this.evt_down.timeStamp + this.MIN_LAPS_FOR_DBL_CLICK ){ clearTimeout(this.timer_down); this.double_click(evt); // => double click } else { this.evt_down = evt; this.timer_down = setTimeout("UI.do_on_mousedown()", this.MIN_LAPS_FOR_DBL_CLICK); } }, evt_up:null, timer_up:null, mouseup:function(evt){ if( this.evt_up && evt.timeStamp < this.evt_up.timeStamp + this.MIN_LAPS_FOR_DBL_CLICK ){ clearTimeout(this.timer_up); } else { this.evt_up = evt; this.timer_up = setTimeout("UI.do_on_mouseup()", this.MIN_LAPS_FOR_DBL_CLICK); } }, do_on_mousedown:function(){ var evt = this.evt_down; // Treatment MOUSE-DOWN here }, do_on_mouseup:function(){ var evt = this.evt_up; // Treatment MOUSE-UP here }, double_click:function(evt){ // Treatment DBL-CLICK here } } // Then the observers $('div#myfoo').bind('mousedown', $.proxy(UI.mousedown, UI)); $('div#myfoo').bind('mouseup', $.proxy(UI.mouseup, UI)); 

添加到@puttyshell的答案,这个代码有一个visualSingleClick函数的空间。 这在setTimeout之前运行,目的是在超时之前向用户显示动作的一些可视化动作,并且可以使用更大的超时。 我在Google云端硬盘浏览界面上使用此function来向用户显示他所选中的文件或文件夹。 Google云端硬盘本身也有类似的function,但没有看到代码。

 /* plugin to enable single and double click on same object */ $.singleDoubleClick = function(visualSingleClk, singleClk, doubleClk) { return (function() { var alreadyclicked = false; var alreadyclickedTimeout; return function(e) { if (alreadyclicked) { // double alreadyclicked = false; alreadyclickedTimeout && clearTimeout(alreadyclickedTimeout); doubleClk && doubleClk(e); } else { // single alreadyclicked = true; visualSingleClk && visualSingleClk(e); alreadyclickedTimeout = setTimeout(function() { alreadyclicked = false; singleClk && singleClk(e); }, 500); } } })(); } 

如果您使用的是backbonejs,则可以使用更优雅的方式来处理此问题:


    初始化:function(){
         this.addListener_openWidget();
     }

     addListener_openWidget:function(){
         this.listenToOnce(this,'openWidgetView',function(e){this.openWidget(e)});
     },

    事件:{
         'click #openWidgetLink':function(e){this.trigger('openWidgetView',e)},
         '点击#closeWidgetLink':'closeWidget'
     },

     openWidget:function(e){
        //做你的东西
     },

     closeWidget:function(){
        this.addListener_openWidget();
     }