Skip to content

Commit

Permalink
Add namespaces to events. Move API creation into a module
Browse files Browse the repository at this point in the history
Public API and each module API methods are namespaced.
This means if you call a plugin API method that results into a panzoom event
then this event will contain that plugin name as event namespace.

Such a behaviour is useful for plugins that want to cancel certain events and
trigger those events by themselves without getting into a recursion. One such
example is a plugin that will animate pan/zoom.

API creation was moved into a module. Reference to inner methods is intentionally
hidden so that it is not accessible from exterior.

Related to #98
  • Loading branch information
bumbu committed Jan 3, 2016
1 parent 36f67e6 commit 53e0355
Show file tree
Hide file tree
Showing 4 changed files with 214 additions and 102 deletions.
165 changes: 165 additions & 0 deletions src/api.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
/**
* Api attribute
* Set it like this so it will not be accessible from outside
*
* @type {String}
*/
var apiAttr = ('__api' + Math.random()).slice(0, 10)

/**
* Api constructor
*
* @param {Object<SvgPanZoom>} svgPanZoomInstance SvgPanZoom object instace
* @param {String} pluginName Plugin name
*/
function PluginApi(svgPanZoomInstance, pluginName) {
this._name = pluginName

// Lock reference to API
Object.defineProperty(this, apiAttr, {
enumerable: false
, configurable: false
, writable: false
, value: svgPanZoomInstance
})
}

// Events handling
// ===============

PluginApi.prototype.on = function(name, fn, ctx) {
if (typeof ctx === 'undefined') ctx = this // Automatically inject plugin context
this[apiAttr].on(name, fn, ctx, this._name)
return this
}

PluginApi.prototype.off = function(name, fn, ctx) {
this[apiAttr].off(name, fn, ctx, this._name)
return this
}

PluginApi.prototype.trigger = function(name, data, originalEvent) {
return this[apiAttr].trigger(name, data, this._name, originalEvent)
}

// Panning
// =======

PluginApi.prototype.pan = function(point) {
this[apiAttr].pan(point, this._name)
return this
}

PluginApi.prototype.panBy = function(point) {
this[apiAttr].panBy(point, this._name)
return this
}

// Not namespaced
PluginApi.prototype.getPan = function() {
return this[apiAttr].getPan()
}

// Zooming
// =======

PluginApi.prototype.zoom = function(scale) {
this[apiAttr].pluginZoom(scale, true, this._name)
return this
}

PluginApi.prototype.zoomBy = function(scale) {
this[apiAttr].pluginZoom(scale, false, this._name)
return this
}

PluginApi.prototype.zoomAtPoint = function(scale, point) {
this[apiAttr].pluginZoomAtPoint(scale, point, true, this._name)
return this
}

PluginApi.prototype.zoomAtPointBy = function(scale, point) {
this[apiAttr].pluginZoomAtPoint(scale, point, false, this._name)
return this
}

// Not namespaced
PluginApi.prototype.getZoom = function() {
return this[apiAttr].getRelativeZoom()
}

// Resetting
// =========

PluginApi.prototype.resetZoom = function() {
this[apiAttr].resetZoom(this._name)
return this
}

PluginApi.prototype.resetPan = function() {
this[apiAttr].resetPan(this._name)
return this
}

PluginApi.prototype.reset = function() {
this[apiAttr].reset()
return this
}

// Size and Resize
// ===============

// Not namespaced
PluginApi.prototype.updateBBox = function() {
this[apiAttr].updateBBox()
return this
}

// Not namespaced
PluginApi.prototype.resize = function() {
this[apiAttr].resize()
return this
}

// Not namespaced
PluginApi.prototype.getSizes = function() {
return {
width: this[apiAttr].width
, height: this[apiAttr].height
, realZoom: this[apiAttr].getZoom()
, viewBox: this[apiAttr].viewport.getViewBox()
}
}

// Plugins
// =======

// Not namespaced
PluginApi.prototype.addPlugin = function(name) {
this[apiAttr].addPlugin(name)
return this
}

// Not namespaced
PluginApi.prototype.removePlugin = function(name) {
this[apiAttr].removePlugin(name)
return this
}

// Destroy
// =======

// Not namespaced
PluginApi.prototype.destroy = function() {
this[apiAttr].destroy()
return this
}

// Export
// ======

module.exports = {
createApi: function(svgPanZoomInstance, pluginName) {
return new PluginApi(svgPanZoomInstance, pluginName)
}
}
13 changes: 12 additions & 1 deletion src/event.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@ var SvgPanZoomEvent = {
*/
, data: null

/**
* Event namespace
* Default is `__system`
* Public API uses `__user`
* Plugins use `pluginName`
*
* @type {String}
*/
, namespace: '__system'

/**
* Event propagation allowance through middlewares
*
Expand Down Expand Up @@ -56,11 +66,12 @@ var SvgPanZoomEvent = {
}

module.exports = {
create: function(data, originalEvent) {
create: function(data, namespace, originalEvent) {
var event = Object.create(SvgPanZoomEvent)

// Add data attributes
data != null && (event.data = data)
namespace != null && (event.namespace = namespace)
originalEvent != null && (event.originalEvent = originalEvent)

return event
Expand Down
4 changes: 2 additions & 2 deletions src/shadow-viewport.js
Original file line number Diff line number Diff line change
Expand Up @@ -205,10 +205,9 @@ ShadowViewport.prototype.getCTM = function() {
ShadowViewport.prototype.setCTM = function(newCTM, namespace) {
if (this.isZoomDifferent(newCTM) || this.isPanDifferent(newCTM)) {
var panZoom = this.convertCTMToPanZoom(newCTM)
panZoom.namespace = namespace

// Render only if event is not prevented
if (this.options.trigger('panzoom', panZoom)) {
if (this.options.trigger('panzoom', panZoom, namespace)) {
// Copy panZoom values in case they were modified
this.copyPanZoomToCTM(panZoom, newCTM)

Expand Down Expand Up @@ -262,6 +261,7 @@ ShadowViewport.prototype.updateCTM = function() {
, panZoom = this.convertCTMToPanZoom(CTM)

// Render only if event is not prevented
// Has no namespace as it is unknown whos change triggered this render
if (this.options.trigger('render', panZoom)) {
// Copy panZoom values in case they were modified
this.copyPanZoomToCTM(panZoom, CTM)
Expand Down
Loading

0 comments on commit 53e0355

Please sign in to comment.