2013-07-15 64 views
8

我正在嘗試處理按鈕單擊。 「按鈕」是一個自定義的div,也可以包含孩子。點擊回調應該在用戶點擊並釋放元素內時觸發。如果用戶點擊內部,然後在外面拖動並釋放,則處理程序不應該觸發。我需要在桌面和移動設備上都能正常工作,因此我正在使用mousedown/mouseuptouchstart/touchend事件。如何檢測元素外部的touchend事件

我需要的按鈕類從「按下」改變爲「正常」,即使用戶的版本之外,所以我需要添加一個監聽器捕捉到在文件釋放事件:

var $myElement = $("#myelement"); //This is a div and can also contain children. 

    $myElement.on("mousedown touchstart", function(e){ 

     $(this).addClass("pressed");  

     $(document).on("mouseup touchend", function listener(e){ 
      $myElement.removeClass("pressed"); 

      $(document).off("mouseup touchend", listener); 

      var $target = $(e.target); 
      if ($target.is($myElement) || $target.parents().is($myElement)){   
       //FIXME 
       alert("Inside!"); 

       //do something here 
       return false; 
      } else { 
       //FIXME 
       alert("Outside!"); 

       //let event bubble 
      } 
     }); 

     return false; 
    }); 

它點擊次數可以正常工作,但不會像觸摸事件那樣按預期工作。我已經在Android版的Chrome中測試了這一點,並且當按下元素時,然後拖出「Inside」!顯示警報。

的問題是在這種情況下:

if ($target.is($myElement) || $target.parents().is($myElement)){ 

我想檢查是否發生在按鈕或任何兒童的touchend事件。如果按鈕沒有孩子,當點擊它然後在外面釋放時,OR子句的第一部分解析爲真。如果按鈕有孩子,我點擊孩子,然後釋放屏幕的任何其他部分,則該子句的第二部分爲真。

這段代碼有什麼問題?

在此先感謝。

UPDATE
我已經在BlackBerry 10中測試過它,結果相同。顯然,touchend事件的目標是按鈕(或孩子),即使我在外面點擊了。這是應該如何工作?

UPDATE
這就是爲什麼。這是what the W3C docs say about the event

此事件的目標必須是接收到touchstart事件時此觸摸點被放置在表面上,即使觸摸點自移動的交互區之外的相同元目標元素。

這是沒有意義的我,但反正這說明我的問題。我假設touchend事件將在手指被釋放的元素上被調用。使用不同的方法是否可以檢測到手指釋放?

UPDATE
我試着讓touchevent的座標得到使用document.elementFromPoint的元素。問題是此事件不包含座標(changedTouchestouches列表爲空)。我已經在調試器中仔細檢查了事件,除了原始事件之外,沒有辦法從中檢索它。然後我想我可以緩存最後的touchmove事件,並從那裏獲得座標,但是這個事件再次沒有自己的座標!爲什麼地球上這兩個事件是無用的呢?我已經在iOS,Android和BB10測試了這種方法,結果相同。

我已經放棄了。即使用戶在外面點擊,我也會打電話給您。我不能相信這是2013年的球員,並沒有(簡單)的方式做到這一點?我可以使用拖動& drop api,但根據this它不支持在移動設備上(愛移動web開發)。

+0

雖然它可能不會直接幫助你,但我已經將VanillaJS腳本放在一起,它完成了幾乎相同的事情,並且發佈了該代碼的簡化版本[在這裏](http://stackoverflow.com/questions/13030210) /的onclick事件 - 是 - 發生的歷史,二,次功能於iphone,混合應用程序/ 13030622#13030622) –

+0

@EliasVanOotegem謝謝,我已經脫脂readed,但我不能測試它。我現在正在閱讀你鏈接的一些圖書館的來源。也許我正試圖在這裏重新發明輪子。 –

回答

8

最後(幾乎)得到它在BB10和Android平臺。我離開的問題更新問題線索,所以綜上所述:touchend事件目標是一樣的touchstart,並談到無座標(出於某種原因,API的設計師決定「隱藏」他們在originalEvent財產:)。所以我檢索到觸摸結束從changedTouches[0].pageXchangedTouches[0].pageY,然後獲得在手指使用document.elementFromPoint發佈的元素座標。 (在用事件座標提供此方法之前,您必須將滾動偏移添加到x和y)。然後,如果該點上的元素是按鈕(或者是它的一個子元素),我將處理該點擊。

var $myElement = $("#myelement"); //This is a div and can also contain children. 
    var startEvent = touchDevice() ? "touchstart" : "mousedown"; 
    var releaseEvent = touchDevice() ? "touchend" : "mouseup"; 

    $myElement.on(startEvent, function(e){ 

     $(this).addClass("pressed");  

     $(document).on(releaseEvent, function listener(e){ 
      $myElement.removeClass("pressed"); 

      $(document).off(releaseEvent, listener); 

      var $target = null; 
      if(e.type === "mouseup"){ 
       $target = $(e.target);   
      } else {    
       var x = e.originalEvent.changedTouches[0].pageX - window.pageXOffset; 
       var y = e.originalEvent.changedTouches[0].pageY - window.pageYOffset; 
       var target = document.elementFromPoint(x, y); 

       if(target){ 
        $target = $(target); 
       }   
      } 

      if ($target !== null && ($target.is($myElement) || $target.parents().is($myElement))){  
       //FIXME 
       alert("Inside!"); 

       //callback here 
       return false; 
      } else { 
       //FIXME 
       alert("Outside!"); 
      } 
     }); 

     return false; 
    }); 

現在我有一個新問題:在iOS中,點擊事件被重複。但是這值得一個不同的問題(如果不存在的話)。

+1

重複的點擊問題是由調試警報引起的。我用'console.log'替換了它們,現在按預期工作。 –

+0

這太可怕了!我感到你的痛苦。 –

+0

座標應該位於名爲targetTouches的列表中的一個對象中,該列表是事件對象的一個​​屬性,儘管我已經聽說過對於spec支持,blackberry可能會是噩夢嗎?那裏。這是必要的,因爲您可能想要在相同的元素原點處處理多個觸摸,以便可以生成彼此非常接近的事件。這很奇怪,但是當你考慮到API的設計處理手指,而不是鼠標替換問題,並且是一個很好的設計,IMO時,API會更有意義。用於提取低級內容的前往庫應該足夠快。 –

1

你需要一個不同的,整潔的做法都在一起。

落實的OnMouseMove分別爲ontouchmove桌面和移動設備。

btn_obj.onmousemove = CancelOnClick (this); 

執行CancelOnClick函數將標誌從按下設置爲正常。它可以幫助您避免您的所有元素及其基於子女的狀況。

希望有所幫助。

+0

'CancelOnClick(this);'將'CancelOnClick'的返回值賦值給'onmousemove'事件,這是一個可怕的想法 –

+1

這並沒有解決檢測元素上的點擊釋放的問題。問題是我需要在點擊完成時調用回調,而不是在啓動時。 –

相關問題