/** * Search * * Basically just an improved version of utilichart * * Dependencies: jQuery, battledata, search-index * Optional dependencies: pokedex, moves, items, abilities * * @author Guangcong Luo */ (function(exports, $){ 'use strict'; function Search(elem) { this.$el = $(elem); this.el = this.$el[0]; } Search.prototype.$ = function(query) { return this.$el.find(query); }; // // Search functions // Search.prototype.q = null; var typeTable = { pokemon: 0, type: 1, move: 2, item: 3, ability: 4, egggroup: 5, category: 6 }; var typeName = { pokemon: 'Pokemon', type: 'Type', move: 'Moves', item: 'Items', ability: 'Abilities', egggroup: 'Egg group', category: 'Category' }; Search.prototype.find = function(query) { query = toId(query); if (query === this.q) { return false; } this.q = query; if (!query) { this.el.innerHTML = ''; this.exactMatch = false; return true; } var i = Search.getClosest(query); if (!BattleSearchIndex[i]) i--; if (BattleSearchIndex[i-1] && BattleSearchIndex[i-1] === query) i--; this.exactMatch = (query === BattleSearchIndex[i]); var bufs = ['','','','']; var topbufIndex = -1; var nearMatch = (BattleSearchIndex[i].substr(0,query.length) !== query); if (nearMatch && i) i--; for (var j=0; j<15; j++) { var id = BattleSearchIndex[i+j]; var type = BattleSearchIndexType[i+j]; var matchLength = query.length; if (!id) break; if (id.substr(0,query.length) !== query) { if (!(nearMatch && j<=1)) break; matchLength = 0; } if (j === 0 && this.exactMatch) { topbufIndex = typeTable[type]; } if (!bufs[typeTable[type]]) bufs[typeTable[type]] = '
  • '+typeName[type]+'

  • '; bufs[typeTable[type]] += Search.renderRow(id, type, 0, matchLength + (BattleSearchIndexOffset[i+j][matchLength-1]||'0').charCodeAt(0)-48); } var topbuf = ''; if (topbufIndex >= 0) { topbuf = bufs[topbufIndex]; bufs[topbufIndex] = ''; } if (nearMatch) topbuf = '
  • No exact match found. The closest matches alphabetically are:
  • '+topbuf; this.el.innerHTML = ''; return true; }; Search.getClosest = function(query) { // binary search through the index! var left = 0; var right = BattleSearchIndex.length - 1; while (right >= left) { var mid = Math.floor((right - left) / 2 + left); if (BattleSearchIndex[mid] === query) { // that's us return mid; } else if (BattleSearchIndex[mid] < query) { left = mid + 1; } else { right = mid - 1; } } return left; }; // // Rendering functions // // These are all static! // Search.urlRoot = ''; Search.renderRow = function(id, type, matchStart, matchLength, errorMessage) { switch (type) { case 'pokemon': var pokemon = BattlePokedex[id]; return Search.renderPokemonRow(pokemon, matchStart, matchLength, errorMessage); case 'move': var move = BattleMovedex[id]; return Search.renderMoveRow(move, matchStart, matchLength, errorMessage); case 'item': var item = BattleItems[id]; return Search.renderItemRow(item, matchStart, matchLength, errorMessage); case 'ability': var ability = BattleAbilities[id]; return Search.renderAbilityRow(ability, matchStart, matchLength, errorMessage); case 'type': var type = {name: id[0].toUpperCase()+id.substr(1)}; return Search.renderTypeRow(type, matchStart, matchLength, errorMessage); case 'egggroup': var egggroup = {name: id[0].toUpperCase()+id.substr(1)}; return Search.renderEggGroupRow(egggroup, matchStart, matchLength, errorMessage); case 'category': var category = {name: id[0].toUpperCase()+id.substr(1)}; return Search.renderCategoryRow(category, matchStart, matchLength, errorMessage); } return 'Error: not found'; }; Search.renderPokemonRow = function(pokemon, matchStart, matchLength, errorMessage) { var attrs = ''; if (Search.urlRoot) attrs = ' href="'+Search.urlRoot+'pokemon/'+toId(pokemon.species)+'" data-target="push"'; var buf = '
  • '; // number buf += ''+(pokemon.num>=0 ? pokemon.num : 'CAP')+' '; // icon buf += ''; buf += ''; buf += ' '; // name var name = pokemon.species; var tagStart = (pokemon.forme ? name.length-pokemon.forme.length-1 : 0); if (tagStart) name = name.substr(0, tagStart); if (matchLength) { name = name.substr(0, matchStart)+''+name.substr(matchStart, matchLength)+''+name.substr(matchStart+matchLength); } if (tagStart) { if (matchLength && matchStart+matchLength > tagStart) { if (matchStart < tagStart) { matchLength -= tagStart - matchStart; matchStart = tagStart; } name += ''+pokemon.species.substr(tagStart, matchStart-tagStart)+''+pokemon.species.substr(matchStart, matchLength)+''+pokemon.species.substr(matchStart+matchLength)+''; } else { name += ''+pokemon.species.substr(tagStart)+''; } } buf += ''+name+' '; // error if (errorMessage) { buf += ''+errorMessage+' '; buf += '
  • '; return buf; } // type buf += ''; for (var i=0; i'; buf += ability; } if (!pokemon.abilities['H']) buf += ''; buf += ''; buf += ''; // base stats buf += ''; buf += 'HP
    '+pokemon.baseStats.hp+'
    '; buf += 'Atk
    '+pokemon.baseStats.atk+'
    '; buf += 'Def
    '+pokemon.baseStats.def+'
    '; buf += 'SpA
    '+pokemon.baseStats.spa+'
    '; buf += 'SpD
    '+pokemon.baseStats.spd+'
    '; buf += 'Spe
    '+pokemon.baseStats.spe+'
    '; var bst = 0; for (i in pokemon.baseStats) bst += pokemon.baseStats[i]; buf += 'BST
    '+bst+'
    '; buf += '
    '; buf += ''; return buf; }; Search.renderTaggedPokemonRowInner = function(pokemon, tag, errorMessage) { var attrs = ''; if (Search.urlRoot) attrs = ' href="'+Search.urlRoot+'pokemon/'+toId(pokemon.species)+'" data-target="push"'; var buf = ''; // tag buf += ''+tag+' '; // icon buf += ''; buf += ''; buf += ' '; // name var name = pokemon.species; var tagStart = (pokemon.forme ? name.length-pokemon.forme.length-1 : 0); if (tagStart) name = name.substr(0, tagStart) + ''+pokemon.species.substr(tagStart)+''; buf += ''+name+' '; // error if (errorMessage) { buf += ''+errorMessage+' '; buf += ''; return buf; } // type buf += ''; for (var i=0; i'; buf += ability; } if (!pokemon.abilities['H']) buf += ''; buf += ''; buf += ''; // base stats buf += ''; buf += 'HP
    '+pokemon.baseStats.hp+'
    '; buf += 'Atk
    '+pokemon.baseStats.atk+'
    '; buf += 'Def
    '+pokemon.baseStats.def+'
    '; buf += 'SpA
    '+pokemon.baseStats.spa+'
    '; buf += 'SpD
    '+pokemon.baseStats.spd+'
    '; buf += 'Spe
    '+pokemon.baseStats.spe+'
    '; var bst = 0; for (i in pokemon.baseStats) bst += pokemon.baseStats[i]; buf += 'BST
    '+bst+'
    '; buf += '
    '; buf += ''; return buf; }; Search.renderItemRow = function(item, matchStart, matchLength, errorMessage) { var attrs = ''; if (Search.urlRoot) attrs = ' href="'+Search.urlRoot+'items/'+toId(item.name)+'" data-target="push"'; var buf = '
  • '; // icon buf += ''; buf += ''; buf += ' '; // name var name = item.name; if (matchLength) { name = name.substr(0, matchStart)+''+name.substr(matchStart, matchLength)+''+name.substr(matchStart+matchLength); } buf += ''+name+' '; // error if (errorMessage) { buf += ''+errorMessage+' '; buf += '
  • '; return buf; } // desc buf += ''+Tools.escapeHTML(item.shortDesc || item.desc)+' '; buf += ''; return buf; }; Search.renderAbilityRow = function(ability, matchStart, matchLength, errorMessage) { var attrs = ''; if (Search.urlRoot) attrs = ' href="'+Search.urlRoot+'abilities/'+toId(ability.name)+'" data-target="push"'; var buf = '
  • '; // name var name = ability.name; if (matchLength) { name = name.substr(0, matchStart)+''+name.substr(matchStart, matchLength)+''+name.substr(matchStart+matchLength); } buf += ''+name+' '; // error if (errorMessage) { buf += ''+errorMessage+' '; buf += '
  • '; return buf; } buf += ''+Tools.escapeHTML(ability.shortDesc || ability.desc)+' '; buf += ''; return buf; }; Search.renderMoveRow = function(move, matchStart, matchLength, errorMessage) { var attrs = ''; if (Search.urlRoot) attrs = ' href="'+Search.urlRoot+'moves/'+toId(move.name)+'" data-target="push"'; var buf = '
  • '; // name var name = move.name; var tagStart = (name.substr(0, 12) === 'Hidden Power' ? 12 : 0); if (tagStart) name = name.substr(0, tagStart); if (matchLength) { name = name.substr(0, matchStart)+''+name.substr(matchStart, matchLength)+''+name.substr(matchStart+matchLength); } if (tagStart) { if (matchLength && matchStart+matchLength > tagStart) { if (matchStart < tagStart) { matchLength -= tagStart - matchStart; matchStart = tagStart; } name += ''+move.name.substr(tagStart, matchStart-tagStart)+''+move.name.substr(matchStart, matchLength)+''+move.name.substr(matchStart+matchLength)+''; } else { name += ''+move.name.substr(tagStart)+''; } } buf += ''+name+' '; // error if (errorMessage) { buf += ''+errorMessage+' '; buf += '
  • '; return buf; } // type buf += ''; buf += Tools.getTypeIcon(move.type); buf += ''+move.category+''; buf += ' '; // power, accuracy, pp buf += ''+(move.category!=='Status'?('Power
    '+(move.basePower||'—')):'')+'
    '; buf += 'Accuracy
    '+(move.accuracy && move.accuracy!==true?move.accuracy+'%':'—')+'
    '; buf += 'PP
    '+(move.pp!==1?move.pp*8/5:move.pp)+'
    '; // desc buf += ''+Tools.escapeHTML(move.shortDesc || move.desc)+' '; buf += ''; return buf; }; Search.renderMoveRowInner = function(move, errorMessage) { var attrs = ''; if (Search.urlRoot) attrs = ' href="'+Search.urlRoot+'moves/'+toId(move.name)+'" data-target="push"'; var buf = ''; // name var name = move.name; var tagStart = (name.substr(0, 12) === 'Hidden Power' ? 12 : 0); if (tagStart) name = name.substr(0, tagStart) + ''+move.name.substr(tagStart)+''; buf += ''+name+' '; // error if (errorMessage) { buf += ''+errorMessage+' '; buf += ''; return buf; } // type buf += ''; buf += Tools.getTypeIcon(move.type); buf += ''+move.category+''; buf += ' '; // power, accuracy, pp buf += ''+(move.category!=='Status'?('Power
    '+(move.basePower||'—')):'')+'
    '; buf += 'Accuracy
    '+(move.accuracy && move.accuracy!==true?move.accuracy+'%':'—')+'
    '; buf += 'PP
    '+(move.pp!==1?move.pp*8/5:move.pp)+'
    '; // desc buf += ''+Tools.escapeHTML(move.shortDesc || move.desc)+' '; buf += ''; return buf; }; Search.renderTaggedMoveRow = function(move, tag, errorMessage) { var attrs = ''; if (Search.urlRoot) attrs = ' href="'+Search.urlRoot+'moves/'+toId(move.name)+'" data-target="push"'; var buf = '
  • '; // tag buf += ''+tag+' '; // name var name = move.name; if (name.substr(0, 12) === 'Hidden Power') name = 'Hidden Power'; buf += ''+name+' '; // error if (errorMessage) { buf += ''+errorMessage+' '; buf += '
  • '; return buf; } // type buf += ''; buf += Tools.getTypeIcon(move.type); buf += ''+move.category+''; buf += ' '; // power, accuracy, pp buf += ''+(move.category!=='Status'?('Power
    '+(move.basePower||'—')):'')+'
    '; buf += 'Accuracy
    '+(move.accuracy && move.accuracy!==true?move.accuracy+'%':'—')+'
    '; buf += 'PP
    '+(move.pp!==1?move.pp*8/5:move.pp)+'
    '; // desc buf += ''+Tools.escapeHTML(move.shortDesc || move.desc)+' '; buf += ''; return buf; }; Search.renderTypeRow = function(type, matchStart, matchLength, errorMessage) { var attrs = ''; if (Search.urlRoot) attrs = ' href="'+Search.urlRoot+'types/'+toId(type.name)+'" data-target="push"'; var buf = '
  • '; // name var name = type.name; if (matchLength) { name = name.substr(0, matchStart)+''+name.substr(matchStart, matchLength)+''+name.substr(matchStart+matchLength); } buf += ''+name+' '; // error if (errorMessage) { buf += ''+errorMessage+' '; buf += '
  • '; return buf; } // type buf += ''; buf += Tools.getTypeIcon(type.name); buf += ' '; buf += ''; return buf; }; Search.renderCategoryRow = function(category, matchStart, matchLength, errorMessage) { var attrs = ''; if (Search.urlRoot) attrs = ' href="'+Search.urlRoot+'categories/'+toId(category.name)+'" data-target="push"'; var buf = '
  • '; // name var name = category.name; if (matchLength) { name = name.substr(0, matchStart)+''+name.substr(matchStart, matchLength)+''+name.substr(matchStart+matchLength); } buf += ''+name+' '; // error if (errorMessage) { buf += ''+errorMessage+' '; buf += '
  • '; return buf; } // category buf += ''; buf += ''+category.name+''; buf += ' '; buf += ''; return buf; }; Search.renderEggGroupRow = function(egggroup, matchStart, matchLength, errorMessage) { var attrs = ''; if (Search.urlRoot) attrs = ' href="'+Search.urlRoot+'egggroups/'+toId(egggroup.name)+'" data-target="push"'; var buf = '
  • '; // name var name = egggroup.name; if (matchLength) { name = name.substr(0, matchStart)+''+name.substr(matchStart, matchLength)+''+name.substr(matchStart+matchLength); } buf += ''+name+' '; // error if (errorMessage) { buf += ''+errorMessage+' '; buf += '
  • '; return buf; } buf += ''; return buf; }; exports.BattleSearch = Search; })(window, jQuery);