You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
154 lines
3.6 KiB
154 lines
3.6 KiB
module.exports = class {
|
|
onCreate(input) {
|
|
this.state = {
|
|
characters: [],
|
|
channels: [],
|
|
eventNames: [],
|
|
filters: [],
|
|
search: "",
|
|
activeMap: {
|
|
events: {},
|
|
characters: {},
|
|
channels: {},
|
|
},
|
|
}
|
|
}
|
|
|
|
onInput(input) {
|
|
this.update(input)
|
|
}
|
|
|
|
onMount(input) {
|
|
this.getEl("search").addEventListener("keydown", ev => {
|
|
if (this.waiting) {
|
|
return
|
|
}
|
|
|
|
if (this.timeout != null) {
|
|
clearTimeout(this.timeout)
|
|
}
|
|
|
|
if (ev.key === "Enter") {
|
|
this.emit("add", "search", ev.target.value)
|
|
this.getEl("search").value = ""
|
|
}
|
|
|
|
this.timeout = setTimeout(() => {
|
|
this.timeout = null
|
|
this.state.search = ev.target.value
|
|
|
|
this.update(this.input)
|
|
}, 200)
|
|
})
|
|
}
|
|
|
|
update(input) {
|
|
if (input.filter) {
|
|
this.updateActive(input)
|
|
}
|
|
|
|
const search = this.state.search.toLocaleLowerCase()
|
|
|
|
this.state.characters = input.characters.filter(c => !this.state.activeMap.characters[c.id]).filter(c => this.matches(c.name, search)).sort((a,b) => compareFilters(a.name, b.name, search))
|
|
this.state.channels = input.channels.filter(c => !this.state.activeMap.channels[c.name]).filter(c => this.matches(c.name, search)).sort((a,b) => compareFilters(a.name, b.name, search))
|
|
this.state.eventNames = input.eventNames.filter(e => !this.state.activeMap.events[e]).filter(e => this.matches(e, search)).sort((a,b) => compareFilters(a, b, search))
|
|
}
|
|
|
|
updateActive({filter, characters, channels, eventNames}) {
|
|
const filters = []
|
|
const activeMap = {
|
|
events: {},
|
|
characters: {},
|
|
channels: {},
|
|
}
|
|
|
|
if (filter.search != null) {
|
|
filters.push({
|
|
type: "search",
|
|
key: "search",
|
|
icon: "T",
|
|
color: "color-text",
|
|
text: filter.search,
|
|
})
|
|
}
|
|
|
|
for (const character of (filter.characters || [])) {
|
|
activeMap.characters[character] = true
|
|
|
|
filters.push({
|
|
type: "characters",
|
|
key: character,
|
|
icon: "C",
|
|
color: "color-tag-character",
|
|
id: character,
|
|
text: (characters.find(c => c.id === character) || {name: "Unknown ("+character+")"}).name,
|
|
})
|
|
}
|
|
|
|
for (const channel of (filter.channels || [])) {
|
|
activeMap.channels[channel] = true
|
|
|
|
filters.push({
|
|
type: "channels",
|
|
key: channel.replace(/'/g, "__"),
|
|
icon: "#",
|
|
color: "color-tag-location",
|
|
id: channel,
|
|
text: channel,
|
|
})
|
|
}
|
|
|
|
for (const event of (filter.events || [])) {
|
|
activeMap.events[event] = true
|
|
|
|
filters.push({
|
|
type: "events",
|
|
key: event.replace(/['\s\.]/g, "__"),
|
|
icon: "E",
|
|
color: "color-tag-event",
|
|
id: event,
|
|
text: event,
|
|
})
|
|
}
|
|
|
|
this.state.filters = filters
|
|
this.state.activeMap = activeMap
|
|
}
|
|
|
|
matches(str, search) {
|
|
if (search == "") {
|
|
return true
|
|
}
|
|
|
|
if (search.length > str.length) {
|
|
return false
|
|
}
|
|
|
|
return str.toLowerCase().indexOf(search) !== -1
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param {string} a
|
|
* @param {string} b
|
|
* @param {string} search
|
|
*/
|
|
function compareFilters(a, b, search) {
|
|
if (search != "") {
|
|
if (search.charAt(0) != "#" && a.charAt(0) == "#" && b.charAt(0) == "#") {
|
|
search = '#' + search
|
|
}
|
|
|
|
const aStarts = a.toLocaleLowerCase().startsWith(search)
|
|
const bStarts = b.toLocaleLowerCase().startsWith(search)
|
|
|
|
if (aStarts && !bStarts) {
|
|
return -1
|
|
} else if (bStarts && !aStarts) {
|
|
return 1
|
|
}
|
|
}
|
|
|
|
return a.localeCompare(b)
|
|
}
|