mirror of
https://github.com/smogon/pokemon-showdown-client.git
synced 2026-03-21 17:50:29 -05:00
Implement teambuilder dropdown selector
This took way too long to get to a presentable state. - search.js has been refactored into battle-search.ts (search logic) and battle-searchresults.tsx (display) - panel-teambuilder.tsx has been split into teambuilder (team list) and teambuilder-team (team editor). - The teambuilder's text editor can now detect which line it's on, and show the appropriate search result panel. - The teambuilder's text editor now detects sets dynamically, and has the beginnings of support for set comments. Currently, everything here is really basic, and mostly just a tech demo for people to play around with and understand the direction of the new teambuilder, but it'll be improved over time.
This commit is contained in:
parent
26fa6f71e1
commit
b47708efa0
|
|
@ -13,6 +13,8 @@ node_modules/
|
|||
/js/battle-animations.js
|
||||
/js/battle-tooltips.js
|
||||
/js/battle-scene-stub.js
|
||||
/js/battle-search.js
|
||||
/js/battle-searchresults.js
|
||||
/js/client-core.js
|
||||
/js/client-main.js
|
||||
/js/client-connection.js
|
||||
|
|
@ -23,4 +25,5 @@ node_modules/
|
|||
/js/panel-rooms.js
|
||||
/js/panel-chat.js
|
||||
/js/panel-teambuilder.js
|
||||
/js/panel-teambuilder-team.js
|
||||
/js/panel-teamdropdown.js
|
||||
|
|
|
|||
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -24,6 +24,8 @@ package-lock.json
|
|||
/js/battle-animations.js
|
||||
/js/battle-tooltips.js
|
||||
/js/battle-scene-stub.js
|
||||
/js/battle-search.js
|
||||
/js/battle-searchresults.js
|
||||
/js/client-core.js
|
||||
/js/client-main.js
|
||||
/js/client-connection.js
|
||||
|
|
@ -34,6 +36,7 @@ package-lock.json
|
|||
/js/panel-rooms.js
|
||||
/js/panel-chat.js
|
||||
/js/panel-teambuilder.js
|
||||
/js/panel-teambuilder-team.js
|
||||
/js/panel-teamdropdown.js
|
||||
|
||||
/replays/caches/
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@
|
|||
linkStyle("/style/sim-types.css");
|
||||
linkStyle("/style/battle.css");
|
||||
linkStyle("/style/teambuilder.css");
|
||||
linkStyle("/style/utilichart.css");
|
||||
linkStyle("style/battle-search.css");
|
||||
linkStyle("/style/font-awesome.css");
|
||||
</script>
|
||||
<script defer src="/js/client-core.js?"></script>
|
||||
|
|
@ -73,7 +73,12 @@
|
|||
<script defer src="/data/moves.js?"></script>
|
||||
<script defer src="/data/items.js?"></script>
|
||||
<script defer src="/data/abilities.js?"></script>
|
||||
<script defer src="/data/search-index.js?"></script>
|
||||
<script defer src="/data/teambuilder-tables.js?"></script>
|
||||
<script defer src="/js/panel-teamdropdown.js"></script>
|
||||
<script defer src="/js/panel-teambuilder.js?"></script>
|
||||
<script defer src="/js/battle-search.js?"></script>
|
||||
<script defer src="/js/battle-searchresults.js?"></script>
|
||||
<script defer src="/js/panel-teambuilder-team.js?"></script>
|
||||
|
||||
</body></html>
|
||||
|
|
|
|||
|
|
@ -622,25 +622,9 @@ const Dex = new class implements ModdedDex {
|
|||
return spriteData;
|
||||
}
|
||||
|
||||
getPokemonIcon(pokemon: any, facingLeft?: boolean) {
|
||||
getPokemonIconNum(id: ID, isFemale?: boolean, facingLeft?: boolean) {
|
||||
let num = 0;
|
||||
if (pokemon === 'pokeball') {
|
||||
return 'background:transparent url(' + Dex.resourcePrefix + 'sprites/smicons-pokeball-sheet.png) no-repeat scroll -0px 4px';
|
||||
} else if (pokemon === 'pokeball-statused') {
|
||||
return 'background:transparent url(' + Dex.resourcePrefix + 'sprites/smicons-pokeball-sheet.png) no-repeat scroll -40px 4px';
|
||||
} else if (pokemon === 'pokeball-fainted') {
|
||||
return 'background:transparent url(' + Dex.resourcePrefix + 'sprites/smicons-pokeball-sheet.png) no-repeat scroll -80px 4px;opacity:.4;filter:contrast(0)';
|
||||
} else if (pokemon === 'pokeball-none') {
|
||||
return 'background:transparent url(' + Dex.resourcePrefix + 'sprites/smicons-pokeball-sheet.png) no-repeat scroll -80px 4px';
|
||||
}
|
||||
let id = toID(pokemon);
|
||||
if (pokemon && pokemon.species) id = toID(pokemon.species);
|
||||
if (pokemon && pokemon.volatiles && pokemon.volatiles.formechange && !pokemon.volatiles.transform) {
|
||||
id = toID(pokemon.volatiles.formechange[1]);
|
||||
}
|
||||
if (pokemon && pokemon.num) {
|
||||
num = pokemon.num;
|
||||
} else if (window.BattlePokemonSprites && BattlePokemonSprites[id] && BattlePokemonSprites[id].num) {
|
||||
if (window.BattlePokemonSprites && BattlePokemonSprites[id] && BattlePokemonSprites[id].num) {
|
||||
num = BattlePokemonSprites[id].num;
|
||||
} else if (window.BattlePokedex && window.BattlePokedex[id] && BattlePokedex[id].num) {
|
||||
num = BattlePokedex[id].num;
|
||||
|
|
@ -652,17 +636,36 @@ const Dex = new class implements ModdedDex {
|
|||
num = BattlePokemonIconIndexes[id];
|
||||
}
|
||||
|
||||
if (pokemon && pokemon.gender === 'F') {
|
||||
if (id === 'unfezant' || id === 'frillish' || id === 'jellicent' || id === 'meowstic' || id === 'pyroar') {
|
||||
if (isFemale) {
|
||||
if (['unfezant', 'frillish', 'jellicent', 'meowstic', 'pyroar'].includes(id)) {
|
||||
num = BattlePokemonIconIndexes[id + 'f'];
|
||||
}
|
||||
}
|
||||
|
||||
if (facingLeft) {
|
||||
if (BattlePokemonIconIndexesLeft[id]) {
|
||||
num = BattlePokemonIconIndexesLeft[id];
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
getPokemonIcon(pokemon: any, facingLeft?: boolean) {
|
||||
if (pokemon === 'pokeball') {
|
||||
return 'background:transparent url(' + Dex.resourcePrefix + 'sprites/smicons-pokeball-sheet.png) no-repeat scroll -0px 4px';
|
||||
} else if (pokemon === 'pokeball-statused') {
|
||||
return 'background:transparent url(' + Dex.resourcePrefix + 'sprites/smicons-pokeball-sheet.png) no-repeat scroll -40px 4px';
|
||||
} else if (pokemon === 'pokeball-fainted') {
|
||||
return 'background:transparent url(' + Dex.resourcePrefix + 'sprites/smicons-pokeball-sheet.png) no-repeat scroll -80px 4px;opacity:.4;filter:contrast(0)';
|
||||
} else if (pokemon === 'pokeball-none') {
|
||||
return 'background:transparent url(' + Dex.resourcePrefix + 'sprites/smicons-pokeball-sheet.png) no-repeat scroll -80px 4px';
|
||||
}
|
||||
|
||||
let id = toID(pokemon);
|
||||
if (pokemon && pokemon.species) id = toID(pokemon.species);
|
||||
if (pokemon && pokemon.volatiles && pokemon.volatiles.formechange && !pokemon.volatiles.transform) {
|
||||
id = toID(pokemon.volatiles.formechange[1]);
|
||||
}
|
||||
let num = this.getPokemonIconNum(id, pokemon && pokemon.gender === 'F', facingLeft);
|
||||
|
||||
let top = Math.floor(num / 12) * 30;
|
||||
let left = (num % 12) * 40;
|
||||
|
|
|
|||
1227
src/battle-search.ts
Normal file
1227
src/battle-search.ts
Normal file
File diff suppressed because it is too large
Load Diff
371
src/battle-searchresults.tsx
Normal file
371
src/battle-searchresults.tsx
Normal file
|
|
@ -0,0 +1,371 @@
|
|||
/**
|
||||
* Search Results
|
||||
*
|
||||
* Code for displaying sesrch results from battle-search.ts
|
||||
*
|
||||
* @author Guangcong Luo <guangcongluo@gmail.com>
|
||||
* @license AGPLv3
|
||||
*/
|
||||
|
||||
class PSSearchResults extends preact.Component<{search: BattleSearch}> {
|
||||
renderPokemonSortRow() {
|
||||
const search = this.props.search;
|
||||
const sortCol = search.sortCol;
|
||||
return <li class="result"><div class="sortrow">
|
||||
<button class={`sortcol numsortcol${!sortCol ? ' cur' : ''}`}>{!sortCol ? 'Sort: ' : (search.defaultResults && !search.filters ? 'Tier' : 'Number')}</button>
|
||||
<button class={`sortcol pnamesortcol${sortCol === 'name' ? ' cur' : ''}`} data-sort="name">Name</button>
|
||||
<button class={`sortcol typesortcol${sortCol === 'type' ? ' cur' : ''}`} data-sort="type">Types</button>
|
||||
<button class={`sortcol abilitysortcol${sortCol === 'ability' ? ' cur' : ''}`} data-sort="ability">Abilities</button>
|
||||
<button class={`sortcol statsortcol${sortCol === 'hp' ? ' cur' : ''}`} data-sort="hp">HP</button>
|
||||
<button class={`sortcol statsortcol${sortCol === 'atk' ? ' cur' : ''}`} data-sort="atk">Atk</button>
|
||||
<button class={`sortcol statsortcol${sortCol === 'def' ? ' cur' : ''}`} data-sort="def">Def</button>
|
||||
<button class={`sortcol statsortcol${sortCol === 'spa' ? ' cur' : ''}`} data-sort="spa">SpA</button>
|
||||
<button class={`sortcol statsortcol${sortCol === 'spd' ? ' cur' : ''}`} data-sort="spd">SpD</button>
|
||||
<button class={`sortcol statsortcol${sortCol === 'spe' ? ' cur' : ''}`} data-sort="spe">Spe</button>
|
||||
<button class={`sortcol statsortcol${sortCol === 'bst' ? ' cur' : ''}`} data-sort="bst">BST</button>
|
||||
</div></li>;
|
||||
}
|
||||
|
||||
renderMoveSortRow() {
|
||||
const sortCol = this.props.search.sortCol;
|
||||
return <li class="result"><div class="sortrow">
|
||||
<button class={`sortcol movenamesortcol${sortCol === 'name' ? ' cur' : ''}`} data-sort="name">Name</button>
|
||||
<button class={`sortcol movetypesortcol${sortCol === 'type' ? ' cur' : ''}`} data-sort="type">Type</button>
|
||||
<button class={`sortcol movetypesortcol${sortCol === 'category' ? ' cur' : ''}`} data-sort="category">Cat</button>
|
||||
<button class={`sortcol powersortcol${sortCol === 'power' ? ' cur' : ''}`} data-sort="power">Pow</button>
|
||||
<button class={`sortcol accuracysortcol${sortCol === 'accuracy' ? ' cur' : ''}`} data-sort="accuracy">Acc</button>
|
||||
<button class={`sortcol ppsortcol${sortCol === 'pp' ? ' cur' : ''}`} data-sort="pp">PP</button>
|
||||
</div></li>;
|
||||
}
|
||||
|
||||
renderPokemonRow(id: ID, matchStart: number, matchEnd: number, errorMessage?: preact.ComponentChildren) {
|
||||
const search = this.props.search;
|
||||
const pokemon = search.dex.getTemplate(id);
|
||||
if (!pokemon) return <li class="result">Unrecognized pokemon</li>;
|
||||
|
||||
let tagStart = (pokemon.forme ? pokemon.name.length - pokemon.forme.length - 1 : 0);
|
||||
|
||||
const stats = pokemon.baseStats;
|
||||
let bst = 0;
|
||||
for (const stat of Object.values(stats)) bst += stat;
|
||||
if (search.gen < 2) bst -= stats['spd'];
|
||||
|
||||
if (errorMessage) {
|
||||
return <li class="result"><a href={`${search.urlRoot}pokemon/${id}`} data-target="push" data-entry={`pokemon|${pokemon.name}`}>
|
||||
<span class="col numcol">{search.getTier(pokemon)}</span>
|
||||
|
||||
<span class="col iconcol">
|
||||
<span style={Dex.getPokemonIcon(pokemon)}></span>
|
||||
</span>
|
||||
|
||||
<span class="col pokemonnamecol">{this.renderName(pokemon.name, matchStart, matchEnd, tagStart)}</span>
|
||||
|
||||
{errorMessage}
|
||||
</a></li>;
|
||||
}
|
||||
|
||||
return <li class="result"><a href={`${search.urlRoot}pokemon/${id}`} data-target="push" data-entry={`pokemon|${pokemon.name}`}>
|
||||
<span class="col numcol">{search.getTier(pokemon)}</span>
|
||||
|
||||
<span class="col iconcol">
|
||||
<span style={Dex.getPokemonIcon(pokemon)}></span>
|
||||
</span>
|
||||
|
||||
<span class="col pokemonnamecol">{this.renderName(pokemon.name, matchStart, matchEnd, tagStart)}</span>
|
||||
|
||||
<span class="col typecol">
|
||||
{pokemon.types.map(type =>
|
||||
<img src={`${Dex.resourcePrefix}sprites/types/${type}.png`} alt={type} height="14" width="32" class="pixelated" />
|
||||
)}
|
||||
</span>
|
||||
|
||||
{search.gen >= 3 && (pokemon.abilities['1'] ?
|
||||
<span class="col twoabilitycol">{pokemon.abilities['0']}<br />{pokemon.abilities['1']}</span>
|
||||
:
|
||||
<span class="col abilitycol">{pokemon.abilities['0']}</span>
|
||||
)}
|
||||
{search.gen >= 5 && (pokemon.abilities['S'] ?
|
||||
<span class={`col twoabilitycol${pokemon.unreleasedHidden ? ' unreleasedhacol' : ''}`}>{pokemon.abilities['H'] || ''}<br />{pokemon.abilities['S']}</span>
|
||||
: pokemon.abilities['H'] ?
|
||||
<span class={`col abilitycol${pokemon.unreleasedHidden ? ' unreleasedhacol' : ''}`}>{pokemon.abilities['H']}</span>
|
||||
:
|
||||
<span class="col abilitycol"></span>
|
||||
)}
|
||||
|
||||
<span class="col statcol"><em>HP</em><br />{stats.hp}</span>
|
||||
<span class="col statcol"><em>Atk</em><br />{stats.atk}</span>
|
||||
<span class="col statcol"><em>Def</em><br />{stats.def}</span>
|
||||
{search.gen > 2 && <span class="col statcol"><em>SpA</em><br />{stats.spa}</span>}
|
||||
{search.gen > 2 && <span class="col statcol"><em>SpD</em><br />{stats.spd}</span>}
|
||||
{search.gen < 2 && <span class="col statcol"><em>Spc</em><br />{stats.spa}</span>}
|
||||
<span class="col statcol"><em>Spe</em><br />{stats.spe}</span>
|
||||
<span class="col bstcol"><em>BST<br />{bst}</em></span>
|
||||
</a></li>;
|
||||
}
|
||||
|
||||
renderName(name: string, matchStart: number, matchEnd: number, tagStart?: number) {
|
||||
if (!matchEnd) {
|
||||
if (!tagStart) return name;
|
||||
return [
|
||||
name.slice(0, tagStart), <small>{name.slice(tagStart)}</small>,
|
||||
];
|
||||
}
|
||||
|
||||
let output: preact.ComponentChild[];
|
||||
if (tagStart && matchStart >= tagStart) {
|
||||
output = [name];
|
||||
} else {
|
||||
output = [
|
||||
name.slice(0, matchStart),
|
||||
<b>{name.slice(matchStart, matchEnd)}</b>,
|
||||
name.slice(matchEnd, tagStart || name.length),
|
||||
];
|
||||
if (!tagStart) return output;
|
||||
}
|
||||
|
||||
if (matchEnd && matchEnd > tagStart) {
|
||||
if (matchStart < tagStart) {
|
||||
matchStart = tagStart;
|
||||
}
|
||||
output.push(
|
||||
<small>{name.slice(tagStart, matchStart)}<b>{name.slice(matchStart, matchEnd)}</b>{name.slice(matchEnd)}</small>
|
||||
);
|
||||
} else {
|
||||
output.push(<small>{name.slice(tagStart)}</small>);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
renderItemRow(id: ID, matchStart: number, matchEnd: number, errorMessage?: preact.ComponentChildren) {
|
||||
const search = this.props.search;
|
||||
const item = search.dex.getItem(id);
|
||||
if (!item) return <li class="result">Unrecognized item</li>;
|
||||
|
||||
return <li class="result"><a href={`${search.urlRoot}items/${id}`} data-target="push" data-entry={`item|${item.name}`}>
|
||||
<span class="col itemiconcol">
|
||||
<span style={Dex.getItemIcon(item)}></span>
|
||||
</span>
|
||||
|
||||
<span class="col namecol">{this.renderName(item.name, matchStart, matchEnd)}</span>
|
||||
|
||||
{errorMessage}
|
||||
|
||||
{!errorMessage && <span class="col itemdesccol">{item.shortDesc}</span>}
|
||||
</a></li>;
|
||||
}
|
||||
|
||||
renderAbilityRow(id: ID, matchStart: number, matchEnd: number, errorMessage?: preact.ComponentChildren) {
|
||||
const search = this.props.search;
|
||||
const ability = search.dex.getAbility(id);
|
||||
if (!ability) return <li class="result">Unrecognized ability</li>;
|
||||
|
||||
return <li class="result"><a href={`${search.urlRoot}abilitys/${id}`} data-target="push" data-entry={`ability|${ability.name}`}>
|
||||
<span class="col namecol">{this.renderName(ability.name, matchStart, matchEnd)}</span>
|
||||
|
||||
{errorMessage}
|
||||
|
||||
{!errorMessage && <span class="col abilitydesccol">{ability.shortDesc}</span>}
|
||||
</a></li>;
|
||||
}
|
||||
|
||||
renderMoveRow(id: ID, matchStart: number, matchEnd: number, errorMessage?: preact.ComponentChildren) {
|
||||
const search = this.props.search;
|
||||
const move = search.dex.getMove(id);
|
||||
if (!move) return <li class="result">Unrecognized move</li>;
|
||||
|
||||
const tagStart = (move.name.startsWith('Hidden Power') ? 12 : 0);
|
||||
|
||||
if (errorMessage) {
|
||||
return <li class="result"><a href={`${search.urlRoot}move/${id}`} data-target="push" data-entry={`move|${move.name}`}>
|
||||
<span class="col movenamecol">{this.renderName(move.name, matchStart, matchEnd, tagStart)}</span>
|
||||
|
||||
{errorMessage}
|
||||
</a></li>;
|
||||
}
|
||||
|
||||
return <li class="result"><a href={`${search.urlRoot}move/${id}`} data-target="push" data-entry={`move|${move.name}`}>
|
||||
<span class="col movenamecol">{this.renderName(move.name, matchStart, matchEnd, tagStart)}</span>
|
||||
|
||||
<span class="col typecol">
|
||||
<img src={`${Dex.resourcePrefix}sprites/types/${move.type}.png`} alt={move.type} height="14" width="32" class="pixelated" />
|
||||
<img src={`${Dex.resourcePrefix}sprites/categories/${move.category}.png`} alt={move.category} height="14" width="32" class="pixelated" />
|
||||
</span>
|
||||
|
||||
<span class="col labelcol">
|
||||
{move.category !== 'Status' ? [<em>Power</em>, <br />, `${move.basePower}` || '\u2014'] : ''}
|
||||
</span>
|
||||
<span class="col widelabelcol">
|
||||
<em>Accuracy</em><br />${move.accuracy && move.accuracy !== true ? `${move.accuracy}%` : '\u2014'}
|
||||
</span>
|
||||
<span class="col pplabelcol">
|
||||
<em>PP</em><br />{move.pp === 1 || move.noPPBoosts ? move.pp : move.pp * 8 / 5}
|
||||
</span>
|
||||
|
||||
<span class="col movedesccol">{move.shortDesc}</span>
|
||||
|
||||
</a></li>;
|
||||
}
|
||||
|
||||
renderTypeRow(id: ID, matchStart: number, matchEnd: number, errorMessage?: preact.ComponentChildren) {
|
||||
const search = this.props.search;
|
||||
const name = id.charAt(0).toUpperCase() + id.slice(1);
|
||||
|
||||
return <li class="result"><a href={`${search.urlRoot}types/${id}`} data-target="push" data-entry={`type|${name}`}>
|
||||
<span class="col namecol">{this.renderName(name, matchStart, matchEnd)}</span>
|
||||
|
||||
<span class="col typecol">
|
||||
<img src={`${Dex.resourcePrefix}sprites/types/${name}.png`} alt={name} height="14" width="32" class="pixelated" />
|
||||
</span>
|
||||
|
||||
{errorMessage}
|
||||
</a></li>;
|
||||
}
|
||||
|
||||
renderCategoryRow(id: ID, matchStart: number, matchEnd: number, errorMessage?: preact.ComponentChildren) {
|
||||
const search = this.props.search;
|
||||
const name = id.charAt(0).toUpperCase() + id.slice(1);
|
||||
|
||||
return <li class="result"><a href={`${search.urlRoot}categories/${id}`} data-target="push" data-entry={`category|${name}`}>
|
||||
<span class="col namecol">{this.renderName(name, matchStart, matchEnd)}</span>
|
||||
|
||||
<span class="col typecol">
|
||||
<img src={`${Dex.resourcePrefix}sprites/categories/${name}.png`} alt={name} height="14" width="32" class="pixelated" />
|
||||
</span>
|
||||
|
||||
{errorMessage}
|
||||
</a></li>;
|
||||
}
|
||||
|
||||
renderArticleRow(id: ID, matchStart: number, matchEnd: number, errorMessage?: preact.ComponentChildren) {
|
||||
const search = this.props.search;
|
||||
const isSearchType = (id === 'pokemon' || id === 'moves');
|
||||
const name = (window.BattleArticleTitles && window.BattleArticleTitles[id]) ||
|
||||
(id.charAt(0).toUpperCase() + id.substr(1));
|
||||
|
||||
return <li class="result"><a href={`${search.urlRoot}articles/${id}`} data-target="push" data-entry={`article|${name}`}>
|
||||
<span class="col namecol">{this.renderName(name, matchStart, matchEnd)}</span>
|
||||
|
||||
<span class="col movedesccol">{isSearchType ? "(search type)" : "(article)"}</span>
|
||||
|
||||
{errorMessage}
|
||||
</a></li>;
|
||||
}
|
||||
|
||||
renderEggGroupRow(id: ID, matchStart: number, matchEnd: number, errorMessage?: preact.ComponentChildren) {
|
||||
const search = this.props.search;
|
||||
// very hardcode
|
||||
let name: string | undefined;
|
||||
if (id === 'humanlike') name = 'Human-Like';
|
||||
else if (id === 'water1') name = 'Water 1';
|
||||
else if (id === 'water2') name = 'Water 2';
|
||||
else if (id === 'water3') name = 'Water 3';
|
||||
if (name) {
|
||||
if (matchEnd > 5) matchEnd++;
|
||||
} else {
|
||||
name = id.charAt(0).toUpperCase() + id.slice(1);
|
||||
}
|
||||
|
||||
return <li class="result"><a href={`${search.urlRoot}egggroups/${id}`} data-target="push" data-entry={`egggroup|${name}`}>
|
||||
<span class="col namecol">{this.renderName(name, matchStart, matchEnd)}</span>
|
||||
|
||||
<span class="col movedesccol">(egg group)</span>
|
||||
|
||||
{errorMessage}
|
||||
</a></li>;
|
||||
}
|
||||
|
||||
renderTierRow(id: ID, matchStart: number, matchEnd: number, errorMessage?: preact.ComponentChildren) {
|
||||
const search = this.props.search;
|
||||
// very hardcode
|
||||
const tierTable: {[id: string]: string} = {
|
||||
uber: "Uber",
|
||||
lcuber: "LC Uber",
|
||||
caplc: "CAP LC",
|
||||
capnfe: "CAP NFE",
|
||||
};
|
||||
const name = tierTable[id] || id.toUpperCase();
|
||||
|
||||
return <li class="result"><a href={`${search.urlRoot}tiers/${id}`} data-target="push" data-entry={`tier|${name}`}>
|
||||
<span class="col namecol">{this.renderName(name, matchStart, matchEnd)}</span>
|
||||
|
||||
<span class="col movedesccol">(tier)</span>
|
||||
|
||||
{errorMessage}
|
||||
</a></li>;
|
||||
}
|
||||
|
||||
renderRow(row: SearchRow) {
|
||||
const search = this.props.search;
|
||||
const [type, id] = row;
|
||||
let matchStart = 0;
|
||||
let matchEnd = 0;
|
||||
if (row.length > 3) {
|
||||
matchStart = row[2]!;
|
||||
matchEnd = row[3]!;
|
||||
}
|
||||
|
||||
let errorMessage: preact.ComponentChild = null;
|
||||
if (search.qType && search.qType !== type) {
|
||||
errorMessage = <span class="col filtercol"><em>Filter</em></span>;
|
||||
} else if (search.legalityFilter && !(id in search.legalityFilter)) {
|
||||
errorMessage = <span class="col illegalcol"><em>{search.legalityLabel}</em></span>;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case 'html':
|
||||
const sanitizedHTML = id.replace(/</g, '<')
|
||||
.replace(/<em>/g, '<em>').replace(/<\/em>/g, '</em>')
|
||||
.replace(/<strong>/g, '<strong>').replace(/<\/strong>/g, '</strong>');
|
||||
return <li class="result">
|
||||
<p dangerouslySetInnerHTML={{__html: sanitizedHTML}}></p>
|
||||
</li>;
|
||||
case 'header':
|
||||
return <li class="result"><h3>{id}</h3></li>;
|
||||
case 'sortpokemon':
|
||||
return this.renderPokemonSortRow();
|
||||
case 'sortmove':
|
||||
return this.renderMoveSortRow();
|
||||
case 'pokemon':
|
||||
return this.renderPokemonRow(id as ID, matchStart, matchEnd, errorMessage);
|
||||
case 'move':
|
||||
return this.renderMoveRow(id as ID, matchStart, matchEnd, errorMessage);
|
||||
case 'item':
|
||||
return this.renderItemRow(id as ID, matchStart, matchEnd, errorMessage);
|
||||
case 'ability':
|
||||
return this.renderAbilityRow(id as ID, matchStart, matchEnd, errorMessage);
|
||||
case 'type':
|
||||
return this.renderTypeRow(id as ID, matchStart, matchEnd, errorMessage);
|
||||
case 'egggroup':
|
||||
return this.renderEggGroupRow(id as ID, matchStart, matchEnd, errorMessage);
|
||||
case 'tier':
|
||||
return this.renderTierRow(id as ID, matchStart, matchEnd, errorMessage);
|
||||
case 'category':
|
||||
return this.renderCategoryRow(id as ID, matchStart, matchEnd, errorMessage);
|
||||
case 'article':
|
||||
return this.renderArticleRow(id as ID, matchStart, matchEnd, errorMessage);
|
||||
}
|
||||
return <li>Error: not found</li>;
|
||||
}
|
||||
|
||||
render() {
|
||||
const search = this.props.search;
|
||||
return <div class="searchresults"><ul class="dexlist">
|
||||
{search.filters && <p>
|
||||
Filters: {}
|
||||
{search.filters.map(([type, name]) =>
|
||||
<button class="filter" value={`${type}:${name}`}>
|
||||
${name} <i class="fa fa-times-circle"></i>
|
||||
</button>
|
||||
)}
|
||||
{!search.q && <small style="color: #888">(backspace = delete filter)</small>}
|
||||
</p>}
|
||||
{search.results &&
|
||||
// TODO: implement windowing
|
||||
// for now, just show first ten results
|
||||
search.results.slice(0, 10).map(result =>
|
||||
this.renderRow(result)
|
||||
)}
|
||||
</ul></div>;
|
||||
}
|
||||
}
|
||||
2
src/globals.d.ts
vendored
2
src/globals.d.ts
vendored
|
|
@ -42,8 +42,6 @@ declare var exports: any;
|
|||
type AnyObject = {[k: string]: any};
|
||||
declare var app: {user: AnyObject, rooms: AnyObject, ignore?: AnyObject};
|
||||
|
||||
declare var BattleSearch: any;
|
||||
|
||||
interface Window {
|
||||
[k: string]: any;
|
||||
}
|
||||
|
|
|
|||
197
src/panel-teambuilder-team.tsx
Normal file
197
src/panel-teambuilder-team.tsx
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
/**
|
||||
* Teambuilder team panel
|
||||
*
|
||||
* @author Guangcong Luo <guangcongluo@gmail.com>
|
||||
* @license AGPLv3
|
||||
*/
|
||||
|
||||
class TeamTextbox extends preact.Component<{sets: PokemonSet[]}> {
|
||||
setInfo: {
|
||||
species: string,
|
||||
bottomY: number,
|
||||
}[] = [];
|
||||
textbox: HTMLTextAreaElement = null!;
|
||||
heightTester: HTMLTextAreaElement = null!;
|
||||
activeType: 'pokemon' | 'move' | 'item' | 'ability' | '' = '';
|
||||
activeOffsetY = -1;
|
||||
search = new BattleSearch();
|
||||
getYAt(index: number, value: string) {
|
||||
if (index < 0) return 10;
|
||||
this.heightTester.value = value.slice(0, index);
|
||||
return this.heightTester.scrollHeight;
|
||||
}
|
||||
input = () => this.update();
|
||||
select = () => this.update(true);
|
||||
update = (cursorOnly?: boolean) => {
|
||||
const textbox = this.textbox;
|
||||
this.heightTester.style.width = `${textbox.offsetWidth}px`;
|
||||
const value = textbox.value;
|
||||
|
||||
let index = 0;
|
||||
let setIndex = -1;
|
||||
if (!cursorOnly) this.setInfo = [];
|
||||
this.activeOffsetY = -1;
|
||||
this.activeType = '';
|
||||
|
||||
const selectionStart = textbox.selectionStart || 0;
|
||||
const selectionEnd = textbox.selectionEnd || 0;
|
||||
|
||||
/** 0 = set top, 1 = set middle */
|
||||
let parseState: 0 | 1 = 0;
|
||||
while (index < value.length) {
|
||||
let nlIndex = value.indexOf('\n', index);
|
||||
if (nlIndex < 0) nlIndex = value.length;
|
||||
const line = value.slice(index, nlIndex).trim();
|
||||
|
||||
if (!line) {
|
||||
parseState = 0;
|
||||
index = nlIndex + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (parseState === 0 && index && !cursorOnly) {
|
||||
this.setInfo[this.setInfo.length - 1].bottomY = this.getYAt(index - 1, value);
|
||||
}
|
||||
|
||||
if (parseState === 0) {
|
||||
if (!cursorOnly) {
|
||||
const atIndex = line.indexOf('@');
|
||||
let species = atIndex >= 0 ? line.slice(0, atIndex).trim() : line;
|
||||
if (species.endsWith(')')) {
|
||||
const parenIndex = species.lastIndexOf(' (');
|
||||
if (parenIndex >= 0) {
|
||||
species = species.slice(parenIndex + 2, -1);
|
||||
}
|
||||
}
|
||||
this.setInfo.push({
|
||||
species,
|
||||
bottomY: -1,
|
||||
});
|
||||
}
|
||||
parseState = 1;
|
||||
setIndex++;
|
||||
}
|
||||
|
||||
const selectionEndCutoff = (selectionStart === selectionEnd ? nlIndex : nlIndex + 1);
|
||||
if (index <= selectionStart && selectionEnd <= selectionEndCutoff) {
|
||||
// both ends within range
|
||||
this.activeOffsetY = this.getYAt(index - 1, value);
|
||||
|
||||
const lcLine = line.toLowerCase().trim();
|
||||
if (lcLine.startsWith('ability:')) {
|
||||
this.activeType = 'ability';
|
||||
} else if (lcLine.startsWith('-')) {
|
||||
this.activeType = 'move';
|
||||
} else if (
|
||||
!lcLine || lcLine.startsWith('ivs:') || lcLine.startsWith('evs:') ||
|
||||
lcLine.startsWith('level:') || lcLine.startsWith('gender:') ||
|
||||
lcLine.endsWith(' nature') || lcLine.startsWith('shiny:')
|
||||
) {
|
||||
// leave activeType blank
|
||||
} else {
|
||||
this.activeType = 'pokemon';
|
||||
}
|
||||
this.search.setType(this.activeType, 'gen7ou' as ID, this.props.sets[setIndex]);
|
||||
this.search.find('');
|
||||
}
|
||||
|
||||
index = nlIndex + 1;
|
||||
}
|
||||
if (!cursorOnly) {
|
||||
const bottomY = this.getYAt(value.length, value);
|
||||
if (this.setInfo.length) {
|
||||
this.setInfo[this.setInfo.length - 1].bottomY = bottomY;
|
||||
}
|
||||
|
||||
textbox.style.height = `${bottomY + 100}px`;
|
||||
}
|
||||
this.forceUpdate();
|
||||
};
|
||||
componentDidMount() {
|
||||
this.textbox = this.base!.getElementsByClassName('teamtextbox')[0] as HTMLTextAreaElement;
|
||||
this.heightTester = this.base!.getElementsByClassName('heighttester')[0] as HTMLTextAreaElement;
|
||||
|
||||
const exportedTeam = PSTeambuilder.exportTeam(this.props.sets);
|
||||
this.textbox.value = exportedTeam;
|
||||
this.update();
|
||||
}
|
||||
componentWillUnmount() {
|
||||
this.textbox = null!;
|
||||
this.heightTester = null!;
|
||||
}
|
||||
render() {
|
||||
return <div class="teameditor">
|
||||
<textarea class="textbox teamtextbox" onInput={this.input} onSelect={this.select} onClick={this.select} onKeyUp={this.select} />
|
||||
<textarea
|
||||
class="textbox teamtextbox heighttester" style="visibility:hidden" tabIndex={-1} aria-hidden={true}
|
||||
/>
|
||||
<div class="teamoverlays">
|
||||
{this.setInfo.slice(0, -1).map(info =>
|
||||
<hr style={`top:${info.bottomY - 18}px`} />
|
||||
)}
|
||||
{this.setInfo.map((info, i) => {
|
||||
if (!info.species) return null;
|
||||
const prevOffset = i === 0 ? 8 : this.setInfo[i - 1].bottomY;
|
||||
const species = info.species;
|
||||
const num = Dex.getPokemonIconNum(toID(species));
|
||||
if (!num) return null;
|
||||
|
||||
const top = Math.floor(num / 12) * 30;
|
||||
const left = (num % 12) * 40;
|
||||
const iconStyle = `background:transparent url(${Dex.resourcePrefix}sprites/smicons-sheet.png?a5) no-repeat scroll -${left}px -${top}px`;
|
||||
|
||||
return <span class="picon" style={
|
||||
`top:${prevOffset + 1}px;left:50px;position:absolute;${iconStyle}`
|
||||
}></span>;
|
||||
})}
|
||||
{this.activeOffsetY >= 0 &&
|
||||
<div class="teaminnertextbox" style={{top: this.activeOffsetY - 1}}></div>
|
||||
}
|
||||
</div>
|
||||
{this.activeType && <PSSearchResults search={this.search} />}
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
|
||||
class TeamPanel extends PSRoomPanel {
|
||||
sets: PokemonSet[] | null = null;
|
||||
backToList = () => {
|
||||
PS.removeRoom(this.props.room);
|
||||
PS.join('teambuilder' as RoomID);
|
||||
};
|
||||
render() {
|
||||
const room = this.props.room;
|
||||
const team = PS.teams.byKey[room.id.slice(5)];
|
||||
if (!team) {
|
||||
return <PSPanelWrapper room={room}>
|
||||
<button class="button" onClick={this.backToList}>
|
||||
<i class="fa fa-chevron-left"></i> List
|
||||
</button>
|
||||
<p class="error">
|
||||
Team doesn't exist
|
||||
</p>
|
||||
</PSPanelWrapper>;
|
||||
}
|
||||
|
||||
const sets = this.sets || PSTeambuilder.unpackTeam(team!.packedTeam);
|
||||
if (!this.sets) this.sets = sets;
|
||||
return <PSPanelWrapper room={room} scrollable>
|
||||
<div class="pad">
|
||||
<button class="button" onClick={this.backToList}>
|
||||
<i class="fa fa-chevron-left"></i> List
|
||||
</button>
|
||||
<h2>
|
||||
{team.name}
|
||||
</h2>
|
||||
<TeamTextbox sets={sets} />
|
||||
</div>
|
||||
</PSPanelWrapper>;
|
||||
}
|
||||
}
|
||||
|
||||
PS.roomTypes['team'] = {
|
||||
Model: PSRoom,
|
||||
Component: TeamPanel,
|
||||
title: "Team",
|
||||
};
|
||||
PS.updateRoomTypes();
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Teambuilder Panel
|
||||
* Teambuilder panel
|
||||
*
|
||||
* @author Guangcong Luo <guangcongluo@gmail.com>
|
||||
* @license AGPLv3
|
||||
|
|
@ -38,7 +38,7 @@ class TeambuilderPanel extends PSRoomPanel {
|
|||
/**
|
||||
* Folders, in a format where lexical sort will sort correctly.
|
||||
*/
|
||||
let folders = [];
|
||||
let folders: string[] = [];
|
||||
for (let i = -2; i < PS.teams.list.length; i++) {
|
||||
const team = i >= 0 ? PS.teams.list[i] : null;
|
||||
if (team) {
|
||||
|
|
@ -99,7 +99,7 @@ class TeambuilderPanel extends PSRoomPanel {
|
|||
</TeamFolder>,
|
||||
];
|
||||
|
||||
let renderedFolders = [];
|
||||
let renderedFolders: preact.ComponentChild[] = [];
|
||||
|
||||
for (let format of folders) {
|
||||
let newGen = '';
|
||||
|
|
@ -220,108 +220,8 @@ class TeambuilderPanel extends PSRoomPanel {
|
|||
}
|
||||
}
|
||||
|
||||
class TeamTextbox extends preact.Component<{sets: PokemonSet[]}> {
|
||||
separators: number[] = [];
|
||||
textbox: HTMLTextAreaElement = null!;
|
||||
heightTester: HTMLTextAreaElement = null!;
|
||||
update = () => {
|
||||
const textbox = this.textbox;
|
||||
const heightTester = this.heightTester;
|
||||
heightTester.style.width = `${textbox.offsetWidth}px`;
|
||||
const value = textbox.value;
|
||||
|
||||
let separatorIndex = value.indexOf('\n\n');
|
||||
const separators: number[] = [];
|
||||
while (separatorIndex >= 0) {
|
||||
while (value.charAt(separatorIndex + 2) === '\n') separatorIndex++;
|
||||
heightTester.value = value.slice(0, separatorIndex);
|
||||
separators.push(heightTester.scrollHeight);
|
||||
|
||||
separatorIndex = value.indexOf('\n\n', separatorIndex + 1);
|
||||
}
|
||||
|
||||
heightTester.value = textbox.value;
|
||||
textbox.style.height = `${heightTester.scrollHeight + 100}px`;
|
||||
this.separators = separators;
|
||||
this.forceUpdate();
|
||||
};
|
||||
componentDidMount() {
|
||||
this.textbox = this.base!.getElementsByClassName('teamtextbox')[0] as HTMLTextAreaElement;
|
||||
this.heightTester = this.base!.getElementsByClassName('heighttester')[0] as HTMLTextAreaElement;
|
||||
|
||||
const exportedTeam = PSTeambuilder.exportTeam(this.props.sets);
|
||||
this.textbox.value = exportedTeam;
|
||||
this.update();
|
||||
}
|
||||
componentWillUnmount() {
|
||||
this.textbox = null!;
|
||||
this.heightTester = null!;
|
||||
}
|
||||
render() {
|
||||
return <div class="teameditor">
|
||||
<textarea class="textbox teamtextbox" onInput={this.update} />
|
||||
<textarea
|
||||
class="textbox teamtextbox heighttester" style="visibility:hidden" tabIndex={-1} aria-hidden={true}
|
||||
/>
|
||||
<div class="teamoverlays">
|
||||
{this.separators.map(offset =>
|
||||
<hr style={`top:${offset}px`} />
|
||||
)}
|
||||
{this.props.sets.map((set, i) => {
|
||||
const prevOffset = i === 0 ? -5 : this.separators[i - 1];
|
||||
return <span class="picon" style={
|
||||
`top:${prevOffset + 10}px;left:50px;position:absolute;` + Dex.getPokemonIcon(set.species)
|
||||
}></span>;
|
||||
})}
|
||||
</div>
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
|
||||
class TeamPanel extends PSRoomPanel {
|
||||
sets: PokemonSet[] | null = null;
|
||||
backToList = () => {
|
||||
PS.removeRoom(this.props.room);
|
||||
PS.join('teambuilder' as RoomID);
|
||||
};
|
||||
render() {
|
||||
const room = this.props.room;
|
||||
const team = PS.teams.byKey[room.id.slice(5)];
|
||||
if (!team) {
|
||||
return <PSPanelWrapper room={room}>
|
||||
<button class="button" onClick={this.backToList}>
|
||||
<i class="fa fa-chevron-left"></i> List
|
||||
</button>
|
||||
<p class="error">
|
||||
Team doesn't exist
|
||||
</p>
|
||||
</PSPanelWrapper>;
|
||||
}
|
||||
|
||||
const sets = this.sets || PSTeambuilder.unpackTeam(team!.packedTeam);
|
||||
if (!this.sets) this.sets = sets;
|
||||
return <PSPanelWrapper room={room} scrollable>
|
||||
<div class="pad">
|
||||
<button class="button" onClick={this.backToList}>
|
||||
<i class="fa fa-chevron-left"></i> List
|
||||
</button>
|
||||
<h2>
|
||||
{team.name}
|
||||
</h2>
|
||||
<TeamTextbox sets={sets} />
|
||||
</div>
|
||||
</PSPanelWrapper>;
|
||||
}
|
||||
}
|
||||
|
||||
PS.roomTypes['teambuilder'] = {
|
||||
Model: PSRoom,
|
||||
Component: TeambuilderPanel,
|
||||
title: "Teambuilder",
|
||||
};
|
||||
PS.roomTypes['team'] = {
|
||||
Model: PSRoom,
|
||||
Component: TeamPanel,
|
||||
title: "Team",
|
||||
};
|
||||
PS.updateRoomTypes();
|
||||
|
|
|
|||
354
style/battle-search.css
Normal file
354
style/battle-search.css
Normal file
|
|
@ -0,0 +1,354 @@
|
|||
.dexlist, .dexlist li {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: block;
|
||||
clear: both;
|
||||
word-wrap: normal;
|
||||
}
|
||||
|
||||
.dexlist li > a {
|
||||
display: block;
|
||||
height: 30px;
|
||||
padding: 0 0 0 4px;
|
||||
border: 1px solid transparent;
|
||||
margin: 0 5px 1px 5px;
|
||||
text-decoration: none;
|
||||
}
|
||||
.dexlist li > a.cur {
|
||||
border-color: #CCCCCC;
|
||||
background: #F2F2F2;
|
||||
}
|
||||
.dexlist .filter,
|
||||
.searchboxwrapper .filter {
|
||||
padding:1px 3px;
|
||||
border-radius: 3px;
|
||||
border: 1px solid #777;
|
||||
background: #EEE;
|
||||
color: black;
|
||||
font-size: 9pt;
|
||||
font-family: Verdana, sans-serif;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
}
|
||||
.dexlist .filter:hover,
|
||||
.searchboxwrapper .filter:hover {
|
||||
color: #777777;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
.searchboxwrapper .filter.noclear:hover {
|
||||
color: black;
|
||||
text-decoration: none;
|
||||
cursor: default;
|
||||
}
|
||||
.dexlist .filter i,
|
||||
.searchboxwrapper .filter i {
|
||||
color: #999999;
|
||||
}
|
||||
.dexlist .filter:hover i,
|
||||
.searchboxwrapper .filter:hover i {
|
||||
color: #BB2222;
|
||||
}
|
||||
.resultheader,
|
||||
.dexlist li.resultheader,
|
||||
.dexlist .result {
|
||||
height: 32px;
|
||||
padding: 1px 0 0 0;
|
||||
}
|
||||
.result p,
|
||||
.resultheader p,
|
||||
.dexlist .result p {
|
||||
padding: 7px 0 0 8px;
|
||||
margin: 0;
|
||||
}
|
||||
.dexlist h3,
|
||||
.dexentry h3,
|
||||
.resultheader h3 {
|
||||
margin: 5px 0 0 -1px;
|
||||
padding: 3px 8px;
|
||||
font-family: Verdana, sans-serif;
|
||||
font-size: 10pt;
|
||||
|
||||
background: #DAE5F0;
|
||||
color: black;
|
||||
border: 1px solid #AAAAAA;
|
||||
text-shadow: 1px 1px 0 rgba(255,255,255,.6);
|
||||
/* box-shadow: inset 1px 1px 0 rgba(255,255,255,.6), 0px 2px 2px rgba(0,0,0,.15); */
|
||||
box-shadow: inset 1px 1px 0 rgba(255,255,255,.6);
|
||||
}
|
||||
.dexlist li > em {
|
||||
display: block;
|
||||
padding: 0 8px;
|
||||
font-size: 10pt;
|
||||
}
|
||||
.dexlist .col {
|
||||
float: left;
|
||||
padding-top: 7px;
|
||||
height: 22px;
|
||||
font-size: 9pt;
|
||||
color: #444444;
|
||||
}
|
||||
.dexlist .iconcol {
|
||||
padding-top: 0px;
|
||||
width: 40px;
|
||||
height: 30px;
|
||||
}
|
||||
.dexlist .iconcol span {
|
||||
display: block;
|
||||
width: 40px;
|
||||
height: 30px;
|
||||
background: transparent none no-repeat scroll 0px -8px;
|
||||
}
|
||||
.dexlist .itemiconcol {
|
||||
padding-top: 3px;
|
||||
width: 24px;
|
||||
height: 27px;
|
||||
}
|
||||
.dexlist .itemiconcol span {
|
||||
display: block;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
background: transparent none no-repeat scroll 0px 0px;
|
||||
}
|
||||
.dexlist .numcol {
|
||||
width: 24px;
|
||||
padding-right: 5px;
|
||||
text-align: right;
|
||||
color: #999999;
|
||||
padding-top: 8px;
|
||||
font-size: 8pt;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.dexlist .statcol,
|
||||
.dexlist .bstcol,
|
||||
.dexlist .labelcol,
|
||||
.dexlist .widelabelcol,
|
||||
.dexlist .pplabelcol {
|
||||
padding-top: 1px;
|
||||
height: 28px;
|
||||
width: 24px;
|
||||
text-align: right;
|
||||
font-size: 8pt;
|
||||
}
|
||||
.dexlist .labelcol {
|
||||
text-align: center;
|
||||
width: 30px;
|
||||
margin-left: -2px;
|
||||
}
|
||||
.dexlist .widelabelcol {
|
||||
text-align: center;
|
||||
width: 50px;
|
||||
}
|
||||
.dexlist .pplabelcol {
|
||||
text-align: center;
|
||||
width: 18px;
|
||||
padding-right: 5px;
|
||||
}
|
||||
.dexlist .bstcol {
|
||||
padding-left: 2px;
|
||||
}
|
||||
.dexlist .labelcol em,
|
||||
.dexlist .widelabelcol em,
|
||||
.dexlist .pplabelcol em,
|
||||
.dexlist .statcol em,
|
||||
.dexlist .bstcol em {
|
||||
color: #999999;
|
||||
font-size: 7pt;
|
||||
font-style: normal;
|
||||
}
|
||||
.dexlist .stattitlecol {
|
||||
padding-top: 2px;
|
||||
width: 20px;
|
||||
text-align: right;
|
||||
font-size: 7pt;
|
||||
color: #999999;
|
||||
}
|
||||
.dexlist .namecol {
|
||||
padding-top: 6px;
|
||||
height: 23px;
|
||||
width: 120px;
|
||||
color: #000000;
|
||||
font-size: 10pt;
|
||||
}
|
||||
.dexlist .pokemonnamecol {
|
||||
padding-top: 6px;
|
||||
height: 23px;
|
||||
width: 127px;
|
||||
color: #000000;
|
||||
font-size: 10pt;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.dexlist .shortpokemonnamecol {
|
||||
padding-top: 6px;
|
||||
height: 23px;
|
||||
width: 118px;
|
||||
color: #000000;
|
||||
font-size: 10pt;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.dexlist .movenamecol {
|
||||
padding-top: 6px;
|
||||
height: 23px;
|
||||
width: 152px;
|
||||
color: #000000;
|
||||
font-size: 10pt;
|
||||
}
|
||||
.dexlist .shortmovenamecol {
|
||||
padding-top: 6px;
|
||||
height: 23px;
|
||||
width: 112px;
|
||||
color: #000000;
|
||||
font-size: 10pt;
|
||||
}
|
||||
.dexlist .tagcol {
|
||||
padding-top: 6px;
|
||||
height: 24px;
|
||||
width: 34px;
|
||||
border-right: 1px solid #CCCCCC;
|
||||
margin-right: 5px;
|
||||
text-align: center;
|
||||
color: #000000;
|
||||
font-size: 10pt;
|
||||
}
|
||||
.dexlist .tagcol.shorttagcol {
|
||||
margin-right: 1px;
|
||||
}
|
||||
.dexlist .typecol {
|
||||
width: 70px;
|
||||
}
|
||||
.dexlist .abilitycol {
|
||||
padding-top: 8px;
|
||||
height: 21px;
|
||||
font-size: 8pt;
|
||||
width: 86px;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.dexlist .twoabilitycol {
|
||||
padding-top: 1px;
|
||||
height: 28px;
|
||||
font-size: 8pt;
|
||||
width: 86px;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.dexlist .hacol {
|
||||
font-style: italic;
|
||||
}
|
||||
.dexlist .unreleasedhacol {
|
||||
font-style: italic;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
.dexlist b {
|
||||
color: #4488CC;
|
||||
text-decoration: underline;
|
||||
}
|
||||
.dexlist small {
|
||||
font-size: 8pt;
|
||||
}
|
||||
.dexlist small b {
|
||||
font-weight: normal;
|
||||
}
|
||||
.dexlist .illegalcol em {
|
||||
padding: 2px 4px;
|
||||
height: auto;
|
||||
border: 1px solid #AA2222;
|
||||
color: #AA2222;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.dexlist .filtercol em {
|
||||
padding: 2px 4px;
|
||||
height: auto;
|
||||
border: 1px solid #22AA22;
|
||||
color: #22AA22;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.dexlist .typecol img {
|
||||
opacity: 0.6;
|
||||
margin-right: 1px;
|
||||
}
|
||||
.dexlist .typecol img.b {
|
||||
opacity: 1;
|
||||
outline: #4488CC solid 1px;
|
||||
outline-offset: 0;
|
||||
background: #4488CC;
|
||||
}
|
||||
.dexlist .itemdesccol,
|
||||
.dexlist .abilitydesccol,
|
||||
.dexlist .movedesccol {
|
||||
white-space: nowrap;
|
||||
padding-top: 8px;
|
||||
font-size: 8pt;
|
||||
width: 488px;
|
||||
height: 21px;
|
||||
overflow: hidden;
|
||||
color: #777777;
|
||||
}
|
||||
.dexlist .movedesccol {
|
||||
width: 284px;
|
||||
}
|
||||
.dexlist .itemdesccol {
|
||||
width: 464px;
|
||||
}
|
||||
|
||||
.dexlist .sortrow {
|
||||
background: #D0D0D0;
|
||||
border-bottom: 1px solid #888;
|
||||
height: 20px;
|
||||
color: black;
|
||||
}
|
||||
.dexlist .sortcol {
|
||||
font-family: Verdana, sans-serif;
|
||||
font-size: 8pt;
|
||||
background: transparent;
|
||||
color: black;
|
||||
float: left;
|
||||
border-radius: 0;
|
||||
border: 0;
|
||||
padding: 0 0 0 0;
|
||||
text-align: center;
|
||||
height: 20px;
|
||||
}
|
||||
.dexlist .sortcol.cur {
|
||||
font-weight: bold;
|
||||
background: #E0E0E0;
|
||||
}
|
||||
.dexlist .sortcol:hover {
|
||||
background: #F0F0F0;
|
||||
}
|
||||
.dexlist .sortcol.numsortcol.cur,
|
||||
.dexlist .sortcol.numsortcol.cur:hover {
|
||||
background: #D0D0D0;
|
||||
cursor: default;
|
||||
}
|
||||
.dexlist .numsortcol {
|
||||
width: 80px;
|
||||
}
|
||||
.dexlist .pnamesortcol {
|
||||
width: 127px;
|
||||
}
|
||||
.dexlist .typesortcol {
|
||||
width: 70px;
|
||||
}
|
||||
.dexlist .abilitysortcol {
|
||||
width: 172px;
|
||||
}
|
||||
.dexlist .statsortcol {
|
||||
width: 24px;
|
||||
text-align: right;
|
||||
}
|
||||
.dexlist .movenamesortcol {
|
||||
width: 159px;
|
||||
}
|
||||
.dexlist .movetypesortcol {
|
||||
width: 35px;
|
||||
}
|
||||
.dexlist .powersortcol {
|
||||
width: 30px;
|
||||
}
|
||||
.dexlist .accuracysortcol {
|
||||
width: 49px;
|
||||
}
|
||||
.dexlist .ppsortcol {
|
||||
width: 23px;
|
||||
}
|
||||
|
|
@ -3,6 +3,33 @@
|
|||
padding-top: 8px;
|
||||
padding-left: 100px;
|
||||
box-sizing: border-box;
|
||||
line-height: 20px;
|
||||
}
|
||||
.teaminnertextbox {
|
||||
width: 320px;
|
||||
height: 18px;
|
||||
left: 96px;
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
|
||||
border: 1px solid #4488CC;
|
||||
border-radius: 3px;
|
||||
box-shadow: inset 0px 1px 2px #D2D2D2, 0px 0px 5px #66AADD;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.searchresults {
|
||||
background: #f2f2f2;
|
||||
border: 1px solid #888888;
|
||||
border-radius: 2px;
|
||||
|
||||
position: fixed;
|
||||
bottom: 5px;
|
||||
left: 5px;
|
||||
width: 640px;
|
||||
min-height: 200px;
|
||||
max-height: 400px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.teameditor {
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@
|
|||
linkStyle("style/sim-types.css");
|
||||
linkStyle("style/battle.css");
|
||||
linkStyle("style/teambuilder.css");
|
||||
linkStyle("style/utilichart.css");
|
||||
linkStyle("style/battle-search.css");
|
||||
linkStyle("style/font-awesome.css");
|
||||
</script>
|
||||
<script src="config/testclient-key.js"></script>
|
||||
|
|
@ -74,7 +74,12 @@
|
|||
<script src="data/moves.js"></script>
|
||||
<script src="data/items.js"></script>
|
||||
<script src="data/abilities.js"></script>
|
||||
<script src="data/search-index.js"></script>
|
||||
<script src="data/teambuilder-tables.js"></script>
|
||||
<script src="js/panel-teamdropdown.js"></script>
|
||||
<script src="js/panel-teambuilder.js"></script>
|
||||
<script src="js/panel-teambuilder.js?"></script>
|
||||
<script src="js/battle-search.js?"></script>
|
||||
<script src="js/battle-searchresults.js?"></script>
|
||||
<script src="js/panel-teambuilder-team.js?"></script>
|
||||
|
||||
</body></html>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user