mirror of
https://github.com/jiojciojsioe3/a3cjroijsiojiorj.git
synced 2024-11-15 07:21:50 +08:00
commit
a7aee747a8
@ -1,39 +0,0 @@
|
|||||||
.pattern-bg{
|
|
||||||
background-image: url("bg-pattern-1.png");
|
|
||||||
}
|
|
||||||
#song-select{
|
|
||||||
background-image: url("bg_genre_0.png");
|
|
||||||
}
|
|
||||||
#title-screen{
|
|
||||||
background-image: url("title-screen.png");
|
|
||||||
}
|
|
||||||
#loading-don{
|
|
||||||
background-image: url("dancing-don.gif");
|
|
||||||
}
|
|
||||||
#touch-full-btn{
|
|
||||||
background-image: url("touch_fullscreen.png");
|
|
||||||
}
|
|
||||||
#touch-pause-btn{
|
|
||||||
background-image: url("touch_pause.png");
|
|
||||||
}
|
|
||||||
.settings-outer{
|
|
||||||
background-image: url("bg_settings.png");
|
|
||||||
}
|
|
||||||
#gamepad-bg,
|
|
||||||
#gamepad-buttons{
|
|
||||||
background-image: url("settings_gamepad.png");
|
|
||||||
}
|
|
||||||
#song-search{
|
|
||||||
background: linear-gradient(to top, rgb(245 246 252 / 8%), #ff5963), url("bg_search.png");
|
|
||||||
background-size: auto, 3.12em;
|
|
||||||
background-position: -1.2em;
|
|
||||||
}
|
|
||||||
.song-search-result-course::before{
|
|
||||||
background-image: url("difficulty.png");
|
|
||||||
}
|
|
||||||
.song-search-result-crown{
|
|
||||||
background-image: url("crown.png");
|
|
||||||
}
|
|
||||||
.song-search-tip-error{
|
|
||||||
background-image: url("miss.png");
|
|
||||||
}
|
|
@ -127,3 +127,15 @@
|
|||||||
#song-lyrics rt{
|
#song-lyrics rt{
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
}
|
}
|
||||||
|
.pixelated #canvas,
|
||||||
|
.pixelated .donbg>div,
|
||||||
|
.pixelated #songbg>div,
|
||||||
|
.pixelated #song-stage,
|
||||||
|
.pixelated #touch-drum-img,
|
||||||
|
.pixelated #flowers1-in,
|
||||||
|
.pixelated #flowers2-in,
|
||||||
|
.pixelated #mikoshi-in,
|
||||||
|
.pixelated #tetsuo-in,
|
||||||
|
.pixelated #hana-in{
|
||||||
|
image-rendering: pixelated;
|
||||||
|
}
|
||||||
|
@ -26,6 +26,8 @@
|
|||||||
padding: 1em 1em 0 1em;
|
padding: 1em 1em 0 1em;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
background-size: auto, 3.12em;
|
||||||
|
background-position: 0%, -2%;
|
||||||
}
|
}
|
||||||
|
|
||||||
#song-search-container.touch-enabled{
|
#song-search-container.touch-enabled{
|
||||||
@ -96,6 +98,7 @@
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
-moz-box-sizing: border-box;
|
-moz-box-sizing: border-box;
|
||||||
-webkit-box-sizing: border-box;
|
-webkit-box-sizing: border-box;
|
||||||
|
border: 0.4em solid;
|
||||||
}
|
}
|
||||||
|
|
||||||
.song-search-result:last-of-type {
|
.song-search-result:last-of-type {
|
||||||
@ -133,6 +136,7 @@
|
|||||||
content: attr(alt);
|
content: attr(alt);
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: -1;
|
z-index: -1;
|
||||||
|
-webkit-text-stroke-width: 0.4em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.song-search-result-course {
|
.song-search-result-course {
|
||||||
|
@ -59,7 +59,9 @@ class RemoteFile{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
blob(){
|
blob(){
|
||||||
return this.arrayBuffer().then(response => new Blob([response]))
|
return loader.ajax(this.url, request => {
|
||||||
|
request.responseType = "blob"
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class LocalFile{
|
class LocalFile{
|
||||||
@ -113,7 +115,7 @@ class GdriveFile{
|
|||||||
this.url = gpicker.filesUrl + this.id + "?alt=media"
|
this.url = gpicker.filesUrl + this.id + "?alt=media"
|
||||||
}
|
}
|
||||||
arrayBuffer(){
|
arrayBuffer(){
|
||||||
return gpicker.downloadFile(this.id, true)
|
return gpicker.downloadFile(this.id, "arraybuffer")
|
||||||
}
|
}
|
||||||
read(encoding){
|
read(encoding){
|
||||||
if(encoding){
|
if(encoding){
|
||||||
@ -123,7 +125,7 @@ class GdriveFile{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
blob(){
|
blob(){
|
||||||
return this.arrayBuffer().then(response => new Blob([response]))
|
return gpicker.downloadFile(this.id, "blob")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class CachedFile{
|
class CachedFile{
|
||||||
@ -144,6 +146,6 @@ class CachedFile{
|
|||||||
return this.arrayBuffer()
|
return this.arrayBuffer()
|
||||||
}
|
}
|
||||||
blob(){
|
blob(){
|
||||||
return this.arrayBuffer().then(response => new Blob([response]))
|
return this.arrayBuffer()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,8 @@ var assets = {
|
|||||||
"customsongs.js",
|
"customsongs.js",
|
||||||
"abstractfile.js",
|
"abstractfile.js",
|
||||||
"idb.js",
|
"idb.js",
|
||||||
"plugins.js"
|
"plugins.js",
|
||||||
|
"search.js"
|
||||||
],
|
],
|
||||||
"css": [
|
"css": [
|
||||||
"main.css",
|
"main.css",
|
||||||
@ -50,20 +51,13 @@ var assets = {
|
|||||||
"view.css",
|
"view.css",
|
||||||
"search.css"
|
"search.css"
|
||||||
],
|
],
|
||||||
"assetsCss": [
|
|
||||||
"img/img.css"
|
|
||||||
],
|
|
||||||
"img": [
|
"img": [
|
||||||
"title-screen.png",
|
|
||||||
"notes.png",
|
"notes.png",
|
||||||
"notes_drumroll.png",
|
"notes_drumroll.png",
|
||||||
"notes_hit.png",
|
"notes_hit.png",
|
||||||
"notes_explosion.png",
|
"notes_explosion.png",
|
||||||
"balloon.png",
|
"balloon.png",
|
||||||
"taiko.png",
|
"taiko.png",
|
||||||
"dancing-don.gif",
|
|
||||||
"bg-pattern-1.png",
|
|
||||||
"difficulty.png",
|
|
||||||
"don_anim_normal_a.png",
|
"don_anim_normal_a.png",
|
||||||
"don_anim_normal_b1.png",
|
"don_anim_normal_b1.png",
|
||||||
"don_anim_normal_b2.png",
|
"don_anim_normal_b2.png",
|
||||||
@ -81,24 +75,26 @@ var assets = {
|
|||||||
"don_anim_clear_b2.png",
|
"don_anim_clear_b2.png",
|
||||||
"fire_anim.png",
|
"fire_anim.png",
|
||||||
"fireworks_anim.png",
|
"fireworks_anim.png",
|
||||||
"bg_genre_def.png",
|
|
||||||
"bg_score_p1.png",
|
"bg_score_p1.png",
|
||||||
"bg_score_p2.png",
|
"bg_score_p2.png",
|
||||||
"bg_settings.png",
|
|
||||||
"bg_pause.png",
|
"bg_pause.png",
|
||||||
"badge_auto.png",
|
"badge_auto.png",
|
||||||
"touch_pause.png",
|
"mimizu.png"
|
||||||
"touch_fullscreen.png",
|
|
||||||
"mimizu.png",
|
|
||||||
"results_flowers.png",
|
|
||||||
"results_mikoshi.png",
|
|
||||||
"results_tetsuohana.png",
|
|
||||||
"results_tetsuohana2.png",
|
|
||||||
"settings_gamepad.png",
|
|
||||||
"crown.png",
|
|
||||||
"miss.png",
|
|
||||||
"bg_search.png"
|
|
||||||
],
|
],
|
||||||
|
"cssBackground": {
|
||||||
|
"#title-screen": "title-screen.png",
|
||||||
|
"#loading-don": "dancing-don.gif",
|
||||||
|
".pattern-bg": "bg-pattern-1.png",
|
||||||
|
".song-search-result-course::before": "difficulty.png",
|
||||||
|
"#song-select": "bg_genre_def.png",
|
||||||
|
".settings-outer": "bg_settings.png",
|
||||||
|
"#touch-pause-btn": "touch_pause.png",
|
||||||
|
"#touch-full-btn": "touch_fullscreen.png",
|
||||||
|
"#gamepad-bg, #gamepad-buttons": "settings_gamepad.png",
|
||||||
|
".song-search-result-crown": "crown.png",
|
||||||
|
".song-search-tip-error": "miss.png",
|
||||||
|
"#song-search": "bg_search.png"
|
||||||
|
},
|
||||||
"audioSfx": [
|
"audioSfx": [
|
||||||
"se_pause.ogg",
|
"se_pause.ogg",
|
||||||
"se_calibration.ogg",
|
"se_calibration.ogg",
|
||||||
|
@ -2,7 +2,7 @@ class CustomSongs{
|
|||||||
constructor(...args){
|
constructor(...args){
|
||||||
this.init(...args)
|
this.init(...args)
|
||||||
}
|
}
|
||||||
init(touchEnabled, noPage){
|
init(touchEnabled, noPage, noLoading){
|
||||||
this.loaderDiv = document.createElement("div")
|
this.loaderDiv = document.createElement("div")
|
||||||
this.loaderDiv.innerHTML = assets.pages["loadsong"]
|
this.loaderDiv.innerHTML = assets.pages["loadsong"]
|
||||||
var loadingText = this.loaderDiv.querySelector("#loading-text")
|
var loadingText = this.loaderDiv.querySelector("#loading-text")
|
||||||
@ -13,6 +13,7 @@ class CustomSongs{
|
|||||||
|
|
||||||
if(noPage){
|
if(noPage){
|
||||||
this.noPage = true
|
this.noPage = true
|
||||||
|
this.noLoading = noLoading
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -262,11 +263,13 @@ class CustomSongs{
|
|||||||
|
|
||||||
var importSongs = new ImportSongs()
|
var importSongs = new ImportSongs()
|
||||||
return importSongs.load(files).then(this.songsLoaded.bind(this), e => {
|
return importSongs.load(files).then(this.songsLoaded.bind(this), e => {
|
||||||
this.browse.parentNode.reset()
|
if(!this.noPage){
|
||||||
|
this.browse.form.reset()
|
||||||
|
}
|
||||||
this.locked = false
|
this.locked = false
|
||||||
this.loading(false)
|
this.loading(false)
|
||||||
if(e === "nosongs"){
|
if(e === "nosongs"){
|
||||||
this.showError(strings.customSongs.noSongs)
|
this.showError(strings.customSongs.noSongs, "nosongs")
|
||||||
}else if(e !== "cancel"){
|
}else if(e !== "cancel"){
|
||||||
return Promise.reject(e)
|
return Promise.reject(e)
|
||||||
}
|
}
|
||||||
@ -308,7 +311,7 @@ class CustomSongs{
|
|||||||
this.locked = false
|
this.locked = false
|
||||||
this.loading(false)
|
this.loading(false)
|
||||||
if(e === "nosongs"){
|
if(e === "nosongs"){
|
||||||
this.showError(strings.customSongs.noSongs)
|
this.showError(strings.customSongs.noSongs, "nosongs")
|
||||||
}else if(e !== "cancel"){
|
}else if(e !== "cancel"){
|
||||||
return Promise.reject(e)
|
return Promise.reject(e)
|
||||||
}
|
}
|
||||||
@ -371,7 +374,7 @@ class CustomSongs{
|
|||||||
open("privacy")
|
open("privacy")
|
||||||
}
|
}
|
||||||
loading(show){
|
loading(show){
|
||||||
if(this.noPage){
|
if(this.noLoading){
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if(show){
|
if(show){
|
||||||
@ -387,14 +390,16 @@ class CustomSongs{
|
|||||||
assets.customSongs = true
|
assets.customSongs = true
|
||||||
assets.customSelected = this.noPage ? +localStorage.getItem("customSelected") : 0
|
assets.customSelected = this.noPage ? +localStorage.getItem("customSelected") : 0
|
||||||
}
|
}
|
||||||
if(!this.noPage){
|
if(this.noPage){
|
||||||
|
pageEvents.send("import-songs", length)
|
||||||
|
}else{
|
||||||
assets.sounds["se_don"].play()
|
assets.sounds["se_don"].play()
|
||||||
}
|
|
||||||
this.clean()
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
new SongSelect("customSongs", false, this.touchEnabled)
|
new SongSelect("customSongs", false, this.touchEnabled)
|
||||||
pageEvents.send("import-songs", length)
|
pageEvents.send("import-songs", length)
|
||||||
}, 500)
|
}, 500)
|
||||||
|
}
|
||||||
|
this.clean()
|
||||||
return songs && songs.length
|
return songs && songs.length
|
||||||
}
|
}
|
||||||
keyPressed(pressed, name){
|
keyPressed(pressed, name){
|
||||||
@ -474,10 +479,14 @@ class CustomSongs{
|
|||||||
resolve()
|
resolve()
|
||||||
}, 500))
|
}, 500))
|
||||||
}
|
}
|
||||||
showError(text){
|
showError(text, errorName){
|
||||||
this.locked = false
|
this.locked = false
|
||||||
this.loading(false)
|
this.loading(false)
|
||||||
if(this.noPage || this.mode === "error"){
|
if(this.noPage){
|
||||||
|
var error = new Error(text)
|
||||||
|
error.name = errorName
|
||||||
|
throw error
|
||||||
|
}else if(this.mode === "error"){
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.mode = "error"
|
this.mode = "error"
|
||||||
|
@ -159,7 +159,7 @@ class Gpicker{
|
|||||||
}
|
}
|
||||||
clientCallback(tokenResponse){
|
clientCallback(tokenResponse){
|
||||||
this.tokenResponse = tokenResponse
|
this.tokenResponse = tokenResponse
|
||||||
this.oauthToken = tokenResponse.access_token
|
this.oauthToken = tokenResponse && tokenResponse.access_token
|
||||||
if(this.oauthToken && this.tokenResolve){
|
if(this.oauthToken && this.tokenResolve){
|
||||||
this.tokenResolve()
|
this.tokenResolve()
|
||||||
}
|
}
|
||||||
@ -220,12 +220,12 @@ class Gpicker{
|
|||||||
.build()
|
.build()
|
||||||
.setVisible(true)
|
.setVisible(true)
|
||||||
}
|
}
|
||||||
downloadFile(id, arrayBuffer, retry){
|
downloadFile(id, responseType, retry){
|
||||||
var url = this.filesUrl + id + "?alt=media"
|
var url = this.filesUrl + id + "?alt=media"
|
||||||
return this.queue().then(this.getToken.bind(this)).then(() =>
|
return this.queue().then(this.getToken.bind(this)).then(() =>
|
||||||
loader.ajax(url, request => {
|
loader.ajax(url, request => {
|
||||||
if(arrayBuffer){
|
if(responseType){
|
||||||
request.responseType = "arraybuffer"
|
request.responseType = responseType
|
||||||
}
|
}
|
||||||
request.setRequestHeader("Authorization", "Bearer " + this.oauthToken)
|
request.setRequestHeader("Authorization", "Bearer " + this.oauthToken)
|
||||||
}, true).then(event => {
|
}, true).then(event => {
|
||||||
@ -238,7 +238,7 @@ class Gpicker{
|
|||||||
var e = response.error
|
var e = response.error
|
||||||
if(e && e.errors[0].reason === "authError"){
|
if(e && e.errors[0].reason === "authError"){
|
||||||
delete this.oauthToken
|
delete this.oauthToken
|
||||||
return this.downloadFile(id, arrayBuffer, true)
|
return this.downloadFile(id, responseType, true)
|
||||||
}else{
|
}else{
|
||||||
return reject()
|
return reject()
|
||||||
}
|
}
|
||||||
|
@ -61,12 +61,6 @@ class Loader{
|
|||||||
stylesheet.href = "/src/css/" + name + this.queryString
|
stylesheet.href = "/src/css/" + name + this.queryString
|
||||||
document.head.appendChild(stylesheet)
|
document.head.appendChild(stylesheet)
|
||||||
})
|
})
|
||||||
assets.assetsCss.forEach(name => {
|
|
||||||
var stylesheet = document.createElement("link")
|
|
||||||
stylesheet.rel = "stylesheet"
|
|
||||||
stylesheet.href = gameConfig.assets_baseurl + name + this.queryString
|
|
||||||
document.head.appendChild(stylesheet)
|
|
||||||
})
|
|
||||||
var checkStyles = () => {
|
var checkStyles = () => {
|
||||||
if(document.styleSheets.length >= cssCount){
|
if(document.styleSheets.length >= cssCount){
|
||||||
resolve()
|
resolve()
|
||||||
@ -84,9 +78,10 @@ class Loader{
|
|||||||
}), url)
|
}), url)
|
||||||
}
|
}
|
||||||
|
|
||||||
assets.img.forEach(name=>{
|
assets.img.forEach(name => {
|
||||||
var id = this.getFilename(name)
|
var id = this.getFilename(name)
|
||||||
var image = document.createElement("img")
|
var image = document.createElement("img")
|
||||||
|
image.crossOrigin = "anonymous"
|
||||||
var url = gameConfig.assets_baseurl + "img/" + name
|
var url = gameConfig.assets_baseurl + "img/" + name
|
||||||
this.addPromise(pageEvents.load(image), url)
|
this.addPromise(pageEvents.load(image), url)
|
||||||
image.id = name
|
image.id = name
|
||||||
@ -95,6 +90,37 @@ class Loader{
|
|||||||
assets.image[id] = image
|
assets.image[id] = image
|
||||||
})
|
})
|
||||||
|
|
||||||
|
var css = []
|
||||||
|
for(let selector in assets.cssBackground){
|
||||||
|
let name = assets.cssBackground[selector]
|
||||||
|
var url = gameConfig.assets_baseurl + "img/" + name
|
||||||
|
this.addPromise(loader.ajax(url, request => {
|
||||||
|
request.responseType = "blob"
|
||||||
|
}).then(blob => {
|
||||||
|
var id = this.getFilename(name)
|
||||||
|
var image = document.createElement("img")
|
||||||
|
let blobUrl = URL.createObjectURL(blob)
|
||||||
|
var promise = pageEvents.load(image).then(() => {
|
||||||
|
var gradient = ""
|
||||||
|
if(selector === ".pattern-bg"){
|
||||||
|
loader.screen.style.backgroundImage = "url(\"" + blobUrl + "\")"
|
||||||
|
}else if(selector === "#song-search"){
|
||||||
|
gradient = "linear-gradient(to top, rgba(245, 246, 252, 0.08), #ff5963), "
|
||||||
|
}
|
||||||
|
css.push(this.cssRuleset({
|
||||||
|
[selector]: {
|
||||||
|
"background-image": gradient + "url(\"" + blobUrl + "\")"
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
image.id = name
|
||||||
|
image.src = blobUrl
|
||||||
|
this.assetsDiv.appendChild(image)
|
||||||
|
assets.image[id] = image
|
||||||
|
return promise
|
||||||
|
}), url)
|
||||||
|
}
|
||||||
|
|
||||||
assets.views.forEach(name => {
|
assets.views.forEach(name => {
|
||||||
var id = this.getFilename(name)
|
var id = this.getFilename(name)
|
||||||
var url = "/src/views/" + name + this.queryString
|
var url = "/src/views/" + name + this.queryString
|
||||||
@ -147,6 +173,10 @@ class Loader{
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var style = document.createElement("style")
|
||||||
|
style.appendChild(document.createTextNode(css.join("\n")))
|
||||||
|
document.head.appendChild(style)
|
||||||
|
|
||||||
this.addPromise(this.ajax("/api/songs").then(songs => {
|
this.addPromise(this.ajax("/api/songs").then(songs => {
|
||||||
songs = JSON.parse(songs)
|
songs = JSON.parse(songs)
|
||||||
songs.forEach(song => {
|
songs.forEach(song => {
|
||||||
@ -179,16 +209,22 @@ class Loader{
|
|||||||
.filter(cat => cat.songSkin && cat.songSkin.bg_img)
|
.filter(cat => cat.songSkin && cat.songSkin.bg_img)
|
||||||
.forEach(cat => {
|
.forEach(cat => {
|
||||||
let name = cat.songSkin.bg_img
|
let name = cat.songSkin.bg_img
|
||||||
|
var url = gameConfig.assets_baseurl + "img/" + name
|
||||||
|
categoryPromises.push(loader.ajax(url, request => {
|
||||||
|
request.responseType = "blob"
|
||||||
|
}).then(blob => {
|
||||||
var id = this.getFilename(name)
|
var id = this.getFilename(name)
|
||||||
var image = document.createElement("img")
|
var image = document.createElement("img")
|
||||||
var url = gameConfig.assets_baseurl + "img/" + name
|
let blobUrl = URL.createObjectURL(blob)
|
||||||
categoryPromises.push(pageEvents.load(image).catch(response => {
|
var promise = pageEvents.load(image)
|
||||||
return this.errorMsg(response, url)
|
|
||||||
}))
|
|
||||||
image.id = name
|
image.id = name
|
||||||
image.src = url
|
image.src = blobUrl
|
||||||
this.assetsDiv.appendChild(image)
|
this.assetsDiv.appendChild(image)
|
||||||
assets.image[id] = image
|
assets.image[id] = image
|
||||||
|
return promise
|
||||||
|
}).catch(response => {
|
||||||
|
return this.errorMsg(response, url)
|
||||||
|
}))
|
||||||
})
|
})
|
||||||
this.addPromise(Promise.all(categoryPromises))
|
this.addPromise(Promise.all(categoryPromises))
|
||||||
|
|
||||||
@ -356,6 +392,7 @@ class Loader{
|
|||||||
this.canvasTest.clean()
|
this.canvasTest.clean()
|
||||||
this.clean()
|
this.clean()
|
||||||
this.callback(songId)
|
this.callback(songId)
|
||||||
|
this.ready = true
|
||||||
pageEvents.send("ready", readyEvent)
|
pageEvents.send("ready", readyEvent)
|
||||||
}, () => this.errorMsg())
|
}, () => this.errorMsg())
|
||||||
}, () => this.errorMsg())
|
}, () => this.errorMsg())
|
||||||
@ -407,7 +444,7 @@ class Loader{
|
|||||||
if(!lang){
|
if(!lang){
|
||||||
lang = "en"
|
lang = "en"
|
||||||
}
|
}
|
||||||
loader.screen.getElementsByClassName("view-content")[0].innerText = allStrings[lang].errorOccured
|
loader.screen.getElementsByClassName("view-content")[0].innerText = allStrings[lang] && allStrings[lang].errorOccured || allStrings.en.errorOccured
|
||||||
}
|
}
|
||||||
var loaderError = loader.screen.getElementsByClassName("loader-error-div")[0]
|
var loaderError = loader.screen.getElementsByClassName("loader-error-div")[0]
|
||||||
loaderError.style.display = "flex"
|
loaderError.style.display = "flex"
|
||||||
@ -472,6 +509,19 @@ class Loader{
|
|||||||
this.screen.innerHTML = assets.pages[name]
|
this.screen.innerHTML = assets.pages[name]
|
||||||
this.screen.classList[patternBg ? "add" : "remove"]("pattern-bg")
|
this.screen.classList[patternBg ? "add" : "remove"]("pattern-bg")
|
||||||
}
|
}
|
||||||
|
cssRuleset(rulesets){
|
||||||
|
var css = []
|
||||||
|
for(var selector in rulesets){
|
||||||
|
var declarationsObj = rulesets[selector]
|
||||||
|
var declarations = []
|
||||||
|
for(var property in declarationsObj){
|
||||||
|
var value = declarationsObj[property]
|
||||||
|
declarations.push("\t" + property + ": " + value + ";")
|
||||||
|
}
|
||||||
|
css.push(selector + "{\n" + declarations.join("\n") + "\n}")
|
||||||
|
}
|
||||||
|
return css.join("\n")
|
||||||
|
}
|
||||||
ajax(url, customRequest, customResponse){
|
ajax(url, customRequest, customResponse){
|
||||||
var request = new XMLHttpRequest()
|
var request = new XMLHttpRequest()
|
||||||
request.open("GET", url)
|
request.open("GET", url)
|
||||||
|
@ -103,8 +103,8 @@ class LoadSong{
|
|||||||
}
|
}
|
||||||
let img = document.createElement("img")
|
let img = document.createElement("img")
|
||||||
let force = imgLoad[i].type === "song" && this.touchEnabled
|
let force = imgLoad[i].type === "song" && this.touchEnabled
|
||||||
if(!songObj.custom && (this.imgScale !== 1 || force)){
|
if(!songObj.custom){
|
||||||
img.crossOrigin = "Anonymous"
|
img.crossOrigin = "anonymous"
|
||||||
}
|
}
|
||||||
let promise = pageEvents.load(img)
|
let promise = pageEvents.load(img)
|
||||||
this.addPromise(promise.then(() => {
|
this.addPromise(promise.then(() => {
|
||||||
@ -147,15 +147,30 @@ class LoadSong{
|
|||||||
}
|
}
|
||||||
if(this.touchEnabled && !assets.image["touch_drum"]){
|
if(this.touchEnabled && !assets.image["touch_drum"]){
|
||||||
let img = document.createElement("img")
|
let img = document.createElement("img")
|
||||||
if(this.imgScale !== 1){
|
img.crossOrigin = "anonymous"
|
||||||
img.crossOrigin = "Anonymous"
|
|
||||||
}
|
|
||||||
var url = gameConfig.assets_baseurl + "img/touch_drum.png"
|
var url = gameConfig.assets_baseurl + "img/touch_drum.png"
|
||||||
this.addPromise(pageEvents.load(img).then(() => {
|
this.addPromise(pageEvents.load(img).then(() => {
|
||||||
return this.scaleImg(img, "touch_drum", "")
|
return this.scaleImg(img, "touch_drum", "")
|
||||||
}), url)
|
}), url)
|
||||||
img.src = url
|
img.src = url
|
||||||
}
|
}
|
||||||
|
var resultsImg = [
|
||||||
|
"results_flowers",
|
||||||
|
"results_mikoshi",
|
||||||
|
"results_tetsuohana",
|
||||||
|
"results_tetsuohana2"
|
||||||
|
]
|
||||||
|
resultsImg.forEach(id => {
|
||||||
|
if(!assets.image[id]){
|
||||||
|
var img = document.createElement("img")
|
||||||
|
img.crossOrigin = "anonymous"
|
||||||
|
var url = gameConfig.assets_baseurl + "img/" + id + ".png"
|
||||||
|
this.addPromise(pageEvents.load(img).then(() => {
|
||||||
|
return this.scaleImg(img, id, "")
|
||||||
|
}), url)
|
||||||
|
img.src = url
|
||||||
|
}
|
||||||
|
})
|
||||||
if(songObj.volume && songObj.volume !== 1){
|
if(songObj.volume && songObj.volume !== 1){
|
||||||
this.promises.push(new Promise(resolve => setTimeout(resolve, 500)))
|
this.promises.push(new Promise(resolve => setTimeout(resolve, 500)))
|
||||||
}
|
}
|
||||||
@ -217,9 +232,7 @@ class LoadSong{
|
|||||||
if(!(filenameAb in assets.image)){
|
if(!(filenameAb in assets.image)){
|
||||||
let img = document.createElement("img")
|
let img = document.createElement("img")
|
||||||
let force = filenameAb.startsWith("bg_song_") && this.touchEnabled
|
let force = filenameAb.startsWith("bg_song_") && this.touchEnabled
|
||||||
if(this.imgScale !== 1 || force){
|
img.crossOrigin = "anonymous"
|
||||||
img.crossOrigin = "Anonymous"
|
|
||||||
}
|
|
||||||
var url = gameConfig.assets_baseurl + "img/" + filenameAb + ".png"
|
var url = gameConfig.assets_baseurl + "img/" + filenameAb + ".png"
|
||||||
this.addPromise(pageEvents.load(img).then(() => {
|
this.addPromise(pageEvents.load(img).then(() => {
|
||||||
return this.scaleImg(img, filenameAb, "", force)
|
return this.scaleImg(img, filenameAb, "", force)
|
||||||
@ -235,7 +248,6 @@ class LoadSong{
|
|||||||
if(force && scale > 0.5){
|
if(force && scale > 0.5){
|
||||||
scale = 0.5
|
scale = 0.5
|
||||||
}
|
}
|
||||||
if(scale !== 1){
|
|
||||||
var canvas = document.createElement("canvas")
|
var canvas = document.createElement("canvas")
|
||||||
var w = Math.floor(img.width * scale)
|
var w = Math.floor(img.width * scale)
|
||||||
var h = Math.floor(img.height * scale)
|
var h = Math.floor(img.height * scale)
|
||||||
@ -247,8 +259,10 @@ class LoadSong{
|
|||||||
let img2 = document.createElement("img")
|
let img2 = document.createElement("img")
|
||||||
pageEvents.load(img2).then(() => {
|
pageEvents.load(img2).then(() => {
|
||||||
assets.image[prefix + filename] = img2
|
assets.image[prefix + filename] = img2
|
||||||
|
loader.assetsDiv.appendChild(img2)
|
||||||
resolve()
|
resolve()
|
||||||
}, reject)
|
}, reject)
|
||||||
|
img2.id = prefix + filename
|
||||||
img2.src = url
|
img2.src = url
|
||||||
}
|
}
|
||||||
if("toBlob" in canvas){
|
if("toBlob" in canvas){
|
||||||
@ -258,10 +272,6 @@ class LoadSong{
|
|||||||
}else{
|
}else{
|
||||||
saveScaled(canvas.toDataURL())
|
saveScaled(canvas.toDataURL())
|
||||||
}
|
}
|
||||||
}else{
|
|
||||||
assets.image[prefix + filename] = img
|
|
||||||
resolve()
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
randInt(min, max){
|
randInt(min, max){
|
||||||
|
@ -582,6 +582,12 @@ class EditFunction extends EditValue{
|
|||||||
if(this.name){
|
if(this.name){
|
||||||
this.original = this.name[0][this.name[1]]
|
this.original = this.name[0][this.name[1]]
|
||||||
}
|
}
|
||||||
|
if(typeof this.original !== "function"){
|
||||||
|
console.error(this.loadCallback)
|
||||||
|
var error = new Error()
|
||||||
|
error.stack = "Error editing the function value of " + this.getName() + ": Original value is not a function"
|
||||||
|
throw error
|
||||||
|
}
|
||||||
var args = plugins.argsFromFunc(this.original)
|
var args = plugins.argsFromFunc(this.original)
|
||||||
try{
|
try{
|
||||||
var output = this.loadCallback(plugins.strFromFunc(this.original), args)
|
var output = this.loadCallback(plugins.strFromFunc(this.original), args)
|
||||||
@ -618,8 +624,13 @@ class EditFunction extends EditValue{
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Patch{
|
class Patch{
|
||||||
edits = []
|
constructor(...args){
|
||||||
addedLanguages = []
|
this.init(...args)
|
||||||
|
}
|
||||||
|
init(){
|
||||||
|
this.edits = []
|
||||||
|
this.addedLanguages = []
|
||||||
|
}
|
||||||
addEdits(...args){
|
addEdits(...args){
|
||||||
args.forEach(arg => this.edits.push(arg))
|
args.forEach(arg => this.edits.push(arg))
|
||||||
}
|
}
|
||||||
|
637
public/src/js/search.js
Normal file
637
public/src/js/search.js
Normal file
@ -0,0 +1,637 @@
|
|||||||
|
class Search{
|
||||||
|
constructor(...args){
|
||||||
|
this.init(...args)
|
||||||
|
}
|
||||||
|
init(songSelect){
|
||||||
|
this.songSelect = songSelect
|
||||||
|
this.opened = false
|
||||||
|
this.enabled = true
|
||||||
|
|
||||||
|
this.style = document.createElement("style")
|
||||||
|
var css = []
|
||||||
|
for(var i in this.songSelect.songSkin){
|
||||||
|
var skin = this.songSelect.songSkin[i]
|
||||||
|
if("id" in skin || i === "default"){
|
||||||
|
var id = "id" in skin ? ("cat" + skin.id) : i
|
||||||
|
|
||||||
|
css.push(loader.cssRuleset({
|
||||||
|
[".song-search-" + id]: {
|
||||||
|
"background-color": skin.background
|
||||||
|
},
|
||||||
|
[".song-search-" + id + "::before"]: {
|
||||||
|
"border-color": skin.border[0],
|
||||||
|
"border-bottom-color": skin.border[1],
|
||||||
|
"border-right-color": skin.border[1]
|
||||||
|
},
|
||||||
|
[".song-search-" + id + " .song-search-result-title::before, .song-search-" + id + " .song-search-result-subtitle::before"]: {
|
||||||
|
"-webkit-text-stroke-color": skin.outline
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.style.appendChild(document.createTextNode(css.join("\n")))
|
||||||
|
loader.screen.appendChild(this.style)
|
||||||
|
}
|
||||||
|
|
||||||
|
perform(query){
|
||||||
|
var results = []
|
||||||
|
var filters = {}
|
||||||
|
|
||||||
|
var querySplit = query.split(" ")
|
||||||
|
var editedSplit = query.split(" ")
|
||||||
|
querySplit.forEach(word => {
|
||||||
|
if(word.length > 0){
|
||||||
|
var parts = word.toLowerCase().split(":")
|
||||||
|
if(parts.length > 1){
|
||||||
|
switch(parts[0]){
|
||||||
|
case "easy":
|
||||||
|
case "normal":
|
||||||
|
case "hard":
|
||||||
|
case "oni":
|
||||||
|
case "ura":
|
||||||
|
var range = this.parseRange(parts[1])
|
||||||
|
if(range){
|
||||||
|
filters[parts[0]] = range
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case "extreme":
|
||||||
|
var range = this.parseRange(parts[1])
|
||||||
|
if(range){
|
||||||
|
filters.oni = this.parseRange(parts[1])
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case "clear":
|
||||||
|
case "silver":
|
||||||
|
case "gold":
|
||||||
|
case "genre":
|
||||||
|
case "lyrics":
|
||||||
|
case "creative":
|
||||||
|
case "played":
|
||||||
|
case "maker":
|
||||||
|
case "diverge":
|
||||||
|
case "random":
|
||||||
|
filters[parts[0]] = parts[1]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
editedSplit.splice(editedSplit.indexOf(word), 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
query = editedSplit.join(" ").trim().normalize("NFD").replace(/[\u0300-\u036f]/g, "")
|
||||||
|
|
||||||
|
var totalFilters = Object.keys(filters).length
|
||||||
|
var random = false
|
||||||
|
for(var i = 0; i < assets.songs.length; i++){
|
||||||
|
var song = assets.songs[i]
|
||||||
|
var passedFilters = 0
|
||||||
|
|
||||||
|
Object.keys(filters).forEach(filter => {
|
||||||
|
var value = filters[filter]
|
||||||
|
switch(filter){
|
||||||
|
case "easy":
|
||||||
|
case "normal":
|
||||||
|
case "hard":
|
||||||
|
case "oni":
|
||||||
|
case "ura":
|
||||||
|
if(song.courses[filter] && song.courses[filter].stars >= value.min && song.courses[filter].stars <= value.max){
|
||||||
|
passedFilters++
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case "clear":
|
||||||
|
case "silver":
|
||||||
|
case "gold":
|
||||||
|
if(value === "any"){
|
||||||
|
var score = scoreStorage.scores[song.hash]
|
||||||
|
scoreStorage.difficulty.forEach(difficulty => {
|
||||||
|
if(score && score[difficulty] && score[difficulty].crown && (filter === "clear" || score[difficulty].crown === filter)){
|
||||||
|
passedFilters++
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
var score = scoreStorage.scores[song.hash]
|
||||||
|
if(score && score[value] && score[value].crown && (filter === "clear" || score[value].crown === filter)){
|
||||||
|
passedFilters++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case "played":
|
||||||
|
var score = scoreStorage.scores[song.hash]
|
||||||
|
if((value === "yes" && score) || (value === "no" && !score)){
|
||||||
|
passedFilters++
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case "lyrics":
|
||||||
|
if((value === "yes" && song.lyrics) || (value === "no" && !song.lyrics)){
|
||||||
|
passedFilters++
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case "creative":
|
||||||
|
if((value === "yes" && song.maker) || (value === "no" && !song.maker)){
|
||||||
|
passedFilters++
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case "maker":
|
||||||
|
if(song.maker && song.maker.name.toLowerCase().includes(value.toLowerCase())){
|
||||||
|
passedFilters++
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case "genre":
|
||||||
|
var cat = assets.categories.find(cat => cat.id === song.category_id)
|
||||||
|
var aliases = cat.aliases ? cat.aliases.concat([cat.title]) : [cat.title]
|
||||||
|
|
||||||
|
if(aliases.find(alias => alias.toLowerCase() === value.toLowerCase())){
|
||||||
|
passedFilters++
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case "diverge":
|
||||||
|
var branch = Object.values(song.courses).find(course => course && course.branch)
|
||||||
|
if((value === "yes" && branch) || (value === "no" && !branch)){
|
||||||
|
passedFilters++
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case "random":
|
||||||
|
if(value === "yes" || value === "no"){
|
||||||
|
random = value === "yes"
|
||||||
|
passedFilters++
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if(passedFilters === totalFilters){
|
||||||
|
results.push(song)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var maxResults = totalFilters > 0 && !query ? 100 : 50
|
||||||
|
|
||||||
|
if(query){
|
||||||
|
results = fuzzysort.go(query, results, {
|
||||||
|
keys: ["titlePrepared", "subtitlePrepared"],
|
||||||
|
allowTypo: true,
|
||||||
|
limit: maxResults,
|
||||||
|
scoreFn: a => {
|
||||||
|
if(a[0]){
|
||||||
|
var score0 = a[0].score
|
||||||
|
a[0].ranges = this.indexesToRanges(a[0].indexes)
|
||||||
|
if(a[0].indexes.length > 1){
|
||||||
|
var rangeAmount = a[0].ranges.length
|
||||||
|
var lastIdx = -3
|
||||||
|
a[0].ranges.forEach(range => {
|
||||||
|
if(range[0] - lastIdx <= 2){
|
||||||
|
rangeAmount--
|
||||||
|
score0 -= 1000
|
||||||
|
}
|
||||||
|
lastIdx = range[1]
|
||||||
|
})
|
||||||
|
var index = a[0].target.toLowerCase().indexOf(query)
|
||||||
|
if(index !== -1){
|
||||||
|
a[0].ranges = [[index, index + query.length - 1]]
|
||||||
|
}else if(rangeAmount > a[0].indexes.length / 2){
|
||||||
|
score0 = -Infinity
|
||||||
|
a[0].ranges = null
|
||||||
|
}else if(rangeAmount !== 1){
|
||||||
|
score0 -= 9000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(a[1]){
|
||||||
|
var score1 = a[1].score - 1000
|
||||||
|
a[1].ranges = this.indexesToRanges(a[1].indexes)
|
||||||
|
if(a[1].indexes.length > 1){
|
||||||
|
var rangeAmount = a[1].ranges.length
|
||||||
|
var lastIdx = -3
|
||||||
|
a[1].ranges.forEach(range => {
|
||||||
|
if(range[0] - lastIdx <= 2){
|
||||||
|
rangeAmount--
|
||||||
|
score1 -= 1000
|
||||||
|
}
|
||||||
|
lastIdx = range[1]
|
||||||
|
})
|
||||||
|
var index = a[1].target.indexOf(query)
|
||||||
|
if(index !== -1){
|
||||||
|
a[1].ranges = [[index, index + query.length - 1]]
|
||||||
|
}else if(rangeAmount > a[1].indexes.length / 2){
|
||||||
|
score1 = -Infinity
|
||||||
|
a[1].ranges = null
|
||||||
|
}else if(rangeAmount !== 1){
|
||||||
|
score1 -= 9000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(a[0]){
|
||||||
|
return a[1] ? Math.max(score0, score1) : score0
|
||||||
|
}else{
|
||||||
|
return a[1] ? score1 : -Infinity
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}else{
|
||||||
|
results = results.slice(0, maxResults).map(result => {
|
||||||
|
return {obj: result}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if(random){
|
||||||
|
for(var i = results.length - 1; i > 0; i--){
|
||||||
|
var j = Math.floor(Math.random() * (i + 1))
|
||||||
|
var temp = results[i]
|
||||||
|
results[i] = results[j]
|
||||||
|
results[j] = temp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
|
createResult(result, resultWidth, fontSize){
|
||||||
|
var song = result.obj
|
||||||
|
var title = this.songSelect.getLocalTitle(song.title, song.title_lang)
|
||||||
|
var subtitle = this.songSelect.getLocalTitle(title === song.title ? song.subtitle : "", song.subtitle_lang)
|
||||||
|
|
||||||
|
var id = "default"
|
||||||
|
if(song.category_id){
|
||||||
|
var cat = assets.categories.find(cat => cat.id === song.category_id)
|
||||||
|
if(cat && "id" in cat){
|
||||||
|
id = "cat" + cat.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var resultDiv = document.createElement("div")
|
||||||
|
resultDiv.classList.add("song-search-result", "song-search-" + id)
|
||||||
|
resultDiv.dataset.songId = song.id
|
||||||
|
|
||||||
|
var resultInfoDiv = document.createElement("div")
|
||||||
|
resultInfoDiv.classList.add("song-search-result-info")
|
||||||
|
var resultInfoTitle = document.createElement("span")
|
||||||
|
resultInfoTitle.classList.add("song-search-result-title")
|
||||||
|
|
||||||
|
resultInfoTitle.appendChild(this.highlightResult(title, result[0]))
|
||||||
|
resultInfoTitle.setAttribute("alt", title)
|
||||||
|
|
||||||
|
resultInfoDiv.appendChild(resultInfoTitle)
|
||||||
|
|
||||||
|
if(subtitle){
|
||||||
|
resultInfoDiv.appendChild(document.createElement("br"))
|
||||||
|
var resultInfoSubtitle = document.createElement("span")
|
||||||
|
resultInfoSubtitle.classList.add("song-search-result-subtitle")
|
||||||
|
|
||||||
|
resultInfoSubtitle.appendChild(this.highlightResult(subtitle, result[1]))
|
||||||
|
resultInfoSubtitle.setAttribute("alt", subtitle)
|
||||||
|
|
||||||
|
resultInfoDiv.appendChild(resultInfoSubtitle)
|
||||||
|
}
|
||||||
|
|
||||||
|
resultDiv.appendChild(resultInfoDiv)
|
||||||
|
|
||||||
|
var courses = ["easy", "normal", "hard", "oni", "ura"]
|
||||||
|
courses.forEach(course => {
|
||||||
|
var courseDiv = document.createElement("div")
|
||||||
|
courseDiv.classList.add("song-search-result-course", "song-search-result-" + course)
|
||||||
|
if (song.courses[course]) {
|
||||||
|
var crown = "noclear"
|
||||||
|
if (scoreStorage.scores[song.hash]) {
|
||||||
|
if (scoreStorage.scores[song.hash][course]) {
|
||||||
|
crown = scoreStorage.scores[song.hash][course].crown || "noclear"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var courseCrown = document.createElement("div")
|
||||||
|
courseCrown.classList.add("song-search-result-crown", "song-search-result-" + crown)
|
||||||
|
var courseStars = document.createElement("div")
|
||||||
|
courseStars.classList.add("song-search-result-stars")
|
||||||
|
courseStars.innerText = song.courses[course].stars + "\u2605"
|
||||||
|
|
||||||
|
courseDiv.appendChild(courseCrown)
|
||||||
|
courseDiv.appendChild(courseStars)
|
||||||
|
} else {
|
||||||
|
courseDiv.classList.add("song-search-result-hidden")
|
||||||
|
}
|
||||||
|
|
||||||
|
resultDiv.appendChild(courseDiv)
|
||||||
|
})
|
||||||
|
|
||||||
|
this.songSelect.ctx.font = (1.2 * fontSize) + "px " + strings.font
|
||||||
|
var titleWidth = this.songSelect.ctx.measureText(title).width
|
||||||
|
var titleRatio = resultWidth / titleWidth
|
||||||
|
if(titleRatio < 1){
|
||||||
|
resultInfoTitle.style.transform = "scale(" + titleRatio + ", 1)"
|
||||||
|
}
|
||||||
|
if(subtitle){
|
||||||
|
this.songSelect.ctx.font = (0.8 * 1.2 * fontSize) + "px " + strings.font
|
||||||
|
var subtitleWidth = this.songSelect.ctx.measureText(subtitle).width
|
||||||
|
var subtitleRatio = resultWidth / subtitleWidth
|
||||||
|
if(subtitleRatio < 1){
|
||||||
|
resultInfoSubtitle.style.transform = "scale(" + subtitleRatio + ", 1)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultDiv
|
||||||
|
}
|
||||||
|
|
||||||
|
highlightResult(text, result){
|
||||||
|
var fragment = document.createDocumentFragment()
|
||||||
|
var ranges = (result ? result.ranges : null) || []
|
||||||
|
var lastIdx = 0
|
||||||
|
ranges.forEach(range => {
|
||||||
|
if(lastIdx !== range[0]){
|
||||||
|
fragment.appendChild(document.createTextNode(text.slice(lastIdx, range[0])))
|
||||||
|
}
|
||||||
|
var span = document.createElement("span")
|
||||||
|
span.classList.add("highlighted-text")
|
||||||
|
span.innerText = text.slice(range[0], range[1] + 1)
|
||||||
|
fragment.appendChild(span)
|
||||||
|
lastIdx = range[1] + 1
|
||||||
|
})
|
||||||
|
if(text.length !== lastIdx){
|
||||||
|
fragment.appendChild(document.createTextNode(text.slice(lastIdx)))
|
||||||
|
}
|
||||||
|
return fragment
|
||||||
|
}
|
||||||
|
|
||||||
|
setActive(idx){
|
||||||
|
this.songSelect.playSound("se_ka")
|
||||||
|
var active = this.div.querySelector(":scope .song-search-result-active")
|
||||||
|
if(active){
|
||||||
|
active.classList.remove("song-search-result-active")
|
||||||
|
}
|
||||||
|
|
||||||
|
if(idx === null){
|
||||||
|
this.active = null
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var el = this.results[idx]
|
||||||
|
this.input.blur()
|
||||||
|
el.classList.add("song-search-result-active")
|
||||||
|
this.scrollTo(el)
|
||||||
|
|
||||||
|
this.active = idx
|
||||||
|
}
|
||||||
|
|
||||||
|
display(fromButton=false){
|
||||||
|
if(!this.enabled){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if(this.opened){
|
||||||
|
return this.remove(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.opened = true
|
||||||
|
this.results = []
|
||||||
|
this.div = document.createElement("div")
|
||||||
|
this.div.innerHTML = assets.pages["search"]
|
||||||
|
|
||||||
|
this.container = this.div.querySelector(":scope #song-search-container")
|
||||||
|
if(this.touchEnabled){
|
||||||
|
this.container.classList.add("touch-enabled")
|
||||||
|
}
|
||||||
|
pageEvents.add(this.container, ["mousedown", "touchstart"], this.onClick.bind(this))
|
||||||
|
|
||||||
|
this.input = this.div.querySelector(":scope #song-search-input")
|
||||||
|
this.input.setAttribute("placeholder", strings.search.searchInput)
|
||||||
|
pageEvents.add(this.input, ["input"], this.onInput.bind(this))
|
||||||
|
|
||||||
|
this.songSelect.playSound("se_pause")
|
||||||
|
loader.screen.appendChild(this.div)
|
||||||
|
this.setTip()
|
||||||
|
cancelTouch = false
|
||||||
|
noResizeRoot = true
|
||||||
|
if(this.songSelect.songs[this.songSelect.selectedSong].courses){
|
||||||
|
snd.previewGain.setVolumeMul(0.5)
|
||||||
|
}else if(this.songSelect.bgmEnabled){
|
||||||
|
snd.musicGain.setVolumeMul(0.5)
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
this.input.focus()
|
||||||
|
this.input.setSelectionRange(0, this.input.value.length)
|
||||||
|
}, 10)
|
||||||
|
|
||||||
|
var lastQuery = localStorage.getItem("lastSearchQuery")
|
||||||
|
if(lastQuery){
|
||||||
|
this.input.value = lastQuery
|
||||||
|
this.input.dispatchEvent(new Event("input", {
|
||||||
|
value: lastQuery
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
remove(byUser=false){
|
||||||
|
if(this.opened){
|
||||||
|
this.opened = false
|
||||||
|
if(byUser){
|
||||||
|
this.songSelect.playSound("se_cancel")
|
||||||
|
}
|
||||||
|
|
||||||
|
pageEvents.remove(this.div.querySelector(":scope #song-search-container"),
|
||||||
|
["mousedown", "touchstart"])
|
||||||
|
pageEvents.remove(this.input, ["input"])
|
||||||
|
|
||||||
|
this.div.remove()
|
||||||
|
delete this.results
|
||||||
|
delete this.div
|
||||||
|
delete this.input
|
||||||
|
delete this.tip
|
||||||
|
delete this.active
|
||||||
|
cancelTouch = true
|
||||||
|
noResizeRoot = false
|
||||||
|
if(this.songSelect.songs[this.songSelect.selectedSong].courses){
|
||||||
|
snd.previewGain.setVolumeMul(1)
|
||||||
|
}else if(this.songSelect.bgmEnabled){
|
||||||
|
snd.musicGain.setVolumeMul(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setTip(tip, error=false){
|
||||||
|
if(this.tip){
|
||||||
|
this.tip.remove()
|
||||||
|
delete this.tip
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!tip){
|
||||||
|
tip = strings.search.tip + " " + strings.search.tips[Math.floor(Math.random() * strings.search.tips.length)]
|
||||||
|
}
|
||||||
|
|
||||||
|
var resultsDiv = this.div.querySelector(":scope #song-search-results")
|
||||||
|
resultsDiv.innerHTML = ""
|
||||||
|
this.results = []
|
||||||
|
|
||||||
|
this.tip = document.createElement("div")
|
||||||
|
this.tip.id = "song-search-tip"
|
||||||
|
this.tip.innerText = tip
|
||||||
|
this.div.querySelector(":scope #song-search").appendChild(this.tip)
|
||||||
|
|
||||||
|
if(error){
|
||||||
|
this.tip.classList.add("song-search-tip-error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
proceed(songId){
|
||||||
|
var song = this.songSelect.songs.find(song => song.id === songId)
|
||||||
|
this.remove()
|
||||||
|
this.songSelect.playBgm(false)
|
||||||
|
|
||||||
|
var songIndex = this.songSelect.songs.findIndex(song => song.id === songId)
|
||||||
|
this.songSelect.setSelectedSong(songIndex)
|
||||||
|
this.songSelect.toSelectDifficulty()
|
||||||
|
}
|
||||||
|
|
||||||
|
scrollTo(element){
|
||||||
|
var parentNode = element.parentNode
|
||||||
|
var selected = element.getBoundingClientRect()
|
||||||
|
var parent = parentNode.getBoundingClientRect()
|
||||||
|
var scrollY = parentNode.scrollTop
|
||||||
|
var selectedPosTop = selected.top - selected.height / 2
|
||||||
|
if(Math.floor(selectedPosTop) < Math.floor(parent.top)){
|
||||||
|
parentNode.scrollTop += selectedPosTop - parent.top
|
||||||
|
}else{
|
||||||
|
var selectedPosBottom = selected.top + selected.height * 1.5 - parent.top
|
||||||
|
if(Math.floor(selectedPosBottom) > Math.floor(parent.height)){
|
||||||
|
parentNode.scrollTop += selectedPosBottom - parent.height
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parseRange(string){
|
||||||
|
var range = string.split("-")
|
||||||
|
if(range.length == 1){
|
||||||
|
var min = parseInt(range[0]) || 0
|
||||||
|
return min > 0 ? {min: min, max: min} : false
|
||||||
|
} else if(range.length == 2){
|
||||||
|
var min = parseInt(range[0]) || 0
|
||||||
|
var max = parseInt(range[1]) || 0
|
||||||
|
return min > 0 && max > 0 ? {min: min, max: max} : false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
indexesToRanges(indexes){
|
||||||
|
var ranges = []
|
||||||
|
var range
|
||||||
|
indexes.forEach(idx => {
|
||||||
|
if(range && range[1] === idx - 1){
|
||||||
|
range[1] = idx
|
||||||
|
}else{
|
||||||
|
range = [idx, idx]
|
||||||
|
ranges.push(range)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return ranges
|
||||||
|
}
|
||||||
|
|
||||||
|
onInput(){
|
||||||
|
var text = this.input.value
|
||||||
|
localStorage.setItem("lastSearchQuery", text)
|
||||||
|
text = text.toLowerCase()
|
||||||
|
|
||||||
|
if(text.length === 0){
|
||||||
|
this.setTip()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var new_results = this.perform(text)
|
||||||
|
|
||||||
|
if(new_results.length === 0){
|
||||||
|
this.setTip(strings.search.noResults, true)
|
||||||
|
return
|
||||||
|
}else if(this.tip){
|
||||||
|
this.tip.remove()
|
||||||
|
delete this.tip
|
||||||
|
}
|
||||||
|
|
||||||
|
var resultsDiv = this.div.querySelector(":scope #song-search-results")
|
||||||
|
resultsDiv.innerHTML = ""
|
||||||
|
this.results = []
|
||||||
|
|
||||||
|
var fontSize = parseFloat(getComputedStyle(this.div.querySelector(":scope #song-search")).fontSize.slice(0, -2))
|
||||||
|
var resultsWidth = parseFloat(getComputedStyle(resultsDiv).width.slice(0, -2))
|
||||||
|
var vmin = Math.min(innerWidth, lastHeight) / 100
|
||||||
|
var courseWidth = Math.min(3 * fontSize * 1.2, 7 * vmin)
|
||||||
|
var resultWidth = resultsWidth - 1.8 * fontSize - 0.8 * fontSize - (courseWidth + 0.4 * fontSize * 1.2) * 5 - 0.6 * fontSize
|
||||||
|
|
||||||
|
this.songSelect.ctx.save()
|
||||||
|
|
||||||
|
var fragment = document.createDocumentFragment()
|
||||||
|
new_results.forEach(result => {
|
||||||
|
var result = this.createResult(result, resultWidth, fontSize)
|
||||||
|
fragment.appendChild(result)
|
||||||
|
this.results.push(result)
|
||||||
|
})
|
||||||
|
resultsDiv.appendChild(fragment)
|
||||||
|
|
||||||
|
this.songSelect.ctx.restore()
|
||||||
|
}
|
||||||
|
|
||||||
|
onClick(e){
|
||||||
|
if((e.target.id === "song-search-container" || e.target.id === "song-search-close") && e.which === 1){
|
||||||
|
this.remove(true)
|
||||||
|
}else if(e.which === 1){
|
||||||
|
var songEl = e.target.closest(".song-search-result")
|
||||||
|
if(songEl){
|
||||||
|
var songId = parseInt(songEl.dataset.songId)
|
||||||
|
this.proceed(songId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
keyPress(pressed, name, event, repeat){
|
||||||
|
if(name === "back" || (event && event.keyCode && event.keyCode === 70 && ctrl)) {
|
||||||
|
this.remove(true)
|
||||||
|
if(event){
|
||||||
|
event.preventDefault()
|
||||||
|
}
|
||||||
|
}else if(name === "down" && this.results.length){
|
||||||
|
if(this.input == document.activeElement && this.results){
|
||||||
|
this.setActive(0)
|
||||||
|
}else if(this.active === this.results.length - 1){
|
||||||
|
this.setActive(null)
|
||||||
|
this.input.focus()
|
||||||
|
}else if(Number.isInteger(this.active)){
|
||||||
|
this.setActive(this.active + 1)
|
||||||
|
}else{
|
||||||
|
this.setActive(0)
|
||||||
|
}
|
||||||
|
}else if(name === "up" && this.results.length){
|
||||||
|
if(this.input == document.activeElement && this.results){
|
||||||
|
this.setActive(this.results.length - 1)
|
||||||
|
}else if(this.active === 0){
|
||||||
|
this.setActive(null)
|
||||||
|
this.input.focus()
|
||||||
|
setTimeout(() => {
|
||||||
|
this.input.setSelectionRange(this.input.value.length, this.input.value.length)
|
||||||
|
}, 0)
|
||||||
|
}else if(Number.isInteger(this.active)){
|
||||||
|
this.setActive(this.active - 1)
|
||||||
|
}else{
|
||||||
|
this.setActive(this.results.length - 1)
|
||||||
|
}
|
||||||
|
}else if(name === "confirm"){
|
||||||
|
if(Number.isInteger(this.active)){
|
||||||
|
this.proceed(parseInt(this.results[this.active].dataset.songId))
|
||||||
|
}else{
|
||||||
|
this.onInput()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
redraw(){
|
||||||
|
if(this.opened && this.container){
|
||||||
|
var vmin = Math.min(innerWidth, lastHeight) / 100
|
||||||
|
if(this.vmin !== vmin){
|
||||||
|
this.container.style.setProperty("--vmin", vmin + "px")
|
||||||
|
this.vmin = vmin
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
this.vmin = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clean(){
|
||||||
|
loader.screen.removeChild(this.style)
|
||||||
|
fuzzysort.cleanup()
|
||||||
|
delete this.container
|
||||||
|
delete this.style
|
||||||
|
delete this.songSelect
|
||||||
|
}
|
||||||
|
}
|
@ -217,15 +217,18 @@ class SettingsView{
|
|||||||
constructor(...args){
|
constructor(...args){
|
||||||
this.init(...args)
|
this.init(...args)
|
||||||
}
|
}
|
||||||
init(touchEnabled, tutorial, songId, toSetting, settingsItems){
|
init(touchEnabled, tutorial, songId, toSetting, settingsItems, noSoundStart){
|
||||||
this.touchEnabled = touchEnabled
|
this.touchEnabled = touchEnabled
|
||||||
this.tutorial = tutorial
|
this.tutorial = tutorial
|
||||||
this.songId = songId
|
this.songId = songId
|
||||||
this.customSettings = !!settingsItems
|
this.customSettings = !!settingsItems
|
||||||
this.settingsItems = settingsItems || settings.items
|
this.settingsItems = settingsItems || settings.items
|
||||||
|
this.locked = false
|
||||||
|
|
||||||
loader.changePage("settings", tutorial)
|
loader.changePage("settings", tutorial)
|
||||||
|
if(!noSoundStart){
|
||||||
assets.sounds["bgm_settings"].playLoop(0.1, false, 0, 1.392, 26.992)
|
assets.sounds["bgm_settings"].playLoop(0.1, false, 0, 1.392, 26.992)
|
||||||
|
}
|
||||||
this.defaultButton = document.getElementById("settings-default")
|
this.defaultButton = document.getElementById("settings-default")
|
||||||
this.viewOuter = this.getElement("view-outer")
|
this.viewOuter = this.getElement("view-outer")
|
||||||
if(touchEnabled){
|
if(touchEnabled){
|
||||||
@ -377,16 +380,48 @@ class SettingsView{
|
|||||||
this.items.push(outputObject)
|
this.items.push(outputObject)
|
||||||
this.getValue(i, valueDiv)
|
this.getValue(i, valueDiv)
|
||||||
}
|
}
|
||||||
|
var selectBack = this.items.length === 0
|
||||||
|
if(this.customSettings){
|
||||||
|
var form = document.createElement("form")
|
||||||
|
this.browse = document.createElement("input")
|
||||||
|
this.browse.id = "browse"
|
||||||
|
this.browse.type = "file"
|
||||||
|
this.browse.multiple = true
|
||||||
|
this.browse.accept = ".taikoweb.js"
|
||||||
|
pageEvents.add(this.browse, "change", this.browseChange.bind(this))
|
||||||
|
form.appendChild(this.browse)
|
||||||
|
loader.screen.appendChild(form)
|
||||||
|
this.browseButton = document.createElement("div")
|
||||||
|
this.browseButton.classList.add("taibtn", "stroke-sub")
|
||||||
|
this.defaultButton.parentNode.insertBefore(this.browseButton, this.defaultButton)
|
||||||
|
this.items.push({
|
||||||
|
id: "browse",
|
||||||
|
settingBox: this.browseButton
|
||||||
|
})
|
||||||
|
this.addTouch(this.browseButton, () => {
|
||||||
|
this.playSound("se_don")
|
||||||
|
this.browse.click()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.showDefault = !this.customSettings || plugins.allPlugins.filter(obj => obj.plugin.imported).length
|
||||||
|
if(this.showDefault){
|
||||||
this.items.push({
|
this.items.push({
|
||||||
id: "default",
|
id: "default",
|
||||||
settingBox: this.defaultButton
|
settingBox: this.defaultButton
|
||||||
})
|
})
|
||||||
this.addTouch(this.defaultButton, this.defaultSettings.bind(this))
|
this.addTouch(this.defaultButton, this.defaultSettings.bind(this))
|
||||||
|
}else{
|
||||||
|
this.defaultButton.parentNode.removeChild(this.defaultButton)
|
||||||
|
}
|
||||||
this.items.push({
|
this.items.push({
|
||||||
id: "back",
|
id: "back",
|
||||||
settingBox: this.endButton
|
settingBox: this.endButton
|
||||||
})
|
})
|
||||||
this.addTouch(this.endButton, this.onEnd.bind(this))
|
this.addTouch(this.endButton, this.onEnd.bind(this))
|
||||||
|
if(selectBack){
|
||||||
|
this.selected = this.items.length - 1
|
||||||
|
this.endButton.classList.add("selected")
|
||||||
|
}
|
||||||
|
|
||||||
if(!this.customSettings){
|
if(!this.customSettings){
|
||||||
this.gamepadSettings = document.getElementById("settings-gamepad")
|
this.gamepadSettings = document.getElementById("settings-gamepad")
|
||||||
@ -606,6 +641,9 @@ class SettingsView{
|
|||||||
valueDiv.innerText = value
|
valueDiv.innerText = value
|
||||||
}
|
}
|
||||||
setValue(name){
|
setValue(name){
|
||||||
|
if(this.locked){
|
||||||
|
return
|
||||||
|
}
|
||||||
var promise
|
var promise
|
||||||
var current = this.settingsItems[name]
|
var current = this.settingsItems[name]
|
||||||
if(current.getItem){
|
if(current.getItem){
|
||||||
@ -674,6 +712,9 @@ class SettingsView{
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
keyPressed(pressed, name, event, repeat){
|
keyPressed(pressed, name, event, repeat){
|
||||||
|
if(this.locked){
|
||||||
|
return
|
||||||
|
}
|
||||||
if(pressed){
|
if(pressed){
|
||||||
if(!this.pressedKeys[name]){
|
if(!this.pressedKeys[name]){
|
||||||
this.pressedKeys[name] = this.getMS() + 300
|
this.pressedKeys[name] = this.getMS() + 300
|
||||||
@ -693,6 +734,11 @@ class SettingsView{
|
|||||||
this.onEnd()
|
this.onEnd()
|
||||||
}else if(selected.id === "default"){
|
}else if(selected.id === "default"){
|
||||||
this.defaultSettings()
|
this.defaultSettings()
|
||||||
|
}else if(selected.id === "browse"){
|
||||||
|
if(event){
|
||||||
|
this.playSound("se_don")
|
||||||
|
this.browse.click()
|
||||||
|
}
|
||||||
}else{
|
}else{
|
||||||
this.setValue(selected.id)
|
this.setValue(selected.id)
|
||||||
}
|
}
|
||||||
@ -700,7 +746,7 @@ class SettingsView{
|
|||||||
selected.settingBox.classList.remove("selected")
|
selected.settingBox.classList.remove("selected")
|
||||||
do{
|
do{
|
||||||
this.selected = this.mod(this.items.length, this.selected + ((name === "right" || name === "down") ? 1 : -1))
|
this.selected = this.mod(this.items.length, this.selected + ((name === "right" || name === "down") ? 1 : -1))
|
||||||
}while(this.items[this.selected].id === "default" && name !== "left")
|
}while((this.items[this.selected].id === "default" || this.items[this.selected].id === "browse") && name !== "left")
|
||||||
selected = this.items[this.selected]
|
selected = this.items[this.selected]
|
||||||
selected.settingBox.classList.add("selected")
|
selected.settingBox.classList.add("selected")
|
||||||
this.scrollTo(selected.settingBox)
|
this.scrollTo(selected.settingBox)
|
||||||
@ -1027,7 +1073,9 @@ class SettingsView{
|
|||||||
defaultSettings(){
|
defaultSettings(){
|
||||||
if(this.customSettings){
|
if(this.customSettings){
|
||||||
plugins.unloadImported()
|
plugins.unloadImported()
|
||||||
return this.onEnd()
|
this.clean(true)
|
||||||
|
this.playSound("se_don")
|
||||||
|
return setTimeout(() => this.restart(), 500)
|
||||||
}
|
}
|
||||||
if(this.mode === "keyboard"){
|
if(this.mode === "keyboard"){
|
||||||
this.keyboardBack(this.items[this.selected])
|
this.keyboardBack(this.items[this.selected])
|
||||||
@ -1046,6 +1094,31 @@ class SettingsView{
|
|||||||
this.drumSounds = settings.getItem("latency").drumSounds
|
this.drumSounds = settings.getItem("latency").drumSounds
|
||||||
this.playSound("se_don")
|
this.playSound("se_don")
|
||||||
}
|
}
|
||||||
|
browseChange(event){
|
||||||
|
this.locked = true
|
||||||
|
var files = []
|
||||||
|
for(var i = 0; i < event.target.files.length; i++){
|
||||||
|
files.push(new LocalFile(event.target.files[i]))
|
||||||
|
}
|
||||||
|
var customSongs = new CustomSongs(this.touchEnabled, true)
|
||||||
|
customSongs.importLocal(files).then(() => {
|
||||||
|
this.clean(true)
|
||||||
|
return this.restart()
|
||||||
|
}).catch(e => {
|
||||||
|
if(e){
|
||||||
|
var message = e.message
|
||||||
|
if(e.name === "nosongs"){
|
||||||
|
message = strings.plugins.noPlugins
|
||||||
|
}
|
||||||
|
if(message){
|
||||||
|
alert(message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.locked = false
|
||||||
|
this.browse.form.reset()
|
||||||
|
return Promise.resolve()
|
||||||
|
})
|
||||||
|
}
|
||||||
onEnd(){
|
onEnd(){
|
||||||
if(this.mode === "number"){
|
if(this.mode === "number"){
|
||||||
this.numberBack(this.items[this.selected])
|
this.numberBack(this.items[this.selected])
|
||||||
@ -1063,6 +1136,12 @@ class SettingsView{
|
|||||||
}
|
}
|
||||||
}, 500)
|
}, 500)
|
||||||
}
|
}
|
||||||
|
restart(){
|
||||||
|
if(this.mode === "number"){
|
||||||
|
this.numberBack(this.items[this.selected])
|
||||||
|
}
|
||||||
|
return new SettingsView(this.touchEnabled, this.tutorial, this.songId, undefined, this.customSettings ? plugins.getSettings() : undefined, true)
|
||||||
|
}
|
||||||
getLocalTitle(title, titleLang){
|
getLocalTitle(title, titleLang){
|
||||||
if(titleLang){
|
if(titleLang){
|
||||||
for(var id in titleLang){
|
for(var id in titleLang){
|
||||||
@ -1109,15 +1188,19 @@ class SettingsView{
|
|||||||
setStrings(){
|
setStrings(){
|
||||||
this.setAltText(this.viewTitle, this.customSettings ? strings.plugins.title : strings.gameSettings)
|
this.setAltText(this.viewTitle, this.customSettings ? strings.plugins.title : strings.gameSettings)
|
||||||
this.setAltText(this.endButton, strings.settings.ok)
|
this.setAltText(this.endButton, strings.settings.ok)
|
||||||
if(!this.customSettings){
|
if(this.customSettings){
|
||||||
|
this.setAltText(this.browseButton, strings.plugins.browse)
|
||||||
|
}else{
|
||||||
this.setAltText(this.gamepadTitle, strings.settings.gamepadLayout.name)
|
this.setAltText(this.gamepadTitle, strings.settings.gamepadLayout.name)
|
||||||
this.setAltText(this.gamepadEndButton, strings.settings.ok)
|
this.setAltText(this.gamepadEndButton, strings.settings.ok)
|
||||||
this.setAltText(this.latencyTitle, strings.settings.latency.name)
|
this.setAltText(this.latencyTitle, strings.settings.latency.name)
|
||||||
this.setAltText(this.latencyDefaultButton, strings.settings.default)
|
this.setAltText(this.latencyDefaultButton, strings.settings.default)
|
||||||
this.setAltText(this.latencyEndButton, strings.settings.ok)
|
this.setAltText(this.latencyEndButton, strings.settings.ok)
|
||||||
}
|
}
|
||||||
|
if(this.showDefault){
|
||||||
this.setAltText(this.defaultButton, this.customSettings ? strings.plugins.unloadAll : strings.settings.default)
|
this.setAltText(this.defaultButton, this.customSettings ? strings.plugins.unloadAll : strings.settings.default)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
setAltText(element, text){
|
setAltText(element, text){
|
||||||
element.innerText = text
|
element.innerText = text
|
||||||
element.setAttribute("alt", text)
|
element.setAttribute("alt", text)
|
||||||
@ -1154,11 +1237,13 @@ class SettingsView{
|
|||||||
getMS(){
|
getMS(){
|
||||||
return Date.now()
|
return Date.now()
|
||||||
}
|
}
|
||||||
clean(){
|
clean(noSoundStop){
|
||||||
this.redrawRunning = false
|
this.redrawRunning = false
|
||||||
this.keyboard.clean()
|
this.keyboard.clean()
|
||||||
this.gamepad.clean()
|
this.gamepad.clean()
|
||||||
|
if(!noSoundStop){
|
||||||
assets.sounds["bgm_settings"].stop()
|
assets.sounds["bgm_settings"].stop()
|
||||||
|
}
|
||||||
pageEvents.remove(window, ["mouseup", "touchstart", "touchmove", "touchend", "blur"], this.windowSymbol)
|
pageEvents.remove(window, ["mouseup", "touchstart", "touchmove", "touchend", "blur"], this.windowSymbol)
|
||||||
if(this.customSettings){
|
if(this.customSettings){
|
||||||
pageEvents.remove(window, "language-change", this.windowSymbol)
|
pageEvents.remove(window, "language-change", this.windowSymbol)
|
||||||
@ -1176,7 +1261,12 @@ class SettingsView{
|
|||||||
if(this.defaultButton){
|
if(this.defaultButton){
|
||||||
delete this.defaultButton
|
delete this.defaultButton
|
||||||
}
|
}
|
||||||
if(!this.customSettings){
|
if(this.customSettings){
|
||||||
|
pageEvents.remove(this.browse, "change")
|
||||||
|
this.removeTouch(this.browseButton)
|
||||||
|
delete this.browse
|
||||||
|
delete this.browseButton
|
||||||
|
}else{
|
||||||
this.removeTouch(this.gamepadSettings)
|
this.removeTouch(this.gamepadSettings)
|
||||||
this.removeTouch(this.gamepadEndButton)
|
this.removeTouch(this.gamepadEndButton)
|
||||||
this.removeTouch(this.gamepadBox)
|
this.removeTouch(this.gamepadBox)
|
||||||
@ -1204,8 +1294,12 @@ class SettingsView{
|
|||||||
delete this.latencyEndButton
|
delete this.latencyEndButton
|
||||||
if(this.resolution !== settings.getItem("resolution")){
|
if(this.resolution !== settings.getItem("resolution")){
|
||||||
for(var i in assets.image){
|
for(var i in assets.image){
|
||||||
if(i === "touch_drum" || i.startsWith("bg_song_") || i.startsWith("bg_stage_") || i.startsWith("bg_don_")){
|
if(i === "touch_drum" || i.startsWith("bg_song_") || i.startsWith("bg_stage_") || i.startsWith("bg_don_") || i.startsWith("results_")){
|
||||||
URL.revokeObjectURL(assets.image[i].src)
|
var img = assets.image[i]
|
||||||
|
URL.revokeObjectURL(img.src)
|
||||||
|
if(img.parentNode){
|
||||||
|
img.parentNode.removeChild(img)
|
||||||
|
}
|
||||||
delete assets.image[i]
|
delete assets.image[i]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -92,22 +92,6 @@ 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 => {
|
|
||||||
var skin = this.songSkin[key]
|
|
||||||
if("id" in skin || key === "default"){
|
|
||||||
var id = "id" in skin ? ("cat" + skin.id) : key
|
|
||||||
|
|
||||||
searchCss.push('.song-search-' + id + ' { background-color: ' + skin.background + ' }')
|
|
||||||
searchCss.push('.song-search-' + id + '::before { border: 0.4em solid ' + skin.border[0] + ' ; border-bottom-color: ' + skin.border[1] + ' ; border-right-color: ' + skin.border[1] + ' }')
|
|
||||||
searchCss.push('.song-search-' + id + ' .song-search-result-title::before { -webkit-text-stroke: 0.4em ' + skin.outline + ' }')
|
|
||||||
searchCss.push('.song-search-' + id + ' .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
|
||||||
|
|
||||||
this.songs = []
|
this.songs = []
|
||||||
@ -194,14 +178,12 @@ class SongSelect{
|
|||||||
category: strings.random
|
category: strings.random
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if(plugins.hasSettings()){
|
|
||||||
this.songs.push({
|
this.songs.push({
|
||||||
title: strings.plugins.title,
|
title: strings.plugins.title,
|
||||||
skin: this.songSkin.plugins,
|
skin: this.songSkin.plugins,
|
||||||
action: "plugins",
|
action: "plugins",
|
||||||
category: strings.random
|
category: strings.random
|
||||||
})
|
})
|
||||||
}
|
|
||||||
|
|
||||||
this.songs.push({
|
this.songs.push({
|
||||||
title: strings.back,
|
title: strings.back,
|
||||||
@ -246,6 +228,8 @@ class SongSelect{
|
|||||||
this.currentSongCache = new CanvasCache(noSmoothing)
|
this.currentSongCache = new CanvasCache(noSmoothing)
|
||||||
this.nameplateCache = new CanvasCache(noSmoothing)
|
this.nameplateCache = new CanvasCache(noSmoothing)
|
||||||
|
|
||||||
|
this.search = new Search(this)
|
||||||
|
|
||||||
this.difficulty = [strings.easy, strings.normal, strings.hard, strings.oni]
|
this.difficulty = [strings.easy, strings.normal, strings.hard, strings.oni]
|
||||||
this.difficultyId = ["easy", "normal", "hard", "oni", "ura"]
|
this.difficultyId = ["easy", "normal", "hard", "oni", "ura"]
|
||||||
|
|
||||||
@ -257,7 +241,6 @@ class SongSelect{
|
|||||||
this.selectedSong = 0
|
this.selectedSong = 0
|
||||||
this.selectedDiff = 0
|
this.selectedDiff = 0
|
||||||
this.lastCurrentSong = {}
|
this.lastCurrentSong = {}
|
||||||
this.searchEnabled = true
|
|
||||||
this.lastRandom = false
|
this.lastRandom = false
|
||||||
assets.sounds["bgm_songsel"].playLoop(0.1, false, 0, 1.442, 3.506)
|
assets.sounds["bgm_songsel"].playLoop(0.1, false, 0, 1.442, 3.506)
|
||||||
|
|
||||||
@ -434,44 +417,14 @@ class SongSelect{
|
|||||||
this.state.showWarning = false
|
this.state.showWarning = false
|
||||||
this.showWarning = false
|
this.showWarning = false
|
||||||
}
|
}
|
||||||
}else if (this.search){
|
}else if(this.search.opened){
|
||||||
if(name === "back" || (event && event.keyCode && event.keyCode === 70 && ctrl)) {
|
this.search.keyPress(pressed, name, event, repeat)
|
||||||
this.removeSearch(true)
|
|
||||||
if(event){ event.preventDefault() }
|
|
||||||
}else if(name === "down" && this.search.results.length){
|
|
||||||
if(this.search.input == document.activeElement && this.search.results){
|
|
||||||
this.searchSetActive(0)
|
|
||||||
}else if(this.search.active === this.search.results.length-1){
|
|
||||||
this.searchSetActive(null)
|
|
||||||
this.search.input.focus()
|
|
||||||
}else if(Number.isInteger(this.search.active)){
|
|
||||||
this.searchSetActive(this.search.active+1)
|
|
||||||
}else{
|
|
||||||
this.searchSetActive(0)
|
|
||||||
}
|
|
||||||
}else if(name === "up" && this.search.results.length){
|
|
||||||
if(this.search.input == document.activeElement && this.search.results){
|
|
||||||
this.searchSetActive(this.search.results.length-1)
|
|
||||||
}else if(this.search.active === 0){
|
|
||||||
this.searchSetActive(null)
|
|
||||||
this.search.input.focus()
|
|
||||||
setTimeout(() => {
|
|
||||||
this.search.input.setSelectionRange(this.search.input.value.length, this.search.input.value.length)
|
|
||||||
}, 0)
|
|
||||||
}else if(Number.isInteger(this.search.active)){
|
|
||||||
this.searchSetActive(this.search.active-1)
|
|
||||||
}else{
|
|
||||||
this.searchSetActive(this.search.results.length-1)
|
|
||||||
}
|
|
||||||
}else if(name === "confirm"){
|
|
||||||
if(Number.isInteger(this.search.active)){
|
|
||||||
this.searchProceed(parseInt(this.search.results[this.search.active].dataset.songId))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}else if(this.state.screen === "song"){
|
}else if(this.state.screen === "song"){
|
||||||
if(event && event.keyCode && event.keyCode === 70 && ctrl){
|
if(event && event.keyCode && event.keyCode === 70 && ctrl){
|
||||||
this.displaySearch()
|
this.search.display()
|
||||||
if(event){ event.preventDefault() }
|
if(event){
|
||||||
|
event.preventDefault()
|
||||||
|
}
|
||||||
}else if(name === "confirm"){
|
}else if(name === "confirm"){
|
||||||
this.toSelectDifficulty()
|
this.toSelectDifficulty()
|
||||||
}else if(name === "back"){
|
}else if(name === "back"){
|
||||||
@ -504,8 +457,10 @@ class SongSelect{
|
|||||||
}
|
}
|
||||||
}else if(this.state.screen === "difficulty"){
|
}else if(this.state.screen === "difficulty"){
|
||||||
if(event && event.keyCode && event.keyCode === 70 && ctrl){
|
if(event && event.keyCode && event.keyCode === 70 && ctrl){
|
||||||
this.displaySearch()
|
this.search.display()
|
||||||
if(event){ event.preventDefault() }
|
if(event){
|
||||||
|
event.preventDefault()
|
||||||
|
}
|
||||||
}else if(name === "confirm"){
|
}else if(name === "confirm"){
|
||||||
if(this.selectedDiff === 0){
|
if(this.selectedDiff === 0){
|
||||||
this.toSongSelect()
|
this.toSongSelect()
|
||||||
@ -528,8 +483,10 @@ class SongSelect{
|
|||||||
}
|
}
|
||||||
}else if(this.state.screen === "title" || this.state.screen === "titleFadeIn"){
|
}else if(this.state.screen === "title" || this.state.screen === "titleFadeIn"){
|
||||||
if(event && event.keyCode && event.keyCode === 70 && ctrl){
|
if(event && event.keyCode && event.keyCode === 70 && ctrl){
|
||||||
this.displaySearch()
|
this.search.display()
|
||||||
if(event){ event.preventDefault() }
|
if(event){
|
||||||
|
event.preventDefault()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -627,7 +584,7 @@ class SongSelect{
|
|||||||
if(408 < mouse.x && mouse.x < 872 && 470 < mouse.y && mouse.y < 550){
|
if(408 < mouse.x && mouse.x < 872 && 470 < mouse.y && mouse.y < 550){
|
||||||
moveTo = "showWarning"
|
moveTo = "showWarning"
|
||||||
}
|
}
|
||||||
}else if(this.state.screen === "song" && !this.search){
|
}else if(this.state.screen === "song" && !this.search.opened){
|
||||||
if(20 < mouse.y && mouse.y < 90 && 410 < mouse.x && mouse.x < 880 && (mouse.x < 540 || mouse.x > 750)){
|
if(20 < mouse.y && mouse.y < 90 && 410 < mouse.x && mouse.x < 880 && (mouse.x < 540 || mouse.x > 750)){
|
||||||
moveTo = mouse.x < 640 ? "categoryPrev" : "categoryNext"
|
moveTo = mouse.x < 640 ? "categoryPrev" : "categoryNext"
|
||||||
}else if(!p2.session && 60 < mouse.x && mouse.x < 332 && 640 < mouse.y && mouse.y < 706 && gameConfig.accounts){
|
}else if(!p2.session && 60 < mouse.x && mouse.x < 332 && 640 < mouse.y && mouse.y < 706 && gameConfig.accounts){
|
||||||
@ -792,7 +749,7 @@ class SongSelect{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}else if(this.state.locked === 0 || fromP2){
|
}else if(this.state.locked === 0 || fromP2){
|
||||||
this.removeSearch()
|
this.search.remove()
|
||||||
if(currentSong.courses){
|
if(currentSong.courses){
|
||||||
if(currentSong.unloaded){
|
if(currentSong.unloaded){
|
||||||
return
|
return
|
||||||
@ -815,7 +772,6 @@ class SongSelect{
|
|||||||
}
|
}
|
||||||
pageEvents.send("song-select-difficulty", currentSong)
|
pageEvents.send("song-select-difficulty", currentSong)
|
||||||
}else if(currentSong.action === "back"){
|
}else if(currentSong.action === "back"){
|
||||||
this.clean()
|
|
||||||
this.toTitleScreen()
|
this.toTitleScreen()
|
||||||
}else if(currentSong.action === "random"){
|
}else if(currentSong.action === "random"){
|
||||||
do{
|
do{
|
||||||
@ -827,7 +783,7 @@ class SongSelect{
|
|||||||
this.toSelectDifficulty(false, playVoice=false)
|
this.toSelectDifficulty(false, playVoice=false)
|
||||||
pageEvents.send("song-select-random")
|
pageEvents.send("song-select-random")
|
||||||
}else if(currentSong.action === "search"){
|
}else if(currentSong.action === "search"){
|
||||||
this.displaySearch(true)
|
this.search.display(true)
|
||||||
}else if(currentSong.action === "tutorial"){
|
}else if(currentSong.action === "tutorial"){
|
||||||
this.toTutorial()
|
this.toTutorial()
|
||||||
}else if(currentSong.action === "about"){
|
}else if(currentSong.action === "about"){
|
||||||
@ -1116,8 +1072,8 @@ class SongSelect{
|
|||||||
|
|
||||||
this.selectableText = ""
|
this.selectableText = ""
|
||||||
|
|
||||||
if(this.search && this.searchContainer){
|
if(this.search.opened && this.search.container){
|
||||||
this.searchInput()
|
this.search.onInput()
|
||||||
}
|
}
|
||||||
}else if(!document.hasFocus() && !p2.session){
|
}else if(!document.hasFocus() && !p2.session){
|
||||||
if(this.state.focused){
|
if(this.state.focused){
|
||||||
@ -1146,15 +1102,7 @@ class SongSelect{
|
|||||||
var screen = this.state.screen
|
var screen = this.state.screen
|
||||||
var selectedWidth = this.songAsset.width
|
var selectedWidth = this.songAsset.width
|
||||||
|
|
||||||
if(this.search && this.searchContainer){
|
this.search.redraw()
|
||||||
var vmin = Math.min(innerWidth, lastHeight) / 100
|
|
||||||
if(this.vmin !== vmin){
|
|
||||||
this.searchContainer.style.setProperty("--vmin", vmin + "px")
|
|
||||||
this.vmin = vmin
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
this.vmin = null
|
|
||||||
}
|
|
||||||
|
|
||||||
if(this.wheelScrolls !== 0 && !this.state.locked && ms >= this.wheelTimer + 20) {
|
if(this.wheelScrolls !== 0 && !this.state.locked && ms >= this.wheelTimer + 20) {
|
||||||
if(p2.session){
|
if(p2.session){
|
||||||
@ -2727,520 +2675,6 @@ class SongSelect{
|
|||||||
return addedSong
|
return addedSong
|
||||||
}
|
}
|
||||||
|
|
||||||
createSearchResult(result, resultWidth, fontSize){
|
|
||||||
var song = result.obj
|
|
||||||
var title = this.getLocalTitle(song.title, song.title_lang)
|
|
||||||
var subtitle = this.getLocalTitle(title === song.title ? song.subtitle : "", song.subtitle_lang)
|
|
||||||
|
|
||||||
var id = "default"
|
|
||||||
if(song.category_id){
|
|
||||||
var cat = assets.categories.find(cat => cat.id === song.category_id)
|
|
||||||
if(cat && "id" in cat){
|
|
||||||
id = "cat" + cat.id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var resultDiv = document.createElement("div")
|
|
||||||
resultDiv.classList.add("song-search-result", "song-search-" + id)
|
|
||||||
resultDiv.dataset.songId = song.id
|
|
||||||
|
|
||||||
var resultInfoDiv = document.createElement("div")
|
|
||||||
resultInfoDiv.classList.add("song-search-result-info")
|
|
||||||
var resultInfoTitle = document.createElement("span")
|
|
||||||
resultInfoTitle.classList.add("song-search-result-title")
|
|
||||||
|
|
||||||
resultInfoTitle.appendChild(this.highlightResult(title, result[0]))
|
|
||||||
resultInfoTitle.setAttribute("alt", title)
|
|
||||||
|
|
||||||
resultInfoDiv.appendChild(resultInfoTitle)
|
|
||||||
|
|
||||||
if(subtitle){
|
|
||||||
resultInfoDiv.appendChild(document.createElement("br"))
|
|
||||||
var resultInfoSubtitle = document.createElement("span")
|
|
||||||
resultInfoSubtitle.classList.add("song-search-result-subtitle")
|
|
||||||
|
|
||||||
resultInfoSubtitle.appendChild(this.highlightResult(subtitle, result[1]))
|
|
||||||
resultInfoSubtitle.setAttribute("alt", subtitle)
|
|
||||||
|
|
||||||
resultInfoDiv.appendChild(resultInfoSubtitle)
|
|
||||||
}
|
|
||||||
|
|
||||||
resultDiv.appendChild(resultInfoDiv)
|
|
||||||
|
|
||||||
var courses = ["easy", "normal", "hard", "oni", "ura"]
|
|
||||||
courses.forEach(course => {
|
|
||||||
var courseDiv = document.createElement("div")
|
|
||||||
courseDiv.classList.add("song-search-result-course", "song-search-result-" + course)
|
|
||||||
if (song.courses[course]) {
|
|
||||||
var crown = "noclear"
|
|
||||||
if (scoreStorage.scores[song.hash]) {
|
|
||||||
if (scoreStorage.scores[song.hash][course]) {
|
|
||||||
crown = scoreStorage.scores[song.hash][course].crown || "noclear"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var courseCrown = document.createElement("div")
|
|
||||||
courseCrown.classList.add("song-search-result-crown", "song-search-result-" + crown)
|
|
||||||
var courseStars = document.createElement("div")
|
|
||||||
courseStars.classList.add("song-search-result-stars")
|
|
||||||
courseStars.innerText = song.courses[course].stars + '★'
|
|
||||||
|
|
||||||
courseDiv.appendChild(courseCrown)
|
|
||||||
courseDiv.appendChild(courseStars)
|
|
||||||
} else {
|
|
||||||
courseDiv.classList.add("song-search-result-hidden")
|
|
||||||
}
|
|
||||||
|
|
||||||
resultDiv.appendChild(courseDiv)
|
|
||||||
})
|
|
||||||
|
|
||||||
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){
|
|
||||||
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 resultDiv
|
|
||||||
}
|
|
||||||
|
|
||||||
highlightResult(text, result){
|
|
||||||
var fragment = document.createDocumentFragment()
|
|
||||||
var ranges = (result ? result.ranges : null) || []
|
|
||||||
var lastIdx = 0
|
|
||||||
ranges.forEach(range => {
|
|
||||||
if(lastIdx !== range[0]){
|
|
||||||
fragment.appendChild(document.createTextNode(text.slice(lastIdx, range[0])))
|
|
||||||
}
|
|
||||||
var span = document.createElement("span")
|
|
||||||
span.classList.add("highlighted-text")
|
|
||||||
span.innerText = text.slice(range[0], range[1] + 1)
|
|
||||||
fragment.appendChild(span)
|
|
||||||
lastIdx = range[1] + 1
|
|
||||||
})
|
|
||||||
if(text.length !== lastIdx){
|
|
||||||
fragment.appendChild(document.createTextNode(text.slice(lastIdx)))
|
|
||||||
}
|
|
||||||
return fragment
|
|
||||||
}
|
|
||||||
|
|
||||||
searchSetActive(idx){
|
|
||||||
this.playSound("se_ka")
|
|
||||||
var active = this.search.div.querySelector(":scope .song-search-result-active")
|
|
||||||
if(active){
|
|
||||||
active.classList.remove("song-search-result-active")
|
|
||||||
}
|
|
||||||
|
|
||||||
if(idx === null){
|
|
||||||
this.search.active = null
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var el = this.search.results[idx]
|
|
||||||
this.search.input.blur()
|
|
||||||
el.classList.add("song-search-result-active")
|
|
||||||
this.scrollTo(el)
|
|
||||||
|
|
||||||
this.search.active = idx
|
|
||||||
}
|
|
||||||
|
|
||||||
scrollTo(element){
|
|
||||||
var parentNode = element.parentNode
|
|
||||||
var selected = element.getBoundingClientRect()
|
|
||||||
var parent = parentNode.getBoundingClientRect()
|
|
||||||
var scrollY = parentNode.scrollTop
|
|
||||||
var selectedPosTop = selected.top - selected.height / 2
|
|
||||||
if(Math.floor(selectedPosTop) < Math.floor(parent.top)){
|
|
||||||
parentNode.scrollTop += selectedPosTop - parent.top
|
|
||||||
}else{
|
|
||||||
var selectedPosBottom = selected.top + selected.height * 1.5 - parent.top
|
|
||||||
if(Math.floor(selectedPosBottom) > Math.floor(parent.height)){
|
|
||||||
parentNode.scrollTop += selectedPosBottom - parent.height
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
displaySearch(fromButton=false){
|
|
||||||
if(!this.searchEnabled){
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if(this.search){
|
|
||||||
return this.removeSearch(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.search = {results: []}
|
|
||||||
this.search.div = document.createElement("div")
|
|
||||||
this.search.div.innerHTML = assets.pages["search"]
|
|
||||||
|
|
||||||
this.searchContainer = this.search.div.querySelector(":scope #song-search-container")
|
|
||||||
if(this.touchEnabled){
|
|
||||||
this.searchContainer.classList.add("touch-enabled")
|
|
||||||
}
|
|
||||||
pageEvents.add(this.searchContainer, ["mousedown", "touchstart"], this.searchClick.bind(this))
|
|
||||||
|
|
||||||
this.search.input = this.search.div.querySelector(":scope #song-search-input")
|
|
||||||
this.search.input.setAttribute("placeholder", strings.search.searchInput)
|
|
||||||
pageEvents.add(this.search.input, ["input"], this.searchInput.bind(this))
|
|
||||||
|
|
||||||
this.playSound("se_pause")
|
|
||||||
loader.screen.appendChild(this.search.div)
|
|
||||||
this.setSearchTip()
|
|
||||||
cancelTouch = false
|
|
||||||
noResizeRoot = true
|
|
||||||
if(this.songs[this.selectedSong].courses){
|
|
||||||
snd.previewGain.setVolumeMul(0.5)
|
|
||||||
}else if(this.bgmEnabled){
|
|
||||||
snd.musicGain.setVolumeMul(0.5)
|
|
||||||
}
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
this.search.input.focus()
|
|
||||||
this.search.input.setSelectionRange(0, this.search.input.value.length)
|
|
||||||
}, 10)
|
|
||||||
|
|
||||||
var lastQuery = localStorage.getItem("lastSearchQuery")
|
|
||||||
if(lastQuery){
|
|
||||||
this.search.input.value = lastQuery
|
|
||||||
this.search.input.dispatchEvent(new Event('input', {value: lastQuery}))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
removeSearch(byUser=false){
|
|
||||||
if(this.search){
|
|
||||||
if(byUser){
|
|
||||||
this.playSound("se_cancel")
|
|
||||||
}
|
|
||||||
|
|
||||||
pageEvents.remove(this.search.div.querySelector(":scope #song-search-container"),
|
|
||||||
["mousedown", "touchstart"])
|
|
||||||
pageEvents.remove(this.search.input, ["input"])
|
|
||||||
|
|
||||||
this.search.div.remove()
|
|
||||||
delete this.search
|
|
||||||
cancelTouch = true
|
|
||||||
noResizeRoot = false
|
|
||||||
if(this.songs[this.selectedSong].courses){
|
|
||||||
snd.previewGain.setVolumeMul(1)
|
|
||||||
}else if(this.bgmEnabled){
|
|
||||||
snd.musicGain.setVolumeMul(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setSearchTip(tip, error=false){
|
|
||||||
if(this.search.tip){
|
|
||||||
this.search.tip.remove()
|
|
||||||
delete this.search.tip
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!tip){
|
|
||||||
tip = strings.search.tip + " " + strings.search.tips[Math.floor(Math.random() * strings.search.tips.length)]
|
|
||||||
}
|
|
||||||
|
|
||||||
var resultsDiv = this.search.div.querySelector(":scope #song-search-results")
|
|
||||||
resultsDiv.innerHTML = ""
|
|
||||||
this.search.results = []
|
|
||||||
|
|
||||||
this.search.tip = document.createElement("div")
|
|
||||||
this.search.tip.setAttribute("id", "song-search-tip")
|
|
||||||
this.search.tip.innerText = tip
|
|
||||||
this.search.div.querySelector(":scope #song-search").appendChild(this.search.tip)
|
|
||||||
|
|
||||||
if(error){
|
|
||||||
this.search.tip.classList.add("song-search-tip-error")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
parseRange(string){
|
|
||||||
var range = string.split("-")
|
|
||||||
if(range.length == 1){
|
|
||||||
var min = parseInt(range[0]) || 0
|
|
||||||
return min > 0 ? {min: min, max: min} : false
|
|
||||||
} else if(range.length == 2){
|
|
||||||
var min = parseInt(range[0]) || 0
|
|
||||||
var max = parseInt(range[1]) || 0
|
|
||||||
return min > 0 && max > 0 ? {min: min, max: max} : false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
performSearch(query){
|
|
||||||
var results = []
|
|
||||||
var filters = {}
|
|
||||||
|
|
||||||
var querySplit = query.split(" ")
|
|
||||||
var editedSplit = query.split(" ")
|
|
||||||
querySplit.forEach(word => {
|
|
||||||
if(word.length > 0){
|
|
||||||
var parts = word.toLowerCase().split(":")
|
|
||||||
if(parts.length > 1){
|
|
||||||
switch(parts[0]){
|
|
||||||
case "easy":
|
|
||||||
case "normal":
|
|
||||||
case "hard":
|
|
||||||
case "oni":
|
|
||||||
case "ura":
|
|
||||||
var range = this.parseRange(parts[1])
|
|
||||||
if (range) { filters[parts[0]] = range }
|
|
||||||
break
|
|
||||||
case "extreme":
|
|
||||||
var range = this.parseRange(parts[1])
|
|
||||||
if (range) { filters.oni = this.parseRange(parts[1]) }
|
|
||||||
break
|
|
||||||
case "clear":
|
|
||||||
case "silver":
|
|
||||||
case "gold":
|
|
||||||
case "genre":
|
|
||||||
case "lyrics":
|
|
||||||
case "creative":
|
|
||||||
case "played":
|
|
||||||
case "maker":
|
|
||||||
case "diverge":
|
|
||||||
filters[parts[0]] = parts[1]
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
editedSplit.splice(editedSplit.indexOf(word), 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
query = editedSplit.join(" ").trim().normalize("NFD").replace(/[\u0300-\u036f]/g, "")
|
|
||||||
|
|
||||||
var totalFilters = Object.keys(filters).length
|
|
||||||
for(var i = 0; i < assets.songs.length; i++){
|
|
||||||
var song = assets.songs[i]
|
|
||||||
var passedFilters = 0
|
|
||||||
|
|
||||||
Object.keys(filters).forEach(filter => {
|
|
||||||
var value = filters[filter]
|
|
||||||
switch(filter){
|
|
||||||
case "easy":
|
|
||||||
case "normal":
|
|
||||||
case "hard":
|
|
||||||
case "oni":
|
|
||||||
case "ura":
|
|
||||||
if(song.courses[filter] && song.courses[filter].stars >= value.min && song.courses[filter].stars <= value.max){
|
|
||||||
passedFilters++
|
|
||||||
}
|
|
||||||
break
|
|
||||||
case "clear":
|
|
||||||
case "silver":
|
|
||||||
case "gold":
|
|
||||||
if(value === "any"){
|
|
||||||
var score = scoreStorage.scores[song.hash]
|
|
||||||
scoreStorage.difficulty.forEach(difficulty => {
|
|
||||||
if(score && score[difficulty] && score[difficulty].crown && (filter === "clear" || score[difficulty].crown === filter)){
|
|
||||||
passedFilters++
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
var score = scoreStorage.scores[song.hash]
|
|
||||||
if(score && score[value] && score[value].crown && (filter === "clear" || score[value].crown === filter)){
|
|
||||||
passedFilters++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break
|
|
||||||
case "played":
|
|
||||||
var score = scoreStorage.scores[song.hash]
|
|
||||||
if((value === "yes" && score) || (value === "no" && !score)){
|
|
||||||
passedFilters++
|
|
||||||
}
|
|
||||||
break
|
|
||||||
case "lyrics":
|
|
||||||
if((value === "yes" && song.lyrics) || (value === "no" && !song.lyrics)){
|
|
||||||
passedFilters++
|
|
||||||
}
|
|
||||||
break
|
|
||||||
case "creative":
|
|
||||||
if((value === "yes" && song.maker) || (value === "no" && !song.maker)){
|
|
||||||
passedFilters++
|
|
||||||
}
|
|
||||||
break
|
|
||||||
case "maker":
|
|
||||||
if(song.maker && song.maker.name.toLowerCase().includes(value.toLowerCase())){
|
|
||||||
passedFilters++
|
|
||||||
}
|
|
||||||
break
|
|
||||||
case "genre":
|
|
||||||
var cat = assets.categories.find(cat => cat.id === song.category_id)
|
|
||||||
var aliases = cat.aliases ? cat.aliases.concat([cat.title]) : [cat.title]
|
|
||||||
|
|
||||||
if(aliases.find(alias => alias.toLowerCase() === value.toLowerCase())){
|
|
||||||
passedFilters++
|
|
||||||
}
|
|
||||||
break
|
|
||||||
case "diverge":
|
|
||||||
var branch = Object.values(song.courses).find(course => course && course.branch)
|
|
||||||
if((value === "yes" && branch) || (value === "no" && !branch)){
|
|
||||||
passedFilters++
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if(passedFilters === totalFilters){
|
|
||||||
results.push(song)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var maxResults = totalFilters > 0 && !query ? 100 : 50
|
|
||||||
|
|
||||||
if(query){
|
|
||||||
results = fuzzysort.go(query, results, {
|
|
||||||
keys: ["titlePrepared", "subtitlePrepared"],
|
|
||||||
allowTypo: true,
|
|
||||||
limit: maxResults,
|
|
||||||
scoreFn: a => {
|
|
||||||
if(a[0]){
|
|
||||||
var score0 = a[0].score
|
|
||||||
a[0].ranges = this.indexesToRanges(a[0].indexes)
|
|
||||||
if(a[0].indexes.length > 1){
|
|
||||||
var rangeAmount = a[0].ranges.length
|
|
||||||
var lastIdx = -3
|
|
||||||
a[0].ranges.forEach(range => {
|
|
||||||
if(range[0] - lastIdx <= 2){
|
|
||||||
rangeAmount--
|
|
||||||
score0 -= 1000
|
|
||||||
}
|
|
||||||
lastIdx = range[1]
|
|
||||||
})
|
|
||||||
var index = a[0].target.toLowerCase().indexOf(query)
|
|
||||||
if(index !== -1){
|
|
||||||
a[0].ranges = [[index, index + query.length - 1]]
|
|
||||||
}else if(rangeAmount > a[0].indexes.length / 2){
|
|
||||||
score0 = -Infinity
|
|
||||||
a[0].ranges = null
|
|
||||||
}else if(rangeAmount !== 1){
|
|
||||||
score0 -= 9000
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(a[1]){
|
|
||||||
var score1 = a[1].score - 1000
|
|
||||||
a[1].ranges = this.indexesToRanges(a[1].indexes)
|
|
||||||
if(a[1].indexes.length > 1){
|
|
||||||
var rangeAmount = a[1].ranges.length
|
|
||||||
var lastIdx = -3
|
|
||||||
a[1].ranges.forEach(range => {
|
|
||||||
if(range[0] - lastIdx <= 2){
|
|
||||||
rangeAmount--
|
|
||||||
score1 -= 1000
|
|
||||||
}
|
|
||||||
lastIdx = range[1]
|
|
||||||
})
|
|
||||||
var index = a[1].target.indexOf(query)
|
|
||||||
if(index !== -1){
|
|
||||||
a[1].ranges = [[index, index + query.length - 1]]
|
|
||||||
}else if(rangeAmount > a[1].indexes.length / 2){
|
|
||||||
score1 = -Infinity
|
|
||||||
a[1].ranges = null
|
|
||||||
}else if(rangeAmount !== 1){
|
|
||||||
score1 -= 9000
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(a[0]){
|
|
||||||
return a[1] ? Math.max(score0, score1) : score0
|
|
||||||
}else{
|
|
||||||
return a[1] ? score1 : -Infinity
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}else{
|
|
||||||
results = results.map(result => {
|
|
||||||
return {obj: result}
|
|
||||||
}).slice(0, maxResults)
|
|
||||||
}
|
|
||||||
|
|
||||||
return results
|
|
||||||
}
|
|
||||||
|
|
||||||
indexesToRanges(indexes){
|
|
||||||
var ranges = []
|
|
||||||
var range
|
|
||||||
indexes.forEach(idx => {
|
|
||||||
if(range && range[1] === idx - 1){
|
|
||||||
range[1] = idx
|
|
||||||
}else{
|
|
||||||
range = [idx, idx]
|
|
||||||
ranges.push(range)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return ranges
|
|
||||||
}
|
|
||||||
|
|
||||||
searchInput(){
|
|
||||||
var text = this.search.input.value
|
|
||||||
localStorage.setItem("lastSearchQuery", text)
|
|
||||||
text = text.toLowerCase()
|
|
||||||
|
|
||||||
if(text.length === 0){
|
|
||||||
this.setSearchTip()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var new_results = this.performSearch(text)
|
|
||||||
|
|
||||||
if (new_results.length === 0) {
|
|
||||||
this.setSearchTip(strings.search.noResults, true)
|
|
||||||
return
|
|
||||||
} else if (this.search.tip) {
|
|
||||||
this.search.tip.remove()
|
|
||||||
delete this.search.tip
|
|
||||||
}
|
|
||||||
|
|
||||||
var resultsDiv = this.search.div.querySelector(":scope #song-search-results")
|
|
||||||
resultsDiv.innerHTML = ""
|
|
||||||
this.search.results = []
|
|
||||||
|
|
||||||
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 vmin = Math.min(innerWidth, lastHeight) / 100
|
|
||||||
var courseWidth = Math.min(3 * fontSize * 1.2, 7 * 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(result => {
|
|
||||||
var result = this.createSearchResult(result, resultWidth, fontSize)
|
|
||||||
fragment.appendChild(result)
|
|
||||||
this.search.results.push(result)
|
|
||||||
})
|
|
||||||
resultsDiv.appendChild(fragment)
|
|
||||||
|
|
||||||
this.ctx.restore()
|
|
||||||
}
|
|
||||||
|
|
||||||
searchClick(e){
|
|
||||||
if((e.target.id === "song-search-container" || e.target.id === "song-search-close") && e.which === 1){
|
|
||||||
this.removeSearch(true)
|
|
||||||
}else if(e.which === 1){
|
|
||||||
var songEl = e.target.closest(".song-search-result")
|
|
||||||
if(songEl){
|
|
||||||
var songId = parseInt(songEl.dataset.songId)
|
|
||||||
this.searchProceed(songId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
searchProceed(songId){
|
|
||||||
var song = this.songs.find(song => song.id === songId)
|
|
||||||
this.removeSearch()
|
|
||||||
this.playBgm(false)
|
|
||||||
|
|
||||||
var songIndex = this.songs.findIndex(song => song.id === songId)
|
|
||||||
this.setSelectedSong(songIndex)
|
|
||||||
this.toSelectDifficulty()
|
|
||||||
}
|
|
||||||
|
|
||||||
onusers(response){
|
onusers(response){
|
||||||
var p2InSong = false
|
var p2InSong = false
|
||||||
this.songs.forEach(song => {
|
this.songs.forEach(song => {
|
||||||
@ -3268,17 +2702,17 @@ class SongSelect{
|
|||||||
if(this.state.screen !== "difficulty"){
|
if(this.state.screen !== "difficulty"){
|
||||||
this.toSelectDifficulty({player: response.value.player})
|
this.toSelectDifficulty({player: response.value.player})
|
||||||
}
|
}
|
||||||
this.searchEnabled = false
|
this.search.enabled = false
|
||||||
p2InSong = true
|
p2InSong = true
|
||||||
this.removeSearch()
|
this.search.remove()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!this.searchEnabled && !p2InSong){
|
if(!this.search.enabled && !p2InSong){
|
||||||
this.searchEnabled = true
|
this.search.enabled = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onsongsel(response){
|
onsongsel(response){
|
||||||
@ -3404,6 +2838,7 @@ class SongSelect{
|
|||||||
this.sessionCache.clean()
|
this.sessionCache.clean()
|
||||||
this.currentSongCache.clean()
|
this.currentSongCache.clean()
|
||||||
this.nameplateCache.clean()
|
this.nameplateCache.clean()
|
||||||
|
this.search.clean()
|
||||||
assets.sounds["bgm_songsel"].stop()
|
assets.sounds["bgm_songsel"].stop()
|
||||||
if(!this.bgmEnabled){
|
if(!this.bgmEnabled){
|
||||||
snd.musicGain.fadeIn()
|
snd.musicGain.fadeIn()
|
||||||
@ -3425,13 +2860,8 @@ class SongSelect{
|
|||||||
pageEvents.remove(this.touchFullBtn, "click")
|
pageEvents.remove(this.touchFullBtn, "click")
|
||||||
delete this.touchFullBtn
|
delete this.touchFullBtn
|
||||||
}
|
}
|
||||||
if(this.searchStyle){
|
|
||||||
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.searchStyle
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1331,6 +1331,17 @@ var translations = {
|
|||||||
version: {
|
version: {
|
||||||
ja: "Ver. %s",
|
ja: "Ver. %s",
|
||||||
en: "Version %s"
|
en: "Version %s"
|
||||||
|
},
|
||||||
|
browse: {
|
||||||
|
ja: "参照する…",
|
||||||
|
en: "Browse...",
|
||||||
|
cn: "浏览…",
|
||||||
|
tw: "開啟檔案…",
|
||||||
|
ko: "찾아보기…"
|
||||||
|
},
|
||||||
|
noPlugins: {
|
||||||
|
ja: null,
|
||||||
|
en: "No .taikoweb.js plugin files have been found in the provided file list."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
search: {
|
search: {
|
||||||
|
@ -8,6 +8,7 @@ class Titlescreen{
|
|||||||
|
|
||||||
if(!songId){
|
if(!songId){
|
||||||
loader.changePage("titlescreen", false)
|
loader.changePage("titlescreen", false)
|
||||||
|
loader.screen.style.backgroundImage = ""
|
||||||
|
|
||||||
this.titleScreen = document.getElementById("title-screen")
|
this.titleScreen = document.getElementById("title-screen")
|
||||||
this.proceed = document.getElementById("title-proceed")
|
this.proceed = document.getElementById("title-proceed")
|
||||||
@ -75,8 +76,9 @@ class Titlescreen{
|
|||||||
}
|
}
|
||||||
pageEvents.remove(p2, "message")
|
pageEvents.remove(p2, "message")
|
||||||
if(this.customFolder && !fromP2 && !assets.customSongs){
|
if(this.customFolder && !fromP2 && !assets.customSongs){
|
||||||
var customSongs = new CustomSongs(this.touched, true)
|
var customSongs = new CustomSongs(this.touched, true, true)
|
||||||
var soundPlayed = false
|
var soundPlayed = false
|
||||||
|
var noError = true
|
||||||
var promises = []
|
var promises = []
|
||||||
var allFiles = []
|
var allFiles = []
|
||||||
this.customFolder.forEach(file => {
|
this.customFolder.forEach(file => {
|
||||||
@ -95,6 +97,13 @@ class Titlescreen{
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
new SongSelect(false, false, this.touched, this.songId)
|
new SongSelect(false, false, this.touched, this.songId)
|
||||||
}, 500)
|
}, 500)
|
||||||
|
noError = false
|
||||||
|
}).then(() => {
|
||||||
|
if(noError){
|
||||||
|
setTimeout(() => {
|
||||||
|
new SongSelect("customSongs", false, this.touchEnabled)
|
||||||
|
}, 500)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}else{
|
}else{
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
@ -12,8 +12,9 @@
|
|||||||
if(noSmoothing){
|
if(noSmoothing){
|
||||||
this.ctx.imageSmoothingEnabled = false
|
this.ctx.imageSmoothingEnabled = false
|
||||||
}
|
}
|
||||||
if(resolution === "lowest"){
|
this.multiplayer = this.controller.multiplayer
|
||||||
this.canvas.style.imageRendering = "pixelated"
|
if(this.multiplayer !== 2 && resolution === "lowest"){
|
||||||
|
document.getElementById("game").classList.add("pixelated")
|
||||||
}
|
}
|
||||||
|
|
||||||
this.gameDiv = document.getElementById("game")
|
this.gameDiv = document.getElementById("game")
|
||||||
@ -97,7 +98,6 @@
|
|||||||
this.branchCache = new CanvasCache(noSmoothing)
|
this.branchCache = new CanvasCache(noSmoothing)
|
||||||
this.nameplateCache = new CanvasCache(noSmoothing)
|
this.nameplateCache = new CanvasCache(noSmoothing)
|
||||||
|
|
||||||
this.multiplayer = this.controller.multiplayer
|
|
||||||
if(this.multiplayer === 2){
|
if(this.multiplayer === 2){
|
||||||
this.player = p2.player === 2 ? 1 : 2
|
this.player = p2.player === 2 ? 1 : 2
|
||||||
}else{
|
}else{
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
<meta name="viewport" content="width=device-width, user-scalable=no">
|
<meta name="viewport" content="width=device-width, user-scalable=no">
|
||||||
<meta name="description" content="パソコンとスマホのブラウザ向けの太鼓の達人シミュレータ 🥁 Taiko no Tatsujin rhythm game simulator for desktop and mobile browsers">
|
<meta name="description" content="パソコンとスマホのブラウザ向けの太鼓の達人シミュレータ 🥁 Taiko no Tatsujin rhythm game simulator for desktop and mobile browsers">
|
||||||
<meta name="keywords" content="taiko no tatsujin, taiko, don chan, online, rhythm, browser, html5, game, for browsers, pc, arcade, emulator, free, download, website, 太鼓の達人, 太鼓ウェブ, 太鼓之達人, 太鼓達人, 太鼓网页, 网页版, 太鼓網頁, 網頁版, 태고의 달인, 태고 웹">
|
<meta name="keywords" content="taiko no tatsujin, taiko, don chan, online, rhythm, browser, html5, game, for browsers, pc, arcade, emulator, free, download, website, 太鼓の達人, 太鼓ウェブ, 太鼓之達人, 太鼓達人, 太鼓网页, 网页版, 太鼓網頁, 網頁版, 태고의 달인, 태고 웹">
|
||||||
|
<meta name="robots" content="notranslate">
|
||||||
|
<meta name="robots" content="noimageindex">
|
||||||
<meta name="color-scheme" content="only light">
|
<meta name="color-scheme" content="only light">
|
||||||
|
|
||||||
<link rel="stylesheet" href="/src/css/loader.css?{{version.commit_short}}">
|
<link rel="stylesheet" href="/src/css/loader.css?{{version.commit_short}}">
|
||||||
@ -22,7 +24,7 @@
|
|||||||
<div id="screen" class="pattern-bg"></div>
|
<div id="screen" class="pattern-bg"></div>
|
||||||
<div data-nosnippet id="version">
|
<div data-nosnippet id="version">
|
||||||
{% if version.version and version.commit_short and version.commit %}
|
{% if version.version and version.commit_short and version.commit %}
|
||||||
<a href="{{version.url}}commit/{{version.commit}}" target="_blank" id="version-link" class="stroke-sub" alt="taiko-web ver.{{version.version}} ({{version.commit_short}})">taiko-web ver.{{version.version}} ({{version.commit_short}})</a>
|
<a href="{{version.url}}commit/{{version.commit}}" target="_blank" rel="noopener" id="version-link" class="stroke-sub" alt="taiko-web ver.{{version.version}} ({{version.commit_short}})">taiko-web ver.{{version.version}} ({{version.commit_short}})</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="{{version.url}}" target="_blank" rel="noopener" id="version-link" class="stroke-sub" alt="taiko-web (unknown version)">taiko-web (unknown version)</a>
|
<a href="{{version.url}}" target="_blank" rel="noopener" id="version-link" class="stroke-sub" alt="taiko-web (unknown version)">taiko-web (unknown version)</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
Loading…
Reference in New Issue
Block a user