1

Jquery-ui sortableのコード例を使用すると、AndroidまたはIOSに基づくタッチデバイスでは機能せず、iOSデバイスでjQueryUIsortableをタッチ有効にします。knockout.jsクリックハンドラーとjQueryUIsortableを登録するときに問題が発生します。同じ要素で。knockout.jsハンドラーは、タッチ対応デバイスでは起動しませんが、デスクトップ/ラップトップでは起動します。

移動と呼ばれるフラグを追加すると、クリックハンドラーをトリガーする必要がある時期を追跡できます。これには、// TRIGGER HERE以下のマークが付いています。

/*
 * Content-Type:text/javascript
 *
 * A bridge between iPad and iPhone touch events and jquery draggable,
 * sortable etc. mouse interactions.
 * @author Oleg Slobodskoi
 *
 * modified by John Hardy to use with any touch device
 * fixed breakage caused by jquery.ui so that mouseHandled internal flag is reset
 * before each touchStart event
 *
 */
(function( $ ) {

  $.support.touch = typeof Touch === 'object';

  if (!$.support.touch) {
      return;
  }

  var proto =  $.ui.mouse.prototype,
  _mouseInit = proto._mouseInit
  moved = true;

  $.extend( proto, {
    _mouseInit: function() {
      this.element
      .bind( "touchstart." + this.widgetName, $.proxy( this, "_touchStart" ) );
      _mouseInit.apply( this, arguments );
    },

    _touchStart: function( event ) {
      if ( event.originalEvent.targetTouches.length != 1 ) {
        return false;
      }

      this.element
      .bind( "touchmove." + this.widgetName, $.proxy( this, "_touchMove" ) )
      .bind( "touchend." + this.widgetName, $.proxy( this, "_touchEnd" ) );

      this._modifyEvent( event );

      $( document ).trigger($.Event("mouseup")); //reset mouseHandled flag in ui.mouse
      this._mouseDown( event );

      moved = false;

      return false;
    },

    _touchMove: function( event ) {
      this._modifyEvent( event );
      this._mouseMove( event );
      moved = true;
    },

    _touchEnd: function( event ) {
      this.element
      .unbind( "touchmove." + this.widgetName )
      .unbind( "touchend." + this.widgetName );
      this._mouseUp( event );
      if (! moved) {
        // TRIGGER HERE
      }
    },

    _modifyEvent: function( event ) {
      event.which = 1;
      var target = event.originalEvent.targetTouches[0];
      event.pageX = target.clientX;
      event.pageY = target.clientY;
    }

  });

})( jQuery );

問題は、 jQueryUIからknockout.jsへのクリックイベントをどのようにトリガーするかです。

this.element.click()、、、などthis.element.get().click()を試しましthis.element.trigger("click")たが無駄になりました。

アップデート:

コードをハッキングして:

  • html.elementが正しいものではないように見えるため、実際のターゲットを追跡します
  • 正しいターゲットでクリックイベントをトリガーする

これで、knockout.jsのクリックイベントで正常に動作します。

/*
 * Content-Type:text/javascript
 *
 * A bridge between iPad and iPhone touch events and jquery draggable,
 * sortable etc. mouse interactions.
 * @author Oleg Slobodskoi
 *
 * modified by John Hardy to use with any touch device
 * fixed breakage caused by jquery.ui so that mouseHandled internal flag is reset
 * before each touchStart event
 *
 */
(function( $ ) {

  $.support.touch = typeof Touch === 'object';

  if (!$.support.touch) {
      return;
  }

  var proto =  $.ui.mouse.prototype,
  _mouseInit = proto._mouseInit
  moved = true,
  currentTarget = null;

  $.extend( proto, {
    _mouseInit: function() {
      this.element
      .bind( "touchstart." + this.widgetName, $.proxy( this, "_touchStart" ) );
      _mouseInit.apply( this, arguments );
    },

    _touchStart: function( event ) {
      if ( event.originalEvent.targetTouches.length != 1 ) {
        return false
      }

      this.element
      .bind( "touchmove." + this.widgetName, $.proxy( this, "_touchMove" ) )
      .bind( "touchend." + this.widgetName, $.proxy( this, "_touchEnd" ) );

      this._modifyEvent( event );

      $( document ).trigger($.Event("mouseup")); //reset mouseHandled flag in ui.mouse
      this._mouseDown( event );

      moved = false;

      return false;
    },

    _touchMove: function( event ) {
      this._modifyEvent( event );
      this._mouseMove( event );
      moved = true;
    },

    _touchEnd: function( event ) {
      this.element
      .unbind( "touchmove." + this.widgetName )
      .unbind( "touchend." + this.widgetName );
      this._mouseUp( event );
      if (! moved) {
        $(currentTarget).click();
      }
    },

    _modifyEvent: function( event ) {
      event.which = 1;
      var target = event.originalEvent.targetTouches[0];
      currentTarget = target.target;
      event.pageX = target.clientX;
      event.pageY = target.clientY;
    }

  });

})( jQuery );
4

1 に答える 1

1

投稿したコードでは、touchstartイベントからfalseを返します。タッチ対応デバイスでは、touchstartイベントが最初に発生し、click約300ミリ秒後に発生します。

event.preventDefault()イベントハンドラからfalseを返す場合、これは呼び出しと同じでevent.stopPropagation()あるためtouchstart、クリックを効果的にキャンセルします。起動しないため、これはデスクトップでは問題になりtouchstartません。

http://jsfiddle.net/madcapnmckay/HkbwV/2/

可能な解決策。

  • falseを返す代わりに、event.stopPropagation()を呼び出すだけです(それが機能する場合)。クリックの代わりに、イベントバインディングを使用してタッチスタートをバインドします。

<div data-bind="event : { touchstart: somfunction }"></div>

  • マークした場所で、イベントバインディングによってサブスクライブされているカスタムイベントをトリガーします。

また、touchstartが使用可能かどうかを検出し、touchstartまたはclickイベントに選択的にバインドするtouchOrClickカスタムバインディングの作成を検討することもできます。

お役に立てれば。

于 2012-06-06T22:50:52.717 に答える