diff --git a/htdocs/plugins.js b/htdocs/plugins.js index 99850da3..525efb37 100644 --- a/htdocs/plugins.js +++ b/htdocs/plugins.js @@ -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 + '" '; } diff --git a/htdocs/plugins/receiver/init.js.sample b/htdocs/plugins/receiver/init.js.sample index bca76ca5..d85da80d 100644 --- a/htdocs/plugins/receiver/init.js.sample +++ b/htdocs/plugins/receiver/init.js.sample @@ -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'); }); diff --git a/htdocs/plugins/receiver/utils/utils.js b/htdocs/plugins/receiver/utils/utils.js index 6c07c74b..ea84e406 100644 --- a/htdocs/plugins/receiver/utils/utils.js +++ b/htdocs/plugins/receiver/utils/utils.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; }