diff --git a/.eslintignore b/.eslintignore
index 70fdae27f..4dd465994 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -14,7 +14,7 @@ node_modules/
/js/battle-animations.js
/js/battle-tooltips.js
/js/battle-scene-stub.js
-/js/battle-search.js
+/js/battle-dex-search.js
/js/battle-searchresults.js
/js/client-core.js
/js/client-main.js
diff --git a/.eslintrc.js b/.eslintrc.js
index 4d106d18e..ecc88048a 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -27,7 +27,7 @@ module.exports = {
"BattleTextParser": false,
// Generic global variables
- "Config": false, "BattleSearch": false, "soundManager": false, "Storage": false, "Dex": false,
+ "Config": false, "BattleSearch": false, "soundManager": false, "Storage": false, "Dex": false, "DexSearch": false,
"app": false, "toID": false, "toRoomid": false, "toUserid": false, "toName": false, "PSUtils": false, "MD5": false,
"ChatHistory": false, "Topbar": false, "UserList": false,
diff --git a/.gitignore b/.gitignore
index 2b5536316..4efba1ddb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,7 +24,7 @@ package-lock.json
/js/battle-animations.js
/js/battle-tooltips.js
/js/battle-scene-stub.js
-/js/battle-search.js
+/js/battle-dex-search.js
/js/battle-searchresults.js
/js/client-core.js
/js/client-main.js
diff --git a/preactalpha.template.html b/preactalpha.template.html
index 73103f7a0..f7ed8d64b 100644
--- a/preactalpha.template.html
+++ b/preactalpha.template.html
@@ -87,7 +87,7 @@
-
+
diff --git a/src/battle-search.ts b/src/battle-dex-search.ts
similarity index 97%
rename from src/battle-search.ts
rename to src/battle-dex-search.ts
index da1239366..2a63714ab 100644
--- a/src/battle-search.ts
+++ b/src/battle-dex-search.ts
@@ -29,7 +29,7 @@ declare const BattleTeambuilderTable: any;
/**
* Backend for search UIs.
*/
-class BattleSearch {
+class DexSearch {
query = '';
/**
@@ -99,7 +99,7 @@ class BattleSearch {
find(query: string) {
query = toID(query);
if (this.query === query && this.results) {
- return this.results;
+ return false;
}
this.query = query;
if (!query) {
@@ -107,12 +107,17 @@ class BattleSearch {
} else {
this.results = this.textSearch(query);
}
+ return true;
}
setType(searchType: SearchType | '', format = '' as ID, speciesOrSet: ID | PokemonSet = '' as ID) {
// invalidate caches
this.results = null;
+ if (searchType !== this.typedSearch?.searchType) {
+ this.filters = null;
+ this.sortCol = null;
+ }
this.typedSearch = this.getTypedSearch(searchType, format, speciesOrSet);
}
@@ -166,6 +171,15 @@ class BattleSearch {
return true;
}
+ toggleSort(sortCol: string) {
+ if (this.sortCol === sortCol) {
+ this.sortCol = null;
+ } else {
+ this.sortCol = sortCol;
+ }
+ this.results = null;
+ }
+
filterLabel(filterType: string) {
if (this.typedSearch && this.typedSearch.searchType !== filterType) {
return 'Filter';
@@ -189,7 +203,7 @@ class BattleSearch {
// If searchType exists, we're searching mainly for results of that type.
// We'll still search for results of other types, but those results
// will only be used to filter results for that type.
- let searchTypeIndex = (searchType ? BattleSearch.typeTable[searchType] : -1);
+ let searchTypeIndex = (searchType ? DexSearch.typeTable[searchType] : -1);
/** searching for "Psychic type" will make the type come up over the move */
let qFilterType: 'type' | '' = '';
@@ -201,7 +215,7 @@ class BattleSearch {
}
// i represents the location of the search index we're looking at
- let i = BattleSearch.getClosest(query);
+ let i = DexSearch.getClosest(query);
this.exactMatch = (BattleSearchIndex[i][0] === query);
// Even with output buffer buckets, we make multiple passes through
@@ -244,7 +258,7 @@ class BattleSearch {
if (['sub', 'tr'].includes(query) || toID(BattleAliases[query]).slice(0, query.length) !== query) {
queryAlias = toID(BattleAliases[query]);
let aliasPassType: SearchPassType = (queryAlias === 'hiddenpower' ? 'exact' : 'normal');
- searchPasses.unshift([aliasPassType, BattleSearch.getClosest(queryAlias), queryAlias]);
+ searchPasses.unshift([aliasPassType, DexSearch.getClosest(queryAlias), queryAlias]);
}
this.exactMatch = true;
}
@@ -329,7 +343,7 @@ class BattleSearch {
if (passType === 'alias') continue;
}
- let typeIndex = BattleSearch.typeTable[type];
+ let typeIndex = DexSearch.typeTable[type];
// For performance, with a query length of 1, we only fill the first bucket
if (query.length === 1 && typeIndex !== (searchType ? searchTypeIndex : 1)) continue;
@@ -388,12 +402,12 @@ class BattleSearch {
// searchType buckets are always on top (but under bucket 0), so
// illegal results will be seamlessly right under legal results.
if (!bufs[typeIndex].length && !bufs[0].length) {
- bufs[0] = [['header', BattleSearch.typeName[type]]];
+ bufs[0] = [['header', DexSearch.typeName[type]]];
}
if (!(id in illegal)) typeIndex = 0;
} else {
if (!bufs[typeIndex].length) {
- bufs[typeIndex] = [['header', BattleSearch.typeName[type]]];
+ bufs[typeIndex] = [['header', DexSearch.typeName[type]]];
}
}
@@ -478,7 +492,7 @@ class BattleSearch {
break;
}
}
- return buf.concat(illegalBuf);
+ return [...buf, ...illegalBuf];
}
static getClosest(query: string) {
@@ -554,7 +568,7 @@ abstract class BattleTypedSearch {
if (format.slice(0, 3) === 'gen') {
const gen = (Number(format.charAt(3)) || 6);
- format = format.slice(4) as ID;
+ format = (format.slice(4) || 'customgame') as ID;
this.dex = Dex.forGen(gen);
} else if (!format) {
this.dex = Dex;
@@ -612,9 +626,16 @@ abstract class BattleTypedSearch {
illegalResults = [];
for (const result of this.baseResults) {
if (this.filter(result, filters)) {
- results.push(result);
+ if (results.length && result[0] === 'header' && results[results.length - 1][0] === 'header') {
+ results[results.length - 1] = result;
+ } else {
+ results.push(result);
+ }
}
}
+ if (results.length && results[results.length - 1][0] === 'header') {
+ results.pop();
+ }
for (const result of this.baseIllegalResults) {
if (this.filter(result, filters)) {
illegalResults.push(result);
@@ -630,7 +651,12 @@ abstract class BattleTypedSearch {
if (illegalResults) illegalResults = this.sort(illegalResults, sortCol);
}
- if (illegalResults) results = results.concat(illegalResults);
+ if (this.sortRow) {
+ results = [this.sortRow, ...results];
+ }
+ if (illegalResults && illegalResults.length) {
+ results = [...results, ['header', "Illegal results"], ...illegalResults];
+ }
return results;
}
protected nextLearnsetid(learnsetid: ID, speciesid?: ID) {
@@ -713,7 +739,7 @@ class BattlePokemonSearch extends BattleTypedSearch<'pokemon'> {
return BattlePokedex;
}
getDefaultResults(): SearchRow[] {
- let results: SearchRow[] = [['sortpokemon', '']];
+ let results: SearchRow[] = [];
for (let id in BattlePokedex) {
switch (id) {
case 'bulbasaur':
@@ -953,7 +979,7 @@ class BattleAbilitySearch extends BattleTypedSearch<'ability'> {
badAbilities.push(['ability', id]);
}
}
- abilitySet = goodAbilities.concat(poorAbilities).concat(badAbilities);
+ abilitySet = [...goodAbilities, ...poorAbilities, ...badAbilities];
if (species.isMega) {
if (format === 'almostanyability') {
abilitySet.unshift(['html', `Will be ${species.abilities['0']} after Mega Evolving.`]);
@@ -1019,12 +1045,12 @@ class BattleItemSearch extends BattleTypedSearch<'item'> {
}
class BattleMoveSearch extends BattleTypedSearch<'move'> {
- sortRow: SearchRow = ['sortpokemon', ''];
+ sortRow: SearchRow = ['sortmove', ''];
getTable() {
return BattleMovedex;
}
getDefaultResults(): SearchRow[] {
- let results: SearchRow[] = [['sortmove', '']];
+ let results: SearchRow[] = [];
results.push(['header', "Moves"]);
for (let id in BattleMovedex) {
switch (id) {
@@ -1310,7 +1336,7 @@ class BattleMoveSearch extends BattleTypedSearch<'move'> {
uselessMoves.push(['move', id as ID]);
}
}
- return usableMoves.concat(uselessMoves);
+ return [...usableMoves, ...uselessMoves];
}
filter(row: SearchRow, filters: string[][]) {
if (!filters) return true;
diff --git a/src/battle-searchresults.tsx b/src/battle-searchresults.tsx
index e434d1717..e5461c2e6 100644
--- a/src/battle-searchresults.tsx
+++ b/src/battle-searchresults.tsx
@@ -1,13 +1,13 @@
/**
* Search Results
*
- * Code for displaying sesrch results from battle-search.ts
+ * Code for displaying sesrch results from battle-dex-search.ts
*
* @author Guangcong Luo
* @license AGPLv3
*/
-class PSSearchResults extends preact.Component<{search: BattleSearch}> {
+class PSSearchResults extends preact.Component<{search: DexSearch}> {
readonly URL_ROOT = '//dex.pokemonshowdown.com/';
renderPokemonSortRow() {
diff --git a/src/panel-teambuilder-team.tsx b/src/panel-teambuilder-team.tsx
index 22256c9ec..79950ff05 100644
--- a/src/panel-teambuilder-team.tsx
+++ b/src/panel-teambuilder-team.tsx
@@ -20,7 +20,7 @@ class TeamTextbox extends preact.Component<{team: Team}> {
activeType: 'pokemon' | 'move' | 'item' | 'ability' | '' = '';
activeOffsetY = -1;
activeSetIndex = -1;
- search = new BattleSearch();
+ search = new DexSearch();
getYAt(index: number, value: string) {
if (index < 0) return 10;
this.heightTester.value = value.slice(0, index);
diff --git a/testclient-beta.html b/testclient-beta.html
index 8ee1a0459..c4e1e8f7f 100644
--- a/testclient-beta.html
+++ b/testclient-beta.html
@@ -88,7 +88,7 @@
-
+