From 07294857fa09ed8cbaaed7693b8f27685901698f Mon Sep 17 00:00:00 2001 From: KatieFrogs <23621460+KatieFrogs@users.noreply.github.com> Date: Sun, 27 Feb 2022 18:49:56 +0300 Subject: [PATCH] Optimize search - Optimize search result insertion, should be 5 to 7 times fater than before - Fix a memory leak when stylesheets are being inserted into the page --- public/src/css/search.css | 2 + public/src/js/songselect.js | 75 ++++++++++++++++++++++--------------- 2 files changed, 46 insertions(+), 31 deletions(-) diff --git a/public/src/css/search.css b/public/src/css/search.css index 0fd63a8..4a85f43 100644 --- a/public/src/css/search.css +++ b/public/src/css/search.css @@ -82,6 +82,8 @@ border: 0.3em black solid; position: relative; --course-width: min(3em, calc(7 * var(--vmin, 1vmin))); + content-visibility: auto; + contain-intrinsic-size: 1px 3.2em; } .song-search-result::before { diff --git a/public/src/js/songselect.js b/public/src/js/songselect.js index f3baed0..c1e0abb 100644 --- a/public/src/js/songselect.js +++ b/public/src/js/songselect.js @@ -90,17 +90,21 @@ class SongSelect{ } } this.songSkin["default"].sort = songSkinLength + 1 - + + this.searchStyle = document.createElement("style") + var searchCss = [] Object.keys(this.songSkin).forEach(key => { var skin = this.songSkin[key] var stripped = key.replace(/\W/g, '') - - document.styleSheets[0].insertRule('.song-search-' + stripped + ' { background-color: ' + skin.background + ' }') - document.styleSheets[0].insertRule('.song-search-' + stripped + '::before { border: 0.4em solid ' + skin.border[0] + ' ; border-bottom-color: ' + skin.border[1] + ' ; border-right-color: ' + skin.border[1] + ' }') - document.styleSheets[0].insertRule('.song-search-' + stripped + ' .song-search-result-title::before { -webkit-text-stroke: 0.4em ' + skin.outline + ' }') - document.styleSheets[0].insertRule('.song-search-' + stripped + ' .song-search-result-subtitle::before { -webkit-text-stroke: 0.4em ' + skin.outline + ' }') + + searchCss.push('.song-search-' + stripped + ' { background-color: ' + skin.background + ' }') + searchCss.push('.song-search-' + stripped + '::before { border: 0.4em solid ' + skin.border[0] + ' ; border-bottom-color: ' + skin.border[1] + ' ; border-right-color: ' + skin.border[1] + ' }') + searchCss.push('.song-search-' + stripped + ' .song-search-result-title::before { -webkit-text-stroke: 0.4em ' + skin.outline + ' }') + searchCss.push('.song-search-' + stripped + ' .song-search-result-subtitle::before { -webkit-text-stroke: 0.4em ' + skin.outline + ' }') }) - + this.searchStyle.appendChild(document.createTextNode(searchCss.join("\n"))) + loader.screen.appendChild(this.searchStyle) + this.font = strings.font this.songs = [] @@ -2694,7 +2698,7 @@ class SongSelect{ return addedSong } - createSearchResult(song, resultsDiv, resultWidth){ + createSearchResult(song, resultWidth, fontSize){ var title = this.getLocalTitle(song.title, song.title_lang) var subtitle = this.getLocalTitle(title === song.title ? song.subtitle : "", song.subtitle_lang) @@ -2751,29 +2755,22 @@ class SongSelect{ resultDiv.appendChild(courseDiv) }) - resultsDiv.appendChild(resultDiv) - - if(typeof resultWidth === "undefined"){ - var computedStyle = getComputedStyle(resultInfoDiv) - var padding = parseFloat(computedStyle.paddingLeft.slice(0, -2)) + parseFloat(computedStyle.paddingRight.slice(0, -2)) - resultWidth = resultInfoDiv.offsetWidth - padding - } - - var titleRatio = resultWidth / resultInfoTitle.offsetWidth + this.ctx.font = (1.2 * fontSize) + "px " + strings.font + var titleWidth = this.ctx.measureText(title).width + var titleRatio = resultWidth / titleWidth if(titleRatio < 1){ resultInfoTitle.style.transform = "scale(" + titleRatio + ", 1)" } if(subtitle){ - var subtitleRatio = resultWidth / resultInfoSubtitle.offsetWidth + this.ctx.font = (0.8 * 1.2 * fontSize) + "px " + strings.font + var subtitleWidth = this.ctx.measureText(subtitle).width + var subtitleRatio = resultWidth / subtitleWidth if(subtitleRatio < 1){ resultInfoSubtitle.style.transform = "scale(" + subtitleRatio + ", 1)" } } - return { - div: resultDiv, - width: resultWidth - } + return resultDiv } searchSetActive(idx){ @@ -2953,7 +2950,11 @@ class SongSelect{ return aScore - bScore }) - assets.songs.forEach(song => { + for(var i = 0; i < songs.length; i++){ + if(i >= 50){ + break + } + var song = songs[i] var passedFilters = 0 Object.keys(filters).forEach(filter => { @@ -3026,9 +3027,8 @@ class SongSelect{ results.push(song) } } - }) - - results = results.slice(0, 50) + } + return results } @@ -3051,15 +3051,26 @@ class SongSelect{ delete this.search.tip } - var resultsDiv = this.search.div.querySelector("#song-search-results") + var resultsDiv = this.search.div.querySelector(":scope #song-search-results") resultsDiv.innerHTML = "" this.search.results = [] - var resultWidth + + var fontSize = parseFloat(getComputedStyle(this.search.div.querySelector(":scope #song-search")).fontSize.slice(0, -2)) + var resultsWidth = parseFloat(getComputedStyle(resultsDiv).width.slice(0, -2)) + var courseWidth = Math.min(3 * fontSize * 1.2, 7 * this.vmin) + var resultWidth = resultsWidth - 1.8 * fontSize - 0.8 * fontSize - (courseWidth + 0.4 * fontSize * 1.2) * 5 - 0.6 * fontSize + + this.ctx.save() + + var fragment = document.createDocumentFragment() new_results.forEach(song => { - var result = this.createSearchResult(song, resultsDiv, resultWidth) - resultWidth = result.width - this.search.results.push(result.div) + var result = this.createSearchResult(song, resultWidth, fontSize) + fragment.appendChild(result) + this.search.results.push(result) }) + resultsDiv.appendChild(fragment) + + this.ctx.restore() } searchClick(e){ @@ -3258,9 +3269,11 @@ class SongSelect{ pageEvents.remove(this.touchFullBtn, "click") delete this.touchFullBtn } + loader.screen.removeChild(this.searchStyle) delete this.selectable delete this.ctx delete this.canvas delete this.searchContainer + delete this.searchStyle } }