'use strict';
var EventEmitter = require('events').EventEmitter;
var inherits = require('inherits');
var isChromeApp = require('./deps/env/isChromeApp');
var hasLocalStorage = require('./deps/env/hasLocalStorage');
var pick = require('./deps/pick');
var call = require('./deps/call');
inherits(Changes, EventEmitter);
/* istanbul ignore next */
function attachBrowserEvents(self) {
Iif (isChromeApp()) {
chrome.storage.onChanged.addListener(function (e) {
// make sure it's event addressed to us
if (e.db_name != null) {
//object only has oldValue, newValue members
self.emit(e.dbName.newValue);
}
});
} else Iif (hasLocalStorage()) {
if (typeof addEventListener !== 'undefined') {
addEventListener("storage", function (e) {
self.emit(e.key);
});
} else { // old IE
window.attachEvent("storage", function (e) {
self.emit(e.key);
});
}
}
}
function Changes() {
EventEmitter.call(this);
this._listeners = {};
attachBrowserEvents(this);
}
Changes.prototype.addListener = function (dbName, id, db, opts) {
Iif (this._listeners[id]) {
return;
}
var self = this;
var inprogress = false;
function eventFunction() {
Iif (!self._listeners[id]) {
return;
}
if (inprogress) {
inprogress = 'waiting';
return;
}
inprogress = true;
var changesOpts = pick(opts, [
'style', 'include_docs', 'attachments', 'conflicts', 'filter',
'doc_ids', 'view', 'since', 'query_params', 'binary'
]);
db.changes(changesOpts).on('change', function (c) {
Eif (c.seq > opts.since && !opts.cancelled) {
opts.since = c.seq;
call(opts.onChange, c);
}
}).on('complete', function () {
if (inprogress === 'waiting') {
setTimeout(function(){
eventFunction();
},0);
}
inprogress = false;
}).on('error', function () {
inprogress = false;
});
}
this._listeners[id] = eventFunction;
this.on(dbName, eventFunction);
};
Changes.prototype.removeListener = function (dbName, id) {
Iif (!(id in this._listeners)) {
return;
}
EventEmitter.prototype.removeListener.call(this, dbName,
this._listeners[id]);
};
/* istanbul ignore next */
Changes.prototype.notifyLocalWindows = function (dbName) {
//do a useless change on a storage thing
//in order to get other windows's listeners to activate
Iif (isChromeApp()) {
chrome.storage.local.set({dbName: dbName});
} else Iif (hasLocalStorage()) {
localStorage[dbName] = (localStorage[dbName] === "a") ? "b" : "a";
}
};
Changes.prototype.notify = function (dbName) {
this.emit(dbName);
this.notifyLocalWindows(dbName);
};
module.exports = Changes; |