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
This commit is contained in:
KatieFrogs 2022-02-27 18:49:56 +03:00
parent 9ceecd90d0
commit 07294857fa
2 changed files with 46 additions and 31 deletions

View File

@ -82,6 +82,8 @@
border: 0.3em black solid; border: 0.3em black solid;
position: relative; position: relative;
--course-width: min(3em, calc(7 * var(--vmin, 1vmin))); --course-width: min(3em, calc(7 * var(--vmin, 1vmin)));
content-visibility: auto;
contain-intrinsic-size: 1px 3.2em;
} }
.song-search-result::before { .song-search-result::before {

View File

@ -91,15 +91,19 @@ class SongSelect{
} }
this.songSkin["default"].sort = songSkinLength + 1 this.songSkin["default"].sort = songSkinLength + 1
this.searchStyle = document.createElement("style")
var searchCss = []
Object.keys(this.songSkin).forEach(key => { Object.keys(this.songSkin).forEach(key => {
var skin = this.songSkin[key] var skin = this.songSkin[key]
var stripped = key.replace(/\W/g, '') var stripped = key.replace(/\W/g, '')
document.styleSheets[0].insertRule('.song-search-' + stripped + ' { background-color: ' + skin.background + ' }') searchCss.push('.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] + ' }') 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] + ' }')
document.styleSheets[0].insertRule('.song-search-' + stripped + ' .song-search-result-title::before { -webkit-text-stroke: 0.4em ' + skin.outline + ' }') searchCss.push('.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 + ' .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.font = strings.font
@ -2694,7 +2698,7 @@ class SongSelect{
return addedSong return addedSong
} }
createSearchResult(song, resultsDiv, resultWidth){ createSearchResult(song, resultWidth, fontSize){
var title = this.getLocalTitle(song.title, song.title_lang) var title = this.getLocalTitle(song.title, song.title_lang)
var subtitle = this.getLocalTitle(title === song.title ? song.subtitle : "", song.subtitle_lang) var subtitle = this.getLocalTitle(title === song.title ? song.subtitle : "", song.subtitle_lang)
@ -2751,29 +2755,22 @@ class SongSelect{
resultDiv.appendChild(courseDiv) resultDiv.appendChild(courseDiv)
}) })
resultsDiv.appendChild(resultDiv) this.ctx.font = (1.2 * fontSize) + "px " + strings.font
var titleWidth = this.ctx.measureText(title).width
if(typeof resultWidth === "undefined"){ var titleRatio = resultWidth / titleWidth
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
if(titleRatio < 1){ if(titleRatio < 1){
resultInfoTitle.style.transform = "scale(" + titleRatio + ", 1)" resultInfoTitle.style.transform = "scale(" + titleRatio + ", 1)"
} }
if(subtitle){ 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){ if(subtitleRatio < 1){
resultInfoSubtitle.style.transform = "scale(" + subtitleRatio + ", 1)" resultInfoSubtitle.style.transform = "scale(" + subtitleRatio + ", 1)"
} }
} }
return { return resultDiv
div: resultDiv,
width: resultWidth
}
} }
searchSetActive(idx){ searchSetActive(idx){
@ -2953,7 +2950,11 @@ class SongSelect{
return aScore - bScore 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 var passedFilters = 0
Object.keys(filters).forEach(filter => { Object.keys(filters).forEach(filter => {
@ -3026,9 +3027,8 @@ class SongSelect{
results.push(song) results.push(song)
} }
} }
}) }
results = results.slice(0, 50)
return results return results
} }
@ -3051,15 +3051,26 @@ class SongSelect{
delete this.search.tip 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 = "" resultsDiv.innerHTML = ""
this.search.results = [] 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 => { new_results.forEach(song => {
var result = this.createSearchResult(song, resultsDiv, resultWidth) var result = this.createSearchResult(song, resultWidth, fontSize)
resultWidth = result.width fragment.appendChild(result)
this.search.results.push(result.div) this.search.results.push(result)
}) })
resultsDiv.appendChild(fragment)
this.ctx.restore()
} }
searchClick(e){ searchClick(e){
@ -3258,9 +3269,11 @@ class SongSelect{
pageEvents.remove(this.touchFullBtn, "click") pageEvents.remove(this.touchFullBtn, "click")
delete this.touchFullBtn delete this.touchFullBtn
} }
loader.screen.removeChild(this.searchStyle)
delete this.selectable delete this.selectable
delete this.ctx delete this.ctx
delete this.canvas delete this.canvas
delete this.searchContainer delete this.searchContainer
delete this.searchStyle
} }
} }