VulpesOS/gaia/apps/bluetooth/js/modules/mvvm/observable.js
OverSu b38dea0597 Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
2026-09-30 23:13:03 +02:00

102 lines
2.7 KiB
JavaScript
Executable file

'use strict';
define(function() {
function unobserve(_eventHandlers, prop, handler) {
// arguments in reverse order to support .bind(handler) for the
// unbind from all case
function removeHandler(handler, prop) {
var handlers = _eventHandlers[prop];
if (!handlers) {
return;
}
var index = handlers.indexOf(handler);
if (index >= 0) {
handlers.splice(index, 1);
}
}
if (typeof prop === 'function') {
// (handler) -- remove from every key in _eventHandlers
Object.keys(_eventHandlers).forEach(removeHandler.bind(null, prop));
} else if (handler) {
// (prop, handler) -- remove handler from the specific prop
removeHandler(handler, prop);
} else if (prop in _eventHandlers) {
// (prop) -- otherwise remove all handlers for property
_eventHandlers[prop] = [];
}
}
/*
* An Observable is able to notify its property change. It is initialized by
* an ordinary object.
*/
function Observable(obj) {
var _eventHandlers = {};
var _observable = {
observe: function o_observe(p, handler) {
/*
* We should check if _observable[_p] exists. Since _observable[_p] is
* created along with _eventHandlers[p], here we simply check
* _eventHandlers[p].
*/
var handlers = _eventHandlers[p];
if (handlers) {
handlers.push(handler);
}
},
/**
* unobserve([prop], handler) - remove handler from observeable callbacks
*/
unobserve: unobserve.bind(null, _eventHandlers)
};
var _getFunctionTemplate = function(p) {
return function() {
return _observable['_' + p];
};
};
var _setFunctionTemplate = function(p) {
return function(value) {
var oldValue = _observable['_' + p];
if (oldValue !== value) {
_observable['_' + p] = value;
var handlers = _eventHandlers[p];
handlers.forEach(function(handler) {
handler(value, oldValue);
});
}
};
};
/*
* Iterate all properties in the object and create corresponding getter and
* setter for them.
*/
for (var p in obj) {
// If p is a function, simply add it to the observable.
if (typeof obj[p] === 'function') {
_observable[p] = obj[p];
continue;
}
_eventHandlers[p] = [];
Object.defineProperty(_observable, '_' + p, {
value: obj[p],
writable: true
});
Object.defineProperty(_observable, p, {
enumerable: true,
get: _getFunctionTemplate(p),
set: _setFunctionTemplate(p)
});
}
return _observable;
}
return Observable;
});