Updating plugin framework.
This commit is contained in:
parent
cd6d80544f
commit
a29c8d6ce8
|
|
@ -9,9 +9,9 @@
|
|||
|
||||
// Wait for the page to load, then load the plugins.
|
||||
$(document).ready(function () {
|
||||
// detect which plugins to load
|
||||
Plugins._type = (typeof mapManager !== 'undefined') ? 'map' : 'receiver';
|
||||
Plugins.init();
|
||||
// detect which plugins to load
|
||||
Plugins._type = (typeof mapManager !== 'undefined') ? 'map' : 'receiver';
|
||||
Plugins.init();
|
||||
});
|
||||
|
||||
// Initialize the Plugins class and some defaults
|
||||
|
|
@ -23,114 +23,118 @@ Plugins._enable_debug = false; // print debug to the console
|
|||
|
||||
// Load plugin
|
||||
Plugins.load = async function (name) {
|
||||
var path = 'static/plugins/' + Plugins._type + "/" + name + "/";
|
||||
var remote = false;
|
||||
var path = 'static/plugins/' + Plugins._type + "/" + name + "/";
|
||||
var remote = false;
|
||||
|
||||
// check if we are loading an url
|
||||
if (name.toLowerCase().startsWith('https://') || name.toLowerCase().startsWith('http://')) {
|
||||
path = name;
|
||||
name = path.split('/').pop().split('.').slice(0, -1);
|
||||
path = path.split('/').slice(0, -1).join('/') + '/';
|
||||
remote = true;
|
||||
}
|
||||
// check if we are loading an url
|
||||
if (name.toLowerCase().startsWith('https://') || name.toLowerCase().startsWith('http://')) {
|
||||
path = name;
|
||||
name = path.split('/').pop().split('.').slice(0, -1);
|
||||
path = path.split('/').slice(0, -1).join('/') + '/';
|
||||
remote = true;
|
||||
}
|
||||
|
||||
if (name in Plugins) {
|
||||
console.warn(Plugins._get_banner(name) + 'is already loaded' + (Plugins[name]._script_loaded ? ' from ' + Plugins[name]._script_loaded : ''));
|
||||
return;
|
||||
}
|
||||
if (name in Plugins) {
|
||||
console.warn(Plugins._banner(name) + 'is already loaded' + (Plugins[name]._script_loaded ? ' from ' + Plugins[name]._script_loaded : ''));
|
||||
return;
|
||||
}
|
||||
|
||||
Plugins._debug(Plugins._get_banner(name) + 'loading.');
|
||||
Plugins._debug(Plugins._banner(name) + 'loading.');
|
||||
|
||||
var script_src = path + name + ".js";
|
||||
var style_src = path + name + '.css';
|
||||
var script_src = path + name + ".js";
|
||||
var style_src = path + name + '.css';
|
||||
|
||||
// init plugin object with defaults
|
||||
Plugins[name] = {
|
||||
_version: 0,
|
||||
_script_loaded: false,
|
||||
_style_loaded: false,
|
||||
_remote: remote,
|
||||
};
|
||||
// init plugin object with defaults
|
||||
Plugins[name] = {
|
||||
_version : 0,
|
||||
_script_loaded : false,
|
||||
_style_loaded : false,
|
||||
_remote : remote
|
||||
};
|
||||
|
||||
|
||||
// try to load the plugin
|
||||
await Plugins._load_script(script_src)
|
||||
.then(function () {
|
||||
// plugin script loaded successfully
|
||||
Plugins[name]._script_loaded = script_src;
|
||||
// try to load the plugin
|
||||
await Plugins._load_script(script_src).then(function () {
|
||||
// plugin script loaded successfully
|
||||
Plugins[name]._script_loaded = script_src;
|
||||
|
||||
// check if the plugin has init() method and execute it
|
||||
if (typeof Plugins[name].init === 'function') {
|
||||
if (!Plugins[name].init()) {
|
||||
console.error(Plugins._get_banner(name) + 'cannot initialize.');
|
||||
return;
|
||||
// check if the plugin has init() method and execute it
|
||||
if (typeof Plugins[name].init === 'function') {
|
||||
if (!Plugins[name].init()) {
|
||||
console.error(Plugins._banner(name) + 'cannot initialize.');
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check if plugin has set the 'no_css', otherwise, load the plugin css style
|
||||
if (!('no_css' in Plugins[name])) {
|
||||
Plugins._load_style(style_src)
|
||||
.then(function () {
|
||||
Plugins[name]._style_loaded = style_src;
|
||||
Plugins._debug(Plugins._get_banner(name) + 'loaded.');
|
||||
}).catch(function () {
|
||||
console.warn(Plugins._get_banner(name) + 'script loaded, but css not found.');
|
||||
});
|
||||
} else {
|
||||
// plugin has no_css
|
||||
Plugins._debug(Plugins._get_banner(name) + 'loaded.');
|
||||
}
|
||||
// check if plugin has set the 'no_css', otherwise, load the plugin css style
|
||||
if (!('no_css' in Plugins[name])) {
|
||||
Plugins._load_style(style_src).then(function () {
|
||||
Plugins[name]._style_loaded = style_src;
|
||||
Plugins._debug(Plugins._banner(name) + 'loaded.');
|
||||
}).catch(function () {
|
||||
console.warn(Plugins._banner(name) + 'script loaded, but css not found.');
|
||||
});
|
||||
} else {
|
||||
// plugin has no_css
|
||||
Plugins._debug(Plugins._banner(name) + 'loaded.');
|
||||
}
|
||||
|
||||
}).catch(function () {
|
||||
// plugin cannot be loaded
|
||||
Plugins._debug(Plugins._get_banner(name) + 'cannot be loaded (does not exist or has errors).');
|
||||
// plugin cannot be loaded
|
||||
Plugins._debug(Plugins._banner(name) + 'cannot be loaded (does not exist or has errors).');
|
||||
});
|
||||
}
|
||||
|
||||
// Check if plugin is loaded
|
||||
Plugins.isLoaded = function (name, version = 0) {
|
||||
if (typeof Plugins[name] === 'object')
|
||||
return (Plugins[name]._script_loaded && Plugins[name]._version >= version);
|
||||
return false;
|
||||
if (typeof(Plugins[name]) === 'object') {
|
||||
return (Plugins[name]._script_loaded && Plugins[name]._version >= version);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initialize plugin loading. We should load the init.js for the {type}. This init() is called onDomReady.
|
||||
Plugins.init = function () {
|
||||
Plugins._debug("Loading " + Plugins._type + " plugins.");
|
||||
// load the init.js for the {type}... user should load their plugins there.
|
||||
Plugins._load_script('static/plugins/' + Plugins._type + "/init.js").then(function () {
|
||||
Plugins._initialized = true;
|
||||
}).catch(function () {
|
||||
Plugins._debug('no plugins to load.');
|
||||
})
|
||||
Plugins._debug("Loading " + Plugins._type + " plugins.");
|
||||
|
||||
// load the init.js for the {type}... user should load their plugins there.
|
||||
Plugins._load_script('static/plugins/' + Plugins._type + "/init.js").then(function () {
|
||||
Plugins._initialized = true;
|
||||
}).catch(function () {
|
||||
Plugins._debug('no plugins to load.');
|
||||
})
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// internal utility methods
|
||||
Plugins._load_script = function (src) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
var script = document.createElement('script');
|
||||
script.onload = resolve;
|
||||
script.onerror = reject;
|
||||
script.src = src;
|
||||
document.head.appendChild(script);
|
||||
});
|
||||
return new Promise(function (resolve, reject) {
|
||||
var script = document.createElement('script');
|
||||
script.onload = resolve;
|
||||
script.onerror = reject;
|
||||
script.src = src;
|
||||
document.head.appendChild(script);
|
||||
});
|
||||
}
|
||||
|
||||
Plugins._load_style = function (src) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
var style = document.createElement('link');
|
||||
style.onload = resolve;
|
||||
style.onerror = reject;
|
||||
style.href = src;
|
||||
style.type = 'text/css';
|
||||
style.rel = 'stylesheet';
|
||||
document.head.appendChild(style);
|
||||
});
|
||||
return new Promise(function (resolve, reject) {
|
||||
var style = document.createElement('link');
|
||||
style.onload = resolve;
|
||||
style.onerror = reject;
|
||||
style.href = src;
|
||||
style.type = 'text/css';
|
||||
style.rel = 'stylesheet';
|
||||
document.head.appendChild(style);
|
||||
});
|
||||
}
|
||||
|
||||
Plugins._debug = function (msg) {
|
||||
if (Plugins._enable_debug) console.debug(msg);
|
||||
if (Plugins._enable_debug) console.debug(msg);
|
||||
}
|
||||
Plugins._get_banner = function (name) {
|
||||
return 'PLUGINS: ' + (Plugins[name] && Plugins[name]._remote ? '[remote]' : '[local]') + ' "' + name + '" ';
|
||||
|
||||
Plugins._banner = function (name) {
|
||||
return 'PLUGINS: ' + (Plugins[name] && Plugins[name]._remote ? '[remote]' : '[local]') + ' "' + name + '" ';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,12 +2,11 @@
|
|||
|
||||
// First load the utils, needed for some plugins
|
||||
Plugins.load('utils').then(function () {
|
||||
// load local plugins
|
||||
Plugins.load('example');
|
||||
Plugins.load('example_theme');
|
||||
Plugins.load('sort_profiles');
|
||||
|
||||
// load local plugins
|
||||
Plugins.load('example');
|
||||
Plugins.load('example_theme');
|
||||
Plugins.load('sort_profiles');
|
||||
|
||||
// load remote plugins
|
||||
Plugins.load('https://0xaf.github.io/openwebrxplus-plugins/receiver/keyboard_shortcuts/keyboard_shortcuts.js');
|
||||
// load remote plugins
|
||||
Plugins.load('https://0xaf.github.io/openwebrxplus-plugins/receiver/keyboard_shortcuts/keyboard_shortcuts.js');
|
||||
});
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ Plugins.utils._version = 0.1;
|
|||
* Wrap an existing function with before and after callbacks.
|
||||
* @param {string} name The name of function to wrap with before and after callbacks.
|
||||
* @param {function(orig, thisArg, args):boolean} before_cb Callback before original. Return true to call the original.
|
||||
* @param {function(result):void} after_cb Callback after original, will receive the result of original
|
||||
* @param {function(result, orig, thisArg, args):void} after_cb Callback after original, will receive the result of original
|
||||
* @param {object} obj [optional] Object to look for function into. Default is 'window'
|
||||
* @description
|
||||
* - Before Callback:
|
||||
|
|
@ -24,6 +24,8 @@ Plugins.utils._version = 0.1;
|
|||
* - After Callback:
|
||||
* - Params:
|
||||
* - res: Result of the original function
|
||||
* - thisArg: local 'this' for the original function
|
||||
* - args: arguments passed to the original function
|
||||
*
|
||||
* @example
|
||||
* // Using before and after callbacks.
|
||||
|
|
@ -36,7 +38,7 @@ Plugins.utils._version = 0.1;
|
|||
* }
|
||||
* return true; // always return true, to call the original function
|
||||
* },
|
||||
* function (res) { // after callback
|
||||
* function (res, thisArg, args) { // after callback
|
||||
* console.log(res);
|
||||
* }
|
||||
* );
|
||||
|
|
@ -51,80 +53,85 @@ Plugins.utils._version = 0.1;
|
|||
* do_something_after_original(res);
|
||||
* return false; // to prevent calling the original and after_cb
|
||||
* },
|
||||
* function (res) { // after callback
|
||||
* function (res, thisArg, args) { // after callback
|
||||
* // ignored
|
||||
* }
|
||||
* );
|
||||
*
|
||||
*/
|
||||
Plugins.utils.wrap_func = function (name, before_cb, after_cb, obj = window) {
|
||||
if (typeof obj[name] !== "function") {
|
||||
console.error("Cannot wrap non existing function: '" + obj + '.' + name + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
var fn_original = obj[name];
|
||||
var proxy = new Proxy(obj[name], {
|
||||
apply: function (target, thisArg, args) {
|
||||
if (before_cb(target, thisArg, args))
|
||||
after_cb(fn_original.apply(thisArg, args));
|
||||
if (typeof(obj[name]) !== "function") {
|
||||
console.error("Cannot wrap non existing function: '" + obj + '.' + name + "'");
|
||||
return false;
|
||||
}
|
||||
});
|
||||
obj[name] = proxy;
|
||||
|
||||
var fn_original = obj[name];
|
||||
var proxy = new Proxy(obj[name], {
|
||||
apply: function (target, thisArg, args) {
|
||||
if (before_cb(target, thisArg, args)) {
|
||||
after_cb(fn_original.apply(thisArg, args), thisArg, args);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
obj[name] = proxy;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Init utils plugin
|
||||
Plugins.utils.init = function () {
|
||||
var send_events_for = {};
|
||||
|
||||
// trigger some events
|
||||
var send_events_for = {
|
||||
'sdr_profile_changed': { // function name to proxy.
|
||||
name: 'profile_changed', // [optional] event name (prepended with 'event:'). Default is function name.
|
||||
data: function () { // [optional] data to send with the event (should be function).
|
||||
return $('#openwebrx-sdr-profiles-listbox').find(':selected').text()
|
||||
}
|
||||
},
|
||||
'on_ws_recv': {
|
||||
handler: function (orig, thisArg, args) { // if handler exist, it will replace the before_cb
|
||||
if (typeof args[0].data === 'string' && args[0].data.substr(0, 16) !== "CLIENT DE SERVER") {
|
||||
try {
|
||||
var json = JSON.parse(args[0].data);
|
||||
$(document).trigger('server:' + json.type + ":before", [json['value']]);
|
||||
} catch (e) {}
|
||||
// function name to proxy.
|
||||
send_events_for['sdr_profile_changed'] = {
|
||||
// [optional] event name (prepended with 'event:'). Default is function name.
|
||||
name: 'profile_changed',
|
||||
// [optional] data to send with the event (should be function).
|
||||
data: function () {
|
||||
return $('#openwebrx-sdr-profiles-listbox').find(':selected').text()
|
||||
}
|
||||
orig.apply(thisArg, args); // we handle original function here
|
||||
if (typeof json === 'object')
|
||||
$(document).trigger('server:' + json.type + ":after", [json['value']]);
|
||||
return false; // do not call the after_cb
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
$.each(send_events_for, function (key, obj) {
|
||||
Plugins.utils.wrap_func(key,
|
||||
(typeof (obj.handler) === 'function') ?
|
||||
obj.handler : function () {
|
||||
return true;
|
||||
},
|
||||
function (res) {
|
||||
var ev_data;
|
||||
var ev_name = key;
|
||||
if (typeof (obj.name) === 'string') ev_name = obj.name;
|
||||
if (typeof (obj.data) === 'function') ev_data = obj.data(res);
|
||||
$(document).trigger('event:' + ev_name, [ev_data]);
|
||||
}
|
||||
);
|
||||
});
|
||||
send_events_for['on_ws_recv'] = {
|
||||
// if handler exist, it will replace the before_cb
|
||||
handler: function (orig, thisArg, args) {
|
||||
if (typeof(args[0].data) === 'string' && args[0].data.substr(0, 16) !== "CLIENT DE SERVER") {
|
||||
try {
|
||||
var json = JSON.parse(args[0].data);
|
||||
$(document).trigger('server:' + json.type + ":before", [json['value']]);
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
var interval = setInterval(function () {
|
||||
if (typeof (clock) === 'undefined') return;
|
||||
clearInterval(interval);
|
||||
$(document).trigger('event:owrx_initialized');
|
||||
}, 10);
|
||||
// we handle original function here
|
||||
orig.apply(thisArg, args);
|
||||
|
||||
return true;
|
||||
if (typeof(json) === 'object') {
|
||||
$(document).trigger('server:' + json.type + ":after", [json['value']]);
|
||||
}
|
||||
|
||||
// do not call the after_cb
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
$.each(send_events_for, function (key, obj) {
|
||||
Plugins.utils.wrap_func(
|
||||
key,
|
||||
typeof(obj.handler)==='function'? obj.handler : function () { return true; },
|
||||
function (res) {
|
||||
var ev_data;
|
||||
var ev_name = key;
|
||||
if (typeof(obj.name) === 'string') ev_name = obj.name;
|
||||
if (typeof(obj.data) === 'function') ev_data = obj.data(res);
|
||||
$(document).trigger('event:' + ev_name, [ev_data]);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
var interval = setInterval(function () {
|
||||
if (typeof(clock) === 'undefined') return;
|
||||
clearInterval(interval);
|
||||
$(document).trigger('event:owrx_initialized');
|
||||
}, 10);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue