From 372508bf98b0f61a8f442441f7ff8309e8dc8056 Mon Sep 17 00:00:00 2001 From: Azareal Date: Fri, 13 Mar 2020 12:56:23 +1000 Subject: [PATCH] fix poll results on ajax topic and eliminate unnecessary allocs for resources that aren't used --- common/pages.go | 48 +++++++++++++------ public/global.js | 108 +++++++++++++++++++++++++++++++----------- public/init.js | 10 ++-- public/member.js | 10 +--- routes/common.go | 4 +- routes/topic.go | 9 +++- templates/header.html | 4 +- 7 files changed, 133 insertions(+), 60 deletions(-) diff --git a/common/pages.go b/common/pages.go index fc2bfbb1..5dcf4082 100644 --- a/common/pages.go +++ b/common/pages.go @@ -46,9 +46,9 @@ type Header struct { LooseCSP bool //StartedAt time.Time StartedAt int64 - Elapsed1 string - Writer http.ResponseWriter - ExtData ExtData + Elapsed1 string + Writer http.ResponseWriter + ExtData ExtData } func (h *Header) AddScript(name string) { @@ -101,6 +101,26 @@ func (h *Header) AddSheet(name string) { h.Stylesheets = append(h.Stylesheets, name) } +// ! Experimental +func (h *Header) AddXRes(names ...string) { + var o string + for i, name := range names { + if name[0] == '/' && name[1] == '/' { + } else { + file, ok := StaticFiles.Get("/s/" + name) + if ok { + name = file.OName + } + } + if i != 0 { + o += "," + name + } else { + o += name + } + } + h.Writer.Header().Set("X-Res", o) +} + func (h *Header) AddNotice(name string) { h.NoticeList = append(h.NoticeList, p.GetNoticePhrase(name)) } @@ -356,12 +376,12 @@ type PanelAnalyticsActiveMemory struct { MemType int } type PanelAnalyticsPerf struct { - Graph PanelTimeGraph + Graph PanelTimeGraph ViewItems []PanelAnalyticsItemUnit TimeRange string - Unit string - TimeType string - PerfType int + Unit string + TimeType string + PerfType int } type PanelStats struct { @@ -476,7 +496,7 @@ type PanelAnalyticsRoutesPage struct { type PanelAnalyticsRoutesPerfItem struct { Route string Count int - Unit string + Unit string } type PanelAnalyticsRoutesPerfPage struct { @@ -677,11 +697,11 @@ type PanelRegLogsPage struct { } type DebugPageTasks struct { - HalfSecond int - Second int + HalfSecond int + Second int FifteenMinute int - Hour int - Shutdown int + Hour int + Shutdown int } type DebugPageCache struct { @@ -742,8 +762,8 @@ type PanelDebugPage struct { Goroutines int CPUs int - Tasks DebugPageTasks - MemStats runtime.MemStats + Tasks DebugPageTasks + MemStats runtime.MemStats Cache DebugPageCache Database DebugPageDatabase Disk DebugPageDisk diff --git a/public/global.js b/public/global.js index 000d192e..c0487316 100644 --- a/public/global.js +++ b/public/global.js @@ -341,6 +341,12 @@ function runWebSockets(resume=false) { } } +// TODO: Surely, there's a prettier and more elegant way of doing this? +function getExt(name) { + if(!name.indexOf('.' > -1)) throw("This file doesn't have an extension"); + return name.split('.').pop(); +} + (() => { addInitHook("pre_init", () => { runInitHook("pre_global"); @@ -813,42 +819,57 @@ function mainInit(){ if(ev.which == 39) this.querySelectorAll("#nextFloat a")[0].click(); }; - //id="poll_results_{{.Poll.ID}}" class="poll_results auto_hide" - $(".poll_results_button").click(function(){ - let pollID = $(this).attr("data-poll-id"); - $("#poll_results_" + pollID).removeClass("auto_hide"); - fetch("/poll/results/" + pollID, { - credentials: 'same-origin' - }).then(resp => resp.text()).catch(err => console.error("err",err)).then(rawData => { - // TODO: Make sure the received data is actually a list of integers - let data = JSON.parse(rawData); - let allZero = true; - for(let i = 0; i < data.length; i++) { - if(data[i] != "0") allZero = false; - } - if(allZero) { - $("#poll_results_"+pollID+" .poll_no_results").removeClass("auto_hide"); - console.log("all zero") - return; + function asyncGetSheet(src) { + return new Promise((resolve,reject) => { + let res = document.createElement('link'); + res.async = true; + + const onloadHandler = (e,isAbort) => { + if (isAbort || !res.readyState || /loaded|complete/.test(res.readyState)) { + res.onload = null; + res.onreadystatechange = null; + res = undefined; + + isAbort ? reject(e) : resolve(); + } } + + res.onerror = (e) => { + reject(e); + }; + res.onload = onloadHandler; + res.onreadystatechange = onloadHandler; + res.href = src; + res.rel = "stylesheet"; + res.type = "text/css"; + + const prior = document.getElementsByTagName('link')[0]; + prior.parentNode.insertBefore(res,prior); + }); + } - $("#poll_results_"+pollID+" .user_content").html("
"); - console.log("rawData",rawData); - console.log("series",data); - Chartist.Pie('#poll_results_chart_'+pollID, { - series: data, - }, { - height: '120px', - }); - }) - }); + function stripQ(name) { + return name.split('?')[0]; + } - $(".rowtopic a, a.rowtopic").click(function(ev) { + $(".rowtopic a,a.rowtopic").click(function(ev) { let base = this.getAttribute("href"); let href = base + "?i=1"; fetch(href, {credentials:"same-origin"}) .then(resp => { if(!resp.ok) throw(href+" failed to load"); + let xRes = resp.headers.get("x-res") + for(let res of xRes.split(",")) { + let pro; + if(stripQ(getExt(res)) == "css") pro = asyncGetSheet("/s/"+res) + else pro = asyncGetScript("/s/"+res) + pro.then(() => console.log("Loaded " + res)) + .catch(e => { + console.log("Unable to get res '"+res+"'"); + console.log("e",e); + console.trace(); + }); + } return resp.text(); }).then(data => { document.querySelector("#back").outerHTML = data; @@ -1002,6 +1023,36 @@ function bindTopic() { quoteItemCallback(src.innerHTML,item); }); + //id="poll_results_{{.Poll.ID}}" class="poll_results auto_hide" + $(".poll_results_button").click(function(){ + let pollID = $(this).attr("data-poll-id"); + $("#poll_results_" + pollID).removeClass("auto_hide"); + fetch("/poll/results/" + pollID, { + credentials: 'same-origin' + }).then(resp => resp.text()).catch(err => console.error("err",err)).then(rawData => { + // TODO: Make sure the received data is actually a list of integers + let data = JSON.parse(rawData); + let allZero = true; + for(let i = 0; i < data.length; i++) { + if(data[i] != "0") allZero = false; + } + if(allZero) { + $("#poll_results_"+pollID+" .poll_no_results").removeClass("auto_hide"); + console.log("all zero") + return; + } + + $("#poll_results_"+pollID+" .user_content").html("
"); + console.log("rawData",rawData); + console.log("series",data); + Chartist.Pie('#poll_results_chart_'+pollID, { + series: data, + }, { + height: '120px', + }); + }) + }); + runHook("end_bind_topic"); } @@ -1012,5 +1063,6 @@ function unbindTopic() { $(".edit_item").unbind("click"); $(".submit_edit").unbind("click"); $(".quote_item").unbind("click"); + $(".poll_results_button").unbind("click"); runHook("end_unbind_topic"); } \ No newline at end of file diff --git a/public/init.js b/public/init.js index 2e5877c2..77ca5bcc 100644 --- a/public/init.js +++ b/public/init.js @@ -110,7 +110,7 @@ function notifyOnScriptW(name,complete,success) { if(success!==undefined) success(); }).catch(e => { console.log("Unable to get script name '"+name+"'"); - console.log("e", e); + console.log("e",e); console.trace(); complete(e); }); @@ -134,11 +134,11 @@ function loadScript(name,callback,fail) { .then(callback) .catch(e => { console.log("Unable to get script '"+iurl+"'"); - console.log("e", e); + console.log("e",e); console.trace(); }); } - console.log("e", e); + console.log("e",e); console.trace(); fail(e); }); @@ -156,7 +156,7 @@ function RelativeTime(date) { return date; } -function initPhrases(loggedIn, panel = false) { +function initPhrases(loggedIn, panel=false) { console.log("in initPhrases") console.log("tmlInits",tmplInits) let e = ""; @@ -167,7 +167,7 @@ function initPhrases(loggedIn, panel = false) { } function fetchPhrases(plist) { - fetch("/api/phrases/?q="+plist, {cache: "no-cache"}) + fetch("/api/phrases/?q="+plist, {cache:"no-cache"}) .then(resp => resp.json()) .then(data => { console.log("loaded phrase endpoint data"); diff --git a/public/member.js b/public/member.js index 9ea763cb..06f3abd9 100644 --- a/public/member.js +++ b/public/member.js @@ -14,12 +14,6 @@ var imageExts = ["png", "jpg", "jpe","jpeg","jif","jfi","jfif", "svg", "bmp", "g document.body.removeChild(el); } - // TODO: Surely, there's a prettier and more elegant way of doing this? - function getExt(name) { - if(!name.indexOf('.' > -1)) throw("This file doesn't have an extension"); - return name.split('.').pop(); - } - function uploadFileHandler(fileList, maxFiles = 5, step1 = () => {}, step2 = () => {}) { let files = []; for(var i = 0; i < fileList.length && i < 5; i++) files[i] = fileList[i]; @@ -289,7 +283,7 @@ var imageExts = ["png", "jpg", "jpe","jpeg","jif","jfi","jfif", "svg", "bmp", "g function addPollInput() { console.log("clicked on pollinputinput"); let dataPollInput = $(this).parent().attr("data-pollinput"); - console.log("dataPollInput", dataPollInput); + console.log("dataPollInput",dataPollInput); if(dataPollInput==undefined) return; if(dataPollInput!=(pollInputIndex-1)) return; $(".poll_content_row .formitem").append(Template_topic_c_poll_input({ @@ -297,7 +291,7 @@ var imageExts = ["png", "jpg", "jpe","jpeg","jif","jfi","jfif", "svg", "bmp", "g Place: phraseBox["topic"]["topic.reply_add_poll_option"].replace("%d",pollInputIndex), })); pollInputIndex++; - console.log("new pollInputIndex", pollInputIndex); + console.log("new pollInputIndex",pollInputIndex); $(".pollinputinput").off("click"); $(".pollinputinput").click(addPollInput); } diff --git a/routes/common.go b/routes/common.go index bdb73050..fd2217c4 100644 --- a/routes/common.go +++ b/routes/common.go @@ -119,7 +119,9 @@ func FootHeaders(w http.ResponseWriter, header *c.Header) { func renderTemplate3(tmplName, hookName string, w http.ResponseWriter, r *http.Request, h *c.Header, pi interface{}) error { s := h.Stylesheets h.Stylesheets = nil - c.PrepResources(&h.CurrentUser, h, h.Theme) + if r.FormValue("i") != "1" { + c.PrepResources(&h.CurrentUser, h, h.Theme) + } for _, ss := range s { h.Stylesheets = append(h.Stylesheets, ss) } diff --git a/routes/topic.go b/routes/topic.go index df837eb8..cbaa26b7 100644 --- a/routes/topic.go +++ b/routes/topic.go @@ -115,8 +115,6 @@ func ViewTopic(w http.ResponseWriter, r *http.Request, user c.User, header *c.He return c.InternalError(err, w, r) } poll = pPoll.Copy() - header.AddSheet("chartist/chartist.min.css") - header.AddScript("chartist/chartist.min.js") } if topic.LikeCount > 0 && user.Liked > 0 { @@ -166,6 +164,9 @@ func ViewTopic(w http.ResponseWriter, r *http.Request, user c.User, header *c.He var rerr c.RouteError tmpl := forum.Tmpl if r.FormValue("i") == "1" { + if tpage.Poll.ID != 0 { + header.AddXRes("chartist/chartist.min.css", "chartist/chartist.min.js") + } if tmpl == "" { rerr = renderTemplate("topic_mini", w, r, header, tpage) } else { @@ -176,6 +177,10 @@ func ViewTopic(w http.ResponseWriter, r *http.Request, user c.User, header *c.He } } } else { + if tpage.Poll.ID != 0 { + header.AddSheet("chartist/chartist.min.css") + header.AddScript("chartist/chartist.min.js") + } if tmpl == "" { rerr = renderTemplate("topic", w, r, header, tpage) } else { diff --git a/templates/header.html b/templates/header.html index 3f5e8e1b..59972cf9 100644 --- a/templates/header.html +++ b/templates/header.html @@ -3,10 +3,10 @@ {{.Title}} | {{.Header.Site.Name}} {{range .Header.Stylesheets}} - {{end}} + {{end}} {{range .Header.PreScriptsAsync}} {{end}} - + {{range .Header.ScriptsAsync}} {{end}}