【问题标题】:Trigger a click event from jQuery UI to knockout.js从 jQuery UI 触发 click 事件到 knockout.js
【发布时间】:2012-06-06 13:09:27
【问题描述】:

使用Jquery-ui sortable doesn't work on touch devices based on Android or IOS 中的代码示例在 iOS 设备上启用 jQuery UI 可排序触摸,在注册 knockout.js 点击处理程序以及可在相同元素上排序的 jQuery UI 时出现问题。 knockout.js 处理程序不会在启用触摸的设备上触发,但会在台式机/笔记本电脑上触发。

添加一个名为 moved 的标志可以跟踪何时需要触发点击处理程序,并在下面标有// 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 );

问题是,如何从 jQuery UI 触发一个 click 事件到 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 );

【问题讨论】:

  • 您只是想触发数据绑定功能,还是需要触发实际的点击事件?
  • 点击事件,同时使用 data-bind="click: function(){alert('hello')}" 和jQuery UI touch bindings时不会触发。

标签: jquery jquery-ui knockout.js jquery-events knockout-sortable


【解决方案1】:

在您发布的代码中,您从 touchstart 事件返回 false。在启用触摸的设备中,touchstart 事件首先触发,click 大约在 300 毫秒后触发。

如果您从事件处理程序返回 false,这与调用 event.preventDefault()event.stopPropagation() 相同,因此 touchstart 有效地取消了单击。这在台式机上不是问题,因为touchstart 永远不会触发。

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

可能的解决方案。

  • 而不是返回 false,只需调用 event.stopPropagation()(如果可以的话)。使用事件绑定来绑定 touchstart 而不是点击。

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

  • 在您标记的位置触发由事件绑定订阅的自定义事件。

您也可以考虑编写一个 touchOrClick 自定义绑定来检测 touchstart 是否可用并选择性地绑定到它或点击事件。

希望这会有所帮助。

【讨论】:

  • 感谢您的回答。虽然我可以在 jsFiddle 中看到逻辑相加,但使用通用脚本触摸启用 jQuery UI 可排序,删除返回语句没有明显效果。最后我更新了脚本以触发正确的目标。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多