2015-05-15 3 views
0

Кодом, у меня есть средства, чтобы принять обработчик событий элемента управления и перемещение этих обработчиков к другому элементу и удалять обработчик событий предыдущего элемента управления скрипкой http://jsfiddle.net/pydty4bq/подкачки обработчики событий между элементами DOM d3

var slider = d3.select('#slider1'); 
     var slider1Config = { 
      element: slider, 
      drag:function(e){ 
       if(d3.event.toElement) 
        console.log('has toElement',d3.event.toElement.valueAsNumber); 
       else 
        console.log(d3.event.sourceEvent.srcElement.valueAsNumber); 
      }, 
      dragstart:function(){console.log('dragstart!');}, 
      dragend: function(){ console.log('dragend!');} 
     } 
     var _drag = new Drag(slider1Config); 
     _drag.element(d3.select('#slider2')); 

функцию _drag.element следует удалить обработчики событий из слайдера1 и поместите их на слайдер2. В настоящее время оба элемента запускают обработчики событий.

// перетаскивание функциональность

var Drag = (function(){ 
    var _opts, 
     _drag = d3.behavior.drag(); 
    var eventList = ['drag','dragstart','dragend']; 
    function attachEvents(opts){ 
     eventList.forEach(function(e,i){ 
      if(opts[e]){ 
       _drag.on(e,this[e]); 
      } 
      else{ 
       _drag.on(e,null); 
      } 
     }.bind(this)); 
    }; 
    function detachEvents(){ 
     eventList.forEach(function(e,i){ 
      if(_opts[e]){ 
       _drag.on(e,null); 
      } 
     }.bind(this)); 
    } 
    function Drag(opts){ 
     _opts = opts; 
     attachEvents.call(this,opts); 
     _opts.element = opts.element.call(_drag); 
     _opts.element.attr('isDraggable',true); 
    } 
    Drag.prototype.drag = function(args){ 
     _opts.drag(args); 
    }; 
    Drag.prototype.dragstart = function(args){ 
     _opts.dragstart(args); 
    } 

    Drag.prototype.dragend = function(args){ 
     _opts.dragend(args); 
    } 
    Drag.prototype.element = function(el){ 
     if(el){ 
      detachEvents.call(this) 
      _opts.element = el; 
      attachEvents.call(this,_opts); 
      _opts.element.call(_drag); 
     } 
    } 
    Drag.prototype.config = function(opts){ 
     _opts = opts; 
     attachEvents.call(this,_opts); 

    } 
    return Drag; 
})(); 

Что случилось с detachEvents, что он не удаляет слушателей событий из предыдущего элемента?

+0

, кстати, в настоящее время ваши объекты _opts и _drag будут перезаписаны каждый раз, когда вы выполняете «новое перетаскивание». –

ответ

0

Вот как работает поведение перетаскивания.

Сначала вы создаете поведение как:

var _drag = d3.behavior.drag(); 

Затем Вы придаете обработчики событий к нему:

_drag 
    .on('dragstart', function() { ... }) 
    .on('drag', function() { ... }) 
    .on('dragend', function() { ... }); 

Затем прикрепить это поведение к элементу:

d3.select('#slider1').call(_drag); 

который эффективно привязывает обработчики, определенные выше к этому элементу (фактические события называются по-разному).

Отсоединение обработчик событий от поведения делается так:

_drag.on('dragstart', null); 

и он работает правильно.

НО

К сожалению, применение такого поведения с отключенным обработчик событий к элементу с оценкой (включен) обработчик события не будет отключить обработчик элемента. То есть

_drag.on('dragstart', null); 
d3.select('#slider1').call(_drag); 

не помешает #slider1 от обработки dragstart, как и раньше.

Вот что показали мои эксперименты. Не знаю, является ли это ошибкой или нет.

В любом случае, есть прямой способ отсоединить обработчики перетаскивания от элемента.
Поскольку все перетаскивать события, связанные расположены внутри .drag пространства имен, вы можете отключить их все сразу, как так:

d3.select('#slider1').on('.drag', null); 

Проверить это JSFiddle

+0

Вы были бы любезны, чтобы «повторить фактор» этого заявления? «К сожалению, применение этого поведения с отключенным обработчиком событий к элементу с связанным (включенным) обработчиком события не приведет к отключению обработчика элемента». Я очень заинтересован в вашем ответе, но я не понимаю, что вы имеете в виду. например вы можете определить «отключенный обработчик событий»; «связанный (активированный) обработчик событий» ... возможно, это поможет. –

+0

Извините, что не понимаете. Я имею в виду это: вы определяете поведение, затем привязываете к нему обработчик событий, затем применяете это поведение к объекту => у объекта теперь есть привязанный к нему обработчик событий. Теперь вы отключите этот обработчик событий ('' .on ('event', null) '' ') для поведения и примените это поведение к тому же объекту => объект, который еще ранее прикреплял обработчик. – dekkard

+0

Ahh ok, я думаю, что я наконец понял, что вы говорите. Событие удаляется из диспетчера, закрытого внутри «поведения», но обратный вызов, который хранится на узле, все еще прослушивается. –

0

Важно понимать, что поведение сопротивления , которая является функцией, возвращаемой d3.behavior.drag(), может быть применена к любому количеству выборок и не знает об элементах DOM, которые она также привязана.

Внутри поведение имеет обычай отправки объект, который абстрагирует искусственные события. Эти события - «drag», «dragstart» и «dragend» - полностью удаляются из любых исходных событий, происходящих из DOM. Внутренняя отправки объект просто система для

  1. Реализуя эти абстрактные события
  2. Управления прикрепления и отсоединения слушателей к ним
  3. Обеспечивая интерфейс для запуска абстрактных событий и
  4. оповещения зарегистрированных слушателей после их запуска

Это то, что вы получаете в результате этого кода ...

var _drag = d3.behavior.drag(); 

_drag 
    .on('dragstart', function() { ... }) 
    .on('drag', function() { ... }) 
    .on('dragend', function() { ... }); 

Обратите внимание, что ни одно из вышеперечисленных не имеет ссылки на любые элементы DOM или их события и само по себе, не способно инициировать что-либо. Поведение ничего не может сделать, пока оно не подключится к интерфейсу DOM selection.call(behavior). В этом случае поведение связано с интерфейсом DOM. Как-то нужно выяснить, что произошло событие dragstart, ему нужно отвлечь это от событий пользовательского интерфейса, и это делается примерно так: selection.on({ "mousedown.drag": mousedown, "touchstart.drag": touchstart }).

Так вот два, совершенно разные, родные события - «MouseDown» и «touchstart» - происходящий из DOM элементов в выборе - которые применяются «под капотом» поведением сопротивления .

(Как упомянуто @dekkard, они в пространстве имен, присоединяя ".drag" в их стандартных имен d3 управляет этим и раздевает их перед подписок..)

слушатели - mousedown и touchstart - объекты, созданные и закрытые внутри объекта d3.behavior.drag, и оба из них обращаются к процессу внутри операции , который инициирует процесс перетаскивания. Пока поведение продолжает существовать, оно продолжит прослушивание этих событий DOM UI.

Таким образом, существует два совершенно разных интерфейса: один для вызова и управления абстрактными событиями «перетаскивания», «dragstart» и «dragend» и один для подключения к событиям DOM UI «mousedown» и «touchstart».

Чистый эффект этого кода, поэтому ...

detachEvents.call(this) 
    _opts.element = el; 
    attachEvents.call(this,_opts); 
    _opts.element.call(_drag); 

является отсоединить и вновь присоединить слушатель к внутренним отправке объекта поведения и добавить поведения в второй выбор. Итак, теперь «mousedown» и «touchstart» из любого выбора приведут к такому же перетаскиванию.

Согласно documentation, метод обеспечивает @dekkard - .on('.drag', null) - это единственный способ, чтобы отключить поведение от выбора, так что это не ошибка в конце концов. Думаю, это просто недостающая функция.

Примечание: Это было бы довольно легко осуществить это в d3, заменив этот код ...

function drag() { 
    this.on("mousedown.drag", mousedown).on("touchstart.drag", touchstart); 
} 

с этим ...

function drag(selection, remove) { 
    [{e:"mousedown.drag", l: mousedown},{e: "touchstart.drag", l: touchstart}] 
    .reduce(function (s, b) {return s = s.on(b.e, remove ? null : b.l)}, this) 
} 

в d3.behavior.drag Тогда мы могли бы это сделать ...

отсоединять поведение.

Смежные вопросы