scriptaculous draggables:拖动元素时需要取消onClick动作

时间:2009-02-16 10:39:20

标签: javascript javascript-events scriptaculous draggable

感谢三个出色的答案,这些答案都确定了我使用“onclick = ...”而不是“观察”(“点击”,......“

的问题

但是接受答案的奖项必须转到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 !!!
  }
});

我的想法是,当点击图像时,应该遵循链接,但是当它被拖动时,应该发生其他事情。

事实上,当拖动图像时,会调用处理程序,但仍会遵循链接。

我想我正在取消错误的事件。

如何在拖动元素后阻止链接被跟踪?


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


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

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

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

6 个答案:

答案 0 :(得分:2)

// 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)

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

使用Prototype,您可以为要拖动的html元素的click事件添加一个观察者函数,并告诉event.stop();。此操作扩展(即Prototype-ize)要传递给处理函数的事件对象,从而丰富了所有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:处理程序的事件不是点击事件,而是 onend 事件。

答案 2 :(得分:1)

<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 :(得分:0)

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

但是我对它不满意,因为它看起来有点乱,而且在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;
  }
});

答案 4 :(得分:0)

我现在无法对此进行测试,但正如我所看到的那样,您正在使<img>可拖动,但您正在观察<a>元素上的点击,所以问题可能就是click事件冒泡到链接,该链接执行默认操作。

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

答案 5 :(得分:0)

尝试这样做

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