Browse Source

EventBus.off is more flexible now

css_transitions
josdejong 11 years ago
parent
commit
279f918b12
7 changed files with 139 additions and 55 deletions
  1. +4
    -0
      Jakefile.js
  2. +5
    -18
      src/component/component.js
  3. +33
    -8
      src/eventbus.js
  4. +1
    -0
      src/events.js
  5. +27
    -0
      src/util.js
  6. +66
    -26
      vis.js
  7. +3
    -3
      vis.min.js

+ 4
- 0
Jakefile.js View File

@ -79,6 +79,10 @@ task('build', {async: true}, function () {
b.bundle({ b.bundle({
standalone: 'vis' standalone: 'vis'
}, function (err, code) { }, function (err, code) {
if(err) {
throw err;
}
// add header and footer // add header and footer
var lib = read('./src/header.js') + code; var lib = read('./src/header.js') + code;

+ 5
- 18
src/component/component.js View File

@ -20,16 +20,19 @@ function Component () {
* set. * set.
* @param {Object} options Available parameters: * @param {Object} options Available parameters:
* {String | function} [className] * {String | function} [className]
* {EventBus} [eventBus]
* {String | Number | function} [left] * {String | Number | function} [left]
* {String | Number | function} [top] * {String | Number | function} [top]
* {String | Number | function} [width] * {String | Number | function} [width]
* {String | Number | function} [height] * {String | Number | function} [height]
*/ */
Component.prototype.setOptions = function(options) { Component.prototype.setOptions = function(options) {
if (options) {
util.extend(this.options, options);
if (!options) {
return;
} }
util.extend(this.options, options);
if (this.controller) { if (this.controller) {
this.requestRepaint(); this.requestRepaint();
this.requestReflow(); this.requestReflow();
@ -98,19 +101,3 @@ Component.prototype.requestReflow = function () {
// TODO: just do a reflow when no parent is configured? // TODO: just do a reflow when no parent is configured?
} }
}; };
/**
* Event handler
* @param {String} event name of the event, for example 'click', 'mousemove'
* @param {function} callback callback handler, invoked with the raw HTML Event
* as parameter.
*/
Component.prototype.on = function (event, callback) {
// TODO: rethink the way of event delegation
if (this.parent) {
this.parent.on(event, callback);
}
else {
throw new Error('Cannot attach event: no root panel found');
}
};

+ 33
- 8
src/eventbus.js View File

@ -11,15 +11,19 @@ function EventBus() {
* @param {String | RegExp} event The event can be a regular expression, or * @param {String | RegExp} event The event can be a regular expression, or
* a string with wildcards, like 'server.*'. * a string with wildcards, like 'server.*'.
* @param {function} callback. Callback are called with three parameters: * @param {function} callback. Callback are called with three parameters:
* {String} event, {Object} [data],
* {*} [source]
* {String} event, {*} [data], {*} [source]
* @param {*} [target] * @param {*} [target]
* @returns {String} id A subscription id * @returns {String} id A subscription id
*/ */
EventBus.prototype.on = function (event, callback, target) { EventBus.prototype.on = function (event, callback, target) {
var regexp = (event instanceof RegExp) ?
event :
new RegExp(event.replace('*', '\\w+'));
var subscription = { var subscription = {
id: util.randomUUID(), id: util.randomUUID(),
event: event instanceof RegExp ? event : new RegExp(event.replace('*', '\\w+')),
event: event,
regexp: regexp,
callback: (typeof callback === 'function') ? callback : null, callback: (typeof callback === 'function') ? callback : null,
target: target target: target
}; };
@ -31,13 +35,34 @@ EventBus.prototype.on = function (event, callback, target) {
/** /**
* Unsubscribe from an event * Unsubscribe from an event
* @param {String} id subscription id
* @param {String | Object} filter Filter for subscriptions to be removed
* Filter can be a string containing a
* subscription id, or an object containing
* one or more of the fields id, event,
* callback, and target.
*/ */
EventBus.prototype.off = function (id) {
EventBus.prototype.off = function (filter) {
var i = 0; var i = 0;
while (i < this.subscriptions.length) { while (i < this.subscriptions.length) {
var subscription = this.subscriptions[i]; var subscription = this.subscriptions[i];
if (subscription.id == id) {
var match = true;
if (filter instanceof Object) {
// filter is an object. All fields must match
for (var prop in filter) {
if (filter.hasOwnProperty(prop)) {
if (filter[prop] !== subscription[prop]) {
match = false;
}
}
}
}
else {
// filter is a string, filter on id
match = (subscription.id == filter);
}
if (match) {
this.subscriptions.splice(i, 1); this.subscriptions.splice(i, 1);
} }
else { else {
@ -49,13 +74,13 @@ EventBus.prototype.off = function (id) {
/** /**
* Emit an event * Emit an event
* @param {String} event * @param {String} event
* @param {Object} [data]
* @param {*} [data]
* @param {*} [source] * @param {*} [source]
*/ */
EventBus.prototype.emit = function (event, data, source) { EventBus.prototype.emit = function (event, data, source) {
for (var i =0; i < this.subscriptions.length; i++) { for (var i =0; i < this.subscriptions.length; i++) {
var subscription = this.subscriptions[i]; var subscription = this.subscriptions[i];
if (subscription.event.test(event)) {
if (subscription.regexp.test(event)) {
if (subscription.callback) { if (subscription.callback) {
subscription.callback(event, data, source); subscription.callback(event, data, source);
} }

+ 1
- 0
src/events.js View File

@ -1,6 +1,7 @@
/** /**
* Event listener (singleton) * Event listener (singleton)
*/ */
// TODO: replace usage of the event listener for the EventBus
var events = { var events = {
'listeners': [], 'listeners': [],

+ 27
- 0
src/util.js View File

@ -808,3 +808,30 @@ if(!Array.isArray) {
return Object.prototype.toString.call(vArg) === "[object Array]"; return Object.prototype.toString.call(vArg) === "[object Array]";
}; };
} }
// Internet Explorer 8 and older does not support Function.bind,
// so we define it here in that case.
// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind
if (!Function.prototype.bind) {
Function.prototype.bind = function (oThis) {
if (typeof this !== "function") {
// closest thing possible to the ECMAScript 5 internal IsCallable function
throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
}
var aArgs = Array.prototype.slice.call(arguments, 1),
fToBind = this,
fNOP = function () {},
fBound = function () {
return fToBind.apply(this instanceof fNOP && oThis
? this
: oThis,
aArgs.concat(Array.prototype.slice.call(arguments)));
};
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
};
}

+ 66
- 26
vis.js View File

@ -840,9 +840,37 @@ if(!Array.isArray) {
}; };
} }
// Internet Explorer 8 and older does not support Function.bind,
// so we define it here in that case.
// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind
if (!Function.prototype.bind) {
Function.prototype.bind = function (oThis) {
if (typeof this !== "function") {
// closest thing possible to the ECMAScript 5 internal IsCallable function
throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
}
var aArgs = Array.prototype.slice.call(arguments, 1),
fToBind = this,
fNOP = function () {},
fBound = function () {
return fToBind.apply(this instanceof fNOP && oThis
? this
: oThis,
aArgs.concat(Array.prototype.slice.call(arguments)));
};
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
};
}
/** /**
* Event listener (singleton) * Event listener (singleton)
*/ */
// TODO: replace usage of the event listener for the EventBus
var events = { var events = {
'listeners': [], 'listeners': [],
@ -2651,15 +2679,19 @@ function EventBus() {
* @param {String | RegExp} event The event can be a regular expression, or * @param {String | RegExp} event The event can be a regular expression, or
* a string with wildcards, like 'server.*'. * a string with wildcards, like 'server.*'.
* @param {function} callback. Callback are called with three parameters: * @param {function} callback. Callback are called with three parameters:
* {String} event, {Object} [data],
* {*} [source]
* {String} event, {*} [data], {*} [source]
* @param {*} [target] * @param {*} [target]
* @returns {String} id A subscription id * @returns {String} id A subscription id
*/ */
EventBus.prototype.on = function (event, callback, target) { EventBus.prototype.on = function (event, callback, target) {
var regexp = (event instanceof RegExp) ?
event :
new RegExp(event.replace('*', '\\w+'));
var subscription = { var subscription = {
id: util.randomUUID(), id: util.randomUUID(),
event: event instanceof RegExp ? event : new RegExp(event.replace('*', '\\w+')),
event: event,
regexp: regexp,
callback: (typeof callback === 'function') ? callback : null, callback: (typeof callback === 'function') ? callback : null,
target: target target: target
}; };
@ -2671,13 +2703,34 @@ EventBus.prototype.on = function (event, callback, target) {
/** /**
* Unsubscribe from an event * Unsubscribe from an event
* @param {String} id subscription id
* @param {String | Object} filter Filter for subscriptions to be removed
* Filter can be a string containing a
* subscription id, or an object containing
* one or more of the fields id, event,
* callback, and target.
*/ */
EventBus.prototype.off = function (id) {
EventBus.prototype.off = function (filter) {
var i = 0; var i = 0;
while (i < this.subscriptions.length) { while (i < this.subscriptions.length) {
var subscription = this.subscriptions[i]; var subscription = this.subscriptions[i];
if (subscription.id == id) {
var match = true;
if (filter instanceof Object) {
// filter is an object. All fields must match
for (var prop in filter) {
if (filter.hasOwnProperty(prop)) {
if (filter[prop] !== subscription[prop]) {
match = false;
}
}
}
}
else {
// filter is a string, filter on id
match = (subscription.id == filter);
}
if (match) {
this.subscriptions.splice(i, 1); this.subscriptions.splice(i, 1);
} }
else { else {
@ -2689,13 +2742,13 @@ EventBus.prototype.off = function (id) {
/** /**
* Emit an event * Emit an event
* @param {String} event * @param {String} event
* @param {Object} [data]
* @param {*} [data]
* @param {*} [source] * @param {*} [source]
*/ */
EventBus.prototype.emit = function (event, data, source) { EventBus.prototype.emit = function (event, data, source) {
for (var i =0; i < this.subscriptions.length; i++) { for (var i =0; i < this.subscriptions.length; i++) {
var subscription = this.subscriptions[i]; var subscription = this.subscriptions[i];
if (subscription.event.test(event)) {
if (subscription.regexp.test(event)) {
if (subscription.callback) { if (subscription.callback) {
subscription.callback(event, data, source); subscription.callback(event, data, source);
} }
@ -2865,16 +2918,19 @@ function Component () {
* set. * set.
* @param {Object} options Available parameters: * @param {Object} options Available parameters:
* {String | function} [className] * {String | function} [className]
* {EventBus} [eventBus]
* {String | Number | function} [left] * {String | Number | function} [left]
* {String | Number | function} [top] * {String | Number | function} [top]
* {String | Number | function} [width] * {String | Number | function} [width]
* {String | Number | function} [height] * {String | Number | function} [height]
*/ */
Component.prototype.setOptions = function(options) { Component.prototype.setOptions = function(options) {
if (options) {
util.extend(this.options, options);
if (!options) {
return;
} }
util.extend(this.options, options);
if (this.controller) { if (this.controller) {
this.requestRepaint(); this.requestRepaint();
this.requestReflow(); this.requestReflow();
@ -2944,22 +3000,6 @@ Component.prototype.requestReflow = function () {
} }
}; };
/**
* Event handler
* @param {String} event name of the event, for example 'click', 'mousemove'
* @param {function} callback callback handler, invoked with the raw HTML Event
* as parameter.
*/
Component.prototype.on = function (event, callback) {
// TODO: rethink the way of event delegation
if (this.parent) {
this.parent.on(event, callback);
}
else {
throw new Error('Cannot attach event: no root panel found');
}
};
/** /**
* A panel can contain components * A panel can contain components
* @param {Component} [parent] * @param {Component} [parent]

+ 3
- 3
vis.min.js
File diff suppressed because it is too large
View File


Loading…
Cancel
Save