2011-03-29 28 views
37

我有一個有趣的情況 - 我有一個表格行,當我單擊「展開」按鈕時,顯示它是隱藏的對應表格。包含展開按鈕的原始(未隱藏)行也在某個單元格中包含一些內容,點擊該單元格後,該內容即可編輯。我想擺脫擴展按鈕,並通過雙擊該行本身中的任何位置來啓用行的擴展,包括單擊時可以編輯的字段。你可以在這裏聞到麻煩。使用jQuery的Javascript:單擊並雙擊相同的元素,不同的效果,一個禁用另一個

當我雙擊一行時,在發生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> 

乾杯

+0

粘貼一些代碼,請 – diEcho 2011-03-29 10:49:32

+3

你可以嘗試使用的setTimeout延遲的點擊處理程序,然後雙擊養「通過DoubleClick已經-發生」標誌,並在你的單,即可查看該旗處理者 – 2011-03-29 10:55:03

+0

@diEcho完成! @freaktm謝謝,我考慮到了這一點,但它似乎不切實際和hackish,特別是因爲我將不得不修改我的可編輯單元助手網站的點擊處理程序。我可能會將此作爲最後的手段,是的,但仍想知道某人是否有更好的解決方案。 – Swader 2011-03-29 11:03:59

回答

22

總體思路:

  1. 第一次點擊時,不要調用相關函數(比如說single_click_function())。相反,設定一段時間(例如x)的計時器。如果我們在這段時間內沒有再次點擊,請進入single_click_function()。如果我們得到一個,請撥打double_click_function()

  2. 一旦收到第二次點擊,計時器將被清除。一旦x毫秒失效,它也將被清除。

BTW,檢查保羅的回答出:Need to cancel click/mouseup events when double-click event detected 當然和整個主題! :-)

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

+0

謝謝,這工作,但我決定反對它到底。我發現了一些更好的可用性解決方案,並與之一起使用。 – Swader 2011-04-01 10:42:26

+10

@Swader可以分享你的解決方案你選擇哪種解決方法b/c我也不想使用settimeout(...)方法。 – zaree 2013-11-19 05:44:20

+4

@Swader正在拉費爾馬 – Dan 2014-07-21 16:58:19

2

只被點擊可編輯字段時,會出現問題,所以附加定期click處理該元素將取消(see stopPropagation)事件的傳播和將設置超時(setTimeout(...))爲600ms(兩次點擊之間的默認時間,視爲dbl點擊爲500ms [src])。如果到那時dblclick還沒有發生(你可以在兩個事件處理程序中都有一個var作爲檢測這個標誌的標誌),那麼你可以假設用戶想要擴展行並繼續這個行爲。

IMO,你應該重新考慮這一點。唉,單擊處理程序無法知道用戶是否要雙擊。

我建議讓這兩個動作都是單擊,並且在單擊時不會從可編輯字段向上傳播。

12

Working demo

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

+1

我總是以這個代碼結束於單一狀態。爲什麼? – briansol 2013-04-12 14:48:12

+0

300ms的不是很長 – Popnoodles 2013-04-12 14:58:59

+0

我把它拍成到1300,它只需一秒鐘延遲我的警報顯示的「單」不管我怎麼快速點擊。 – briansol 2013-04-12 15:00:39

2

重寫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. 
}); 
+0

我似乎無法要得到這個工作...保持在函數調用中得到一個)失蹤錯誤 – briansol 2013-04-12 14:36:58

1
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)); 
-2

還有一種更優雅的方式,如果你正在使用backbonejs處理這個問題:

 

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

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

    events: { 
     'click #openWidgetLink' : function(e){this.trigger('openWidgetView',e)}, 
     'click #closeWidgetLink' : 'closeWidget' 
    }, 

    openWidget: function(e){ 
     //Do your stuff 
    }, 

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

0

添加從@puttyshell回答,這個代碼有一個visualSingleClick功能空間。這在setTimeout之前運行,目的是在超時之前向用戶顯示一些可視的動作,並且我可以使用更大的超時。我在Google雲端硬盤瀏覽界面上使用此功能來向用戶顯示他選中的文件或文件夾。 Google雲端硬盤本身有類似的功能,但沒有看到它的代碼。

/* 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); 
     } 
    } 
    })(); 
} 
2

我寫了一個簡單的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... 
} 
+0

的偉大工程的歡呼:) – kofifus 2016-02-19 11:09:42

+0

感謝您的快速解決辦法;) – gMirian 2017-05-28 15:28:37

相關問題