blob: d5ba0ed4910ba2163a1d3bda809eac1ae44d4219 [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
var BaseEvent = require('mercury').BaseEvent;
var extend = require('xtend');
var hg = require('mercury');
var delegator = hg.Delegator();
// Listen to the low frequency, drag related events. The high frequency "data"
// event is managed directly during event registration and removal in the drag
// handler.
delegator.listenTo('dragstart');
delegator.listenTo('dragend');
module.exports = BaseEvent(handleDrag); // jshint ignore:line
// # var drag = require('./events/drag')
//
// Use as a drag handler in virtual-dom using either ev-event or ev-mousedown.
// NOTE: The `draggable` attribute must be set to true on the vnode.
//
// h('.drag-me', {
// draggable: true,
// 'ev-event': drag(sink, { foo: 'bar' })
// })
//
// The `drag` handler will manage all event registration and listening across
// the lifespan of dragging on the target element. The broadcast to the `sink`
// will happen with an extra attribute merged into the passed in data:
//
// * dragstart: { dragging: true }
// * dragend: { dragging: false }
//
// Additionally, on the dragstart event any passed in data will be JSON encoded
// and attached to the native event's dataTransfer object. This enables it's
// retrieval from the drop DOM event (handled by `./events/drop`).
//
// NOTE: Currently this handle does not broadcast on high-frequency drag events,
// the necessary code has been stubbed out below for easy modification in the
// future.
function handleDrag(ev, broadcast) {
// Only handle mousedown events, allows usage of ev-events for simplicity.
if (ev.type !== 'mousedown') {
return;
}
var data = this.data;
var element = ev.target;
delegator.listenTo('drag');
delegator.addEventListener(element, 'dragstart', dragstart);
delegator.addEventListener(element, 'drag', drag);
delegator.addEventListener(element, 'dragend', dragend);
// NOTE: Do not broadcast until the actual drag events have been fired.
return;
// Fired when the user starts dragging the target element.
// SEE: https://developer.mozilla.org/en-US/docs/Web/Events/dragstart
function dragstart(event) {
// Using the raw DOM Event to access the DataTransfer object to set
// draggable data and the drag effect. This makes it possible for drop
// targets to access the data later.
//
// NOTE: dragover events do not have access to the data set below.
// SEE: https://goo.gl/fpwfP3
var raw = event._rawEvent;
raw.dataTransfer.setData('application/json', JSON.stringify(data));
raw.dataTransfer.effectAllowed = 'move';
broadcast(extend(data, { dragging: true }));
}
// Fires when the element is being dragged every few hundred ms. Currently a
// noop.
// SEE: https://developer.mozilla.org/en-US/docs/Web/Events/drag
function drag(event) {}
// Fired when dragging has ended.
// SEE: https://developer.mozilla.org/en-US/docs/Web/Events/dragend
function dragend(event) {
delegator.unlistenTo('drag');
delegator.removeEventListener(element, 'dragstart', dragstart);
delegator.removeEventListener(element, 'drag', drag);
delegator.removeEventListener(element, 'dragend', dragend);
broadcast(extend(data, { dragging: false }));
}
}