jsdav-ext
Version:
jsDAV allows you to easily add WebDAV support to a NodeJS application. jsDAV is meant to cover the entire standard, and attempts to allow integration using an easy to understand API.
143 lines (122 loc) • 5.04 kB
JavaScript
/*
* @package jsDAV
* @subpackage shared
* @copyright Copyright(c) 2011 Ajax.org B.V. <info AT ajax DOT org>
* @author Mike de Boer <info AT mikedeboer DOT nl>
* @license http://github.com/mikedeboer/jsDAV/blob/master/LICENSE MIT License
*/
"use strict";
var jsDAV = require("./../jsdav");
var Util = require("./util");
var Async = require("asyncjs");
exports.EventEmitter = function() {};
exports.EventEmitter.DEFAULT_TIMEOUT = 30000; // in milliseconds
exports.EventEmitter.PRIO_LOW = 0x0001;
exports.EventEmitter.PRIO_NORMAL = 0x0002;
exports.EventEmitter.PRIO_HIGH = 0x0004;
var _slice = Array.prototype.slice;
(function() {
var _ev = exports.EventEmitter;
function persistRegistry() {
if (this.$eventRegistry)
return;
this.$eventRegistry = {};
this.$eventRegistry[_ev.PRIO_LOW] = {};
this.$eventRegistry[_ev.PRIO_NORMAL] = {};
this.$eventRegistry[_ev.PRIO_HIGH] = {};
}
function getListeners(eventName) {
return (this.$eventRegistry[_ev.PRIO_HIGH][eventName] || []).concat(
this.$eventRegistry[_ev.PRIO_NORMAL][eventName] || []).concat(
this.$eventRegistry[_ev.PRIO_LOW][eventName] || []);
}
this.dispatchEvent = function() {
persistRegistry.call(this);
var e,
returnValue = null,
args = _slice.call(arguments),
eventName = args.shift().toLowerCase(),
listeners = getListeners.call(this, eventName),
cbdispatch = (typeof args[args.length - 1] == "function")
? args.pop()
: function(){};
if (!listeners.length)
return cbdispatch();
Async.list(listeners).each(function(listener, cbnext) {
// If a previous event is still in scope, record the return value.
// It's OK if the previous value is overwritten, that's just the way
// event bubbling works.
if (e)
returnValue = e.returnValue;
e = new exports.Event(eventName, cbnext);
listener.apply(null, [e].concat(args));
if (listener.$usetimeout > 0) {
clearTimeout(listener.$timeout);
listener.$timeout = setTimeout(function() {
if (!e.$done) {
e.next("Event callback timeout: timeout reached, no callback fired within "
+ listener.$usetimeout + "ms");
}
}, listener.$usetimeout);
}
}).end(function(err) {
// everything except TRUE as an argument is an error
if (jsDAV.debugMode && !!err) {
if (err === true)
Util.log("event propagation '" + eventName + "' stopped", "info");
else
Util.log("argument after event '" + eventName + "': {" + typeof err + "} " + err, "error");
}
cbdispatch(err, returnValue);
});
};
this.addEventListener = function(eventName, listener, prio, timeout) {
persistRegistry.call(this);
// disable timeouts while debugging
if (jsDAV.debugMode)
timeout = false;
listener.$usetimeout = timeout === false
? 0
: (typeof timeout == "number")
? timeout
: exports.EventEmitter.DEFAULT_TIMEOUT;
eventName = eventName.toLowerCase();
prio = prio || _ev.PRIO_NORMAL;
var allListeners = getListeners.call(this, eventName);
var listeners = this.$eventRegistry[prio][eventName];
if (!listeners)
listeners = this.$eventRegistry[prio][eventName] = [];
if (allListeners.indexOf(listener) === -1)
listeners.push(listener);
};
this.removeEventListener = function(eventName, listener) {
persistRegistry.call(this);
eventName = eventName.toLowerCase();
var _self = this;
[_ev.PRIO_LOW, _ev.PRIO_NORMAL, _ev.PRIO_HIGH].forEach(function(prio) {
var listeners = _self.$eventRegistry[prio][eventName];
if (!listeners)
return;
var index = listeners.indexOf(listener);
if (index !== -1)
listeners.splice(index, 1);
});
};
}).call(exports.EventEmitter.prototype);
exports.Event = function(type, callback) {
this.$event = true;
this.$done = false;
this.type = type;
this.returnValue = null;
this.next = function(err, ret) {
if (!Util.empty(ret))
this.returnValue = ret;
if (this.$done || !callback)
return (!callback ? this.$done = true : false);
this.$done = true;
callback(err, this.returnValue);
};
this.stop = function(ret) {
return this.next(true, ret);
};
};