-
Notifications
You must be signed in to change notification settings - Fork 853
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
5137cbb
commit 0abfa1b
Showing
8 changed files
with
427 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
<p>A listener is an object that allows you to listen for events triggered by other objects and, if needed, remove them all at once.</p> | ||
|
||
<p>Two signatures are used to listen to events:</p> | ||
<ol> | ||
<li>Listening to specific event passed as string:</li> | ||
<pre><code>const listener = new mvc.Listener(callbackArgument); | ||
const callback = (callbackArgument, elementView) => {}; | ||
listener.listenTo(paper, 'element:pointerclick', callback); | ||
|
||
// Optionally | ||
const context = { foo: 'bar' }; | ||
listener.listenTo(paper, 'element:pointerclick', callback, context);</code></pre> | ||
<li>Listening to multiple events by passing event map:</li> | ||
<pre><code>const listener = new mvc.Listener(callbackArgument); | ||
const eventMap = { | ||
'remove': (callbackArgument, cell) => {}, | ||
'add': (callbackArgument, cell) => {} | ||
}; | ||
listener.listenTo(graph, eventMap); | ||
|
||
// Optionally | ||
const context = { foo: 'bar' }; | ||
listener.listenTo(graph, eventMap, context);</code></pre> | ||
</ol> | ||
|
||
<p>Example usage for toggling between view and edit mode:</p> | ||
<pre><code>class ViewController extends mvc.Listener { | ||
|
||
startListening() { | ||
const [{ paper }] = this.callbackArguments; | ||
this.listenTo(paper, 'element:mouseenter', (appContext, elementView) => { | ||
joint.highlighters.mask.add(elementView, 'body', 'highlighted-element'); | ||
}); | ||
this.listenTo(paper, 'element:mouseleave', (appContext, elementView) => { | ||
joint.highlighters.mask.remove(elementView, 'highlighted-element'); | ||
}); | ||
} | ||
} | ||
|
||
class EditController extends mvc.Listener { | ||
|
||
startListening() { | ||
const [{ paper }] = this.callbackArguments; | ||
this.listenTo(paper, 'element:pointerclick', (appContext, elementView) => { | ||
elementView.model.remove(); | ||
}); | ||
} | ||
} | ||
|
||
const appContext = { paper, graph }; | ||
|
||
const viewController = new ViewController(appContext); | ||
const editController = new EditController(appContext); | ||
|
||
let editMode = false; | ||
function toggleEditMode(canEdit = !editMode) { | ||
editMode = canEdit; | ||
if (editMode) { | ||
editController.startListening(); | ||
viewController.stopListening(); | ||
} else { | ||
viewController.startListening(); | ||
editController.stopListening(); | ||
} | ||
} | ||
|
||
// start app in view mode | ||
toggleEditMode(false);</code></pre> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,218 @@ | ||
'use strict'; | ||
|
||
const createPaperHTMLElement = () => { | ||
const fixtureEl = document.createElement('div'); | ||
fixtureEl.setAttribute('id', 'qunit-fixture'); | ||
document.body.appendChild(fixtureEl); | ||
|
||
const paperEl = document.createElement('div'); | ||
fixtureEl.appendChild(paperEl); | ||
|
||
return paperEl; | ||
}; | ||
|
||
QUnit.module('joint.mvc.Listener', (hooks) => { | ||
QUnit.test('passing/getting callbackArguments', (assert) => { | ||
const n1 = 100; | ||
const s1 = 'foo'; | ||
const listener = new joint.mvc.Listener(n1, s1); | ||
const [cbArg1, cbArg2] = listener.callbackArguments; | ||
|
||
assert.equal(cbArg1, n1); | ||
assert.equal(cbArg2, s1); | ||
}); | ||
|
||
QUnit.module('events', (hooks) => { | ||
hooks.beforeEach(() => { | ||
this.graph = new joint.dia.Graph; | ||
this.rect = new joint.shapes.standard.Rectangle(); | ||
this.graph.resetCells([this.rect]); | ||
}); | ||
|
||
hooks.afterEach(() => { | ||
this.graph = null; | ||
this.rect = null; | ||
}); | ||
|
||
QUnit.test('stop listening', (assert) => { | ||
const newPosition = { x: 100, y: 100 }; | ||
const newSize = { width: 100, height: 100 }; | ||
|
||
const positionCb = sinon.spy(); | ||
const sizeCb = sinon.spy(); | ||
const rectEvents = { | ||
'change:size': sizeCb | ||
}; | ||
|
||
const listener = new joint.mvc.Listener(); | ||
listener.listenTo(this.graph, 'change:position', positionCb); | ||
listener.listenTo(this.rect, rectEvents); | ||
|
||
this.rect.position(newPosition.x, newPosition.y); | ||
this.rect.resize(newSize.width, newSize.height); | ||
listener.stopListening(); | ||
this.rect.position(newPosition.x + 1, newPosition.y + 1); | ||
this.rect.resize(newSize.width + 1, newSize.height + 1); | ||
|
||
assert.ok(positionCb.calledOnce); | ||
assert.ok(sizeCb.calledOnce); | ||
}); | ||
|
||
QUnit.module('signature 1', () => { | ||
QUnit.test('multiple objects', (assert) => { | ||
const newPosition = { x: 100, y: 100 }; | ||
const args = [{ foo: 'bar' }, 'baz', 10]; | ||
const paper = new joint.dia.Paper({ | ||
el: createPaperHTMLElement(), | ||
gridSize: 10, | ||
model: this.graph | ||
}); | ||
|
||
const listener = new joint.mvc.Listener(...args); | ||
const graphCb = sinon.spy(); | ||
const graphEvents = { | ||
'change:position': graphCb | ||
}; | ||
const paperCb = sinon.spy(); | ||
const paperEvents = { | ||
'render:done': paperCb | ||
}; | ||
|
||
listener.listenTo(this.graph, graphEvents); | ||
listener.listenTo(paper, paperEvents); | ||
|
||
this.rect.position(newPosition.x, newPosition.y); | ||
this.rect.remove(); | ||
assert.ok(graphCb.calledWith(...args, this.rect, newPosition)); | ||
assert.ok(paperCb.calledWith(...args)); | ||
|
||
paper.remove(); | ||
}); | ||
|
||
QUnit.test('no callbackArguments', (assert) => { | ||
const newPosition = { x: 100, y: 100 }; | ||
|
||
const removeCb = sinon.spy(); | ||
const positionCb = sinon.spy(); | ||
|
||
const events = { | ||
'remove': removeCb, | ||
'change:position': positionCb | ||
}; | ||
|
||
const listener = new joint.mvc.Listener(); | ||
listener.listenTo(this.graph, events); | ||
|
||
this.rect.position(newPosition.x, newPosition.y); | ||
this.rect.remove(); | ||
assert.ok(removeCb.calledWith(this.rect)); | ||
assert.ok(positionCb.calledWith(this.rect, newPosition)); | ||
}); | ||
|
||
QUnit.test('pass callbackArguments', (assert) => { | ||
const newPosition = { x: 100, y: 100 }; | ||
const args = [{ foo: 'bar' }, 'baz', 10]; | ||
|
||
const removeCb = sinon.spy(); | ||
const positionCb = sinon.spy(); | ||
|
||
const events = { | ||
'remove': removeCb, | ||
'change:position': positionCb | ||
}; | ||
|
||
const listener = new joint.mvc.Listener(...args); | ||
listener.listenTo(this.graph, events); | ||
|
||
this.rect.position(newPosition.x, newPosition.y); | ||
this.rect.remove(); | ||
assert.ok(removeCb.calledWith(...args, this.rect)); | ||
assert.ok(positionCb.calledWith(...args, this.rect, newPosition)); | ||
}); | ||
|
||
QUnit.test('call on context', (assert) => { | ||
const newPosition = { x: 100, y: 100 }; | ||
const args = [{ foo: 'bar' }, 'baz', 10]; | ||
const context = { foo: 'bar' }; | ||
|
||
const removeCb = sinon.spy(); | ||
const positionCb = sinon.spy(); | ||
|
||
const events = { | ||
'remove': removeCb, | ||
'change:position': positionCb | ||
}; | ||
|
||
const listener = new joint.mvc.Listener(...args); | ||
listener.listenTo(this.graph, events, context); | ||
|
||
this.rect.position(newPosition.x, newPosition.y); | ||
this.rect.remove(); | ||
assert.ok(removeCb.calledOn(context)); | ||
assert.ok(removeCb.calledWith(...args, this.rect)); | ||
assert.ok(positionCb.calledOn(context)); | ||
assert.ok(positionCb.calledWith(...args, this.rect, newPosition)); | ||
}); | ||
}); | ||
|
||
QUnit.module('signature 2', () => { | ||
QUnit.test('multiple objects', (assert) => { | ||
const newPosition = { x: 100, y: 100 }; | ||
const paper = new joint.dia.Paper({ | ||
el: createPaperHTMLElement(), | ||
gridSize: 10, | ||
model: this.graph | ||
}); | ||
|
||
const listener = new joint.mvc.Listener(); | ||
const graphCb = sinon.spy(); | ||
const paperCb = sinon.spy(); | ||
listener.listenTo(this.graph, 'change:position', graphCb); | ||
listener.listenTo(paper, 'render:done', paperCb); | ||
|
||
this.rect.position(newPosition.x, newPosition.y); | ||
assert.ok(graphCb.calledWith(this.rect, newPosition)); | ||
assert.ok(paperCb.called); | ||
|
||
paper.remove(); | ||
}); | ||
|
||
QUnit.test('no callbackArguments', (assert) => { | ||
const newPosition = { x: 100, y: 100 }; | ||
|
||
const listener = new joint.mvc.Listener(); | ||
const callback = sinon.spy(); | ||
listener.listenTo(this.graph, 'change:position', callback); | ||
|
||
this.rect.position(newPosition.x, newPosition.y); | ||
assert.ok(callback.calledWith(this.rect, newPosition)); | ||
}); | ||
|
||
QUnit.test('pass callbackArguments', (assert) => { | ||
const newPosition = { x: 100, y: 100 }; | ||
const args = [{ foo: 'bar' }, 'baz', 10]; | ||
|
||
const listener = new joint.mvc.Listener(...args); | ||
const callback = sinon.spy(); | ||
listener.listenTo(this.graph, 'change:position', callback); | ||
|
||
this.rect.position(newPosition.x, newPosition.y); | ||
assert.ok(callback.calledWith(...args, this.rect, newPosition)); | ||
}); | ||
|
||
QUnit.test('call on context', (assert) => { | ||
const newPosition = { x: 100, y: 100 }; | ||
const args = [{ foo: 'bar' }, 'baz', 10]; | ||
const context = { foo: 'bar' }; | ||
|
||
const listener = new joint.mvc.Listener(...args); | ||
const callback = sinon.spy(); | ||
listener.listenTo(this.graph, 'change:position', callback, context); | ||
|
||
this.rect.position(newPosition.x, newPosition.y); | ||
assert.ok(callback.calledOn(context)); | ||
assert.ok(callback.calledWith(...args, this.rect, newPosition)); | ||
}); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.