PageSourceSearch

https://thecodingcolosseum.com/Scripts/PluginHandler.js?v=2.8.0.4

js thecodingcolosseum.com collected 2026-10-03 21:19:31 UTC 8,010 bytes, 186 lines download raw bytes

1/// <reference path="UI.js" />
2/* eslint eqeqeq: 0, "no-extra-parens": "off" */
3/* global UI */
4
5const PluginHandler = (function () {
6    "use strict";
7    let Plugins = {};
8    let PluginList = [];
9    let FeatureSet = [];
10
11    let PluginHandlerObject = {
12        SetFeatures: (features) => { FeatureSet = features; },
13        HasFeature: (feature) => FeatureSet.contains(feature),
14        RunPluginsPostAMPInit: function()
15        {
16            for (const plugin of Object.values(Plugins)) {
17                if (!plugin.hasOwnProperty("AMPDataLoaded")) { continue; }
18                plugin.AMPDataLoaded(plugin);
19            }
20        },
21        NotifyPluginSettingChanged: function(node, value)
22        {
23            for (const plugin of Object.values(Plugins)) {
24                if (!plugin.hasOwnProperty("SettingChanged")) { continue; }
25                plugin.SettingChanged(node, value);
26            }
27        },
28        NotifyPluginFailureState: function(newState)
29        {
30            for (const plugin of Object.values(Plugins)) {
31                if (!plugin.hasOwnProperty("StartupFailure")) { continue; }
32                plugin.StartupFailure(newState);
33            }
34        },
35        NotifyPluginMessage: function(source, message, parameters)
36        {
37            for (const plugin of Object.values(Plugins))
38            {
39                if (!plugin.hasOwnProperty("PushedMessage")) { continue; }
40                plugin.PushedMessage(source, message, parameters);
41            }
42        },
43        GetSearchResults: async function(query)
44        {
45            let data = [];
46            for (const plugin of Object.values(Plugins)) {
47                if (!plugin.hasOwnProperty("GetSearchResultsAsync")) { continue; }
48
49                const result = await plugin.GetSearchResultsAsync(query);
50                if (result != null)
51                {
52                    data.push(result);
53                }
54            }
55            return data;
56        },
57        LoadPluginAsync: async function (pluginName)
58        {
59            const pluginRoot = `/Plugins/${pluginName}/`;
60            const rnd = "?t=" + (0 + Date.now());
61            const scriptFile = pluginRoot + "Plugin.js" + rnd;
62            //add pluginName to PluginList, don't continue if it's already loaded.
63            if (PluginList.contains(pluginName)) {
64                console.log(`Plugin ${pluginName} already loaded.`);
65                return;
66            }
67            PluginList.push(pluginName);
68
69            async function scriptLoaded (data) {
70                const localPluginName = pluginName;
71                console.log(`Running init for ${localPluginName}`);
72                data = "'use strict';\n" + data;
73                let pluginConstructor = new Function(data);
74                let module = null;
75                function create() {
76                    let constr = new pluginConstructor();
77                    return constr;
78                }
79                try {
80                    module = create();
81                }
82                catch (e) {
83                    await UI.ShowModalAsync("Plugin Error", `An error ocurred while loading plugin ${localPluginName}. Startup will continue, but this plugin will not be loaded.`, UI.Icons.Exclamation, UI.OKActionOnly, null, null, `${e.message}\n\n${e.stack}`);
84                    return;
85                }
86                let loadedPlugin = module.plugin;
87                let tabs = module.tabs || module.plugin.tabs || [];
88
89                Plugins[pluginName] = loadedPlugin;
90                if (loadedPlugin.PreInit !== undefined) {
91                    loadedPlugin.PreInit();
92                }
93
94                loadedPlugin.name = pluginName;
95
96                if (tabs === undefined) { module.tabs = []; }
97
98                if (module.stylesheet !== undefined && module.stylesheet !== "") {
99                    const cssPath = pluginRoot + module.stylesheet;
100                    const stylesheet = $("<link/>", { type: "text/css", rel: "stylesheet", href: cssPath + rnd });
101                    $("head").append(stylesheet);
102                }
103
104                let tabPromises = [];
105
106                for (const tab of tabs) {
107                    if (tab.Disabled === true) { continue; }
108                    if (tab.RequiredPermission != null && !userHasPermission(tab.RequiredPermission)) { continue; }
109                    if (tab.FeatureSet && !FeatureSet.contains(tab.FeatureSet)) { continue; }
110
111                    const tabId = `tab_${pluginName}_${tab.ShortName}`;
112
113                    tab.id = tabId;
114                    let bodyTab = $("<div class='bodyTab pluginTabContents' style='display:none;'></div>");
115                    bodyTab.attr("id", tabId);
116
117                    if (tab.IsWizard == null || !tab.IsWizard) {
118                        tab.vm = UI.AddSideMenuItem(tab.Name, "#" + tabId, tab.Icon, tab.Click || $.noop, tab.Order || 0, tab.IsDefault || false);
119                        tab.vm.disabled(true);
120                        tab.vm.bodyElement = bodyTab;
121                        if (tab.PopHandler != null) {
122                            UI.RegisterPopstateHandler(tab.vm.shortName, tab.PopHandler);
123                        }
124                    }
125
126                    if (tab.IsWizard != null && tab.IsWizard) { bodyTab.addClass("wizardTab"); }
127                    if (tab.BodyClass) { bodyTab.addClass(tab.BodyClass); }
128                    if (tab.ViewModel) { bodyTab.attr("data-viewmodel", tab.ViewModel); }
129
130                    const loadUrl = (tab.ExternalTab ? tab.File : pluginRoot + tab.File + rnd);
131
132                    if (tab.IsWizard != null && tab.IsWizard) {
133                        $("#mainBodyArea").append(bodyTab);
134                    }
135                    else {
136                        //MB: Tabs not loading? Loading in the wrong place? This is probably why!
137                        $("#tab_support").after(bodyTab);
138                    }
139
140                    tabPromises.push(new Promise(resolve => bodyTab.load(loadUrl, resolve)))
141                }
142
143                await Promise.all(tabPromises);
144
145                if (module.features !== undefined)
146                {
147                    Features[pluginName] = {};
148                    for (const feature of Object.keys(module.features)) {
149                        Features[pluginName][feature] = module.features[feature];
150                    }
151                }
152
153                if (loadedPlugin.PostInit !== undefined) {
154                    loadedPlugin.PostInit();
155                }
156
157                for (const tab of tabs) {
158                    Locale.ApplyLocale(`#${tab.id}`);
159                    $(`#${tab.id} a`).on("click", UI.HandleClickedURL);
160                    tab.vm?.disabled(false);
161                }
162            }
163
164            const data = await fetch(scriptFile);
165            await scriptLoaded(await data.text());
166        },
167        PluginIsLoaded: (pluginName) =>  Plugins[pluginName] !== undefined,
168        LoadPluginExternalScript: function (pluginName, assetPath, callback) {
169            const scriptFile = `/Plugins/${pluginName}/${assetPath}`;
170
171            const doc = document, elementType = 'script',
172                newEl = doc.createElement(elementType),
173                firstScript = doc.getElementsByTagName(elementType)[0];
174            newEl.src = scriptFile;
175            if (callback) { newEl.addEventListener('load', function (e) { callback(null, e); }, false); }
176            firstScript.parentNode.insertBefore(newEl, firstScript);
177        },
178        LoadPluginExternalScriptAsync: async function (pluginName, assetPath) {
179            return new Promise(function (accept) {
180                PluginHandlerObject.LoadPluginExternalScript(pluginName, assetPath, accept);
181            });
182        }
183    };
184
185    return PluginHandlerObject;
186})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.