Pokemon GO - Learnsets

https://strategywiki.org/wiki/Pok%C3%A9mon_GO/Pok%C3%A9dex https://pokemongo.gamepress.gg/legacy-pokemon-list

by MrPolywhirl

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.11.1/bootstrap-table.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.11.1/bootstrap-table.min.css">
<link rel="stylesheet" href="https://cdn.rawgit.com/ryankane/d8446dce9a19dbabbbfeecdeccad0438/raw/321b38367653ac439fbce97623a55c21218c4bf6/sprites.css">
<script src="https://cdn.rawgit.com/ryankane/d8446dce9a19dbabbbfeecdeccad0438/raw/321b38367653ac439fbce97623a55c21218c4bf6/spritesheet.png"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.17.1/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tooltipster/3.3.0/js/jquery.tooltipster.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tooltipster/3.3.0/css/tooltipster.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tooltipster/3.3.0/css/themes/tooltipster-shadow.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/sprintf/1.0.3/sprintf.min.js"></script>
<h2 style="text-align:center">Pokémon GO Learnsets</h2>
<div class="container">
  <table id="learnset-table" class="table table-striped table-bordered table-hover" data-height="800">
    <thead>
      <tr>
        <th data-field="id">No.</th>
        <th data-field="name">Name</th>
        <th data-field="types">Types</th>
        <th data-field="stats">Stats</th>
        <th data-field="fastMoves">Fast Moves</th>
        <th data-field="cinematicMoves">Cinematic Moves</th>
      </tr>
    </thead>
  </table>
</div>

<!--
Attributions:

Sprites (Gen VI converted to PNG): http://www.pokestadium.com/tools/sprites
Spritesheet generated via: https://www.leshylabs.com/apps/sstool/
CSS selector sorting:...

CSS

.center { float: none; margin-left: auto; margin-right: auto; }

.sprite { margin: 0 auto; }

/*.table > tbody > tr > td {
  vertical-align: middle;
}*/

.stat-label {
  font-family: monospace;
  text-transform: uppercase;
}
.stat-label:after { content: ': ' }

/*.table > tbody > tr > td:nth-child(2) {
  vertical-align: bottom;
}*/

.move-legacy { text-decoration: line-through; }
.move-recent:after { content : '(?)'; vertical-align: super; font-size: 0.75em; }
.move-stab   { font-weight: bold; }

.move-wrapper { margin-bottom: 0.25em; }

.move-type { display: inline-block; width: 5em; text-align: center; color: #FFF; border-radius: 0.25em; }
/*.move-type:before { content: '['; } */
/*.move-type:after { content: ']'; } */

.move-power {}
.move-power:before { content: '('; }
.move-power:after { content: ')'; }

.type-normal-bg   { background-color: #A8A878; }
.type-fire-bg     { background-color: #F08030; }
.type-fighting-bg { background-color: #C03028; }
.type-water-bg    { background-color: #6890F0; }
.type-flying-bg   { background-color: #A890F0; }
.type-grass-bg    { background-color: #78C850; }
.type-poison-bg   { background-color: #A040A0; }
.type-electric-bg { background-color: #F8D030; }
.type-ground-bg   { background-color: #E0C068; }
.type-psychic-bg  { background-color: #F85888; }
.type-rock-bg     { background-color: #B8A038; }
.type-ice-bg      { background-color: #98D8D8; }
.type-bug-bg      { background-color: #A8B820; }
.type-dragon-bg   { background-color: #7038F8; }
.type-ghost-bg    { background-color: #705898; }
.type-dark-bg     { background-color: #705848; }
.type-steel-bg    { background-color: #B8B8D0; }
.type-fairy-bg    { background-color: #EE99AC; }
.type-unkown-bg   { background-color: #68A090; }

JavaScript

const baseUrl = 'https://cdn.rawgit.com/ryankane/d8446dce9a19dbabbbfeecdeccad0438/raw/',
      learnsetUrl = baseUrl + 'd86ca65479500045f9658c70452778fa704b4310/learnset.json',
      moveUrl = baseUrl + 'f93dd493d90041d37ffbdb1cd9c1a2858a55d836/moves.json',
      classesIf = classMap => Object.keys(classMap).filter(cls => (classMap[cls] || '') != '').join(' '),
      pad = (val, padding) => (padding + val).substr(-padding.length),
      formatId = id => '#' + pad(id, '000'),
      sanitize = text => text.replace(/\W+/g, '-').toLowerCase(),
      replacementMapper = (s, m) =>  m.reduce((r, e) => r.replace(e.pattern, e.replacement), s),
      normalizeMap = [
        { pattern : '♀',    replacement : 'f' },
        { pattern : '♂',    replacement : 'm' },
        { pattern : /[']/g, replacement : '' },
        { pattern : /\W+/g, replacement : '-' }
      ];
      
(function($) {
  $.extendObjectArray = (destArr, srcArr, key) => {
    srcArr.forEach(srcObj => (existObj => {
      if (existObj.length) {
        $.extend(true, destArr[destArr.indexOf(existObj[0])], srcObj);
      } else {
        destArr.push(srcObj);
      }
    })(destArr.filter(v => v[key] === srcObj[key])));
    return destArr;
  };
  $.fn.scanColumns = function() {
    return this.find('thead tr:first-child th').map((index, col) => ({
      field: $(col).data('field'), title: $(col).text()
    })).toArray();
  };
  $.fn.asHTML = function() {
  	return this.prop('outerHTML');
  }
})(jQuery);

$(function() {
  var $table = $('#learnset-table');
  $.getJSON(moveUrl, function(moveData) {
    $.getJSON(learnsetUrl, function(learnsetData) {
      $table.bootstrapTable({
        data: learnsetData,
        columns: $.extendObjectArray($table.scanColumns(), [{
          field: 'id',
          sortable : true,
          align: 'center',
          valign : 'middle',
          halign : 'center',
          formatter: formatId
        }, {
        	field: 'name',
          sortable : true,
          align :...