| import { EventEmitter as EventEmitter } from 'events'; |
| import inherits from 'inherits'; |
| import hasLocalStorage from './env/hasLocalStorage'; |
| import pick from './pick'; |
| import nextTick from './nextTick'; |
| |
| inherits(Changes, EventEmitter); |
| |
| /* istanbul ignore next */ |
| function attachBrowserEvents(self) { |
| if (hasLocalStorage()) { |
| addEventListener("storage", function (e) { |
| self.emit(e.key); |
| }); |
| } |
| } |
| |
| function Changes() { |
| EventEmitter.call(this); |
| this._listeners = {}; |
| |
| attachBrowserEvents(this); |
| } |
| Changes.prototype.addListener = function (dbName, id, db, opts) { |
| /* istanbul ignore if */ |
| if (this._listeners[id]) { |
| return; |
| } |
| var self = this; |
| var inprogress = false; |
| function eventFunction() { |
| /* istanbul ignore if */ |
| if (!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' |
| ]); |
| |
| /* istanbul ignore next */ |
| function onError() { |
| inprogress = false; |
| } |
| |
| db.changes(changesOpts).on('change', function (c) { |
| if (c.seq > opts.since && !opts.cancelled) { |
| opts.since = c.seq; |
| opts.onChange(c); |
| } |
| }).on('complete', function () { |
| if (inprogress === 'waiting') { |
| nextTick(eventFunction); |
| } |
| inprogress = false; |
| }).on('error', onError); |
| } |
| this._listeners[id] = eventFunction; |
| this.on(dbName, eventFunction); |
| }; |
| |
| Changes.prototype.removeListener = function (dbName, id) { |
| /* istanbul ignore if */ |
| if (!(id in this._listeners)) { |
| return; |
| } |
| EventEmitter.prototype.removeListener.call(this, dbName, |
| this._listeners[id]); |
| delete 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 |
| if (hasLocalStorage()) { |
| localStorage[dbName] = (localStorage[dbName] === "a") ? "b" : "a"; |
| } |
| }; |
| |
| Changes.prototype.notify = function (dbName) { |
| this.emit(dbName); |
| this.notifyLocalWindows(dbName); |
| }; |
| |
| export default Changes; |