diagram-js
Advanced tools
Comparing version 0.6.0 to 0.7.0
@@ -522,4 +522,4 @@ 'use strict'; | ||
Canvas.prototype._fireViewboxChange = function(viewbox) { | ||
this._eventBus.fire('canvas.viewbox.changed', { viewbox: viewbox || this.viewbox() }); | ||
Canvas.prototype._fireViewboxChange = function() { | ||
this._eventBus.fire('canvas.viewbox.changed', { viewbox: this.viewbox(false) }); | ||
}; | ||
@@ -548,4 +548,7 @@ | ||
if (box === undefined && this._cachedViewbox) { | ||
return this._cachedViewbox; | ||
} | ||
var viewport = this._viewport, | ||
innerBox, | ||
@@ -566,3 +569,3 @@ outerBox = this.getSize(), | ||
return { | ||
box = this._cachedViewbox = { | ||
x: x ? x / scale : 0, | ||
@@ -581,2 +584,4 @@ y: y ? y / scale : 0, | ||
}; | ||
return box; | ||
} else { | ||
@@ -583,0 +588,0 @@ scale = Math.max(outerBox.width / box.width, outerBox.height / box.height); |
@@ -126,5 +126,6 @@ var LayoutUtil = require('../../layout/Util'), | ||
this.start = function(event, source) { | ||
this.start = function(event, source, autoActivate) { | ||
dragging.activate(event, 'connect', { | ||
autoActivate: autoActivate, | ||
data: { | ||
@@ -131,0 +132,0 @@ shape: source, |
@@ -90,3 +90,3 @@ 'use strict'; | ||
*/ | ||
ContextPad.prototype.trigger = function(action, event) { | ||
ContextPad.prototype.trigger = function(action, event, autoActivate) { | ||
@@ -115,7 +115,7 @@ var current = this._current, | ||
if (action === 'click') { | ||
return handler(originalEvent, element); | ||
return handler(originalEvent, element, autoActivate); | ||
} | ||
} else { | ||
if (handler[action]) { | ||
return handler[action](originalEvent, element); | ||
return handler[action](originalEvent, element, autoActivate); | ||
} | ||
@@ -189,2 +189,4 @@ } | ||
}; | ||
this._eventBus.fire('contextPad.open', { current: this._current }); | ||
}; | ||
@@ -227,2 +229,4 @@ | ||
pads = overlays.get({ element: element, type: 'context-pad' }); | ||
this._eventBus.fire('contextPad.create', { element: element, pad: pads[0] }); | ||
} | ||
@@ -244,2 +248,4 @@ | ||
this._current.open = false; | ||
this._eventBus.fire('contextPad.close', { current: this._current }); | ||
} | ||
@@ -246,0 +252,0 @@ }; |
@@ -117,2 +117,3 @@ | ||
cursor: 'grabbing', | ||
autoActivate: true, | ||
data: { | ||
@@ -119,0 +120,0 @@ shape: shape, |
@@ -0,1 +1,3 @@ | ||
/* global TouchEvent */ | ||
var _ = require('lodash'); | ||
@@ -7,2 +9,10 @@ | ||
function suppressEvent(event) { | ||
if (event instanceof MouseEvent) { | ||
Event.stopEvent(event, true); | ||
} else { | ||
Event.preventDefault(event); | ||
} | ||
} | ||
function getLength(point) { | ||
@@ -82,3 +92,14 @@ return Math.sqrt(Math.pow(point.x, 2) + Math.pow(point.y, 2)); | ||
function fire(type) { | ||
var event = _.extend({}, context.payload, context.data); | ||
var ActualEvent = require('../../core/EventBus').Event; | ||
var event = new ActualEvent(); | ||
event.init(_.extend({}, context.payload, context.data)); | ||
// default integration | ||
if (!eventBus.fire('drag.' + type, event)) { | ||
return false; | ||
} | ||
return eventBus.fire(context.prefix + '.' + type, event); | ||
@@ -89,15 +110,4 @@ } | ||
function move(event) { | ||
function move(event, activate) { | ||
// only intercept move events inside the root SVG node | ||
// | ||
// we would otherwise have no chance to retrieve the svg-relative | ||
// position of the move event | ||
// | ||
// looks better for users, too | ||
// | ||
if (!Dom.closest(event.target, 'svg')) { | ||
return; | ||
} | ||
var payload = context.payload, | ||
@@ -107,2 +117,3 @@ start = context.start, | ||
delta = substract(position, start), | ||
clientRect = canvas._container.getBoundingClientRect(), | ||
offset; | ||
@@ -113,4 +124,4 @@ | ||
offset = { | ||
x: (event.offsetX || event.layerX), | ||
y: (event.offsetY || event.layerY) | ||
x: clientRect.left, | ||
y: clientRect.top | ||
}; | ||
@@ -123,4 +134,4 @@ | ||
var movement = { | ||
x: viewbox.x + offset.x / viewbox.scale, | ||
y: viewbox.y + offset.y / viewbox.scale, | ||
x: viewbox.x + (position.x - offset.x) / viewbox.scale, | ||
y: viewbox.y + (position.y - offset.y) / viewbox.scale, | ||
dx: delta.x / viewbox.scale, | ||
@@ -130,7 +141,6 @@ dy: delta.y / viewbox.scale | ||
// activate context explicitly or once threshold is reached | ||
// activate context once threshold is reached | ||
if (!context.active && (activate || getLength(delta) > context.threshold)) { | ||
if (!context.active && getLength(delta) > context.threshold) { | ||
// fire start event with original | ||
@@ -151,4 +161,12 @@ // starting coordinates | ||
context.active = true; | ||
// unset selection | ||
if (!context.keepSelection) { | ||
context.previousSelection = selection.get(); | ||
selection.select(null); | ||
} | ||
} | ||
suppressEvent(event); | ||
if (context.active) { | ||
@@ -159,8 +177,2 @@ | ||
// unset selection | ||
if (!context.keepSelection) { | ||
context.previousSelection = selection.get(); | ||
selection.select(null); | ||
} | ||
// allow custom cursor | ||
@@ -176,2 +188,3 @@ if (context.cursor) { | ||
function end(event) { | ||
var restore = true; | ||
@@ -186,3 +199,3 @@ | ||
// because we just ended a drag operation | ||
Event.stopEvent(event); | ||
suppressEvent(event); | ||
} | ||
@@ -213,2 +226,28 @@ | ||
// prevent ghost click that might occur after a finished | ||
// drag and drop session | ||
function trapClickAndEnd(event) { | ||
var untrap = function(e) { | ||
Dom.off(document, 'click', trap, true); | ||
}; | ||
var trap = function(e) { | ||
suppressEvent(e); | ||
untrap(); | ||
}; | ||
if (context.active) { | ||
Dom.on(document, 'click', trap, true); | ||
setTimeout(untrap, 400); | ||
} | ||
end(event); | ||
} | ||
function trapTouch(event) { | ||
move(event); | ||
} | ||
// update the drag events hover (djs.model.Base) and hoverGfx (Snap<SVGElement>) | ||
@@ -261,11 +300,18 @@ // properties during hover and out and fire {prefix}.hover and {prefix}.out properties | ||
Dom.off(document, 'mousemove', move); | ||
Dom.off(document, 'mouseup', end); | ||
Dom.off(document, 'click', end); | ||
Dom.off(document, 'mousedown', trapClickAndEnd, true); | ||
Dom.off(document, 'mouseup', end, true); | ||
Dom.off(document, 'keyup', checkCancel); | ||
Dom.off(document, 'touchstart', trapTouch, true); | ||
Dom.off(document, 'touchcancel', cancel, true); | ||
Dom.off(document, 'touchmove', move, true); | ||
Dom.off(document, 'touchend', end, true); | ||
eventBus.off('element.hover', hover); | ||
eventBus.off('element.out', out); | ||
// restore selection | ||
if (restore !== false && context.previousSelection) { | ||
// restore selection, unless it has changed | ||
if (restore !== false && context.previousSelection && !selection.get().length) { | ||
selection.select(context.previousSelection); | ||
@@ -286,3 +332,4 @@ } | ||
var data = options.data || {}; | ||
var data = options.data || {}, | ||
originalEvent = Event.getOriginal(event) || event; | ||
@@ -296,3 +343,2 @@ context = _.extend({ | ||
// skip dom registration if trigger | ||
@@ -302,6 +348,16 @@ // is set to manual (during testing) | ||
// add dom listeners | ||
Dom.on(document, 'mousemove', move); | ||
Dom.on(document, 'mouseup', end); | ||
Dom.on(document, 'click', end); | ||
if (originalEvent instanceof MouseEvent) { | ||
// add dom listeners | ||
Dom.on(document, 'mousemove', move); | ||
Dom.on(document, 'mousedown', trapClickAndEnd, true); | ||
Dom.on(document, 'mouseup', end, true); | ||
} else | ||
if (originalEvent instanceof TouchEvent) { | ||
Dom.on(document, 'touchstart', trapTouch, true); | ||
Dom.on(document, 'touchcancel', cancel, true); | ||
Dom.on(document, 'touchmove', move, true); | ||
Dom.on(document, 'touchend', end, true); | ||
} | ||
Dom.on(document, 'keyup', checkCancel); | ||
@@ -313,6 +369,9 @@ | ||
// cancel original event | ||
Event.stopEvent(event); | ||
suppressEvent(event); | ||
fire('activate'); | ||
if (options.autoActivate) { | ||
move(event, true); | ||
} | ||
} | ||
@@ -319,0 +378,0 @@ |
@@ -46,3 +46,2 @@ 'use strict'; | ||
if (!gfx || !element) { | ||
console.error('NO GFX OR ELEMENT FOR EVENT', event); | ||
return; | ||
@@ -58,12 +57,6 @@ } | ||
function handler(type) { | ||
return function(event) { | ||
fire(type, event); | ||
}; | ||
} | ||
function mouseHandler(type) { | ||
return function(event) { | ||
if (event.button === 0) { | ||
// only indicate left mouse button interactions | ||
// only indicate left mouse button=0 interactions | ||
if (!event.button) { | ||
fire(type, event); | ||
@@ -90,3 +83,3 @@ } | ||
*/ | ||
Dom.on(node, 'mouseover', handler('element.hover')); | ||
Dom.on(node, 'mouseover', mouseHandler('element.hover')); | ||
@@ -103,3 +96,3 @@ /** | ||
*/ | ||
Dom.on(node, 'mouseout', handler('element.out')); | ||
Dom.on(node, 'mouseout', mouseHandler('element.out')); | ||
@@ -202,2 +195,6 @@ /** | ||
// API | ||
this.fire = fire; | ||
} | ||
@@ -204,0 +201,0 @@ |
@@ -136,3 +136,3 @@ var _ = require('lodash'); | ||
function start(event, element) { | ||
function start(event, element, activate) { | ||
@@ -146,2 +146,3 @@ // do not move connections or the root element | ||
cursor: 'grabbing', | ||
autoActivate: activate, | ||
data: { | ||
@@ -148,0 +149,0 @@ shape: element, |
@@ -87,2 +87,6 @@ 'use strict'; | ||
}); | ||
this._eventBus.fire('palette.create', { | ||
html: container | ||
}); | ||
}; | ||
@@ -130,3 +134,3 @@ | ||
*/ | ||
Palette.prototype.trigger = function(action, event) { | ||
Palette.prototype.trigger = function(action, event, autoActivate) { | ||
@@ -153,7 +157,7 @@ var entries = this._entries, | ||
if (action === 'click') { | ||
return handler(originalEvent); | ||
return handler(originalEvent, autoActivate); | ||
} | ||
} else { | ||
if (handler[action]) { | ||
return handler[action](originalEvent); | ||
return handler[action](originalEvent, autoActivate); | ||
} | ||
@@ -160,0 +164,0 @@ } |
@@ -7,12 +7,14 @@ 'use strict'; | ||
ResizeUtil = require('./Util'), | ||
Event = require('../../util/Event'); | ||
Dom = require('../../util/Dom'); | ||
var OUTLINE_OFFSET = 5; | ||
var ANCHOR_LENGTH = 5; | ||
var MARKER_RESIZING = 'djs-resizing'; | ||
var MARKER_RESIZE_NOT_OK = 'resize-not-ok'; | ||
var CLASS_RESIZER = '.djs-resizer'; | ||
var HANDLE_OFFSET = -2, | ||
HANDLE_SIZE = 5, | ||
HANDLE_HIT_SIZE = 20; | ||
var MARKER_RESIZING = 'djs-resizing', | ||
MARKER_RESIZE_NOT_OK = 'resize-not-ok', | ||
CLS_RESIZER = 'djs-resizer'; | ||
/** | ||
@@ -147,2 +149,3 @@ * Implements resize on shapes by | ||
dragging.activate(event, 'resize', { | ||
autoActivate: true, | ||
data: { | ||
@@ -158,76 +161,62 @@ shape: shape, | ||
function makeDraggable(element, gfx, direction) { | ||
// resize handles implementation /////////////////////////////// | ||
function listener(event) { | ||
// only start on left-click (button=0) | ||
if (!event.button) { | ||
start(event, element, direction); | ||
} | ||
} | ||
function addResize(shape) { | ||
Dom.on(gfx.node, 'mousedown', listener); | ||
Dom.on(gfx.node, 'touchstart', listener); | ||
} | ||
if (!canResize({ shape: shape })) { | ||
return; | ||
} | ||
function __createResizer(gfx, x, y, rotation, direction) { | ||
function makeDraggable(resizer, direction) { | ||
var group = gfx.group().addClass(CLS_RESIZER).addClass(CLS_RESIZER + '-' + direction); | ||
resizer.mousedown(function(event) { | ||
start(event, shape, direction); | ||
}); | ||
} | ||
var origin = -HANDLE_SIZE + HANDLE_OFFSET; | ||
var gfx = elementRegistry.getGraphics(shape); | ||
// Create four drag indicators on the outline | ||
var overlayNorthWest = Snap.create('rect', { | ||
class: 'djs-resizer nort-west', | ||
cursor: 'nwse-resize', | ||
width: ANCHOR_LENGTH + 'px', | ||
height: ANCHOR_LENGTH + 'px', | ||
x: - (ANCHOR_LENGTH + ANCHOR_LENGTH / 2) + 'px', | ||
y: - (ANCHOR_LENGTH + ANCHOR_LENGTH / 2) + 'px', | ||
fill: '#fff', | ||
strokeWidth: '1px', | ||
stroke: '#000' | ||
}).appendTo(gfx); | ||
var visual = group.rect(origin, origin, HANDLE_SIZE, HANDLE_SIZE).addClass(CLS_RESIZER + '-visual'); | ||
var hit = group.rect(origin, origin, HANDLE_HIT_SIZE, HANDLE_HIT_SIZE).addClass(CLS_RESIZER + '-hit'); | ||
makeDraggable(overlayNorthWest, 'nw'); | ||
var matrix = new Snap.Matrix().translate(x, y).rotate(rotation, 0, 0); | ||
group.transform(matrix); | ||
var overlayNorthEast = Snap.create('rect', { | ||
class: 'djs-resizer nort-east', | ||
cursor: 'nesw-resize', | ||
width: ANCHOR_LENGTH + 'px', | ||
height: ANCHOR_LENGTH + 'px', | ||
x: shape.width + ANCHOR_LENGTH / 2 + 'px', | ||
y: - (ANCHOR_LENGTH + ANCHOR_LENGTH / 2) + 'px', | ||
fill: '#fff', | ||
strokeWidth: '1px', | ||
stroke: '#000' | ||
}).appendTo(gfx); | ||
return group; | ||
} | ||
makeDraggable(overlayNorthEast, 'ne'); | ||
function createResizer(element, gfx, direction) { | ||
var overlaySouthEast = Snap.create('rect', { | ||
class: 'djs-resizer south-east', | ||
cursor: 'nwse-resize', | ||
width: ANCHOR_LENGTH + 'px', | ||
height: ANCHOR_LENGTH + 'px', | ||
x: shape.width + ANCHOR_LENGTH / 2 + 'px', | ||
y: shape.height + ANCHOR_LENGTH / 2 + 'px', | ||
fill: '#fff', | ||
strokeWidth: '1px', | ||
stroke: '#000' | ||
}).appendTo(gfx); | ||
var resizer; | ||
makeDraggable(overlaySouthEast, 'se'); | ||
if (direction === 'nw') { | ||
resizer = __createResizer(gfx, 0, 0, 0, direction); | ||
} else if (direction === 'ne') { | ||
resizer = __createResizer(gfx, element.width, 0, 90, direction); | ||
} else if (direction === 'se') { | ||
resizer = __createResizer(gfx, element.width, element.height, 180, direction); | ||
} else { | ||
resizer = __createResizer(gfx, 0, element.height, 270, direction); | ||
} | ||
var overlaySouthWest = Snap.create('rect', { | ||
class: 'djs-resizer south-west', | ||
cursor: 'nesw-resize', | ||
width: ANCHOR_LENGTH + 'px', | ||
height: ANCHOR_LENGTH + 'px', | ||
x: - (ANCHOR_LENGTH + ANCHOR_LENGTH / 2) + 'px', | ||
y: shape.height + ANCHOR_LENGTH / 2 + 'px', | ||
fill: '#fff', | ||
strokeWidth: '1px', | ||
stroke: '#000' | ||
}).appendTo(gfx); | ||
makeDraggable(element, resizer, direction); | ||
} | ||
makeDraggable(overlaySouthWest, 'sw'); | ||
// resize handles implementation /////////////////////////////// | ||
function addResize(shape) { | ||
if (!canResize({ shape: shape })) { | ||
return; | ||
} | ||
var gfx = elementRegistry.getGraphics(shape); | ||
createResizer(shape, gfx, 'nw'); | ||
createResizer(shape, gfx, 'ne'); | ||
createResizer(shape, gfx, 'se'); | ||
createResizer(shape, gfx, 'sw'); | ||
} | ||
@@ -238,3 +227,3 @@ | ||
var gfx = elementRegistry.getGraphics(shape); | ||
var resizers = gfx.selectAll(CLASS_RESIZER); | ||
var resizers = gfx.selectAll('.' + CLS_RESIZER); | ||
@@ -241,0 +230,0 @@ _.forEach(resizers, function(resizer){ |
'use strict'; | ||
module.exports = { | ||
__init__: [ 'selectionVisuals' ], | ||
__init__: [ 'selectionVisuals', 'selectionBehavior' ], | ||
__depends__: [ | ||
@@ -10,3 +10,4 @@ require('../interaction-events'), | ||
selection: [ 'type', require('./Selection') ], | ||
selectionVisuals: [ 'type', require('./SelectionVisuals') ] | ||
selectionVisuals: [ 'type', require('./SelectionVisuals') ], | ||
selectionBehavior: [ 'type', require('./SelectionBehavior') ] | ||
}; |
@@ -5,8 +5,2 @@ 'use strict'; | ||
function originalEvent(e) { | ||
return e.originalEvent || e; | ||
} | ||
var MARKER_HOVER = 'hover', | ||
@@ -28,3 +22,3 @@ MARKER_SELECTED = 'selected'; | ||
*/ | ||
function SelectionVisuals(events, selection, canvas) { | ||
function SelectionVisuals(events, canvas) { | ||
@@ -39,23 +33,2 @@ function addMarker(e, cls) { | ||
/** | ||
* Wire click on shape to select the shape | ||
* | ||
* @param {Object} event the fired event | ||
*/ | ||
events.on('element.click', function(event) { | ||
var element = event.element; | ||
// do not select the root element | ||
// or connections | ||
if (element === canvas.getRootElement() || | ||
element.waypoints) { | ||
element = null; | ||
} | ||
var add = originalEvent(event).shiftKey; | ||
selection.select(element, add); | ||
}); | ||
events.on('element.hover', function(event) { | ||
@@ -98,3 +71,2 @@ addMarker(event.element, MARKER_HOVER); | ||
'eventBus', | ||
'selection', | ||
'canvas' | ||
@@ -101,0 +73,0 @@ ]; |
@@ -30,5 +30,2 @@ 'use strict'; | ||
this._createSnapLines(); | ||
var self = this; | ||
@@ -147,3 +144,3 @@ | ||
var line = this._snapLines[orientation]; | ||
var line = this.getSnapLine(orientation); | ||
if (line) { | ||
@@ -156,2 +153,10 @@ line.update(snap); | ||
Snapping.prototype.getSnapLine = function(orientation) { | ||
if (!this._snapLines) { | ||
this._createSnapLines(); | ||
} | ||
return this._snapLines[orientation]; | ||
}; | ||
Snapping.prototype.hide = function() { | ||
@@ -158,0 +163,0 @@ _.forEach(this._snapLines, function(l) { |
module.exports = { | ||
__depends__: [ require('../interaction-events') ], | ||
__init__: [ 'touchInteractionEvents' ], | ||
@@ -3,0 +4,0 @@ touchInteractionEvents: [ 'type', require('./TouchInteractionEvents') ], |
@@ -1,93 +0,322 @@ | ||
'use strict'; | ||
var _ = require('lodash'), | ||
Hammer = require('hammerjs'); | ||
Hammer = require('hammerjs'), | ||
Snap = require('snapsvg'), | ||
Dom = require('../../util/Dom'), | ||
Event = require('../../util/Event'); | ||
var MIN_ZOOM = 0.2, | ||
MAX_ZOOM = 4; | ||
function createTapRecognizer(element) { | ||
var h = new Hammer(element, {}); | ||
function log() { | ||
if (false) { | ||
console.log.apply(console, arguments); | ||
} | ||
} | ||
function get(service, injector) { | ||
try { | ||
return injector.get(service); | ||
} catch (e) { | ||
return null; | ||
} | ||
} | ||
function createTouchRecognizer(node) { | ||
function stopEvent(event) { | ||
Event.stopEvent(event, true); | ||
} | ||
function stopMouse(event) { | ||
Dom.on(node, 'mousedown', stopEvent, true); | ||
Dom.on(node, 'mouseup', stopEvent, true); | ||
Dom.on(node, 'mouseover', stopEvent, true); | ||
Dom.on(node, 'mouseout', stopEvent, true); | ||
Dom.on(node, 'click', stopEvent, true); | ||
Dom.on(node, 'dblclick', stopEvent, true); | ||
} | ||
function allowMouse(event) { | ||
setTimeout(function() { | ||
Dom.off(node, 'mousedown', stopEvent, true); | ||
Dom.off(node, 'mouseup', stopEvent, true); | ||
Dom.off(node, 'mouseover', stopEvent, true); | ||
Dom.off(node, 'mouseout', stopEvent, true); | ||
Dom.off(node, 'click', stopEvent, true); | ||
Dom.off(node, 'dblclick', stopEvent, true); | ||
}, 500); | ||
} | ||
node.addEventListener('touchstart', stopMouse, true); | ||
node.addEventListener('touchend', allowMouse, true); | ||
node.addEventListener('touchcancel', allowMouse, true); | ||
// A touch event recognizer that handles | ||
// touch events only (we know, we can already handle | ||
// mouse events out of the box) | ||
var recognizer = new Hammer.Manager(node, { | ||
inputClass: Hammer.TouchInput, | ||
recognizers: [] | ||
}); | ||
var tap = new Hammer.Tap(); | ||
var pan = new Hammer.Pan({ threshold: 10 }); | ||
var press = new Hammer.Press(); | ||
var pinch = new Hammer.Pinch(); | ||
var doubleTap = new Hammer.Tap({ event: 'doubletap', taps: 2 }); | ||
doubleTap.recognizeWith(tap); | ||
tap.requireFailure([ doubleTap ]); | ||
pinch.requireFailure(pan); | ||
pinch.requireFailure(press); | ||
h.add([ doubleTap, tap ]); | ||
recognizer.add([ pan, press, pinch, doubleTap, tap ]); | ||
return h; | ||
recognizer.reset = function(force) { | ||
var recognizers = this.recognizers, | ||
session = this.session; | ||
if (session.stopped) { | ||
return; | ||
} | ||
log('recognizer', 'stop'); | ||
recognizer.stop(force); | ||
setTimeout(function() { | ||
var i, r; | ||
log('recognizer', 'reset'); | ||
for (i = 0; !!(r = recognizers[i]); i++) { | ||
r.reset(); | ||
r.state = 8; // FAILED STATE | ||
} | ||
session.curRecognizer = null; | ||
}, 0); | ||
}; | ||
recognizer.on('hammer.input', function(event) { | ||
if (event.srcEvent.defaultPrevented) { | ||
recognizer.reset(true); | ||
} | ||
}); | ||
return recognizer; | ||
} | ||
/** | ||
* @class | ||
* | ||
* A plugin that provides touch events for elements. | ||
* | ||
* @param {EventBus} eventBus | ||
* @param {Canvas} canvas | ||
* @param {InteractionEvents} interactionEvents | ||
*/ | ||
function TouchInteractioneventBus(eventBus, canvas) { | ||
function TouchInteractionEvents(injector, canvas, eventBus, elementRegistry, interactionEvents) { | ||
function createEvent(event, baseEvent) { | ||
return _.extend({}, baseEvent, event); | ||
// optional integrations | ||
var dragging = get('dragging', injector), | ||
move = get('move', injector), | ||
contextPad = get('contextPad', injector), | ||
palette = get('palette', injector); | ||
// the touch recognizer | ||
var recognizer; | ||
function handler(type) { | ||
return function(event) { | ||
log('element', type, event); | ||
interactionEvents.fire(type, event); | ||
}; | ||
} | ||
function makeSelectable(element, gfx, options) { | ||
var type = options.type; | ||
function getGfx(target) { | ||
var node = Dom.closest(target, 'svg, .djs-element'); | ||
return node && new Snap(node); | ||
} | ||
var baseEvent = { element: element, gfx: gfx }; | ||
function initEvents(svg) { | ||
// Touch | ||
var h = createTapRecognizer(gfx.node); | ||
// touch recognizer | ||
recognizer = createTouchRecognizer(svg); | ||
h.on('doubletap', function(e) { | ||
var event = createEvent(e, baseEvent); | ||
recognizer.on('doubletap', handler('element.dblclick')); | ||
eventBus.fire(type + '.dbltap', event); | ||
eventBus.fire(type + '.dblclick', event); | ||
recognizer.on('tap', handler('element.click')); | ||
e.preventDefault(); | ||
}); | ||
function startGrabCanvas(event) { | ||
h.on('tap', function(e) { | ||
var event = createEvent(e, baseEvent); | ||
log('canvas', 'grab start'); | ||
eventBus.fire(type + '.tap', event); | ||
eventBus.fire(type + '.click', event); | ||
var lx = 0, ly = 0; | ||
e.preventDefault(); | ||
}); | ||
function update(e) { | ||
var dx = e.deltaX - lx, | ||
dy = e.deltaY - ly; | ||
canvas.scroll({ dx: dx, dy: dy }); | ||
lx = e.deltaX; | ||
ly = e.deltaY; | ||
} | ||
function end(e) { | ||
recognizer.off('panmove', update); | ||
recognizer.off('panend', end); | ||
recognizer.off('pancancel', end); | ||
log('canvas', 'grab end'); | ||
} | ||
recognizer.on('panmove', update); | ||
recognizer.on('panend', end); | ||
recognizer.on('pancancel', end); | ||
} | ||
function startGrab(event) { | ||
var gfx = getGfx(event.target), | ||
element = gfx && elementRegistry.get(gfx); | ||
// recognizer | ||
if (move && canvas.getRootElement() !== element) { | ||
log('element', 'move start', element, event, true); | ||
return move.start(event, element, true); | ||
} else { | ||
startGrabCanvas(event); | ||
} | ||
} | ||
function startZoom(e) { | ||
log('canvas', 'zoom start'); | ||
var zoom = canvas.zoom(), | ||
mid = e.center; | ||
function update(e) { | ||
var ratio = 1 - (1 - e.scale) / 1.50, | ||
newZoom = Math.max(MIN_ZOOM, Math.min(MAX_ZOOM, ratio * zoom)); | ||
canvas.zoom(newZoom, mid); | ||
Event.stopEvent(e, true); | ||
} | ||
function end(e) { | ||
recognizer.off('pinchmove', update); | ||
recognizer.off('pinchend', end); | ||
recognizer.off('pinchcancel', end); | ||
recognizer.reset(true); | ||
log('canvas', 'zoom end'); | ||
} | ||
recognizer.on('pinchmove', update); | ||
recognizer.on('pinchend', end); | ||
recognizer.on('pinchcancel', end); | ||
} | ||
recognizer.on('panstart', startGrab); | ||
recognizer.on('press', startGrab); | ||
recognizer.on('pinchstart', startZoom); | ||
} | ||
function registerEvents(eventBus) { | ||
if (dragging) { | ||
eventBus.on('canvas.init', function(event) { | ||
var viewport = event.viewport, | ||
svg = event.svg.node; | ||
// simulate hover during dragging | ||
eventBus.on('drag.move', function(event) { | ||
createTapRecognizer(svg).on('tap', function(e) { | ||
var position = Event.toPoint(event.originalEvent); | ||
if (e.target === svg) { | ||
var evt = createEvent(e, { viewport: viewport }); | ||
eventBus.fire('canvas.tap', evt); | ||
eventBus.fire('canvas.click', evt); | ||
var node = document.elementFromPoint(position.x, position.y), | ||
gfx = getGfx(node), | ||
element = gfx && elementRegistry.get(gfx); | ||
if (element !== event.hover) { | ||
if (event.hover) { | ||
dragging.out(event); | ||
} | ||
}); | ||
if (element) { | ||
dragging.hover({ element: element, gfx: gfx }); | ||
event.hover = element; | ||
event.hoverGfx = gfx; | ||
} | ||
} | ||
}); | ||
} | ||
eventBus.on('shape.added', function(event) { | ||
makeSelectable(event.element, event.gfx, { type: 'shape' }); | ||
if (contextPad) { | ||
eventBus.on('contextPad.create', function(event) { | ||
var node = event.pad.html.get(0); | ||
// touch recognizer | ||
var padRecognizer = createTouchRecognizer(node); | ||
padRecognizer.on('panstart', function(event) { | ||
log('context-pad', 'panstart', event); | ||
contextPad.trigger('dragstart', event, true); | ||
}); | ||
padRecognizer.on('press', function(event) { | ||
log('context-pad', 'press', event); | ||
contextPad.trigger('dragstart', event, true); | ||
}); | ||
padRecognizer.on('tap', function(event) { | ||
log('context-pad', 'tap', event); | ||
contextPad.trigger('click', event); | ||
}); | ||
}); | ||
} | ||
eventBus.on('connection.added', function(event) { | ||
makeSelectable(event.element, event.gfx, { type: 'connection' }); | ||
if (palette) { | ||
eventBus.on('palette.create', function(event) { | ||
var node = event.html.get(0); | ||
// touch recognizer | ||
var padRecognizer = createTouchRecognizer(node); | ||
padRecognizer.on('panstart', function(event) { | ||
log('palette', 'panstart', event); | ||
palette.trigger('dragstart', event, true); | ||
}); | ||
padRecognizer.on('press', function(event) { | ||
log('palette', 'press', event); | ||
palette.trigger('dragstart', event, true); | ||
}); | ||
padRecognizer.on('tap', function(event) { | ||
log('palette', 'tap', event); | ||
palette.trigger('click', event); | ||
}); | ||
}); | ||
} | ||
registerEvents(eventBus); | ||
eventBus.on('canvas.init', function(event) { | ||
initEvents(event.svg.node); | ||
}); | ||
} | ||
TouchInteractioneventBus.$inject = [ 'eventBus', 'canvas', 'touchFix' ]; | ||
TouchInteractionEvents.$inject = [ | ||
'injector', | ||
'canvas', | ||
'eventBus', | ||
'elementRegistry', | ||
'interactionEvents', | ||
'touchFix' | ||
]; | ||
module.exports = TouchInteractioneventBus; | ||
module.exports = TouchInteractionEvents; |
module.exports = { | ||
__depends__: [ | ||
require('../../features/touch') | ||
], | ||
__init__: [ 'touchInteraction' ], | ||
touchInteraction: [ 'type', require('./TouchInteraction') ] | ||
}; | ||
__depends__: [ require('../../features/touch') ] | ||
}; |
@@ -77,4 +77,4 @@ | ||
function on(element, type, fn) { | ||
element.addEventListener(type, fn); | ||
function on(element, type, fn, useCapture) { | ||
element.addEventListener(type, fn, useCapture || false); | ||
} | ||
@@ -85,6 +85,19 @@ | ||
function off(element, type, fn) { | ||
element.removeEventListener(type, fn); | ||
function off(element, type, fn, useCapture) { | ||
element.removeEventListener(type, fn, useCapture || false); | ||
} | ||
module.exports.off = off; | ||
module.exports.off = off; | ||
function once(element, type, fn, useCapture) { | ||
var wrappedFn = function(e) { | ||
fn(e); | ||
off(element, type, wrappedFn, useCapture); | ||
}; | ||
on(element, type, wrappedFn, useCapture); | ||
} | ||
module.exports.once = once; |
@@ -1,21 +0,48 @@ | ||
function stopEvent(event) { | ||
var originalEvent = event.originalEvent; | ||
function __preventDefault(event) { | ||
return event && event.preventDefault(); | ||
} | ||
event.stopPropagation(); | ||
event.preventDefault(); | ||
function __stopPropagation(event, immediate) { | ||
if (!event) { | ||
return; | ||
} | ||
if (originalEvent) { | ||
originalEvent.stopPropagation(); | ||
originalEvent.preventDefault(); | ||
if (event.stopPropagation) { | ||
event.stopPropagation(); | ||
} | ||
if (immediate && event.stopImmediatePropagation) { | ||
event.stopImmediatePropagation(); | ||
} | ||
} | ||
function getOriginal(event) { | ||
return event.originalEvent || event.srcEvent; | ||
} | ||
module.exports.getOriginal = getOriginal; | ||
function stopEvent(event, immediate) { | ||
stopPropagation(event, immediate); | ||
preventDefault(event); | ||
} | ||
module.exports.stopEvent = stopEvent; | ||
function stopPropagation(event) { | ||
event = event.originalEvent || event; | ||
event.stopPropagation(); | ||
function preventDefault(event) { | ||
__preventDefault(event); | ||
__preventDefault(getOriginal(event)); | ||
} | ||
module.exports.preventDefault = preventDefault; | ||
function stopPropagation(event, immediate) { | ||
__stopPropagation(event, immediate); | ||
__stopPropagation(getOriginal(event), immediate); | ||
} | ||
module.exports.stopPropagation = stopPropagation; | ||
@@ -25,8 +52,17 @@ | ||
function toPoint(event) { | ||
return { | ||
if (event.pointers && event.pointers.length) { | ||
event = event.pointers[0]; | ||
} | ||
if (event.touches && event.touches.length) { | ||
event = event.touches[0]; | ||
} | ||
return event ? { | ||
x: event.clientX, | ||
y: event.clientY | ||
}; | ||
} : null; | ||
} | ||
module.exports.toPoint = toPoint; |
{ | ||
"name": "diagram-js", | ||
"version": "0.6.0", | ||
"version": "0.7.0", | ||
"description": "A modeling framework for the web", | ||
@@ -21,3 +21,3 @@ "scripts": { | ||
"devDependencies": { | ||
"brfs": "^1.1.1", | ||
"brfs": "~1.2.0", | ||
"grunt": "~0.4.4", | ||
@@ -29,5 +29,5 @@ "grunt-contrib-jshint": "^0.7.2", | ||
"jasmine-test-container-support": "^0.1.2", | ||
"jsondiffpatch": "^0.1.7", | ||
"jsondiffpatch": "^0.1.26", | ||
"karma": "^0.12.8", | ||
"karma-browserify": "^1.0.0", | ||
"karma-browserify": "^2.0.0", | ||
"karma-chrome-launcher": "^0.1.2", | ||
@@ -34,0 +34,0 @@ "karma-firefox-launcher": "^0.1.3", |
@@ -23,8 +23,20 @@ var _ = require('lodash'); | ||
var Event; | ||
beforeEach(inject(function(dragging) { | ||
dragging.setOptions({ manual: true }); | ||
})); | ||
beforeEach(inject(function(canvas, dragging) { | ||
Event = Events.target(canvas._svg); | ||
var createEvent; | ||
dragging.setOptions({ manual: true }); | ||
beforeEach(inject(function(canvas) { | ||
var Event = Events.target(canvas._svg); | ||
createEvent = function(data) { | ||
var clientRect = canvas._container.getBoundingClientRect(); | ||
data.x += clientRect.left; | ||
data.y += clientRect.top; | ||
return Event.create(data); | ||
}; | ||
})); | ||
@@ -58,3 +70,3 @@ | ||
// given | ||
var event = Event.create({ x: 10, y: 10 }); | ||
var event = createEvent({ x: 10, y: 10 }); | ||
@@ -66,3 +78,2 @@ // when | ||
expect(event.defaultPrevented).toBe(true); | ||
expect(event.propagationStopped).toBe(true); | ||
})); | ||
@@ -77,3 +88,3 @@ | ||
// when | ||
dragging.activate(Event.create({ x: 10, y: 10 }), 'foo', { | ||
dragging.activate(createEvent({ x: 10, y: 10 }), 'foo', { | ||
data: { foo: 'BAR' } | ||
@@ -91,3 +102,3 @@ }); | ||
it('should fire life-cycle events', inject(function(dragging) { | ||
it('should fire life-cycle events', inject(function(dragging, canvas) { | ||
@@ -97,6 +108,8 @@ // given | ||
debugger; | ||
// when | ||
dragging.activate(Event.create({ x: 10, y: 10 }), 'foo'); | ||
dragging.move(Event.create({ x: 30, y: 20 })); | ||
dragging.move(Event.create({ x: 5, y: 10 })); | ||
dragging.activate(createEvent({ x: 10, y: 10 }), 'foo'); | ||
dragging.move(createEvent({ x: 30, y: 20 })); | ||
dragging.move(createEvent({ x: 5, y: 10 })); | ||
@@ -123,7 +136,7 @@ dragging.cancel(); | ||
// a is active | ||
dragging.activate(Event.create({ x: 10, y: 10 }), 'foo', { data: { element: 'a' } }); | ||
dragging.activate(createEvent({ x: 10, y: 10 }), 'foo', { data: { element: 'a' } }); | ||
// when | ||
// activate b | ||
dragging.activate(Event.create({ x: 10, y: 10 }), 'foo', { data: { element: 'b' } }); | ||
dragging.activate(createEvent({ x: 10, y: 10 }), 'foo', { data: { element: 'b' } }); | ||
@@ -130,0 +143,0 @@ // then |
var TestHelper = require('../../../TestHelper'), | ||
Events = require('../../../util/Events'); | ||
/* global bootstrapDiagram, inject, iit */ | ||
/* global bootstrapDiagram, inject */ | ||
@@ -6,0 +6,0 @@ var _ = require('lodash'); |
@@ -5,3 +5,3 @@ 'use strict'; | ||
/* global bootstrapDiagram, inject, iit */ | ||
/* global bootstrapDiagram, inject */ | ||
@@ -8,0 +8,0 @@ var rulesModule = require('./rules'), |
@@ -17,8 +17,4 @@ 'use strict'; | ||
describe('bootstrap', function() { | ||
it('should bootstrap', inject(function(touchInteraction) { | ||
expect(touchInteraction).not.toBe(null); | ||
})); | ||
it('should bootstrap', inject(function() {})); | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
421532
12610
157