diff --git a/package-lock.json b/package-lock.json
index ca799e74..821ed8ad 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "openseadragon",
- "version": "3.1.0",
+ "version": "4.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "openseadragon",
- "version": "3.1.0",
+ "version": "4.0.0",
"license": "BSD-3-Clause",
"devDependencies": {
"grunt": "^1.4.1",
diff --git a/src/eventsource.js b/src/eventsource.js
index 9bc29704..f92adb67 100644
--- a/src/eventsource.js
+++ b/src/eventsource.js
@@ -58,7 +58,7 @@ $.EventSource.prototype = {
/**
* Add an event handler to be triggered only once (or a given number of times)
- * for a given event.
+ * for a given event. It is not removable with removeHandler().
* @function
* @param {String} eventName - Name of event to register.
* @param {OpenSeadragon.EventHandler} handler - Function to call when event
@@ -67,8 +67,9 @@ $.EventSource.prototype = {
* to the handler.
* @param {Number} [times=1] - The number of times to handle the event
* before removing it.
+ * @param {Number} [priority=0] - Handler priority. By default, all priorities are 0. Higher number = priority.
*/
- addOnceHandler: function(eventName, handler, userData, times) {
+ addOnceHandler: function(eventName, handler, userData, times, priority) {
var self = this;
times = times || 1;
var count = 0;
@@ -77,9 +78,9 @@ $.EventSource.prototype = {
if (count === times) {
self.removeHandler(eventName, onceHandler);
}
- handler(event);
+ return handler(event);
};
- this.addHandler(eventName, onceHandler, userData);
+ this.addHandler(eventName, onceHandler, userData, priority);
},
/**
@@ -88,14 +89,22 @@ $.EventSource.prototype = {
* @param {String} eventName - Name of event to register.
* @param {OpenSeadragon.EventHandler} handler - Function to call when event is triggered.
* @param {Object} [userData=null] - Arbitrary object to be passed unchanged to the handler.
+ * @param {Number} [priority=0] - Handler priority. By default, all priorities are 0. Higher number = priority.
*/
- addHandler: function ( eventName, handler, userData ) {
+ addHandler: function ( eventName, handler, userData, priority ) {
var events = this.events[ eventName ];
if ( !events ) {
this.events[ eventName ] = events = [];
}
if ( handler && $.isFunction( handler ) ) {
- events[ events.length ] = { handler: handler, userData: userData || null };
+ var index = events.length,
+ event = { handler: handler, userData: userData || null, priority: priority || 0 };
+ events[ index ] = event;
+ while ( index > 0 && events[ index - 1 ].priority < events[ index ].priority ) {
+ events[ index ] = events[ index - 1 ];
+ events[ index - 1 ] = event;
+ index--;
+ }
}
},
@@ -156,7 +165,7 @@ $.EventSource.prototype = {
* @function
* @param {String} eventName - Name of event to get handlers for.
*/
- getHandler: function ( eventName ) {
+ getHandler: function ( eventName) {
var events = this.events[ eventName ];
if ( !events || !events.length ) {
return null;
@@ -186,15 +195,12 @@ $.EventSource.prototype = {
raiseEvent: function( eventName, eventArgs ) {
//uncomment if you want to get a log of all events
//$.console.log( eventName );
+
var handler = this.getHandler( eventName );
-
if ( handler ) {
- if ( !eventArgs ) {
- eventArgs = {};
- }
-
- handler( this, eventArgs );
+ return handler( this, eventArgs || {} );
}
+ return undefined;
}
};
diff --git a/src/openseadragon.js b/src/openseadragon.js
index 45e4c8e7..cb111195 100644
--- a/src/openseadragon.js
+++ b/src/openseadragon.js
@@ -826,14 +826,16 @@ function OpenSeadragon( options ){
* @private
*/
var class2type = {
- '[object Boolean]': 'boolean',
- '[object Number]': 'number',
- '[object String]': 'string',
- '[object Function]': 'function',
- '[object Array]': 'array',
- '[object Date]': 'date',
- '[object RegExp]': 'regexp',
- '[object Object]': 'object'
+ '[object Boolean]': 'boolean',
+ '[object Number]': 'number',
+ '[object String]': 'string',
+ '[object Function]': 'function',
+ '[object AsyncFunction]': 'function',
+ '[object Promise]': 'promise',
+ '[object Array]': 'array',
+ '[object Date]': 'date',
+ '[object RegExp]': 'regexp',
+ '[object Object]': 'object'
},
// Save a reference to some core methods
toString = Object.prototype.toString,
@@ -849,7 +851,6 @@ function OpenSeadragon( options ){
return $.type(obj) === "function";
};
-
/**
* Taken from jQuery 1.6.1
* @function isArray
diff --git a/test/coverage.html b/test/coverage.html
index 6d392209..68756461 100644
--- a/test/coverage.html
+++ b/test/coverage.html
@@ -65,6 +65,7 @@
+
diff --git a/test/modules/event-source.js b/test/modules/event-source.js
new file mode 100644
index 00000000..2f61e5ee
--- /dev/null
+++ b/test/modules/event-source.js
@@ -0,0 +1,85 @@
+/* global QUnit, $, TouchUtil, Util, testLog */
+
+(function () {
+ var context, result=[], eName = "test", eventCounter = 0, finished = false;
+
+ function evaluateTest(e) {
+ if (finished) return;
+ finished = true;
+ e.assert.strictEqual(JSON.stringify(result), JSON.stringify(e.expected), e.message);
+ e.done();
+ }
+
+ function executor(i, ms) {
+ if (ms === undefined) return function (e) {
+ eventCounter++;
+ result.push(i);
+ if (eventCounter === context.numberOfHandlers(eName)) {
+ evaluateTest(e);
+ }
+ };
+
+ return function (e) {
+ return new Promise(function (resolve) {
+ setTimeout(function () {
+ eventCounter++;
+ result.push(i);
+ if (eventCounter === context.numberOfHandlers(eName)) {
+ evaluateTest(e);
+ }
+ resolve();
+ }, ms);
+ });
+ }
+ }
+
+ function runTest(e) {
+ context.raiseEvent(eName, e);
+ }
+
+ QUnit.module( 'EventSource', {
+ beforeEach: function () {
+ context = new OpenSeadragon.EventSource();
+ eventCounter = 0;
+ result = [];
+ finished = false;
+ }
+ } );
+
+ // ----------
+ QUnit.test('EventSource: no events', function(assert) {
+ context.addHandler(eName, evaluateTest);
+ runTest({
+ assert: assert,
+ done: assert.async(),
+ expected: [],
+ message: 'No handlers registered - arrays should be empty.'
+ });
+ });
+
+ QUnit.test('EventSource: simple callbacks order', function(assert) {
+ context.addHandler(eName, executor(1));
+ context.addHandler(eName, executor(2));
+ context.addHandler(eName, executor(3));
+ runTest({
+ assert: assert,
+ done: assert.async(),
+ expected: [1, 2, 3],
+ message: 'Simple callback order should follow [1,2,3].'
+ });
+ });
+
+ QUnit.test('EventSource: priority callbacks order', function(assert) {
+ context.addHandler(eName, executor(1), undefined, 20);
+ context.addHandler(eName, executor(2), undefined, 124);
+ context.addHandler(eName, executor(3), undefined, -5);
+ context.addHandler(eName, executor(4));
+ context.addHandler(eName, executor(5), undefined, -2);
+ runTest({
+ assert: assert,
+ done: assert.async(),
+ expected: [2, 1, 4, 5, 3],
+ message: 'Prioritized callback order should follow [2,1,4,5,3].'
+ });
+ });
+} )();
diff --git a/test/test.html b/test/test.html
index 8b85a123..761db1f2 100644
--- a/test/test.html
+++ b/test/test.html
@@ -22,6 +22,7 @@
+