diff --git a/.eslintrc.json b/.eslintrc.json
index 702fb65a..44fd050f 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -22,7 +22,10 @@
},
"globals": {
"$": true,
- "session": true,
- "siteURL": true
+ "addHook": true,
+ "runHook": true,
+ "addInitHook": true,
+ "runInitHook": true,
+ "loadScript": true
}
}
\ No newline at end of file
diff --git a/common/parser.go b/common/parser.go
index 2b58c587..59287749 100644
--- a/common/parser.go
+++ b/common/parser.go
@@ -758,7 +758,7 @@ func parseMediaBytes(data []byte) (media MediaEmbed, ok bool) {
hostname = strings.Split(Site.URL, ":")[0]
// ?- Test this as I'm not sure it'll do what it should. If someone's running SSL on port 80 or non-SSL on port 443 then... Well... They're in far worse trouble than this...
port = Site.Port
- if scheme == "" && Site.EnableSsl {
+ if Site.EnableSsl {
scheme = "https"
}
}
diff --git a/public/global.js b/public/global.js
index 2237eb25..eb66d260 100644
--- a/public/global.js
+++ b/public/global.js
@@ -1,32 +1,15 @@
'use strict';
var formVars = {};
-var tmplInits = {};
-var tmplPhrases = []; // [key] array of phrases indexed by order of use
-var phraseBox = {};
var alertList = [];
var alertCount = 0;
var moreTopicCount = 0;
var conn;
-var me = {};
var selectedTopics = [];
var attachItemCallback = function(){}
-var hooks = {
- "start_init": [],
- "end_init": [],
-};
// Topic move
var forumToMoveTo = 0;
-function runHook(name, ...args) {
- if(!(name in hooks)) return;
-
- let hook = hooks[name];
- for (const callback in hook) {
- callback(...args);
- }
-}
-
// TODO: Write a friendlier error handler which uses a .notice or something, we could have a specialised one for alerts
function ajaxError(xhr,status,errstr) {
console.log("The AJAX request failed");
@@ -193,6 +176,10 @@ function runWebSockets() {
conn = new WebSocket("wss://" + document.location.host + "/ws/");
} else conn = new WebSocket("ws://" + document.location.host + "/ws/");
+ conn.onerror = (err) => {
+ console.log(err);
+ }
+
conn.onopen = () => {
console.log("The WebSockets connection was opened");
conn.send("page " + document.location.pathname + '\r');
@@ -201,10 +188,12 @@ function runWebSockets() {
Notification.requestPermission();
}
}
+
conn.onclose = () => {
conn = false;
console.log("The WebSockets connection was closed");
}
+
conn.onmessage = (event) => {
//console.log("WSMessage:", event.data);
if(event.data[0] == "{") {
@@ -270,102 +259,29 @@ function runWebSockets() {
}
}
-// Temporary hack for templates
-function len(item) {
- return item.length;
-}
-
-function loadScript(name, callback) {
- let url = "/static/"+name
- $.getScript(url)
- .done(callback)
- .fail((e,xhr,settings,ex) => {
- console.log("Unable to get script '"+url+"'");
- console.log("e: ", e);
- console.log("xhr: ", xhr);
- console.log("settings: ", settings);
- console.log("ex: ",ex);
- console.trace();
- });
-}
-
-function DoNothingButPassBack(item) {
- return item;
-}
-
-function fetchPhrases() {
- fetch("/api/phrases/?query=status,topic_list")
- .then((resp) => resp.json())
- .then((data) => {
- console.log("loaded phrase endpoint data");
- console.log("data:",data);
- Object.keys(tmplInits).forEach((key) => {
- let phrases = [];
- let tmplInit = tmplInits[key];
- for(let phraseName of tmplInit) {
- phrases.push(data[phraseName]);
- }
- console.log("Adding phrases");
- console.log("key:",key);
- console.log("phrases:",phrases);
- tmplPhrases[key] = phrases;
- });
-
- let prefixes = {};
- Object.keys(data).forEach((key) => {
- let prefix = key.split(".")[0];
- if(prefixes[prefix]===undefined) {
- prefixes[prefix] = {};
- }
- prefixes[prefix][key] = data[key];
- });
- Object.keys(prefixes).forEach((prefix) => {
- console.log("adding phrase prefix '"+prefix+"' to box");
- phraseBox[prefix] = prefixes[prefix];
- });
- });
-}
-
(() => {
- runHook("pre_iife");
- let loggedIn = document.head.querySelector("[property='x-loggedin']").content;
-
- fetch("/api/me/")
- .then((resp) => resp.json())
- .then((data) => {
- console.log("loaded me endpoint data");
- console.log("data:",data);
- me = data;
- runHook("pre_init");
-
- // We can only get away with this because template_alert has no phrases, otherwise it too would have to be part of the "dance", I miss Go concurrency :(
- loadScript("template_alert.js", () => {
- console.log("Loaded template_alert.js");
+ addInitHook("pre_init", () => {
+ // We can only get away with this because template_alert has no phrases, otherwise it too would have to be part of the "dance", I miss Go concurrency :(
+ loadScript("template_alert.js", () => {
+ console.log("Loaded template_alert.js");
+ $(document).ready(() => {
alertsInitted = true;
var alertMenuList = document.getElementsByClassName("menu_alerts");
for(var i = 0; i < alertMenuList.length; i++) {
loadAlerts(alertMenuList[i]);
}
});
-
- if(window["WebSocket"]) runWebSockets();
- else conn = false;
-
- $(document).ready(mainInit);
});
-
- if(loggedIn) {
- let toLoad = 1;
- loadScript("template_topics_topic.js", () => {
- console.log("Loaded template_topics_topic.js");
- toLoad--;
- if(toLoad===0) fetchPhrases();
- });
- }
+
+ if(window["WebSocket"]) runWebSockets();
+ else conn = false;
+
+ $(document).ready(mainInit);
+ });
})();
function mainInit(){
- runHook("start_init");
+ runInitHook("start_init");
$(".more_topics").click((event) => {
event.preventDefault();
@@ -839,5 +755,5 @@ function mainInit(){
})
});
- runHook("end_init");
+ runInitHook("end_init");
};
diff --git a/public/init.js b/public/init.js
new file mode 100644
index 00000000..a49a8441
--- /dev/null
+++ b/public/init.js
@@ -0,0 +1,146 @@
+'use strict';
+
+var me = {};
+var phraseBox = {};
+var tmplInits = {};
+var tmplPhrases = []; // [key] array of phrases indexed by order of use
+var hooks = {
+ "pre_iffe": [],
+ "pre_init": [],
+ "start_init": [],
+ "end_init": [],
+};
+var ranInitHooks = {}
+
+function runHook(name, ...args) {
+ if(!(name in hooks)) {
+ console.log("Couldn't find hook '" + name + "'");
+ return;
+ }
+ console.log("Running hook '"+name+"'");
+
+ let hook = hooks[name];
+ for (const index in hook) {
+ hook[index](...args);
+ }
+}
+
+function addHook(name, callback) {
+ hooks[name].push(callback);
+}
+
+// InitHooks are slightly special, as if they are run, then any adds after the initial run will run immediately, this is to deal with the async nature of script loads
+function runInitHook(name) {
+ runHook(name);
+ ranInitHooks[name] = true;
+}
+
+function addInitHook(name, callback) {
+ addHook(name, callback);
+ if(name in ranInitHooks) {
+ callback();
+ }
+}
+
+// Temporary hack for templates
+function len(item) {
+ return item.length;
+}
+
+const asyncGetScript = (source) => {
+ return new Promise((resolve, reject) => {
+ let script = document.createElement('script');
+ script.async = true;
+
+ const onloadHander = (haha, isAbort) => {
+ if (isAbort || !script.readyState || /loaded|complete/.test(script.readyState)) {
+ script.onload = null;
+ script.onreadystatechange = null;
+ script = undefined;
+
+ isAbort ? reject(haha) : resolve();
+ }
+ }
+
+ script.onerror = (haha) => {
+ reject(haha);
+ };
+ script.onload = onloadHander;
+ script.onreadystatechange = onloadHander;
+ script.src = source;
+
+ const prior = document.getElementsByTagName('script')[0];
+ prior.parentNode.insertBefore(script, prior);
+ });
+};
+
+function loadScript(name, callback) {
+ let url = "/static/"+name
+ asyncGetScript(url)
+ .then(callback)
+ .catch((haha) => {
+ console.log("Unable to get script '"+url+"'");
+ console.log("haha: ", haha);
+ console.trace();
+ });
+}
+
+function DoNothingButPassBack(item) {
+ return item;
+}
+
+function fetchPhrases() {
+ fetch("/api/phrases/?query=status,topic_list")
+ .then((resp) => resp.json())
+ .then((data) => {
+ console.log("loaded phrase endpoint data");
+ console.log("data:",data);
+ Object.keys(tmplInits).forEach((key) => {
+ let phrases = [];
+ let tmplInit = tmplInits[key];
+ for(let phraseName of tmplInit) {
+ phrases.push(data[phraseName]);
+ }
+ console.log("Adding phrases");
+ console.log("key:",key);
+ console.log("phrases:",phrases);
+ tmplPhrases[key] = phrases;
+ });
+
+ let prefixes = {};
+ Object.keys(data).forEach((key) => {
+ let prefix = key.split(".")[0];
+ if(prefixes[prefix]===undefined) {
+ prefixes[prefix] = {};
+ }
+ prefixes[prefix][key] = data[key];
+ });
+ Object.keys(prefixes).forEach((prefix) => {
+ console.log("adding phrase prefix '"+prefix+"' to box");
+ phraseBox[prefix] = prefixes[prefix];
+ });
+ });
+}
+
+(() => {
+ runInitHook("pre_iife");
+ let loggedIn = document.head.querySelector("[property='x-loggedin']").content;
+
+ fetch("/api/me/")
+ .then((resp) => resp.json())
+ .then((data) => {
+ console.log("loaded me endpoint data");
+ console.log("data:",data);
+ me = data;
+ runInitHook("pre_init");
+ });
+
+ if(loggedIn) {
+ let toLoad = 1;
+ loadScript("template_topics_topic.js", () => {
+ console.log("Loaded template_topics_topic.js");
+ toLoad--;
+ if(toLoad===0) fetchPhrases();
+ });
+ }
+})();
\ No newline at end of file
diff --git a/routes.go b/routes.go
index 07bb8951..0bd9b04c 100644
--- a/routes.go
+++ b/routes.go
@@ -101,10 +101,17 @@ func routeAPI(w http.ResponseWriter, r *http.Request, user common.User) common.R
return nil
}
+// TODO: Remove this line after we move routeAPIPhrases to the routes package
+var cacheControlMaxAge = "max-age=" + strconv.Itoa(int(common.Day))
+
// TODO: Be careful with exposing the panel phrases here, maybe move them into a different namespace? We also need to educate the admin that phrases aren't necessarily secret
+// TODO: Move to the routes package
func routeAPIPhrases(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
// TODO: Don't make this too JSON dependent so that we can swap in newer more efficient formats
- w.Header().Set("Content-Type", "application/json")
+ h := w.Header()
+ h.Set("Content-Type", "application/json")
+ h.Set("Cache-Control", cacheControlMaxAge) //Cache-Control: max-age=31536000
+
err := r.ParseForm()
if err != nil {
return common.PreErrorJS("Bad Form", w, r)
diff --git a/templates/header.html b/templates/header.html
index b37fc87c..886d5718 100644
--- a/templates/header.html
+++ b/templates/header.html
@@ -6,12 +6,13 @@
{{range .Header.Stylesheets}}
{{end}}
+
+
{{range .Header.Scripts}}
{{end}}
-
{{if .Header.MetaDesc}}{{end}}