cordova-plugin-googlemaps
Version:
Google Maps native SDK for Android and iOS, and Google Maps JavaScript API v3 for browser.
226 lines (189 loc) • 6.25 kB
JavaScript
var VARS_FIELD = typeof Symbol === 'undefined' ? '__vars' + Date.now() : Symbol('vars');
var SUBSCRIPTIONS_FIELD = typeof Symbol === 'undefined' ? '__subs' + Date.now() : Symbol('subscriptions');
function BaseClass() {
this[VARS_FIELD] = {};
this[SUBSCRIPTIONS_FIELD] = {};
this.errorHandler = this.errorHandler.bind(this);
Object.defineProperty(this, 'hashCode', {
value: Math.floor(Date.now() * Math.random())
});
}
BaseClass.prototype = {
empty: function () {
var vars = this[VARS_FIELD];
Object.keys(vars).forEach(function (name) {
vars[name] = null;
delete vars[name];
});
},
get: function (key) {
return this[VARS_FIELD].hasOwnProperty(key) ? this[VARS_FIELD][key] : undefined;
},
set: function (key, value, noNotify) {
if (key === '__pgmId') return;
var prev = this.get(key);
this[VARS_FIELD][key] = value;
if (!noNotify && prev !== value) {
this.trigger(key + '_changed', prev, value, key);
}
return this;
},
bindTo: function (key, target, targetKey, noNotify) {
if (key === '__pgmId') return;
targetKey = targetKey || key;
// If `noNotify` is true, prevent `(targetKey)_changed` event occurrs,
// when bind the value for the first time only.
// (Same behaviour as Google Maps JavaScript v3)
target.set(targetKey, this[VARS_FIELD][key], noNotify);
this.on(key + '_changed', function (oldValue, value) {
target.set(targetKey, value);
});
},
trigger: function (eventName) {
if (!eventName) {
return this;
}
if (!this[SUBSCRIPTIONS_FIELD][eventName]) {
return this;
}
var listenerHashMap = this[SUBSCRIPTIONS_FIELD][eventName];
var keys = Object.keys(listenerHashMap);
var args = Array.prototype.slice.call(arguments, 1);
var self = this;
keys.forEach(function (_hashCode) {
if (self[SUBSCRIPTIONS_FIELD] &&
self[SUBSCRIPTIONS_FIELD][eventName] &&
_hashCode in self[SUBSCRIPTIONS_FIELD][eventName]) {
var info = self[SUBSCRIPTIONS_FIELD][eventName][_hashCode];
switch (info.kind) {
case 'on':
info.listener.apply(self, args);
break;
case 'onThrottled':
info.args = args;
if (!info.timer) {
info.timer = setTimeout(function () {
info.listener.apply(this, info.args);
info.timer = null;
}.bind(self), info.interval);
}
break;
}
}
});
return this;
},
on: function (eventName, listener) {
if (!listener || typeof listener !== 'function') {
throw Error('Listener for on()/addEventListener() method is not a function');
}
if (!listener._hashCode) {
Object.defineProperty(listener, '_hashCode', {
value: Math.floor(Date.now() * Math.random()),
writable: false,
enumerable: false
});
}
this[SUBSCRIPTIONS_FIELD][eventName] = this[SUBSCRIPTIONS_FIELD][eventName] || {};
this[SUBSCRIPTIONS_FIELD][eventName][listener._hashCode] = {
'kind': 'on',
'listener': listener
};
return this;
},
onThrottled: function (eventName, listener, interval) {
if (!listener || typeof listener !== 'function') {
throw Error('Listener for on()/addEventListener() method is not a function');
}
if (typeof interval !== 'number' || interval < 1) {
throw Error('interval argument must be bigger number than 0');
}
if (!listener._hashCode) {
Object.defineProperty(listener, '_hashCode', {
value: Math.floor(Date.now() * Math.random()),
writable: false,
enumerable: false
});
}
this[SUBSCRIPTIONS_FIELD][eventName] = this[SUBSCRIPTIONS_FIELD][eventName] || {};
this[SUBSCRIPTIONS_FIELD][eventName][listener._hashCode] = {
'kind': 'onThrottled',
'interval': interval,
'timer': null,
'listener': listener
};
return this;
},
off: function (eventName, listener) {
if (!eventName && !listener) {
this[SUBSCRIPTIONS_FIELD] = {};
return this;
}
if (eventName && !listener) {
this[SUBSCRIPTIONS_FIELD][eventName] = null;
delete this[SUBSCRIPTIONS_FIELD][eventName];
} else if (this[SUBSCRIPTIONS_FIELD][eventName] && listener._hashCode) {
delete this[SUBSCRIPTIONS_FIELD][eventName][listener._hashCode];
}
return this;
},
one: function (eventName, listener) {
if (!listener || typeof listener !== 'function') {
throw Error('Listener for one()/addEventListenerOnce() method is not a function');
}
var self = this;
var callback = function () {
self.off(eventName, arguments.callee);
listener.apply(self, arguments);
callback = undefined;
};
this.on(eventName, callback);
return this;
},
hasEventListener: function (eventName) {
return (eventName in this[SUBSCRIPTIONS_FIELD] && Object.keys(this[SUBSCRIPTIONS_FIELD][eventName]).length > 0);
},
destroy: function () {
this.off();
this.empty();
},
errorHandler: function (error) {
if (error) {
if (typeof console.error === 'function') {
if (this.__pgmId) {
console.error(this.__pgmId, error);
} else {
console.error(error);
}
} else {
if (this.__pgmId) {
console.log(this.__pgmId, error);
} else {
console.log(error);
}
}
this.trigger('error', error instanceof Error ? error : createError(error));
}
return false;
}
};
BaseClass.prototype.addEventListener = BaseClass.prototype.on;
BaseClass.prototype.addThrottledEventListener = BaseClass.prototype.onThrottled;
BaseClass.prototype.addEventListenerOnce = BaseClass.prototype.one;
BaseClass.prototype.removeEventListener = BaseClass.prototype.off;
function createError(message, methodName, args) {
var error = new Error(methodName ? [
'Got error with message: "', message, '" ',
'after calling "', methodName, '"'
].join('') : message);
Object.defineProperties(error, {
methodName: {
value: methodName
},
args: {
value: args
}
});
return error;
}
module.exports = BaseClass;