【问题标题】:scriptaculous draggables: need to cancel onClick action when element is draggedscriptaculous draggables:拖动元素时需要取消onClick动作
【发布时间】:2009-02-16 10:39:19
【问题描述】:

感谢三个出色的答案,它们都确定了我使用“onclick = ...”而不是“observe(“click”,...”)的问题

但是,Accepted Answer 奖必须授予 Paolo Bergantino,因为它使用了添加类名来标记拖动元素的机制,这为我节省了更多工作!


在我的 HTML 中,我有一个表格,每行都有一个图片链接。

<table class="search_results">
  <tr>
     <td class="thumbnail"><a href="..."><img src="..." /></a></td>
...

包含的 Javascript 文件包含使图像可拖动的代码:

$$( ".thumbnail a img" ).each(
  function( img )
  {
    new Draggable( img, {revert:true} );
  }
);

和一个简单的处理程序来检测拖动的结束

Draggables.addObserver({
  onEnd:function( eventName, draggable, event )
  {
    // alert ( eventName ); // leaving this in stops IE from following the link
    event.preventDefault(); // Does Not Work !!!
    // event.stop(); // Does Not Work either !!!
  }
});

我的想法是,当点击图片时,应该跟随链接,但当它被拖动时,应该会发生其他事情。

事实上,当图像被拖动时,处理程序被调用,但链接仍然被跟踪。

我猜我取消了错误的活动。

如何防止元素被拖动后链接被点击?


编辑:在尝试了 graystate 的建议后添加了event.stop


我现在有一个适用于 FireFox、Apache 等的基本解决方案。请参阅下面我自己的答案。

但我仍在寻找 IE7(希望是 IE6)的解决方案。

在 IE 中拖动图像的另一个问题是,当工具提示出现时,图像与鼠标指针分离,您必须释放鼠标并再次单击图像才能重新获得拖动。所以我也在寻找任何可能有助于解决这个问题的想法。

【问题讨论】:

    标签: javascript dom-events draggable scriptaculous


    【解决方案1】:
    // for keeping track of the dragged anchor
    var anchorID = null;
    
    // register a click handler on all anchors
    $$('.thumbnail a').invoke('observe', 'click', function(e) {
        var a = e.findElement('a');
        // stop the event from propagating if this anchor was dragged
        if (a.id == anchorID) {
            e.stop();
            anchorID = null;
        }
    });
    
    $$('.thumbnail a img').each(function(img) {
        new Draggable(img, { revert:true });
    });
    
    Draggables.addObserver({
        onStart: function(eventName, draggable, e) {
            // store the dragged anchor
            anchorID = e.findElement('a').id;
        }
    });
    

    【讨论】:

    • +1 回答问题,我不明白为什么这也被否决了
    • 现在又回到 1 - 我很困惑
    【解决方案2】:
    <script>
    document.observe("dom:loaded", function() {
        $$( ".thumbnail a img" ).each(function(img) {
            new Draggable(img, {
                revert: true,
                onEnd: function(draggable, event) {
                    $(draggable.element).up('a').addClassName('been_dragged');
                }
            });
        });
    
        $$(".thumbnail a").each(function(a) {
            Event.observe(a, 'click', function(event) {
                var a = Event.findElement(event, 'a');
                if(a.hasClassName('been_dragged')) {
                    event.preventDefault();
                    // or do whatever else
                }
            });
        });
    });
    </script>
    

    在 Firefox、IE 上为我工作。它有点使用你的“标记”想法,但我认为用类标记已经拖动的元素比 javascript 变量更优雅。

    【讨论】:

    • 非常感谢 - 很好的回答!
    【解决方案3】:

    好的,我找到的方式是使用“拖动状态”变量,类似于您之前的帖子,但它在 IE7 和 FF 下都可以使用。

    使用 Prototype,您可以为要拖动的 html 元素的单击事件添加一个观察者函数,在那里告诉event.stop();。此操作扩展(即原型化)要传递给处理函数的事件对象,从而丰富它的所有 Prototype 附加方法并使其能够调用 stop() 方法而不必担心它运行到的浏览器,因为 Prototype 会为您管理这方面。

    这是我的示例代码:

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
          <script type="text/javascript" src="lib/prototype.js"></script>
          <script type="text/javascript" src="src/scriptaculous.js"></script>
        <title>Draggables Test</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      </head>
      <body>
        <div id="dragme"><a href="http://www.google.it">Ok, you can drag this one.</a></div>
        <script type="text/javascript">
            function processIt(event) {
                if ( isDragging ) {
                    event.stop();
                }
                isDragging = false;
            }
    
            new Draggable('dragme', { revert: false });
            var isDragging = false;
    
            $('dragme').observe('click', processIt );
            Draggables.addObserver({
                onDrag:function( eventName, draggable, event ) {
                    isDragging = true;
                }
            });
            </script>
      </body>
    </html>
    

    不同之处在于,在您的原始示例中,您将事件视为标准 DOM 事件(请参阅参数规范here,页面底部),这对于 FF 是可以的,但对于 IE 则完全不行,因为它以稍微(但绝对)不同的方式处理事件。最重要的是,您在 onEnd: 处理程序中处理的事件不是 click 事件,而是 onend 事件。

    【讨论】:

    • +1 来自我,有用的答案!我不明白为什么这被否决了。
    • 现在又回到 1 - 我很困惑
    • 谢谢你,诺埃尔。我很感激。
    【解决方案4】:

    我现在无法对此进行测试,但正如我所见,您正在使 &lt;img&gt; 可拖动,但您正在观察对 &lt;a&gt; 元素的点击,所以问题可能是点击事件冒泡直到执行其默认操作的链接。

    Prototype 有一个 stop() 事件方法,除了阻止默认操作外,还取消事件冒泡 - 您可以在 onEnd 函数中尝试,而不是 preventDefault()

    【讨论】:

    • 感谢您的建议。我尝试在两个版本中使用 Event.stop 但结果是一样的。第二个版本适用于大多数浏览器,但没有一个版本适用于 IE。
    【解决方案5】:

    经过一些实验,我想出了以下修复方法。

    但我对它不太满意,因为它看起来有点乱,而且它在 IE7 中不起作用。

    编辑

    还尝试了“ev.stop”和“return false”作为 ev.preventDefault 的替代方案。所有都给出相同的结果,在除 IE 之外的所有浏览器中工作。

    取消注释警报证明即使在 IE 中也正在执行 preventDefault

    将 onEnd 处理程序更改为 onDrag 处理程序以避免处理程序调用顺序的潜在问题。

    $$( ".thumbnail a img" ).each(
      function( img )
      {
        new Draggable( img, {revert:true} );
      }
    );
    
    var drag_occurred = false;
    $$( ".thumbnail a" ).each(
      function( tag )
      {
        tag.onclick = function( ev )
        {
          if ( drag_occurred )
          {
            // alert( "!" );
            ev.preventDefault();
          }
          drag_occurred = false;
        }
      }
    );
    
    Draggables.addObserver({
      onDrag:function( eventName, draggable, event )
      {
        drag_occurred = true;
      }
    });
    

    【讨论】:

      【解决方案6】:

      尝试这样做

      $$( ".thumbnail a" ).each(
        function( tag )
        {
          tag.onclick = function( ev )
          {
            if ( drag_occurred )
            {
              ev.cancelBubble = true;
              if (ev.stopPropagation) ev.stopPropagation();
            }
            drag_occurred = false;
          }
        }
      );
      

      【讨论】:

      • 不,这在 IE7 或 Firefox 中不起作用(未在其他浏览器上测试)
      猜你喜欢
      • 1970-01-01
      • 2010-10-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-05
      • 2023-03-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多