带有 jQ​​uery 的 Javascript:单击并双击同一元素,效果不同,一个禁用另一个

IT技术 javascript jquery events event-bubbling propagation
2021-02-06 10:17:49

我有一个有趣的情况 - 我有一个表格行,当前,当我单击“展开”按钮时,该行显示它是隐藏的对应项。包含展开按钮的原始(未隐藏)行在某个单元格中也有一些内容,当单击该内容时,这些内容变得可编辑。我想去掉扩展按钮,并通过双击行本身的任何地方来扩展行,包括单击它时变为可编辑的字段。你已经可以闻到这里的麻烦了。

当我双击一行时,在 dblclick 发生之前,首先触发两个单击事件。这意味着如果我双击该字段,它将变成一个可编辑的字段,并且该行将展开。我想防止这种情况发生。我希望双击以防止单击触发,并且单击像往常一样执行。

使用 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>

干杯

6个回答

总体思路:

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

  2. 一旦收到第二次点击,计时器将被清除。一旦 x 毫秒过去,它也会被清除。

顺便说一句,请查看 Paolo 的回复:需要在检测到双击事件时取消单击/鼠标点击事件 ,当然还有整个线程!:-)

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

@Swader 你能分享你的解决方案你选择 b/ci 的解决方法也不想使用 settimeout(...) 方法。
2021-03-24 10:17:49
@BrianStinar 我会 - 如果 OP 发布了他解决问题的 Javascript 尝试。HTML 伪结构或冗长的解释都不算数。
2021-03-27 10:17:49
谢谢,这行得通,但我最终决定反对。我找到了一些更好的可用性解决方案并采用了这些解决方案。
2021-03-31 10:17:49
@Swader 正在拉费马
2021-04-11 10:17:49
我猜这个家伙从来没有发布过更好的解决方案......?
2021-04-12 10:17:49

工作演示

$('#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">

不,我的逻辑是合理的jsfiddle.net/V8twU您是否将双击事件的程序放在正确的位置?
2021-03-22 10:17:49
实际上,如果我缓慢单击,我可以让 dbl 用 1300 窗口触发。单击 1 = 0,单击 2 = 500 毫秒后 (-ish) 时间范围。2 缓慢的故意点击。是通过 JS 文件(function(){} 包装器中的一堆东西用于加载等待导致它的时间?
2021-03-23 10:17:49
我把它调到 1300,不管我点击多快,它都会将我显示“单身”的警报再延迟一秒。
2021-04-01 10:17:49
呵呵,我愿意。不幸的是,这就是这里的“环境”,也是唯一仍在使用的浏览器。:(
2021-04-01 10:17:49
你在ie8上试过吗?即使对我来说使用这个小提琴,它似乎也不能正确触发。
2021-04-06 10:17:49

我编写了一个简单的 jQuery 插件,它允许您使用自定义的“singleclick”事件来区分单击和双击。这允许您构建一个界面,其中单击使输入可编辑,而双击将其展开。很像 Windows/OSX 文件系统重命名/打开 UI。

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...
}

重写 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){
  //single click.
}, function(e){
  //double click.
}));
我似乎无法让它工作......在函数调用中不断收到 ) 丢失错误。
2021-03-28 10:17:49

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

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

我建议单击这两个操作,并且在单击时不要从可编辑字段向上传播。