scriptaculous draggables: необходимо отменить действие onClick при перетаскивании элемента - PullRequest
1 голос
/ 16 февраля 2009

Спасибо за три отличных ответа, которые все определили мою проблему использования "onclick = ..." вместо "наблюдаем (" нажмите ", ..."

Но награда за «Принятый ответ» должна достаться Паоло Бергантино за механизм добавления имени класса для пометки перетаскиваемого элемента, что спасло мне еще немного работы!

<ч />

В моем 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 !!!
  }
});

Моя идея заключается в том, что при нажатии на изображение следует переходить по ссылке, но при перетаскивании должно произойти что-то еще.

На самом деле происходит то, что при перетаскивании изображения вызывается обработчик, но ссылка по-прежнему сохраняется.

Полагаю, я отменяю неправильное событие.

Как я могу предотвратить переход по ссылке после перетаскивания элемента?

<ч />

edit: добавлен event.stop после попытки предложения greystate

<ч />

Теперь у меня есть базовое решение, которое работает для FireFox, Apache и т. Д. См. Мой собственный ответ ниже.

Но я все еще ищу решение для IE7 (и, надеюсь, IE6).

Еще одна проблема при перетаскивании изображений в IE заключается в том, что при появлении всплывающей подсказки изображение отсоединяется от указателя мыши, вам нужно отпустить кнопку мыши и снова щелкнуть изображение, чтобы заново перетащить изображение. Поэтому я также ищу любые идеи, которые могут помочь решить эту проблему.

Ответы [ 6 ]

2 голосов
/ 24 февраля 2009
// 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 голос
/ 24 февраля 2009
<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.

1 голос
/ 24 февраля 2009

Хорошо, я нашел способ с переменной состояния перетаскивания, похожий на ваш предыдущий пост, но он работает как в IE7, так и в FF.

Используя Prototype, вы можете добавить функцию наблюдателя для события click элемента html, который вы хотите перетащить, сообщая там event.stop();. Это действие расширяет (т.е. Prototype-ize) объект события, передаваемый в функцию-обработчик, таким образом обогащая его всеми дополнительными методами Prototype и позволяя ему вызывать метод stop(), не беспокоясь о браузере, с которым он работает Прототип управляет этим аспектом для вас.

Вот код моего примера:

<!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 (см. Спецификации параметров здесь , внизу страницы), что нормально для FF, но совсем не для IE, поскольку он имеет дело с событиями немного (но определенно) по-другому. Кроме того, событие, с которым вы работали в обработчике onEnd:, было не событием click , а событием onend .

0 голосов
/ 23 февраля 2009

Попробуйте сделать это

$$( ".thumbnail a" ).each(
  function( tag )
  {
    tag.onclick = function( ev )
    {
      if ( drag_occurred )
      {
        ev.cancelBubble = true;
        if (ev.stopPropagation) ev.stopPropagation();
      }
      drag_occurred = false;
    }
  }
);
0 голосов
/ 17 февраля 2009

Я не могу проверить это прямо сейчас, но, как я вижу, вы делаете перетаскивание <img>, но вы наблюдаете клики по элементу <a>, поэтому проблема, вероятно, заключается в том, что событие click вспыхивает до ссылки, которая выполняет свое действие по умолчанию.

В прототипе есть метод stop() для событий, который, помимо предотвращения действия по умолчанию, также отменяет всплытие событий - вы можете попробовать это в функции onEnd вместо preventDefault().

0 голосов
/ 16 февраля 2009

После некоторых экспериментов я придумал следующее исправление.

Но я менее чем доволен этим, так как он кажется немного грязным, и он не работает в IE7. редактировать

также пытался использовать ev.stop и return false в качестве альтернативы ev.preventDefault. Все дают одинаковый результат, работая в любом браузере, кроме IE.

снятие комментария с предупреждения свидетельствует о том, что protectDefault выполняется даже в IE

изменен обработчик 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;
  }
});
...