mirror of
https://github.com/smogon/pokemon-showdown-client.git
synced 2026-03-21 17:50:29 -05:00
Split battle-log.ts off from battle-dex.ts
This splits battle-dex.ts up into: - `battle-dex.ts` - dex data access, misc tools - `battle-log.ts` - manipulating HTML, especially in battle logs This turned out to be a pretty significant portion of what was previously battle-dex.
This commit is contained in:
parent
368ee06bcc
commit
5f05adc856
|
|
@ -4,6 +4,7 @@ node_modules/
|
|||
|
||||
/js/battle.js
|
||||
/js/battledata.js
|
||||
/js/battle-log.js
|
||||
/js/battle-dex.js
|
||||
/js/battle-dex-data.js
|
||||
/js/battle-animations-moves.js
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ module.exports = {
|
|||
"fs": false, "gui": false, "ga": false, "macgap": false, "nwWindow": false, "webkitNotifications": false,
|
||||
|
||||
// Battle stuff
|
||||
"Battle": true, "Pokemon": true, "BattleSound": true, "BattleTooltips": true,
|
||||
"Battle": true, "Pokemon": true, "BattleSound": true, "BattleTooltips": true, "BattleLog": true,
|
||||
"BattleAbilities": false, "BattleAliases": false, "BattleBackdrops": false, "BattleBackdropsFive": false, "BattleBackdropsFour": false, "BattleBackdropsThree": false, "BattleEffects": false,
|
||||
"BattleFormats": false, "BattleFormatsData": false, "BattleLearnsets": false, "BattleItems": false, "BattleMoveAnims": false, "BattleMovedex": false, "BattleNatures": false,
|
||||
"BattleOtherAnims": false, "BattlePokedex": false,"BattlePokemonSprites": false, "BattlePokemonSpritesBW": false, "BattleSearchCountIndex": false, "BattleSearchIndex": false, "BattleArticleTitles": false,
|
||||
|
|
@ -26,7 +26,7 @@ module.exports = {
|
|||
|
||||
// Generic global variables
|
||||
"Config": false, "BattleSearch": false, "soundManager": false, "Storage": false, "Tools": false,
|
||||
"app": false, "toId": false, "toRoomid": false, "toUserid": false, "toName": false, "getString": false, "hashColor": false, "MD5": false,
|
||||
"app": false, "toId": false, "toRoomid": false, "toUserid": false, "toName": false, "getString": false, "MD5": false,
|
||||
"ChatHistory": false, "Topbar": false, "UserList": false,
|
||||
|
||||
// Rooms
|
||||
|
|
|
|||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -15,6 +15,7 @@ package-lock.json
|
|||
|
||||
/js/battle.js
|
||||
/js/battledata.js
|
||||
/js/battle-log.js
|
||||
/js/battle-dex.js
|
||||
/js/battle-dex-data.js
|
||||
/js/battle-animations-moves.js
|
||||
|
|
|
|||
|
|
@ -52,7 +52,8 @@ fs.writeFileSync(
|
|||
'js/battledata.js',
|
||||
fs.readFileSync('js/battle-dex.js') + '\n\n' +
|
||||
fs.readFileSync('js/battle-dex-data.js') + '\n\n' +
|
||||
fs.readFileSync('src/battle-dex-misc.js')
|
||||
fs.readFileSync('js/battle-log.js') + '\n\n' +
|
||||
fs.readFileSync('src/battle-log-misc.js')
|
||||
);
|
||||
|
||||
if (!ignoreGraphics) {
|
||||
|
|
|
|||
|
|
@ -99,12 +99,12 @@ var BattleTooltips = (function () {
|
|||
BattleTooltips.prototype.tooltipAttrs = function (thing, type, ownHeight) {
|
||||
var roomid = this.room.id;
|
||||
return ' onclick="BattleTooltips._handleClickFor(event)"' +
|
||||
' ontouchstart="BattleTooltips._handleTouchStartFor(event, \'' + roomid + '\', \'' + Tools.escapeHTML('' + thing, true) + '\',\'' + type + '\', this, ' + (ownHeight ? 'true' : 'false') + ')"' +
|
||||
' ontouchstart="BattleTooltips._handleTouchStartFor(event, \'' + roomid + '\', \'' + BattleLog.escapeHTML('' + thing, true) + '\',\'' + type + '\', this, ' + (ownHeight ? 'true' : 'false') + ')"' +
|
||||
' ontouchend="BattleTooltips._handleTouchEndFor(event, this)"' +
|
||||
' ontouchleave="BattleTooltips._handleTouchLeaveFor(event)"' +
|
||||
' ontouchcancel="BattleTooltips._handleTouchLeaveFor(event)"' +
|
||||
' onmouseover="BattleTooltips.showTooltipFor(\'' + roomid + '\', \'' + Tools.escapeHTML('' + thing, true) + '\',\'' + type + '\', this, ' + (ownHeight ? 'true' : 'false') + ')"' +
|
||||
' onfocus="BattleTooltips.showTooltipFor(\'' + roomid + '\', \'' + Tools.escapeHTML('' + thing, true) + '\',\'' + type + '\', this, ' + (ownHeight ? 'true' : 'false') + ')"' +
|
||||
' onmouseover="BattleTooltips.showTooltipFor(\'' + roomid + '\', \'' + BattleLog.escapeHTML('' + thing, true) + '\',\'' + type + '\', this, ' + (ownHeight ? 'true' : 'false') + ')"' +
|
||||
' onfocus="BattleTooltips.showTooltipFor(\'' + roomid + '\', \'' + BattleLog.escapeHTML('' + thing, true) + '\',\'' + type + '\', this, ' + (ownHeight ? 'true' : 'false') + ')"' +
|
||||
' onmouseout="BattleTooltips.hideTooltip()"' +
|
||||
' onblur="BattleTooltips.hideTooltip()"' +
|
||||
' onmouseup="BattleTooltips._handleMouseUpFor()"' +
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@
|
|||
switch (args[0]) {
|
||||
case 'trapped':
|
||||
requestData.trapped = true;
|
||||
var pokeName = pokemon.side.n === 0 ? Tools.escapeHTML(pokemon.name) : "The opposing " + (this.battle.ignoreOpponent || this.battle.ignoreNicks ? pokemon.species : Tools.escapeHTML(pokemon.name));
|
||||
var pokeName = pokemon.side.n === 0 ? BattleLog.escapeHTML(pokemon.name) : "The opposing " + (this.battle.ignoreOpponent || this.battle.ignoreNicks ? pokemon.species : BattleLog.escapeHTML(pokemon.name));
|
||||
this.battle.activityQueue.push('|message|' + pokeName + ' is trapped and cannot switch!');
|
||||
break;
|
||||
case 'cant':
|
||||
|
|
@ -554,7 +554,7 @@
|
|||
} else if (!pokemon || pokemon.fainted) {
|
||||
targetMenus[0] += '<button name="chooseMoveTarget" value="' + (i + 1) + '"><span class="picon" style="' + Tools.getPokemonIcon('missingno') + '"></span></button> ';
|
||||
} else {
|
||||
targetMenus[0] += '<button name="chooseMoveTarget" value="' + (i + 1) + '"' + this.tooltips.tooltipAttrs("your" + i, 'pokemon', true) + '><span class="picon" style="' + Tools.getPokemonIcon(pokemon) + '"></span>' + (this.battle.ignoreOpponent || this.battle.ignoreNicks ? pokemon.species : Tools.escapeHTML(pokemon.name)) + '<span class="hpbar' + pokemon.getHPColorClass() + '"><span style="width:' + (Math.round(pokemon.hp * 92 / pokemon.maxhp) || 1) + 'px"></span></span>' + (pokemon.status ? '<span class="status ' + pokemon.status + '"></span>' : '') + '</button> ';
|
||||
targetMenus[0] += '<button name="chooseMoveTarget" value="' + (i + 1) + '"' + this.tooltips.tooltipAttrs("your" + i, 'pokemon', true) + '><span class="picon" style="' + Tools.getPokemonIcon(pokemon) + '"></span>' + (this.battle.ignoreOpponent || this.battle.ignoreNicks ? pokemon.species : BattleLog.escapeHTML(pokemon.name)) + '<span class="hpbar' + pokemon.getHPColorClass() + '"><span style="width:' + (Math.round(pokemon.hp * 92 / pokemon.maxhp) || 1) + 'px"></span></span>' + (pokemon.status ? '<span class="status ' + pokemon.status + '"></span>' : '') + '</button> ';
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < myActive.length; i++) {
|
||||
|
|
@ -573,7 +573,7 @@
|
|||
} else if (!pokemon || pokemon.fainted) {
|
||||
targetMenus[1] += '<button name="chooseMoveTarget" value="' + (-(i + 1)) + '"><span class="picon" style="' + Tools.getPokemonIcon('missingno') + '"></span></button> ';
|
||||
} else {
|
||||
targetMenus[1] += '<button name="chooseMoveTarget" value="' + (-(i + 1)) + '"' + this.tooltips.tooltipAttrs(i, 'sidepokemon') + '><span class="picon" style="' + Tools.getPokemonIcon(pokemon) + '"></span>' + Tools.escapeHTML(pokemon.name) + '<span class="hpbar' + pokemon.getHPColorClass() + '"><span style="width:' + (Math.round(pokemon.hp * 92 / pokemon.maxhp) || 1) + 'px"></span></span>' + (pokemon.status ? '<span class="status ' + pokemon.status + '"></span>' : '') + '</button> ';
|
||||
targetMenus[1] += '<button name="chooseMoveTarget" value="' + (-(i + 1)) + '"' + this.tooltips.tooltipAttrs(i, 'sidepokemon') + '><span class="picon" style="' + Tools.getPokemonIcon(pokemon) + '"></span>' + BattleLog.escapeHTML(pokemon.name) + '<span class="hpbar' + pokemon.getHPColorClass() + '"><span style="width:' + (Math.round(pokemon.hp * 92 / pokemon.maxhp) || 1) + 'px"></span></span>' + (pokemon.status ? '<span class="status ' + pokemon.status + '"></span>' : '') + '</button> ';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -587,7 +587,7 @@
|
|||
} else {
|
||||
// Move chooser
|
||||
var hpBar = '<small class="' + (hpRatio < 0.2 ? 'critical' : hpRatio < 0.5 ? 'weak' : 'healthy') + '">HP ' + switchables[pos].hp + '/' + switchables[pos].maxhp + '</small>';
|
||||
requestTitle += ' What will <strong>' + Tools.escapeHTML(switchables[pos].name) + '</strong> do? ' + hpBar;
|
||||
requestTitle += ' What will <strong>' + BattleLog.escapeHTML(switchables[pos].name) + '</strong> do? ' + hpBar;
|
||||
|
||||
var hasMoves = false;
|
||||
var moveMenu = '';
|
||||
|
|
@ -605,7 +605,7 @@
|
|||
if (moveData.disabled) {
|
||||
movebuttons += '<button disabled="disabled"' + this.tooltips.tooltipAttrs(moveData.move, 'move') + '>';
|
||||
} else {
|
||||
movebuttons += '<button class="type-' + moveType + '" name="chooseMove" value="' + (i + 1) + '" data-move="' + Tools.escapeHTML(moveData.move) + '" data-target="' + Tools.escapeHTML(moveData.target) + '"' + this.tooltips.tooltipAttrs(moveData.move, 'move') + '>';
|
||||
movebuttons += '<button class="type-' + moveType + '" name="chooseMove" value="' + (i + 1) + '" data-move="' + BattleLog.escapeHTML(moveData.move) + '" data-target="' + BattleLog.escapeHTML(moveData.target) + '"' + this.tooltips.tooltipAttrs(moveData.move, 'move') + '>';
|
||||
hasMoves = true;
|
||||
}
|
||||
movebuttons += name + '<br /><small class="type">' + (moveType ? Tools.getType(moveType).name : "Unknown") + '</small> <small class="pp">' + pp + '</small> </button> ';
|
||||
|
|
@ -620,7 +620,7 @@
|
|||
var move = Tools.getMove(moveData.move);
|
||||
var moveType = this.tooltips.getMoveType(move, this.battle.mySide.active[pos] || this.myPokemon[pos]);
|
||||
if (canZMove[i]) {
|
||||
movebuttons += '<button class="type-' + moveType + '" name="chooseMove" value="' + (i + 1) + '" data-move="' + Tools.escapeHTML(canZMove[i].move) + '" data-target="' + Tools.escapeHTML(canZMove[i].target) + '"' + this.tooltips.tooltipAttrs(moveData.move, 'zmove') + '>';
|
||||
movebuttons += '<button class="type-' + moveType + '" name="chooseMove" value="' + (i + 1) + '" data-move="' + BattleLog.escapeHTML(canZMove[i].move) + '" data-target="' + BattleLog.escapeHTML(canZMove[i].target) + '"' + this.tooltips.tooltipAttrs(moveData.move, 'zmove') + '>';
|
||||
movebuttons += canZMove[i].move + '<br /><small class="type">' + (moveType ? Tools.getType(moveType).name : "Unknown") + '</small> <small class="pp">1/1</small> </button> ';
|
||||
} else {
|
||||
movebuttons += '<button disabled="disabled"> </button>';
|
||||
|
|
@ -662,9 +662,9 @@
|
|||
var pokemon = switchables[i];
|
||||
pokemon.name = pokemon.ident.substr(4);
|
||||
if (pokemon.fainted || i < this.battle.mySide.active.length || this.choice.switchFlags[i]) {
|
||||
switchMenu += '<button class="disabled" name="chooseDisabled" value="' + Tools.escapeHTML(pokemon.name) + (pokemon.fainted ? ',fainted' : i < this.battle.mySide.active.length ? ',active' : '') + '"' + this.tooltips.tooltipAttrs(i, 'sidepokemon') + '><span class="picon" style="' + Tools.getPokemonIcon(pokemon) + '"></span>' + Tools.escapeHTML(pokemon.name) + (pokemon.hp ? '<span class="hpbar' + pokemon.getHPColorClass() + '"><span style="width:' + (Math.round(pokemon.hp * 92 / pokemon.maxhp) || 1) + 'px"></span></span>' + (pokemon.status ? '<span class="status ' + pokemon.status + '"></span>' : '') : '') + '</button> ';
|
||||
switchMenu += '<button class="disabled" name="chooseDisabled" value="' + BattleLog.escapeHTML(pokemon.name) + (pokemon.fainted ? ',fainted' : i < this.battle.mySide.active.length ? ',active' : '') + '"' + this.tooltips.tooltipAttrs(i, 'sidepokemon') + '><span class="picon" style="' + Tools.getPokemonIcon(pokemon) + '"></span>' + BattleLog.escapeHTML(pokemon.name) + (pokemon.hp ? '<span class="hpbar' + pokemon.getHPColorClass() + '"><span style="width:' + (Math.round(pokemon.hp * 92 / pokemon.maxhp) || 1) + 'px"></span></span>' + (pokemon.status ? '<span class="status ' + pokemon.status + '"></span>' : '') : '') + '</button> ';
|
||||
} else {
|
||||
switchMenu += '<button name="chooseSwitch" value="' + i + '"' + this.tooltips.tooltipAttrs(i, 'sidepokemon') + '><span class="picon" style="' + Tools.getPokemonIcon(pokemon) + '"></span>' + Tools.escapeHTML(pokemon.name) + '<span class="hpbar' + pokemon.getHPColorClass() + '"><span style="width:' + (Math.round(pokemon.hp * 92 / pokemon.maxhp) || 1) + 'px"></span></span>' + (pokemon.status ? '<span class="status ' + pokemon.status + '"></span>' : '') + '</button> ';
|
||||
switchMenu += '<button name="chooseSwitch" value="' + i + '"' + this.tooltips.tooltipAttrs(i, 'sidepokemon') + '><span class="picon" style="' + Tools.getPokemonIcon(pokemon) + '"></span>' + BattleLog.escapeHTML(pokemon.name) + '<span class="hpbar' + pokemon.getHPColorClass() + '"><span style="width:' + (Math.round(pokemon.hp * 92 / pokemon.maxhp) || 1) + 'px"></span></span>' + (pokemon.status ? '<span class="status ' + pokemon.status + '"></span>' : '') + '</button> ';
|
||||
}
|
||||
}
|
||||
if (this.finalDecisionSwitch && this.battle.gen > 2) {
|
||||
|
|
@ -711,11 +711,11 @@
|
|||
for (var i = 0; i < myActive.length; i++) {
|
||||
var pokemon = this.myPokemon[i];
|
||||
if (pokemon && !pokemon.fainted || this.choice.switchOutFlags[i]) {
|
||||
controls += '<button disabled' + this.tooltips.tooltipAttrs(i, 'sidepokemon') + '><span class="picon" style="' + Tools.getPokemonIcon(pokemon) + '"></span>' + Tools.escapeHTML(pokemon.name) + (!pokemon.fainted ? '<span class="hpbar' + pokemon.getHPColorClass() + '"><span style="width:' + (Math.round(pokemon.hp * 92 / pokemon.maxhp) || 1) + 'px"></span></span>' + (pokemon.status ? '<span class="status ' + pokemon.status + '"></span>' : '') : '') + '</button> ';
|
||||
controls += '<button disabled' + this.tooltips.tooltipAttrs(i, 'sidepokemon') + '><span class="picon" style="' + Tools.getPokemonIcon(pokemon) + '"></span>' + BattleLog.escapeHTML(pokemon.name) + (!pokemon.fainted ? '<span class="hpbar' + pokemon.getHPColorClass() + '"><span style="width:' + (Math.round(pokemon.hp * 92 / pokemon.maxhp) || 1) + 'px"></span></span>' + (pokemon.status ? '<span class="status ' + pokemon.status + '"></span>' : '') : '') + '</button> ';
|
||||
} else if (!pokemon) {
|
||||
controls += '<button disabled></button> ';
|
||||
} else {
|
||||
controls += '<button name="chooseSwitchTarget" value="' + i + '"' + this.tooltips.tooltipAttrs(i, 'sidepokemon') + '><span class="picon" style="' + Tools.getPokemonIcon(pokemon) + '"></span>' + Tools.escapeHTML(pokemon.name) + '<span class="hpbar' + pokemon.getHPColorClass() + '"><span style="width:' + (Math.round(pokemon.hp * 92 / pokemon.maxhp) || 1) + 'px"></span></span>' + (pokemon.status ? '<span class="status ' + pokemon.status + '"></span>' : '') + '</button> ';
|
||||
controls += '<button name="chooseSwitchTarget" value="' + i + '"' + this.tooltips.tooltipAttrs(i, 'sidepokemon') + '><span class="picon" style="' + Tools.getPokemonIcon(pokemon) + '"></span>' + BattleLog.escapeHTML(pokemon.name) + '<span class="hpbar' + pokemon.getHPColorClass() + '"><span style="width:' + (Math.round(pokemon.hp * 92 / pokemon.maxhp) || 1) + 'px"></span></span>' + (pokemon.status ? '<span class="status ' + pokemon.status + '"></span>' : '') + '</button> ';
|
||||
}
|
||||
}
|
||||
controls += '</div>';
|
||||
|
|
@ -729,18 +729,18 @@
|
|||
if (this.choice.freedomDegrees >= 1) {
|
||||
requestTitle += "Choose a Pokémon to send to battle!";
|
||||
} else {
|
||||
requestTitle += "Switch <strong>" + Tools.escapeHTML(switchables[pos].name) + "</strong> to:";
|
||||
requestTitle += "Switch <strong>" + BattleLog.escapeHTML(switchables[pos].name) + "</strong> to:";
|
||||
}
|
||||
|
||||
var switchMenu = '';
|
||||
for (var i = 0; i < switchables.length; i++) {
|
||||
var pokemon = switchables[i];
|
||||
if (pokemon.fainted || i < this.battle.mySide.active.length || this.choice.switchFlags[i]) {
|
||||
switchMenu += '<button class="disabled" name="chooseDisabled" value="' + Tools.escapeHTML(pokemon.name) + (pokemon.fainted ? ',fainted' : i < this.battle.mySide.active.length ? ',active' : '') + '"' + this.tooltips.tooltipAttrs(i, 'sidepokemon') + '>';
|
||||
switchMenu += '<button class="disabled" name="chooseDisabled" value="' + BattleLog.escapeHTML(pokemon.name) + (pokemon.fainted ? ',fainted' : i < this.battle.mySide.active.length ? ',active' : '') + '"' + this.tooltips.tooltipAttrs(i, 'sidepokemon') + '>';
|
||||
} else {
|
||||
switchMenu += '<button name="chooseSwitch" value="' + i + '"' + this.tooltips.tooltipAttrs(i, 'sidepokemon') + '>';
|
||||
}
|
||||
switchMenu += '<span class="picon" style="' + Tools.getPokemonIcon(pokemon) + '"></span>' + Tools.escapeHTML(pokemon.name) + (!pokemon.fainted ? '<span class="hpbar' + pokemon.getHPColorClass() + '"><span style="width:' + (Math.round(pokemon.hp * 92 / pokemon.maxhp) || 1) + 'px"></span></span>' + (pokemon.status ? '<span class="status ' + pokemon.status + '"></span>' : '') : '') + '</button> ';
|
||||
switchMenu += '<span class="picon" style="' + Tools.getPokemonIcon(pokemon) + '"></span>' + BattleLog.escapeHTML(pokemon.name) + (!pokemon.fainted ? '<span class="hpbar' + pokemon.getHPColorClass() + '"><span style="width:' + (Math.round(pokemon.hp * 92 / pokemon.maxhp) || 1) + 'px"></span></span>' + (pokemon.status ? '<span class="status ' + pokemon.status + '"></span>' : '') : '') + '</button> ';
|
||||
}
|
||||
|
||||
var controls = (
|
||||
|
|
@ -774,9 +774,9 @@
|
|||
var oIndex = this.choice.teamPreview[i] - 1;
|
||||
var pokemon = switchables[oIndex];
|
||||
if (i < this.choice.done) {
|
||||
switchMenu += '<button disabled="disabled"' + this.tooltips.tooltipAttrs(oIndex, 'sidepokemon') + '><span class="picon" style="' + Tools.getPokemonIcon(pokemon) + '"></span>' + Tools.escapeHTML(pokemon.name) + '</button> ';
|
||||
switchMenu += '<button disabled="disabled"' + this.tooltips.tooltipAttrs(oIndex, 'sidepokemon') + '><span class="picon" style="' + Tools.getPokemonIcon(pokemon) + '"></span>' + BattleLog.escapeHTML(pokemon.name) + '</button> ';
|
||||
} else {
|
||||
switchMenu += '<button name="chooseTeamPreview" value="' + i + '"' + this.tooltips.tooltipAttrs(oIndex, 'sidepokemon') + '><span class="picon" style="' + Tools.getPokemonIcon(pokemon) + '"></span>' + Tools.escapeHTML(pokemon.name) + '</button> ';
|
||||
switchMenu += '<button name="chooseTeamPreview" value="' + i + '"' + this.tooltips.tooltipAttrs(oIndex, 'sidepokemon') + '><span class="picon" style="' + Tools.getPokemonIcon(pokemon) + '"></span>' + BattleLog.escapeHTML(pokemon.name) + '</button> ';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -987,7 +987,7 @@
|
|||
filename += '-' + toId(this.battle.p1.name);
|
||||
filename += '-' + toId(this.battle.p2.name);
|
||||
|
||||
e.currentTarget.href = Tools.createReplayFileHref(this);
|
||||
e.currentTarget.href = BattleLog.createReplayFileHref(this);
|
||||
e.currentTarget.download = filename + '.html';
|
||||
|
||||
e.stopPropagation();
|
||||
|
|
|
|||
|
|
@ -271,7 +271,7 @@
|
|||
case 'create':
|
||||
var formatName = window.BattleFormats && BattleFormats[data[0]] ? BattleFormats[data[0]].name : data[0];
|
||||
var type = data[1];
|
||||
this.room.$chat.append("<div class=\"notice tournament-message-create\">" + Tools.escapeHTML(formatName) + " " + Tools.escapeHTML(type) + " Tournament created.</div>");
|
||||
this.room.$chat.append("<div class=\"notice tournament-message-create\">" + BattleLog.escapeHTML(formatName) + " " + BattleLog.escapeHTML(type) + " Tournament created.</div>");
|
||||
this.room.notifyOnce("Tournament created", "Room: " + this.room.title + "\nFormat: " + formatName + "\nType: " + type, 'tournament-create');
|
||||
this.curTeamIndex = 0;
|
||||
this.updateTeams();
|
||||
|
|
@ -317,7 +317,7 @@
|
|||
break;
|
||||
|
||||
case 'disqualify':
|
||||
this.room.$chat.append("<div class=\"notice tournament-message-disqualify\">" + Tools.escapeHTML(data[0]) + " has been disqualified from the tournament.</div>");
|
||||
this.room.$chat.append("<div class=\"notice tournament-message-disqualify\">" + BattleLog.escapeHTML(data[0]) + " has been disqualified from the tournament.</div>");
|
||||
break;
|
||||
|
||||
case 'autodq':
|
||||
|
|
@ -448,7 +448,7 @@
|
|||
case 'battlestart':
|
||||
var roomid = toRoomid(data[2]).toLowerCase();
|
||||
this.room.$chat.append('<div class="notice tournament-message-battlestart tournament-' + roomid + '"><a href="' + app.root + roomid + '" class="ilink">' +
|
||||
"Tournament battle between " + Tools.escapeHTML(data[0]) + " and " + Tools.escapeHTML(data[1]) + " started." +
|
||||
"Tournament battle between " + BattleLog.escapeHTML(data[0]) + " and " + BattleLog.escapeHTML(data[1]) + " started." +
|
||||
'</a></div>');
|
||||
break;
|
||||
|
||||
|
|
@ -458,7 +458,7 @@
|
|||
result = "won";
|
||||
else if (data[2] === 'loss')
|
||||
result = "lost";
|
||||
var message = Tools.escapeHTML(data[0]) + " has " + result + " the match " + Tools.escapeHTML(data[3].split(',').join(' - ')) + " against " + Tools.escapeHTML(data[1]) +
|
||||
var message = BattleLog.escapeHTML(data[0]) + " has " + result + " the match " + BattleLog.escapeHTML(data[3].split(',').join(' - ')) + " against " + BattleLog.escapeHTML(data[1]) +
|
||||
(data[4] === 'fail' ? " but the tournament does not support drawing, so it did not count" : "") + ".";
|
||||
var $battleMessage = data[5] ? this.room.$chat.find('.tournament-' + toRoomid(data[5]).toLowerCase()) : '';
|
||||
if ($battleMessage && $battleMessage.length) {
|
||||
|
|
@ -483,9 +483,9 @@
|
|||
}
|
||||
|
||||
var type = endData.generator;
|
||||
this.room.$chat.append("<div class=\"notice tournament-message-end-winner\">Congratulations to " + Tools.escapeHTML(arrayToPhrase(endData.results[0])) + " for winning the " + Tools.escapeFormat(endData.format) + " " + Tools.escapeHTML(type) + " Tournament!</div>");
|
||||
this.room.$chat.append("<div class=\"notice tournament-message-end-winner\">Congratulations to " + BattleLog.escapeHTML(arrayToPhrase(endData.results[0])) + " for winning the " + BattleLog.escapeFormat(endData.format) + " " + BattleLog.escapeHTML(type) + " Tournament!</div>");
|
||||
if (endData.results[1])
|
||||
this.room.$chat.append("<div class=\"notice tournament-message-end-runnerup\">Runner-up" + (endData.results[1].length > 1 ? "s" : "") + ": " + Tools.escapeHTML(arrayToPhrase(endData.results[1])) + "</div>");
|
||||
this.room.$chat.append("<div class=\"notice tournament-message-end-runnerup\">Runner-up" + (endData.results[1].length > 1 ? "s" : "") + ": " + BattleLog.escapeHTML(arrayToPhrase(endData.results[1])) + "</div>");
|
||||
|
||||
// Fallthrough
|
||||
|
||||
|
|
@ -510,7 +510,7 @@
|
|||
|
||||
case 'error':
|
||||
var appendError = function (message) {
|
||||
this.room.$chat.append("<div class=\"notice tournament-message-forceend\">" + Tools.sanitizeHTML(message) + "</div>");
|
||||
this.room.$chat.append("<div class=\"notice tournament-message-forceend\">" + BattleLog.sanitizeHTML(message) + "</div>");
|
||||
}.bind(this);
|
||||
|
||||
switch (data[0]) {
|
||||
|
|
@ -586,7 +586,7 @@
|
|||
if (!data.rootNode) {
|
||||
if (!('users' in data)) return;
|
||||
var users = data.users.length;
|
||||
if (users) $div.html('<b>' + users + '</b> user' + (users !== 1 ? 's' : '') + ':<br />' + Tools.escapeHTML(data.users.join(", ")));
|
||||
if (users) $div.html('<b>' + users + '</b> user' + (users !== 1 ? 's' : '') + ':<br />' + BattleLog.escapeHTML(data.users.join(", ")));
|
||||
return $div;
|
||||
}
|
||||
|
||||
|
|
@ -803,7 +803,7 @@
|
|||
var UserPopup = this.Popup.extend({
|
||||
initialize: function (data) {
|
||||
this.$el.html('<ul class="popupmenu">' + data.users.map(function (user) {
|
||||
var escapedUser = Tools.escapeHTML(user);
|
||||
var escapedUser = BattleLog.escapeHTML(user);
|
||||
return '<li><button name="selectUser" value="' + escapedUser + '"' + (user === data.user ? ' class="sel"' : '') + '>' + escapedUser + '</button></li>';
|
||||
}).join('') + '</ul>');
|
||||
},
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
var name = app.user.get('name');
|
||||
var userid = app.user.get('userid');
|
||||
if (this.expired) {
|
||||
this.$chatAdd.html(this.expired === true ? 'This room is expired' : Tools.sanitizeHTML(this.expired));
|
||||
this.$chatAdd.html(this.expired === true ? 'This room is expired' : BattleLog.sanitizeHTML(this.expired));
|
||||
this.$chatbox = null;
|
||||
} else if (!name) {
|
||||
this.$chatAdd.html('Connecting...');
|
||||
|
|
@ -37,7 +37,7 @@
|
|||
this.$chatAdd.html('<form><button name="login">Join chat</button></form>');
|
||||
this.$chatbox = null;
|
||||
} else {
|
||||
this.$chatAdd.html('<form class="chatbox"><label style="' + hashColor(userid) + '">' + Tools.escapeHTML(name) + ':</label> <textarea class="textbox" type="text" size="70" autocomplete="off"></textarea></form>');
|
||||
this.$chatAdd.html('<form class="chatbox"><label style="' + BattleLog.hashColor(userid) + '">' + BattleLog.escapeHTML(name) + ':</label> <textarea class="textbox" type="text" size="70" autocomplete="off"></textarea></form>');
|
||||
this.$chatbox = this.$chatAdd.find('textarea');
|
||||
this.$chatbox.autoResize({
|
||||
animate: false,
|
||||
|
|
@ -479,7 +479,7 @@
|
|||
if (target === 'extractteams') {
|
||||
app.addPopup(Popup, {
|
||||
type: 'modal',
|
||||
htmlMessage: "Extracted team data:<br /><textarea rows=\"10\" cols=\"60\">" + Tools.escapeHTML(JSON.stringify(Storage.teams)) + "</textarea>"
|
||||
htmlMessage: "Extracted team data:<br /><textarea rows=\"10\" cols=\"60\">" + BattleLog.escapeHTML(JSON.stringify(Storage.teams)) + "</textarea>"
|
||||
});
|
||||
} else {
|
||||
this.add('|error|Unknown debug command.');
|
||||
|
|
@ -795,7 +795,7 @@
|
|||
buffer += '<tr>';
|
||||
} else {
|
||||
buffer += '<tr class="hidden">';
|
||||
hiddenFormats.push(Tools.escapeFormat(formatId));
|
||||
hiddenFormats.push(BattleLog.escapeFormat(formatId));
|
||||
}
|
||||
|
||||
// Validate all the numerical data
|
||||
|
|
@ -804,7 +804,7 @@
|
|||
if (typeof values[j] !== 'number' && typeof values[j] !== 'string' || isNaN(values[j])) return self.add('|raw|Error: corrupted ranking data');
|
||||
}
|
||||
|
||||
buffer += '<td>' + Tools.escapeFormat(formatId) + '</td><td><strong>' + Math.round(row.elo) + '</strong></td>';
|
||||
buffer += '<td>' + BattleLog.escapeFormat(formatId) + '</td><td><strong>' + Math.round(row.elo) + '</strong></td>';
|
||||
if (row.rprd > 100) {
|
||||
// High rating deviation. Provisional rating.
|
||||
buffer += '<td>–</td>';
|
||||
|
|
@ -1231,7 +1231,7 @@
|
|||
if (!matches) {
|
||||
return; // bogus room ID could be used to inject JavaScript
|
||||
}
|
||||
var format = Tools.escapeFormat(matches[1]);
|
||||
var format = BattleLog.escapeFormat(matches[1]);
|
||||
|
||||
if (silent && !Tools.prefs('showbattles')) return;
|
||||
|
||||
|
|
@ -1241,7 +1241,7 @@
|
|||
battletype = format + ' battle';
|
||||
if (format === 'Random Battle') battletype = 'Random Battle';
|
||||
}
|
||||
this.$chat.append('<div class="notice"><a href="' + app.root + id + '" class="ilink">' + battletype + ' started between <strong style="' + hashColor(toUserid(name)) + '">' + Tools.escapeHTML(name) + '</strong> and <strong style="' + hashColor(toUserid(name2)) + '">' + Tools.escapeHTML(name2) + '</strong>.</a></div>');
|
||||
this.$chat.append('<div class="notice"><a href="' + app.root + id + '" class="ilink">' + battletype + ' started between <strong style="' + BattleLog.hashColor(toUserid(name)) + '">' + BattleLog.escapeHTML(name) + '</strong> and <strong style="' + BattleLog.hashColor(toUserid(name2)) + '">' + BattleLog.escapeHTML(name2) + '</strong>.</a></div>');
|
||||
break;
|
||||
|
||||
case 'j':
|
||||
|
|
@ -1281,7 +1281,7 @@
|
|||
|
||||
case 'raw':
|
||||
case 'html':
|
||||
this.$chat.append('<div class="notice">' + Tools.sanitizeHTML(row.slice(1).join('|')) + '</div>');
|
||||
this.$chat.append('<div class="notice">' + BattleLog.sanitizeHTML(row.slice(1).join('|')) + '</div>');
|
||||
break;
|
||||
|
||||
case 'notify':
|
||||
|
|
@ -1307,7 +1307,7 @@
|
|||
break;
|
||||
|
||||
case 'error':
|
||||
this.$chat.append('<div class="notice message-error">' + Tools.escapeHTML(row.slice(1).join('|')) + '</div>');
|
||||
this.$chat.append('<div class="notice message-error">' + BattleLog.escapeHTML(row.slice(1).join('|')) + '</div>');
|
||||
break;
|
||||
|
||||
case 'uhtml':
|
||||
|
|
@ -1317,12 +1317,12 @@
|
|||
if (!html) {
|
||||
$elements.remove();
|
||||
} else if (!$elements.length) {
|
||||
this.$chat.append('<div class="notice uhtml-' + toId(row[1]) + '">' + Tools.sanitizeHTML(html) + '</div>');
|
||||
this.$chat.append('<div class="notice uhtml-' + toId(row[1]) + '">' + BattleLog.sanitizeHTML(html) + '</div>');
|
||||
} else if (row[0] === 'uhtmlchange') {
|
||||
$elements.html(Tools.sanitizeHTML(html));
|
||||
$elements.html(BattleLog.sanitizeHTML(html));
|
||||
} else {
|
||||
$elements.remove();
|
||||
this.$chat.append('<div class="notice uhtml-' + toId(row[1]) + '">' + Tools.sanitizeHTML(html) + '</div>');
|
||||
this.$chat.append('<div class="notice uhtml-' + toId(row[1]) + '">' + BattleLog.sanitizeHTML(html) + '</div>');
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -1349,7 +1349,7 @@
|
|||
case 'tournaments':
|
||||
if (Tools.prefs('notournaments')) {
|
||||
if (row[1] === 'create') {
|
||||
this.$chat.append('<div class="notice">' + Tools.escapeFormat(row[2]) + ' ' + Tools.escapeHTML(row[3]) + ' tournament created (and hidden because you have tournaments disabled).</div>');
|
||||
this.$chat.append('<div class="notice">' + BattleLog.escapeFormat(row[2]) + ' ' + BattleLog.escapeHTML(row[3]) + ' tournament created (and hidden because you have tournaments disabled).</div>');
|
||||
} else if (row[1] === 'start') {
|
||||
this.$chat.append('<div class="notice">Tournament started.</div>');
|
||||
} else if (row[1] === 'forceend') {
|
||||
|
|
@ -1364,11 +1364,11 @@
|
|||
// fallthrough in case of unparsed message
|
||||
|
||||
case '':
|
||||
this.$chat.append('<div class="notice">' + Tools.escapeHTML(row.slice(1).join('|')) + '</div>');
|
||||
this.$chat.append('<div class="notice">' + BattleLog.escapeHTML(row.slice(1).join('|')) + '</div>');
|
||||
break;
|
||||
|
||||
default:
|
||||
this.$chat.append('<div class="notice"><code>|' + Tools.escapeHTML(row.join('|')) + '</code></div>');
|
||||
this.$chat.append('<div class="notice"><code>|' + BattleLog.escapeHTML(row.join('|')) + '</code></div>');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1465,7 +1465,7 @@
|
|||
message += ', ';
|
||||
}
|
||||
}
|
||||
message += Tools.escapeHTML(list[j]);
|
||||
message += BattleLog.escapeHTML(list[j]);
|
||||
}
|
||||
message += ' joined';
|
||||
}
|
||||
|
|
@ -1494,7 +1494,7 @@
|
|||
message += ', ';
|
||||
}
|
||||
}
|
||||
message += Tools.escapeHTML(list[j]);
|
||||
message += BattleLog.escapeHTML(list[j]);
|
||||
}
|
||||
message += ' left<br />';
|
||||
}
|
||||
|
|
@ -1519,11 +1519,11 @@
|
|||
if (pm) {
|
||||
var pmuserid = toUserid(pm);
|
||||
var oName = pmuserid === app.user.get('userid') ? name : pm;
|
||||
var clickableName = '<span class="username" data-name="' + Tools.escapeHTML(name) + '">' + Tools.escapeHTML(name.substr(1)) + '</span>';
|
||||
var clickableName = '<span class="username" data-name="' + BattleLog.escapeHTML(name) + '">' + BattleLog.escapeHTML(name.substr(1)) + '</span>';
|
||||
this.$chat.append(
|
||||
'<div class="chat chatmessage-' + toId(name) + '">' + ChatRoom.getTimestamp('lobby', msgTime) +
|
||||
'<strong style="' + hashColor(userid) + '">' + clickableName + ':</strong>' +
|
||||
'<span class="message-pm"><i class="pmnote" data-name="' + Tools.escapeHTML(oName) + '">(Private to ' + Tools.escapeHTML(pm) + ')</i> ' + Tools.parseMessage(message) + '</span>' +
|
||||
'<strong style="' + BattleLog.hashColor(userid) + '">' + clickableName + ':</strong>' +
|
||||
'<span class="message-pm"><i class="pmnote" data-name="' + BattleLog.escapeHTML(oName) + '">(Private to ' + BattleLog.escapeHTML(pm) + ')</i> ' + BattleLog.parseMessage(message) + '</span>' +
|
||||
'</div>'
|
||||
);
|
||||
return; // PMs independently notify in the main menu; no need to make them notify again with `inchatpm`.
|
||||
|
|
@ -1546,7 +1546,7 @@
|
|||
}
|
||||
|
||||
var isHighlighted = userid !== app.user.get('userid') && this.getHighlight(message);
|
||||
var parsedMessage = Tools.parseChatMessage(message, name, ChatRoom.getTimestamp('chat', msgTime), isHighlighted);
|
||||
var parsedMessage = BattleLog.parseChatMessage(message, name, ChatRoom.getTimestamp('chat', msgTime), isHighlighted);
|
||||
if (!$.isArray(parsedMessage)) parsedMessage = [parsedMessage];
|
||||
for (var i = 0; i < parsedMessage.length; i++) {
|
||||
if (!parsedMessage[i]) continue;
|
||||
|
|
@ -1687,17 +1687,17 @@
|
|||
var text = '';
|
||||
// Sanitising the `userid` here is probably unnecessary, because
|
||||
// IDs can't contain anything dangerous.
|
||||
text += '<li' + (this.room.userForm === userid ? ' class="cur"' : '') + ' id="' + this.room.id + '-userlist-user-' + Tools.escapeHTML(userid) + '">';
|
||||
text += '<button class="userbutton username" data-name="' + Tools.escapeHTML(name) + '">';
|
||||
text += '<li' + (this.room.userForm === userid ? ' class="cur"' : '') + ' id="' + this.room.id + '-userlist-user-' + BattleLog.escapeHTML(userid) + '">';
|
||||
text += '<button class="userbutton username" data-name="' + BattleLog.escapeHTML(name) + '">';
|
||||
var group = name.charAt(0);
|
||||
var details = Config.groups[group] || {type: 'user'};
|
||||
text += '<em class="group' + (details.group === 2 ? ' staffgroup' : '') + '">' + Tools.escapeHTML(group) + '</em>';
|
||||
text += '<em class="group' + (details.group === 2 ? ' staffgroup' : '') + '">' + BattleLog.escapeHTML(group) + '</em>';
|
||||
if (details.type === 'leadership') {
|
||||
text += '<strong><em style="' + hashColor(userid) + '">' + Tools.escapeHTML(name.substr(1)) + '</em></strong>';
|
||||
text += '<strong><em style="' + BattleLog.hashColor(userid) + '">' + BattleLog.escapeHTML(name.substr(1)) + '</em></strong>';
|
||||
} else if (details.type === 'staff') {
|
||||
text += '<strong style="' + hashColor(userid) + '">' + Tools.escapeHTML(name.substr(1)) + '</strong>';
|
||||
text += '<strong style="' + BattleLog.hashColor(userid) + '">' + BattleLog.escapeHTML(name.substr(1)) + '</strong>';
|
||||
} else {
|
||||
text += '<span style="' + hashColor(userid) + '">' + Tools.escapeHTML(name.substr(1)) + '</span>';
|
||||
text += '<span style="' + BattleLog.hashColor(userid) + '">' + BattleLog.escapeHTML(name.substr(1)) + '</span>';
|
||||
}
|
||||
text += '</button>';
|
||||
text += '</li>';
|
||||
|
|
|
|||
|
|
@ -48,14 +48,14 @@
|
|||
break;
|
||||
|
||||
case 'pagehtml':
|
||||
this.$el.html(Tools.sanitizeHTML(row[1]));
|
||||
this.$el.html(BattleLog.sanitizeHTML(row[1]));
|
||||
this.subtleNotifyOnce();
|
||||
break;
|
||||
|
||||
case 'selectorhtml':
|
||||
var pipeIndex2 = row[1].indexOf('|');
|
||||
if (pipeIndex2 < 0) return;
|
||||
this.$(row[1].slice(0, pipeIndex2)).html(Tools.sanitizeHTML(row[1].slice(pipeIndex2 + 1)));
|
||||
this.$(row[1].slice(0, pipeIndex2)).html(BattleLog.sanitizeHTML(row[1].slice(pipeIndex2 + 1)));
|
||||
this.subtleNotifyOnce();
|
||||
break;
|
||||
|
||||
|
|
@ -96,7 +96,7 @@
|
|||
return;
|
||||
}
|
||||
if (this.curFormat !== data[0]) return;
|
||||
buf += Tools.sanitizeHTML(data[1]) + '</div>';
|
||||
buf += BattleLog.sanitizeHTML(data[1]) + '</div>';
|
||||
this.$el.html(buf);
|
||||
}, this);
|
||||
},
|
||||
|
|
@ -119,9 +119,9 @@
|
|||
if (!format.rated || !format.searchShow) continue;
|
||||
if (format.section && format.section !== curSection) {
|
||||
curSection = format.section;
|
||||
buf += '</ul><h3>' + Tools.escapeHTML(curSection) + '</h3><ul style="list-style:none;margin:0;padding:0">';
|
||||
buf += '</ul><h3>' + BattleLog.escapeHTML(curSection) + '</h3><ul style="list-style:none;margin:0;padding:0">';
|
||||
}
|
||||
buf += '<li style="margin:5px"><button name="selectFormat" value="' + i + '" class="button" style="width:320px;height:30px;text-align:left;font:12pt Verdana">' + Tools.escapeFormat(format.id) + '</button></li>';
|
||||
buf += '<li style="margin:5px"><button name="selectFormat" value="' + i + '" class="button" style="width:320px;height:30px;text-align:left;font:12pt Verdana">' + BattleLog.escapeFormat(format.id) + '</button></li>';
|
||||
}
|
||||
buf += '</ul></div>';
|
||||
this.$el.html(buf);
|
||||
|
|
@ -141,7 +141,7 @@
|
|||
}, function (data) {
|
||||
if (self.curFormat !== format) return;
|
||||
var buf = '<div class="ladder pad"><p><button name="selectFormat"><i class="fa fa-chevron-left"></i> Format List</button></p><p><button class="button" name="refresh"><i class="fa fa-refresh"></i> Refresh</button></p>';
|
||||
buf += '<h3>' + Tools.escapeFormat(format) + ' Top 500</h3>';
|
||||
buf += '<h3>' + BattleLog.escapeFormat(format) + ' Top 500</h3>';
|
||||
buf += data + '</div>';
|
||||
self.$el.html(buf);
|
||||
}, 'html');
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@
|
|||
|
||||
var autoscroll = ($chatFrame.scrollTop() + 60 >= $chat.height() - $chatFrame.height());
|
||||
|
||||
var parsedMessage = Tools.parseChatMessage(message, name, ChatRoom.getTimestamp('pms'), false, $chat);
|
||||
var parsedMessage = BattleLog.parseChatMessage(message, name, ChatRoom.getTimestamp('pms'), false, $chat);
|
||||
if (!$.isArray(parsedMessage)) parsedMessage = [parsedMessage];
|
||||
for (var i = 0; i < parsedMessage.length; i++) {
|
||||
if (!parsedMessage[i]) continue;
|
||||
|
|
@ -176,12 +176,12 @@
|
|||
if (group === ' ') {
|
||||
group = '';
|
||||
} else {
|
||||
group = '<small>' + Tools.escapeHTML(group) + '</small>';
|
||||
group = '<small>' + BattleLog.escapeHTML(group) + '</small>';
|
||||
}
|
||||
var buf = '<div class="pm-window pm-window-' + userid + '" data-userid="' + userid + '" data-name="' + name + '">';
|
||||
buf += '<h3><button class="closebutton" href="' + app.root + 'teambuilder" tabindex="-1" aria-label="Close"><i class="fa fa-times-circle"></i></button>';
|
||||
buf += '<button class="minimizebutton" href="' + app.root + 'teambuilder" tabindex="-1" aria-label="Minimize"><i class="fa fa-minus-circle"></i></button>';
|
||||
buf += group + Tools.escapeHTML(name.substr(1)) + '</h3>';
|
||||
buf += group + BattleLog.escapeHTML(name.substr(1)) + '</h3>';
|
||||
buf += '<div class="pm-log"><div class="inner" role="log"></div></div>';
|
||||
buf += '<div class="pm-log-add"><form class="chatbox nolabel"><textarea class="textbox" type="text" size="70" autocomplete="off" name="message"></textarea></form></div></div>';
|
||||
$pmWindow = $(buf).prependTo(this.$pmBox);
|
||||
|
|
@ -569,7 +569,7 @@
|
|||
for (var roomid in this.games) {
|
||||
var name = this.games[roomid];
|
||||
if (name.slice(-1) === '*') name = name.slice(0, -1);
|
||||
buf += '<div><a href="/' + toRoomid(roomid) + '" class="ilink" style="text-align: center">' + Tools.escapeHTML(name) + '</a></div>';
|
||||
buf += '<div><a href="/' + toRoomid(roomid) + '" class="ilink" style="text-align: center">' + BattleLog.escapeHTML(name) + '</a></div>';
|
||||
}
|
||||
buf += '</div>';
|
||||
if (!$searchGroup.is(':visible')) buf += '<p class="buttonbar"><button name="showSearchGroup">Add game</button></p>';
|
||||
|
|
@ -606,7 +606,7 @@
|
|||
var userid = toId(name);
|
||||
var $challenge = this.openChallenge(name);
|
||||
|
||||
var buf = '<form class="battleform"><p>Waiting for ' + Tools.escapeHTML(name) + '...</p>';
|
||||
var buf = '<form class="battleform"><p>Waiting for ' + BattleLog.escapeHTML(name) + '...</p>';
|
||||
buf += '<p><label class="label">Format:</label>' + this.renderFormats(challenge.format, true) + '</p>';
|
||||
buf += '<p class="buttonbar"><button name="cancelChallenge">Cancel</button></p></form>';
|
||||
|
||||
|
|
@ -623,10 +623,10 @@
|
|||
if (data.challengesFrom[userid]) {
|
||||
var format = data.challengesFrom[userid];
|
||||
if (!$pmWindow.find('.challenge').length) {
|
||||
self.notifyOnce("Challenge from " + name, "Format: " + Tools.escapeFormat(format), 'challenge:' + userid);
|
||||
self.notifyOnce("Challenge from " + name, "Format: " + BattleLog.escapeFormat(format), 'challenge:' + userid);
|
||||
}
|
||||
var $challenge = self.openChallenge(name, $pmWindow);
|
||||
var buf = '<form class="battleform"><p>' + Tools.escapeHTML(name) + ' wants to battle!</p>';
|
||||
var buf = '<form class="battleform"><p>' + BattleLog.escapeHTML(name) + ' wants to battle!</p>';
|
||||
buf += '<p><label class="label">Format:</label>' + self.renderFormats(format, true) + '</p>';
|
||||
buf += '<p><label class="label">Team:</label>' + self.renderTeams(format) + '</p>';
|
||||
buf += '<p class="buttonbar"><button name="acceptChallenge"><strong>Accept</strong></button> <button name="rejectChallenge">Reject</button></p></form>';
|
||||
|
|
@ -729,7 +729,7 @@
|
|||
}
|
||||
|
||||
$challenge = this.openChallenge(name);
|
||||
var buf = '<form class="battleform"><p>Challenge ' + Tools.escapeHTML(name) + '?</p>';
|
||||
var buf = '<form class="battleform"><p>Challenge ' + BattleLog.escapeHTML(name) + '?</p>';
|
||||
buf += '<p><label class="label">Format:</label>' + this.renderFormats(format) + '</p>';
|
||||
buf += '<p><label class="label">Team:</label>' + this.renderTeams(format, teamIndex) + '</p>';
|
||||
buf += '<p class="buttonbar"><button name="makeChallenge"><strong>Challenge</strong></button> <button name="dismissChallenge">Cancel</button></p></form>';
|
||||
|
|
@ -773,7 +773,7 @@
|
|||
return;
|
||||
}
|
||||
|
||||
var buf = '<form class="battleform pending"><p>Challenging ' + Tools.escapeHTML(name) + '...</p>';
|
||||
var buf = '<form class="battleform pending"><p>Challenging ' + BattleLog.escapeHTML(name) + '...</p>';
|
||||
buf += '<p><label class="label">Format:</label>' + this.renderFormats(format, true) + '</p>';
|
||||
buf += '<p class="buttonbar"><button name="cancelChallenge">Cancel</button></p></form>';
|
||||
|
||||
|
|
@ -802,7 +802,7 @@
|
|||
curFormat: '',
|
||||
renderFormats: function (formatid, noChoice) {
|
||||
if (!window.BattleFormats) {
|
||||
return '<button class="select formatselect" name="format" disabled value="' + Tools.escapeHTML(formatid) + '"><em>Loading...</em></button>';
|
||||
return '<button class="select formatselect" name="format" disabled value="' + BattleLog.escapeHTML(formatid) + '"><em>Loading...</em></button>';
|
||||
}
|
||||
if (_.isEmpty(BattleFormats)) {
|
||||
return '<button class="select formatselect" name="format" disabled><em>No formats available</em></button>';
|
||||
|
|
@ -820,7 +820,7 @@
|
|||
}
|
||||
formatid = this.curFormat;
|
||||
}
|
||||
return '<button class="select formatselect' + (noChoice ? ' preselected' : '') + '" name="format" value="' + formatid + '"' + (noChoice ? ' disabled' : '') + '>' + Tools.escapeFormat(formatid) + '</button>';
|
||||
return '<button class="select formatselect' + (noChoice ? ' preselected' : '') + '" name="format" value="' + formatid + '"' + (noChoice ? ' disabled' : '') + '>' + BattleLog.escapeFormat(formatid) + '</button>';
|
||||
},
|
||||
curTeamFormat: '',
|
||||
curTeamIndex: 0,
|
||||
|
|
@ -957,9 +957,9 @@
|
|||
if (!bufs[curBuf]) {
|
||||
bufs[curBuf] = '';
|
||||
}
|
||||
bufs[curBuf] += '<li><h3>' + Tools.escapeHTML(curSection) + '</li>';
|
||||
bufs[curBuf] += '<li><h3>' + BattleLog.escapeHTML(curSection) + '</li>';
|
||||
}
|
||||
var formatName = Tools.escapeFormat(format.id);
|
||||
var formatName = BattleLog.escapeFormat(format.id);
|
||||
if (formatName.charAt(0) !== '[') formatName = '[Gen 6] ' + formatName;
|
||||
formatName = formatName.replace('[Gen 7] ', '');
|
||||
bufs[curBuf] += '<li><button name="selectFormat" value="' + i + '"' + (curFormat === i ? ' class="sel"' : '') + '>' + formatName + '</button></li>';
|
||||
|
|
@ -989,7 +989,7 @@
|
|||
var $teamButton = this.sourceEl.closest('form').find('button[name=team]');
|
||||
if ($teamButton.length) $teamButton.replaceWith(app.rooms[''].renderTeams(format));
|
||||
}
|
||||
this.sourceEl.val(format).html(Tools.escapeFormat(format) || '(Select a format)');
|
||||
this.sourceEl.val(format).html(BattleLog.escapeFormat(format) || '(Select a format)');
|
||||
|
||||
this.close();
|
||||
}
|
||||
|
|
@ -1023,22 +1023,22 @@
|
|||
|
||||
if (!teams.length) {
|
||||
bufs[curBuf] = '<li><p><em>You have no teams</em></p></li>';
|
||||
bufs[curBuf] += '<li><button name="teambuilder" class="button"><strong>Teambuilder</strong><br />' + Tools.escapeFormat(teamFormat) + ' teams</button></li>';
|
||||
bufs[curBuf] += '<li><button name="teambuilder" class="button"><strong>Teambuilder</strong><br />' + BattleLog.escapeFormat(teamFormat) + ' teams</button></li>';
|
||||
} else {
|
||||
var curTeam = (data.team === '' ? -1 : +data.team);
|
||||
var count = 0;
|
||||
if (teamFormat) {
|
||||
bufs[curBuf] = '<li><h3>' + Tools.escapeFormat(teamFormat) + ' teams</h3></li>';
|
||||
bufs[curBuf] = '<li><h3>' + BattleLog.escapeFormat(teamFormat) + ' teams</h3></li>';
|
||||
for (var i = 0; i < teams.length; i++) {
|
||||
if ((!teams[i].format && !teamFormat) || teams[i].format === teamFormat) {
|
||||
var selected = (i === curTeam);
|
||||
bufs[curBuf] += '<li><button name="selectTeam" value="' + i + '"' + (selected ? ' class="sel"' : '') + '>' + Tools.escapeHTML(teams[i].name) + '</button></li>';
|
||||
bufs[curBuf] += '<li><button name="selectTeam" value="' + i + '"' + (selected ? ' class="sel"' : '') + '>' + BattleLog.escapeHTML(teams[i].name) + '</button></li>';
|
||||
count++;
|
||||
if (count % bufBoundary == 0 && curBuf < 4) curBuf++;
|
||||
}
|
||||
}
|
||||
if (!count) bufs[curBuf] += '<li><p><em>You have no ' + Tools.escapeFormat(teamFormat) + ' teams</em></p></li>';
|
||||
bufs[curBuf] += '<li><button name="teambuilder" class="button"><strong>Teambuilder</strong><br />' + Tools.escapeFormat(teamFormat) + ' teams</button></li>';
|
||||
if (!count) bufs[curBuf] += '<li><p><em>You have no ' + BattleLog.escapeFormat(teamFormat) + ' teams</em></p></li>';
|
||||
bufs[curBuf] += '<li><button name="teambuilder" class="button"><strong>Teambuilder</strong><br />' + BattleLog.escapeFormat(teamFormat) + ' teams</button></li>';
|
||||
bufs[curBuf] += '<li><h3>Other teams</h3></li>';
|
||||
} else {
|
||||
bufs[curBuf] = '<li><button name="teambuilder" class="button"><strong>Teambuilder</strong></button></li>';
|
||||
|
|
@ -1049,7 +1049,7 @@
|
|||
for (var i = 0; i < teams.length; i++) {
|
||||
if (teamFormat && teams[i].format === teamFormat) continue;
|
||||
var selected = (i === curTeam);
|
||||
bufs[curBuf] += '<li><button name="selectTeam" value="' + i + '"' + (selected ? ' class="sel"' : '') + '>' + Tools.escapeHTML(teams[i].name) + '</button></li>';
|
||||
bufs[curBuf] += '<li><button name="selectTeam" value="' + i + '"' + (selected ? ' class="sel"' : '') + '>' + BattleLog.escapeHTML(teams[i].name) + '</button></li>';
|
||||
count++;
|
||||
if (count % bufBoundary == 0 && curBuf < 4) curBuf++;
|
||||
}
|
||||
|
|
@ -1112,7 +1112,7 @@
|
|||
}
|
||||
var team = Storage.teams[i];
|
||||
if (!team) return 'Error: Corrupted team';
|
||||
var buf = '<strong>' + Tools.escapeHTML(team.name) + '</strong><small>';
|
||||
var buf = '<strong>' + BattleLog.escapeHTML(team.name) + '</strong><small>';
|
||||
buf += Storage.getTeamIcons(team) + '</small>';
|
||||
return buf;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,12 +59,12 @@
|
|||
},
|
||||
renderRoomBtn: function (roomData) {
|
||||
var id = toId(roomData.title);
|
||||
var buf = '<div><a href="' + app.root + id + '" class="ilink"><small style="float:right">(' + Number(roomData.userCount) + ' users)</small><strong><i class="fa fa-comment-o"></i> ' + Tools.escapeHTML(roomData.title) + '<br /></strong><small>' + Tools.escapeHTML(roomData.desc || '');
|
||||
var buf = '<div><a href="' + app.root + id + '" class="ilink"><small style="float:right">(' + Number(roomData.userCount) + ' users)</small><strong><i class="fa fa-comment-o"></i> ' + BattleLog.escapeHTML(roomData.title) + '<br /></strong><small>' + BattleLog.escapeHTML(roomData.desc || '');
|
||||
if (roomData.subRooms && roomData.subRooms.length) {
|
||||
buf += '<br/><i class="fa fa-level-up fa-rotate-90"></i> Subrooms: <strong>';
|
||||
for (var i = 0; i < roomData.subRooms.length; i++) {
|
||||
if (i) buf += ', ';
|
||||
buf += '<i class="fa fa-comment-o"></i> ' + Tools.escapeHTML(roomData.subRooms[i]);
|
||||
buf += '<i class="fa fa-comment-o"></i> ' + BattleLog.escapeHTML(roomData.subRooms[i]);
|
||||
}
|
||||
buf += '</strong>';
|
||||
}
|
||||
|
|
@ -167,14 +167,14 @@
|
|||
renderRoomBtn: function (id, roomData, matches) {
|
||||
var format = (matches[1] || '');
|
||||
var formatBuf = '';
|
||||
if (roomData.minElo) formatBuf += '<small style="float:right">(' + (typeof roomData.minElo === 'number' ? 'rated: ' : '') + Tools.escapeHTML(roomData.minElo) + ')</small>';
|
||||
formatBuf += (format ? '<small>[' + Tools.escapeFormat(format) + ']</small><br />' : '');
|
||||
var roomDesc = formatBuf + '<em class="p1">' + Tools.escapeHTML(roomData.p1) + '</em> <small class="vs">vs.</small> <em class="p2">' + Tools.escapeHTML(roomData.p2) + '</em>';
|
||||
if (roomData.minElo) formatBuf += '<small style="float:right">(' + (typeof roomData.minElo === 'number' ? 'rated: ' : '') + BattleLog.escapeHTML(roomData.minElo) + ')</small>';
|
||||
formatBuf += (format ? '<small>[' + BattleLog.escapeFormat(format) + ']</small><br />' : '');
|
||||
var roomDesc = formatBuf + '<em class="p1">' + BattleLog.escapeHTML(roomData.p1) + '</em> <small class="vs">vs.</small> <em class="p2">' + BattleLog.escapeHTML(roomData.p2) + '</em>';
|
||||
if (!roomData.p1) {
|
||||
matches = id.match(/[^0-9]([0-9]*)$/);
|
||||
roomDesc = formatBuf + 'empty room ' + matches[1];
|
||||
} else if (!roomData.p2) {
|
||||
roomDesc = formatBuf + '<em class="p1">' + Tools.escapeHTML(roomData.p1) + '</em>';
|
||||
roomDesc = formatBuf + '<em class="p1">' + BattleLog.escapeHTML(roomData.p1) + '</em>';
|
||||
}
|
||||
return '<div><a href="' + app.root + id + '" class="ilink">' + roomDesc + '</a></div>';
|
||||
},
|
||||
|
|
@ -204,8 +204,8 @@
|
|||
buf.push(this.renderRoomBtn(id, roomData, matches));
|
||||
}
|
||||
|
||||
if (!buf.length) return this.$list.html('<p>No ' + Tools.escapeFormat(this.format) + ' battles are going on right now.</p>');
|
||||
return this.$list.html('<p>' + buf.length + (buf.length === 100 ? '+' : '') + ' ' + Tools.escapeFormat(this.format) + ' ' + (buf.length === 1 ? 'battle' : 'battles') + '</p>' + buf.join(""));
|
||||
if (!buf.length) return this.$list.html('<p>No ' + BattleLog.escapeFormat(this.format) + ' battles are going on right now.</p>');
|
||||
return this.$list.html('<p>' + buf.length + (buf.length === 100 ? '+' : '') + ' ' + BattleLog.escapeFormat(this.format) + ' ' + (buf.length === 1 ? 'battle' : 'battles') + '</p>' + buf.join(""));
|
||||
},
|
||||
refresh: function () {
|
||||
var elofilter = '';
|
||||
|
|
|
|||
|
|
@ -149,14 +149,14 @@
|
|||
if (this.exportMode) {
|
||||
if (this.curFolder) {
|
||||
buf = '<div class="pad"><button name="back"><i class="fa fa-chevron-left"></i> List</button></div>';
|
||||
buf += '<div class="teamedit"><textarea readonly class="textbox" rows="17">' + Tools.escapeHTML(Storage.exportFolder(this.curFolder)) + '</textarea></div>';
|
||||
buf += '<div class="teamedit"><textarea readonly class="textbox" rows="17">' + BattleLog.escapeHTML(Storage.exportFolder(this.curFolder)) + '</textarea></div>';
|
||||
} else {
|
||||
buf = '<div class="pad"><button name="back"><i class="fa fa-chevron-left"></i> List</button> <button name="saveBackup" class="savebutton"><i class="fa fa-floppy-o"></i> Save</button></div>';
|
||||
buf += '<div class="teamedit"><textarea class="textbox" rows="17">';
|
||||
if (Storage.teams.length > 350) {
|
||||
buf += Tools.escapeHTML(Storage.getPackedTeams());
|
||||
buf += BattleLog.escapeHTML(Storage.getPackedTeams());
|
||||
} else {
|
||||
buf += Tools.escapeHTML(Storage.exportAllTeams());
|
||||
buf += BattleLog.escapeHTML(Storage.exportAllTeams());
|
||||
}
|
||||
buf += '</textarea></div>';
|
||||
}
|
||||
|
|
@ -291,7 +291,7 @@
|
|||
formatName = '(uncategorized)';
|
||||
format = '/';
|
||||
} else {
|
||||
formatName = Tools.escapeHTML(formatName);
|
||||
formatName = BattleLog.escapeHTML(formatName);
|
||||
}
|
||||
buf += '<div class="folder' + (this.curFolder === format ? ' cur"><div class="folderhack3"><div class="folderhack1"></div><div class="folderhack2"></div>' : '">') + '<div class="selectFolder" data-value="' + format + '"><i class="fa ' + (this.curFolder === format ? 'fa-folder-open' : 'fa-folder') + (format === '/' ? '-o' : '') + '"></i>' + formatName + '</div></div>' + (this.curFolder === format ? '</div>' : '');
|
||||
continue;
|
||||
|
|
@ -347,7 +347,7 @@
|
|||
var newButtonText = "New Team";
|
||||
if (filterFolder) newButtonText = "New Team in folder";
|
||||
if (filterFormat && filterFormat !== 'gen7') {
|
||||
newButtonText = "New " + Tools.escapeFormat(filterFormat) + " Team";
|
||||
newButtonText = "New " + BattleLog.escapeFormat(filterFormat) + " Team";
|
||||
}
|
||||
buf += '<p><button name="newTop" class="button big"><i class="fa fa-plus-circle"></i> ' + newButtonText + '</button></p>';
|
||||
|
||||
|
|
@ -399,7 +399,7 @@
|
|||
|
||||
// teams are <div>s rather than <button>s because Firefox doesn't
|
||||
// support dragging and dropping buttons.
|
||||
buf += '<li><div name="edit" data-value="' + i + '" class="team" draggable="true">' + formatText + '<strong>' + Tools.escapeHTML(team.name) + '</strong><br /><small>';
|
||||
buf += '<li><div name="edit" data-value="' + i + '" class="team" draggable="true">' + formatText + '<strong>' + BattleLog.escapeHTML(team.name) + '</strong><br /><small>';
|
||||
buf += Storage.getTeamIcons(team);
|
||||
buf += '</small></div><button name="edit" value="' + i + '"><i class="fa fa-pencil" aria-label="Edit" title="Edit (you can also just click on the team)"></i></button><button name="newTop" value="' + i + '" title="Duplicate" aria-label="Duplicate"><i class="fa fa-clone"></i></button><button name="delete" value="' + i + '"><i class="fa fa-trash"></i> Delete</button></li>';
|
||||
}
|
||||
|
|
@ -1019,10 +1019,10 @@
|
|||
|
||||
var buf = '';
|
||||
if (this.exportMode) {
|
||||
buf = '<div class="pad"><button name="back"><i class="fa fa-chevron-left"></i> List</button> <input class="textbox teamnameedit" type="text" class="teamnameedit" size="30" value="' + Tools.escapeHTML(this.curTeam.name) + '" /> <button name="saveImport"><i class="fa fa-upload"></i> Import/Export</button> <button name="saveImport" class="savebutton"><i class="fa fa-floppy-o"></i> Save</button></div>';
|
||||
buf += '<div class="teamedit"><textarea class="textbox" rows="17">' + Tools.escapeHTML(Storage.exportTeam(this.curSetList)) + '</textarea></div>';
|
||||
buf = '<div class="pad"><button name="back"><i class="fa fa-chevron-left"></i> List</button> <input class="textbox teamnameedit" type="text" class="teamnameedit" size="30" value="' + BattleLog.escapeHTML(this.curTeam.name) + '" /> <button name="saveImport"><i class="fa fa-upload"></i> Import/Export</button> <button name="saveImport" class="savebutton"><i class="fa fa-floppy-o"></i> Save</button></div>';
|
||||
buf += '<div class="teamedit"><textarea class="textbox" rows="17">' + BattleLog.escapeHTML(Storage.exportTeam(this.curSetList)) + '</textarea></div>';
|
||||
} else {
|
||||
buf = '<div class="pad"><button name="back"><i class="fa fa-chevron-left"></i> List</button> <input class="textbox teamnameedit" type="text" class="teamnameedit" size="30" value="' + Tools.escapeHTML(this.curTeam.name) + '" /> <button name="import"><i class="fa fa-upload"></i> Import/Export</button></div>';
|
||||
buf = '<div class="pad"><button name="back"><i class="fa fa-chevron-left"></i> List</button> <input class="textbox teamnameedit" type="text" class="teamnameedit" size="30" value="' + BattleLog.escapeHTML(this.curTeam.name) + '" /> <button name="import"><i class="fa fa-upload"></i> Import/Export</button></div>';
|
||||
buf += '<div class="teamchartbox">';
|
||||
buf += '<ol class="teamchart">';
|
||||
buf += '<li>' + this.clipboardHTML() + '</li>';
|
||||
|
|
@ -1038,7 +1038,7 @@
|
|||
};
|
||||
if (exports.BattleFormats) {
|
||||
buf += '<li class="format-select">';
|
||||
buf += '<label class="label">Format:</label><button class="select formatselect teambuilderformatselect" name="format" value="' + this.curTeam.format + '">' + (isGenericFormat(this.curTeam.format) ? '<em>Select a format</em>' : Tools.escapeFormat(this.curTeam.format)) + '</button>';
|
||||
buf += '<label class="label">Format:</label><button class="select formatselect teambuilderformatselect" name="format" value="' + this.curTeam.format + '">' + (isGenericFormat(this.curTeam.format) ? '<em>Select a format</em>' : BattleLog.escapeFormat(this.curTeam.format)) + '</button>';
|
||||
var btnClass = 'button' + (!this.curSetList.length ? ' disabled' : '');
|
||||
buf += ' <button name="validate" class="' + btnClass + '"><i class="fa fa-check"></i> Validate</button></li>';
|
||||
}
|
||||
|
|
@ -1081,7 +1081,7 @@
|
|||
}
|
||||
buf += '<div class="setmenu"><button name="copySet"><i class="fa fa-files-o"></i>Copy</button> <button name="importSet"><i class="fa fa-upload"></i>Import/Export</button> <button name="moveSet"><i class="fa fa-arrows"></i>Move</button> <button name="deleteSet"><i class="fa fa-trash"></i>Delete</button></div>';
|
||||
buf += '<div class="setchart-nickname">';
|
||||
buf += '<label>Nickname</label><input type="text" name="nickname" class="textbox" value="' + Tools.escapeHTML(set.name || '') + '" placeholder="' + Tools.escapeHTML(template.baseSpecies) + '" />';
|
||||
buf += '<label>Nickname</label><input type="text" name="nickname" class="textbox" value="' + BattleLog.escapeHTML(set.name || '') + '" placeholder="' + BattleLog.escapeHTML(template.baseSpecies) + '" />';
|
||||
buf += '</div>';
|
||||
buf += '<div class="setchart" style="' + Tools.getTeambuilderSprite(set, this.curTeam.gen) + ';">';
|
||||
|
||||
|
|
@ -1092,7 +1092,7 @@
|
|||
} else {
|
||||
buf += '<div class="setcell-sprite"></div>';
|
||||
}
|
||||
buf += '<div class="setcell setcell-pokemon"><label>Pokémon</label><input type="text" name="pokemon" class="textbox chartinput" value="' + Tools.escapeHTML(set.species) + '" /></div></div>';
|
||||
buf += '<div class="setcell setcell-pokemon"><label>Pokémon</label><input type="text" name="pokemon" class="textbox chartinput" value="' + BattleLog.escapeHTML(set.species) + '" /></div></div>';
|
||||
|
||||
// details
|
||||
buf += '<div class="setcol setcol-details"><div class="setrow">';
|
||||
|
|
@ -1131,17 +1131,17 @@
|
|||
buf += '</div></div>';
|
||||
|
||||
buf += '<div class="setrow">';
|
||||
if (this.curTeam.gen > 1) buf += '<div class="setcell setcell-item"><label>Item</label><input type="text" name="item" class="textbox chartinput" value="' + Tools.escapeHTML(set.item) + '" /></div>';
|
||||
if (this.curTeam.gen > 2) buf += '<div class="setcell setcell-ability"><label>Ability</label><input type="text" name="ability" class="textbox chartinput" value="' + Tools.escapeHTML(set.ability) + '" /></div>';
|
||||
if (this.curTeam.gen > 1) buf += '<div class="setcell setcell-item"><label>Item</label><input type="text" name="item" class="textbox chartinput" value="' + BattleLog.escapeHTML(set.item) + '" /></div>';
|
||||
if (this.curTeam.gen > 2) buf += '<div class="setcell setcell-ability"><label>Ability</label><input type="text" name="ability" class="textbox chartinput" value="' + BattleLog.escapeHTML(set.ability) + '" /></div>';
|
||||
buf += '</div></div>';
|
||||
|
||||
// moves
|
||||
if (!set.moves) set.moves = [];
|
||||
buf += '<div class="setcol setcol-moves"><div class="setcell"><label>Moves</label>';
|
||||
buf += '<input type="text" name="move1" class="textbox chartinput" value="' + Tools.escapeHTML(set.moves[0]) + '" /></div>';
|
||||
buf += '<div class="setcell"><input type="text" name="move2" class="textbox chartinput" value="' + Tools.escapeHTML(set.moves[1]) + '" /></div>';
|
||||
buf += '<div class="setcell"><input type="text" name="move3" class="textbox chartinput" value="' + Tools.escapeHTML(set.moves[2]) + '" /></div>';
|
||||
buf += '<div class="setcell"><input type="text" name="move4" class="textbox chartinput" value="' + Tools.escapeHTML(set.moves[3]) + '" /></div>';
|
||||
buf += '<input type="text" name="move1" class="textbox chartinput" value="' + BattleLog.escapeHTML(set.moves[0]) + '" /></div>';
|
||||
buf += '<div class="setcell"><input type="text" name="move2" class="textbox chartinput" value="' + BattleLog.escapeHTML(set.moves[1]) + '" /></div>';
|
||||
buf += '<div class="setcell"><input type="text" name="move3" class="textbox chartinput" value="' + BattleLog.escapeHTML(set.moves[2]) + '" /></div>';
|
||||
buf += '<div class="setcell"><input type="text" name="move4" class="textbox chartinput" value="' + BattleLog.escapeHTML(set.moves[3]) + '" /></div>';
|
||||
buf += '</div>';
|
||||
|
||||
// stats
|
||||
|
|
@ -1533,9 +1533,9 @@
|
|||
buf += '<button disabled="disabled" class="addpokemon" aria-label="Add Pokémon"><i class="fa fa-plus"></i></button> ';
|
||||
isAdd = true;
|
||||
} else if (i == this.curSetLoc) {
|
||||
buf += '<button disabled="disabled" class="pokemon">' + pokemonicon + Tools.escapeHTML(set.name || Tools.getTemplate(set.species).baseSpecies || '<i class="fa fa-plus"></i>') + '</button> ';
|
||||
buf += '<button disabled="disabled" class="pokemon">' + pokemonicon + BattleLog.escapeHTML(set.name || Tools.getTemplate(set.species).baseSpecies || '<i class="fa fa-plus"></i>') + '</button> ';
|
||||
} else {
|
||||
buf += '<button name="selectPokemon" value="' + i + '" class="pokemon">' + pokemonicon + Tools.escapeHTML(set.name || Tools.getTemplate(set.species).baseSpecies) + '</button> ';
|
||||
buf += '<button name="selectPokemon" value="' + i + '" class="pokemon">' + pokemonicon + BattleLog.escapeHTML(set.name || Tools.getTemplate(set.species).baseSpecies) + '</button> ';
|
||||
}
|
||||
}
|
||||
if (this.curSetList.length < 6 && !isAdd) {
|
||||
|
|
@ -1902,7 +1902,7 @@
|
|||
buf += '<div class="col evslidercol"><div></div>';
|
||||
for (var i in stats) {
|
||||
if (i === 'spd' && this.curTeam.gen === 1) continue;
|
||||
buf += '<div><input type="range" name="evslider-' + i + '" value="' + Tools.escapeHTML(set.evs[i] === undefined ? (this.curTeam.gen > 2 ? '0' : '252') : '' + set.evs[i]) + '" min="0" max="252" step="4" class="evslider" tabindex="-1" aria-hidden="true" /></div>';
|
||||
buf += '<div><input type="range" name="evslider-' + i + '" value="' + BattleLog.escapeHTML(set.evs[i] === undefined ? (this.curTeam.gen > 2 ? '0' : '252') : '' + set.evs[i]) + '" min="0" max="252" step="4" class="evslider" tabindex="-1" aria-hidden="true" /></div>';
|
||||
}
|
||||
buf += '</div>';
|
||||
|
||||
|
|
@ -1912,7 +1912,7 @@
|
|||
for (var i in stats) {
|
||||
if (set.ivs[i] === undefined || isNaN(set.ivs[i])) set.ivs[i] = 31;
|
||||
var val = '' + (set.ivs[i]);
|
||||
buf += '<div><input type="number" name="iv-' + i + '" value="' + Tools.escapeHTML(val) + '" class="textbox inputform numform" min="0" max="31" step="1" /></div>';
|
||||
buf += '<div><input type="number" name="iv-' + i + '" value="' + BattleLog.escapeHTML(val) + '" class="textbox inputform numform" min="0" max="31" step="1" /></div>';
|
||||
}
|
||||
var hpType = '';
|
||||
if (set.moves) {
|
||||
|
|
@ -2032,7 +2032,7 @@
|
|||
for (var i in stats) {
|
||||
if (set.ivs[i] === undefined || isNaN(set.ivs[i])) set.ivs[i] = 31;
|
||||
var val = '' + Math.floor(set.ivs[i] / 2);
|
||||
buf += '<div><input type="number" name="iv-' + i + '" value="' + Tools.escapeHTML(val) + '" class="textbox inputform numform" min="0" max="15" step="1" /></div>';
|
||||
buf += '<div><input type="number" name="iv-' + i + '" value="' + BattleLog.escapeHTML(val) + '" class="textbox inputform numform" min="0" max="15" step="1" /></div>';
|
||||
}
|
||||
buf += '</div>';
|
||||
}
|
||||
|
|
@ -2304,7 +2304,7 @@
|
|||
buf += '<div class="resultheader"><h3>Details</h3></div>';
|
||||
buf += '<form class="detailsform">';
|
||||
|
||||
buf += '<div class="formrow"><label class="formlabel">Level:</label><div><input type="number" min="1" max="100" step="1" name="level" value="' + Tools.escapeHTML(set.level || 100) + '" class="textbox inputform numform" /></div></div>';
|
||||
buf += '<div class="formrow"><label class="formlabel">Level:</label><div><input type="number" min="1" max="100" step="1" name="level" value="' + BattleLog.escapeHTML(set.level || 100) + '" class="textbox inputform numform" /></div></div>';
|
||||
|
||||
if (this.curTeam.gen > 1) {
|
||||
buf += '<div class="formrow"><label class="formlabel">Gender:</label><div>';
|
||||
|
|
@ -3354,7 +3354,7 @@
|
|||
if (i !== data.i && i !== data.i + 1) {
|
||||
buf += '<li><button name="moveHere" value="' + i + '"><i class="fa fa-arrow-right"></i> Move here</button></li>';
|
||||
}
|
||||
buf += '<li' + (i === data.i ? ' style="opacity:.3"' : ' style="opacity:.6"') + '><span class="picon" style="display:inline-block;vertical-align:middle;' + Tools.getPokemonIcon(set) + '"></span> ' + Tools.escapeHTML(set.name || set.species) + '</li>';
|
||||
buf += '<li' + (i === data.i ? ' style="opacity:.3"' : ' style="opacity:.6"') + '><span class="picon" style="display:inline-block;vertical-align:middle;' + Tools.getPokemonIcon(set) + '"></span> ' + BattleLog.escapeHTML(set.name || set.species) + '</li>';
|
||||
}
|
||||
if (i !== data.i && i !== data.i + 1) {
|
||||
buf += '<li><button name="moveHere" value="' + i + '"><i class="fa fa-arrow-right"></i> Move here</button></li>';
|
||||
|
|
@ -3387,7 +3387,7 @@
|
|||
initialize: function (data) {
|
||||
this.room = data.room;
|
||||
this.folder = data.folder;
|
||||
var buf = '<form><p>Remove "' + data.folder.slice(0, -1) + '"?</p><p><label><input type="checkbox" name="addname" /> Add "' + Tools.escapeHTML(this.folder.slice(0, -1)) + '" before team names</label></p>';
|
||||
var buf = '<form><p>Remove "' + data.folder.slice(0, -1) + '"?</p><p><label><input type="checkbox" name="addname" /> Add "' + BattleLog.escapeHTML(this.folder.slice(0, -1)) + '" before team names</label></p>';
|
||||
buf += '<p><button type="submit"><strong>Remove (keep teams)</strong></button> <!--button name="removeDelete"><strong>Remove (delete teams)</strong></button--> <button name="close" class="autofocus">Cancel</button></p></form>';
|
||||
this.$el.html(buf);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -30,11 +30,11 @@
|
|||
updateUserbar: function () {
|
||||
var buf = '';
|
||||
var name = ' ' + app.user.get('name');
|
||||
var color = hashColor(app.user.get('userid'));
|
||||
var color = BattleLog.hashColor(app.user.get('userid'));
|
||||
if (!app.user.loaded) {
|
||||
buf = '<button disabled>Loading...</button>';
|
||||
} else if (app.user.get('named')) {
|
||||
buf = '<span class="username" data-name="' + Tools.escapeHTML(name) + '" style="' + color + '"><i class="fa fa-user" style="color:#779EC5"></i> ' + Tools.escapeHTML(name) + '</span>';
|
||||
buf = '<span class="username" data-name="' + BattleLog.escapeHTML(name) + '" style="' + color + '"><i class="fa fa-user" style="color:#779EC5"></i> ' + BattleLog.escapeHTML(name) + '</span>';
|
||||
} else {
|
||||
buf = '<button name="login">Choose name</button>';
|
||||
}
|
||||
|
|
@ -74,7 +74,7 @@
|
|||
if (room.notifications[tag].title) title += room.notifications[tag].title + '\n';
|
||||
if (room.notifications[tag].body) title += room.notifications[tag].body + '\n';
|
||||
}
|
||||
if (title) buf += ' title="' + Tools.escapeHTML(title) + '"';
|
||||
if (title) buf += ' title="' + BattleLog.escapeHTML(title) + '"';
|
||||
}
|
||||
switch (room ? room.type : id) {
|
||||
case '':
|
||||
|
|
@ -89,7 +89,7 @@
|
|||
case 'rooms':
|
||||
return buf + ' aria-label="Join chatroom"><i class="fa fa-plus" style="margin:7px auto -6px auto"></i> <span> </span></a></li>';
|
||||
case 'battle':
|
||||
var name = Tools.escapeHTML(room.title);
|
||||
var name = BattleLog.escapeHTML(room.title);
|
||||
var idChunks = id.substr(7).split('-');
|
||||
var formatid;
|
||||
if (idChunks.length <= 1) {
|
||||
|
|
@ -101,25 +101,25 @@
|
|||
var p1 = (room.battle && room.battle.p1 && room.battle.p1.name) || '';
|
||||
var p2 = (room.battle && room.battle.p2 && room.battle.p2.name) || '';
|
||||
if (p1 && p2) {
|
||||
name = '' + Tools.escapeHTML(p1) + ' v. ' + Tools.escapeHTML(p2);
|
||||
name = '' + BattleLog.escapeHTML(p1) + ' v. ' + BattleLog.escapeHTML(p2);
|
||||
} else if (p1 || p2) {
|
||||
name = '' + Tools.escapeHTML(p1) + Tools.escapeHTML(p2);
|
||||
name = '' + BattleLog.escapeHTML(p1) + BattleLog.escapeHTML(p2);
|
||||
} else {
|
||||
name = '(empty room)';
|
||||
}
|
||||
}
|
||||
return buf + ' draggable="true"><i class="text">' + Tools.escapeFormat(formatid) + '</i><span>' + name + '</span></a><button class="closebutton" name="closeRoom" value="' + id + '" aria-label="Close"><i class="fa fa-times-circle"></i></a></li>';
|
||||
return buf + ' draggable="true"><i class="text">' + BattleLog.escapeFormat(formatid) + '</i><span>' + name + '</span></a><button class="closebutton" name="closeRoom" value="' + id + '" aria-label="Close"><i class="fa fa-times-circle"></i></a></li>';
|
||||
case 'chat':
|
||||
return buf + ' draggable="true"><i class="fa fa-comment-o"></i> <span>' + (Tools.escapeHTML(room.title) || (id === 'lobby' ? 'Lobby' : id)) + '</span></a><button class="closebutton" name="closeRoom" value="' + id + '" aria-label="Close"><i class="fa fa-times-circle"></i></a></li>';
|
||||
return buf + ' draggable="true"><i class="fa fa-comment-o"></i> <span>' + (BattleLog.escapeHTML(room.title) || (id === 'lobby' ? 'Lobby' : id)) + '</span></a><button class="closebutton" name="closeRoom" value="' + id + '" aria-label="Close"><i class="fa fa-times-circle"></i></a></li>';
|
||||
case 'html':
|
||||
default:
|
||||
if (room.title && room.title.charAt(0) === '[') {
|
||||
var closeBracketIndex = room.title.indexOf(']');
|
||||
if (closeBracketIndex > 0) {
|
||||
return buf + ' draggable="true"><i class="text">' + Tools.escapeFormat(room.title.slice(1, closeBracketIndex)) + '</i><span>' + Tools.escapeHTML(room.title.slice(closeBracketIndex + 1)) + '</span></a><button class="closebutton" name="closeRoom" value="' + id + '" aria-label="Close"><i class="fa fa-times-circle"></i></a></li>';
|
||||
return buf + ' draggable="true"><i class="text">' + BattleLog.escapeFormat(room.title.slice(1, closeBracketIndex)) + '</i><span>' + BattleLog.escapeHTML(room.title.slice(closeBracketIndex + 1)) + '</span></a><button class="closebutton" name="closeRoom" value="' + id + '" aria-label="Close"><i class="fa fa-times-circle"></i></a></li>';
|
||||
}
|
||||
}
|
||||
return buf + ' draggable="true"><i class="fa fa-file-text-o"></i> <span>' + (Tools.escapeHTML(room.title) || id) + '</span></a><button class="closebutton" name="closeRoom" value="' + id + '" aria-label="Close"><i class="fa fa-times-circle"></i></a></li>';
|
||||
return buf + ' draggable="true"><i class="fa fa-file-text-o"></i> <span>' + (BattleLog.escapeHTML(room.title) || id) + '</span></a><button class="closebutton" name="closeRoom" value="' + id + '" aria-label="Close"><i class="fa fa-times-circle"></i></a></li>';
|
||||
}
|
||||
},
|
||||
updateTabbar: function () {
|
||||
|
|
@ -456,7 +456,7 @@
|
|||
var avatar = app.user.get('avatar');
|
||||
|
||||
var buf = '';
|
||||
buf += '<p>' + (avatar ? '<img class="trainersprite" src="' + Tools.resolveAvatar(avatar) + '" width="40" height="40" style="vertical-align:middle;cursor:pointer" />' : '') + '<strong>' + Tools.escapeHTML(name) + '</strong></p>';
|
||||
buf += '<p>' + (avatar ? '<img class="trainersprite" src="' + Tools.resolveAvatar(avatar) + '" width="40" height="40" style="vertical-align:middle;cursor:pointer" />' : '') + '<strong>' + BattleLog.escapeHTML(name) + '</strong></p>';
|
||||
buf += '<p><button name="avatars">Change avatar</button></p>';
|
||||
if (app.user.get('named')) {
|
||||
var registered = app.user.get('registered');
|
||||
|
|
@ -776,7 +776,7 @@
|
|||
var buf = '<form>';
|
||||
|
||||
if (data.error) {
|
||||
buf += '<p class="error">' + Tools.escapeHTML(data.error) + '</p>';
|
||||
buf += '<p class="error">' + BattleLog.escapeHTML(data.error) + '</p>';
|
||||
if (data.error.indexOf('inappropriate') >= 0) {
|
||||
buf += '<p>Keep in mind these rules:</p>';
|
||||
buf += '<ol>';
|
||||
|
|
@ -786,14 +786,14 @@
|
|||
buf += '</ol>';
|
||||
}
|
||||
} else if (data.reason) {
|
||||
buf += '<p>' + Tools.parseMessage(data.reason) + '</p>';
|
||||
buf += '<p>' + BattleLog.parseMessage(data.reason) + '</p>';
|
||||
} else if (!data.force) {
|
||||
var noRenameGames = '';
|
||||
if (app.rooms[''].games) {
|
||||
for (var roomid in app.rooms[''].games) {
|
||||
var title = app.rooms[''].games[roomid];
|
||||
if (title.slice(-1) === '*') {
|
||||
noRenameGames += '<li>' + Tools.escapeHTML(title.slice(0, -1)) + '</li>';
|
||||
noRenameGames += '<li>' + BattleLog.escapeHTML(title.slice(0, -1)) + '</li>';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -810,7 +810,7 @@
|
|||
|
||||
var name = (data.name || '');
|
||||
if (!name && app.user.get('named')) name = app.user.get('name');
|
||||
buf += '<p><label class="label">Username: <small class="preview" style="' + hashColor(toUserid(name)) + '">(color)</small><input class="textbox autofocus" type="text" name="username" value="' + Tools.escapeHTML(name) + '" autocomplete="username"></label></p>';
|
||||
buf += '<p><label class="label">Username: <small class="preview" style="' + BattleLog.hashColor(toUserid(name)) + '">(color)</small><input class="textbox autofocus" type="text" name="username" value="' + BattleLog.escapeHTML(name) + '" autocomplete="username"></label></p>';
|
||||
if (name) {
|
||||
buf += '<p><small>(Others will be able to see your name change. To change name privately, use "Log out")</small></p>';
|
||||
}
|
||||
|
|
@ -825,7 +825,7 @@
|
|||
updateColor: function (e) {
|
||||
var name = e.currentTarget.value;
|
||||
var preview = this.$('.preview');
|
||||
var css = hashColor(toUserid(name)).slice(6, -1);
|
||||
var css = BattleLog.hashColor(toUserid(name)).slice(6, -1);
|
||||
preview.css('color', css);
|
||||
},
|
||||
force: function () {
|
||||
|
|
@ -890,11 +890,11 @@
|
|||
} else {
|
||||
buf += '<p>Register your account:</p>';
|
||||
}
|
||||
buf += '<p><label class="label">Username: <strong><input type="text" name="name" value="' + Tools.escapeHTML(data.name || app.user.get('name')) + '" style="color:inherit;background:transparent;border:0;font:inherit;font-size:inherit;display:block" readonly autocomplete="username" /></strong></label></p>';
|
||||
buf += '<p><label class="label">Username: <strong><input type="text" name="name" value="' + BattleLog.escapeHTML(data.name || app.user.get('name')) + '" style="color:inherit;background:transparent;border:0;font:inherit;font-size:inherit;display:block" readonly autocomplete="username" /></strong></label></p>';
|
||||
buf += '<p><label class="label">Password: <input class="textbox autofocus" type="password" name="password" autocomplete="new-password" /></label></p>';
|
||||
buf += '<p><label class="label">Password (confirm): <input class="textbox" type="password" name="cpassword" autocomplete="new-password" /></label></p>';
|
||||
buf += '<p><label class="label"><img src="' + Tools.resourcePrefix + 'sprites/bwani/pikachu.gif" /></label></p>';
|
||||
buf += '<p><label class="label">What is this pokemon? <input class="textbox" type="text" name="captcha" value="' + Tools.escapeHTML(data.captcha) + '" /></label></p>';
|
||||
buf += '<p><label class="label">What is this pokemon? <input class="textbox" type="text" name="captcha" value="' + BattleLog.escapeHTML(data.captcha) + '" /></label></p>';
|
||||
buf += '<p class="buttonbar"><button type="submit"><strong>Register</strong></button> <button name="close">Cancel</button></p></form>';
|
||||
this.$el.html(buf);
|
||||
},
|
||||
|
|
@ -933,7 +933,7 @@
|
|||
var buf = '<form>';
|
||||
|
||||
if (data.error) {
|
||||
buf += '<p class="error">' + Tools.escapeHTML(data.error) + '</p>';
|
||||
buf += '<p class="error">' + BattleLog.escapeHTML(data.error) + '</p>';
|
||||
if (data.error.indexOf(' forced you to change ') >= 0) {
|
||||
buf += '<p>Keep in mind these rules:</p>';
|
||||
buf += '<ol>';
|
||||
|
|
@ -943,13 +943,13 @@
|
|||
buf += '</ol>';
|
||||
}
|
||||
} else if (data.reason) {
|
||||
buf += '<p>' + Tools.escapeHTML(data.reason) + '</p>';
|
||||
buf += '<p>' + BattleLog.escapeHTML(data.reason) + '</p>';
|
||||
} else {
|
||||
buf += '<p class="error">The name you chose is registered.</p>';
|
||||
}
|
||||
|
||||
buf += '<p>If this is your account:</p>';
|
||||
buf += '<p><label class="label">Username: <strong><input type="text" name="username" value="' + Tools.escapeHTML(data.username) + '" style="color:inherit;background:transparent;border:0;font:inherit;font-size:inherit;display:block" readonly autocomplete="username" /></strong></label></p>';
|
||||
buf += '<p><label class="label">Username: <strong><input type="text" name="username" value="' + BattleLog.escapeHTML(data.username) + '" style="color:inherit;background:transparent;border:0;font:inherit;font-size:inherit;display:block" readonly autocomplete="username" /></strong></label></p>';
|
||||
if (data.special === '@gmail') {
|
||||
buf += '<div id="gapi-custom-signin" style="width:240px;margin:0 auto">[loading Google log-in button]</div>';
|
||||
buf += '<p class="buttonbar"><button name="close">Cancel</button></p>';
|
||||
|
|
|
|||
20
js/client.js
20
js/client.js
|
|
@ -831,7 +831,7 @@
|
|||
var replayLink = 'https://replay.pokemonshowdown.com/' + replayid;
|
||||
$.ajax(replayLink + '.json', {dataType: 'json'}).done(function (replay) {
|
||||
if (replay) {
|
||||
var title = Tools.escapeHTML(replay.p1) + ' vs. ' + Tools.escapeHTML(replay.p2);
|
||||
var title = BattleLog.escapeHTML(replay.p1) + ' vs. ' + BattleLog.escapeHTML(replay.p2);
|
||||
app.receive('>battle-' + replayid + '\n|init|battle\n|title|' + title + '\n' + replay.log);
|
||||
app.receive('>battle-' + replayid + '\n|expire|<a href=' + replayLink + ' target="_blank">Open replay in new tab</a>');
|
||||
} else {
|
||||
|
|
@ -980,7 +980,7 @@
|
|||
app.addPopup(Popup, {
|
||||
type: type,
|
||||
maxWidth: maxWidth,
|
||||
htmlMessage: Tools.sanitizeHTML(data)
|
||||
htmlMessage: BattleLog.sanitizeHTML(data)
|
||||
});
|
||||
} else {
|
||||
app.addPopup(Popup, {
|
||||
|
|
@ -993,7 +993,7 @@
|
|||
break;
|
||||
|
||||
case 'disconnect':
|
||||
app.trigger('init:socketclosed', Tools.sanitizeHTML(data.substr(12)));
|
||||
app.trigger('init:socketclosed', BattleLog.sanitizeHTML(data.substr(12)));
|
||||
break;
|
||||
|
||||
case 'pm':
|
||||
|
|
@ -1060,7 +1060,7 @@
|
|||
if (!groupName) Config.defaultGroup = symbol;
|
||||
|
||||
groups[symbol] = {
|
||||
name: groupName ? Tools.escapeHTML(groupName + ' (' + symbol + ')') : null,
|
||||
name: groupName ? BattleLog.escapeHTML(groupName + ' (' + symbol + ')') : null,
|
||||
type: groupType,
|
||||
order: i + 1
|
||||
};
|
||||
|
|
@ -2231,7 +2231,7 @@
|
|||
},
|
||||
initialize: function (data) {
|
||||
if (!this.type) this.type = 'semimodal';
|
||||
this.$el.html('<form><p style="white-space:pre-wrap;word-wrap:break-word">' + (data.htmlMessage || Tools.parseMessage(data.message)) + '</p><p class="buttonbar">' + (data.buttons || '<button name="close" class="autofocus"><strong>OK</strong></button>') + '</p></form>').css('max-width', data.maxWidth || 480);
|
||||
this.$el.html('<form><p style="white-space:pre-wrap;word-wrap:break-word">' + (data.htmlMessage || BattleLog.parseMessage(data.message)) + '</p><p class="buttonbar">' + (data.buttons || '<button name="close" class="autofocus"><strong>OK</strong></button>') + '</p></form>').css('max-width', data.maxWidth || 480);
|
||||
},
|
||||
|
||||
dispatchClickButton: function (e) {
|
||||
|
|
@ -2284,7 +2284,7 @@
|
|||
|
||||
var buf = '<form>';
|
||||
buf += '<p><label class="label">' + data.message;
|
||||
buf += '<input class="textbox autofocus" type="text" name="data" value="' + Tools.escapeHTML(data.value || '') + '" /></label></p>';
|
||||
buf += '<input class="textbox autofocus" type="text" name="data" value="' + BattleLog.escapeHTML(data.value || '') + '" /></label></p>';
|
||||
buf += '<p class="buttonbar"><button type="submit"><strong>' + data.button + '</strong></button> <button name="close">Cancel</button></p>';
|
||||
buf += '</form>';
|
||||
|
||||
|
|
@ -2403,7 +2403,7 @@
|
|||
|
||||
var buf = '<div class="userdetails">';
|
||||
if (avatar) buf += '<img class="trainersprite' + (userid === ownUserid ? ' yours' : '') + '" src="' + Tools.resolveAvatar(avatar) + '" />';
|
||||
buf += '<strong><a href="//pokemonshowdown.com/users/' + userid + '" target="_blank">' + Tools.escapeHTML(name) + '</a></strong><br />';
|
||||
buf += '<strong><a href="//pokemonshowdown.com/users/' + userid + '" target="_blank">' + BattleLog.escapeHTML(name) + '</a></strong><br />';
|
||||
buf += '<small>' + (group || ' ') + '</small>';
|
||||
if (globalgroup) buf += '<br /><small>' + globalgroup + '</small>';
|
||||
if (data.rooms) {
|
||||
|
|
@ -2421,7 +2421,7 @@
|
|||
var p1 = data.rooms[i].p1.substr(1);
|
||||
var p2 = data.rooms[i].p2.substr(1);
|
||||
var ownBattle = (ownUserid === toUserid(p1) || ownUserid === toUserid(p2));
|
||||
var room = '<span title="' + (Tools.escapeHTML(p1) || '?') + ' v. ' + (Tools.escapeHTML(p2) || '?') + '">' + '<a href="' + app.root + roomid + '" class="ilink' + ((ownBattle || app.rooms[i]) ? ' yours' : '') + '">' + roomrank + roomid.substr(7) + '</a></span>';
|
||||
var room = '<span title="' + (BattleLog.escapeHTML(p1) || '?') + ' v. ' + (BattleLog.escapeHTML(p2) || '?') + '">' + '<a href="' + app.root + roomid + '" class="ilink' + ((ownBattle || app.rooms[i]) ? ' yours' : '') + '">' + roomrank + roomid.substr(7) + '</a></span>';
|
||||
if (data.rooms[i].isPrivate) {
|
||||
if (!privatebuf) privatebuf = '<br /><em>Private rooms:</em> ';
|
||||
else privatebuf += ', ';
|
||||
|
|
@ -2524,7 +2524,7 @@
|
|||
}
|
||||
var $pm = $('.pm-window-' + this.userid);
|
||||
if ($pm.length && $pm.css('display') !== 'none') {
|
||||
$pm.find('.inner').append('<div class="chat">' + Tools.escapeHTML(buf) + '</div>');
|
||||
$pm.find('.inner').append('<div class="chat">' + BattleLog.escapeHTML(buf) + '</div>');
|
||||
} else {
|
||||
var room = (app.curRoom && app.curRoom.add ? app.curRoom : app.curSideRoom);
|
||||
if (!room || !room.add) {
|
||||
|
|
@ -2619,7 +2619,7 @@
|
|||
var warning = ('warning' in data);
|
||||
var buf = '';
|
||||
if (warning) {
|
||||
buf += '<p><strong style="color:red">' + (Tools.escapeHTML(data.warning) || 'You have been warned for breaking the rules.') + '</strong></p>';
|
||||
buf += '<p><strong style="color:red">' + (BattleLog.escapeHTML(data.warning) || 'You have been warned for breaking the rules.') + '</strong></p>';
|
||||
}
|
||||
buf += '<h2>Pokémon Showdown Rules</h2>';
|
||||
buf += '<b>Global</b><br /><br /><b>1.</b> Be nice to people. Respect people. Don\'t be rude or mean to people.<br /><br /><b>2.</b> Follow US laws (PS is based in the US). No porn (minors use PS), don\'t distribute pirated material, and don\'t slander others.<br /><br /><b>3.</b> No sex. Don\'t discuss anything sexually explicit, not even in private messages, not even if you\'re both adults.<br /><b></b><br /><b>4.</b> No cheating. Don\'t exploit bugs to gain an unfair advantage. Don\'t game the system (by intentionally losing against yourself or a friend in a ladder match, by timerstalling, etc). Don\'t impersonate staff if you\'re not.<br /><br /><b>5.</b> Moderators have discretion to punish any behaviour they deem inappropriate, whether or not it\'s on this list. If you disagree with a moderator ruling, appeal to a leader (a user with & next to their name) or <a href="https://pokemonshowdown.com/appeal">Discipline Appeals</a>.<br /><br />(Note: The First Amendment does not apply to PS, since PS is not a government organization.)<br /><br />';
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ var Replays = {
|
|||
var replayid = this.$('input[name=replayid]').val();
|
||||
var m = /^([a-z0-9]+)-[a-z0-9]+-[0-9]+$/.exec(replayid);
|
||||
if (m) {
|
||||
this.battle.log('<hr /><div class="chat">This replay was uploaded from a third-party server (<code>' + Tools.escapeHTML(m[1]) + '</code>). It contains errors and cannot be viewed.</div><div class="chat">Replays uploaded from third-party servers can contain errors if the server is running custom code, or the server operator has otherwise incorrectly configured their server.</div>', true);
|
||||
this.battle.log('<hr /><div class="chat">This replay was uploaded from a third-party server (<code>' + BattleLog.escapeHTML(m[1]) + '</code>). It contains errors and cannot be viewed.</div><div class="chat">Replays uploaded from third-party servers can contain errors if the server is running custom code, or the server operator has otherwise incorrectly configured their server.</div>', true);
|
||||
this.battle.pause();
|
||||
}
|
||||
},
|
||||
|
|
|
|||
40
js/search.js
40
js/search.js
|
|
@ -541,7 +541,7 @@
|
|||
var text = this.filters[i][1];
|
||||
if (this.filters[i][0] === 'move') text = Tools.getMove(text).name;
|
||||
if (this.filters[i][0] === 'pokemon') text = Tools.getTemplate(text).name;
|
||||
buf += '<button class="filter" value="' + Tools.escapeHTML(this.filters[i].join(':')) + '">' + text + ' <i class="fa fa-times-circle"></i></button> ';
|
||||
buf += '<button class="filter" value="' + BattleLog.escapeHTML(this.filters[i].join(':')) + '">' + text + ' <i class="fa fa-times-circle"></i></button> ';
|
||||
}
|
||||
if (!q) buf += '<small style="color: #888">(backspace = delete filter)</small>';
|
||||
return buf + '</p>';
|
||||
|
|
@ -878,7 +878,7 @@
|
|||
template = Tools.getTemplate(set.species);
|
||||
var abilitySet = [['header', "Abilities"]];
|
||||
if (template.isMega) {
|
||||
abilitySet.unshift(['html', '<p>Will be <strong>' + Tools.escapeHTML(template.abilities['0']) + '</strong> after Mega Evolving.</p>']);
|
||||
abilitySet.unshift(['html', '<p>Will be <strong>' + BattleLog.escapeHTML(template.abilities['0']) + '</strong> after Mega Evolving.</p>']);
|
||||
template = Tools.getTemplate(template.baseSpecies);
|
||||
}
|
||||
var abilitiesInThisGen = Tools.getAbilitiesFor(template.id, this.gen);
|
||||
|
|
@ -898,7 +898,7 @@
|
|||
template = Tools.getTemplate(set.species);
|
||||
var abilities = [];
|
||||
if (template.isMega) {
|
||||
if (format === 'almostanyability') abilitySet.unshift(['html', '<p>Will be <strong>' + Tools.escapeHTML(template.abilities['0']) + '</strong> after Mega Evolving.</p>']);
|
||||
if (format === 'almostanyability') abilitySet.unshift(['html', '<p>Will be <strong>' + BattleLog.escapeHTML(template.abilities['0']) + '</strong> after Mega Evolving.</p>']);
|
||||
// template is unused after this, so no need to replace
|
||||
}
|
||||
for (var i in BattleAbilities) {
|
||||
|
|
@ -1290,7 +1290,7 @@
|
|||
if (!pokemon) return '<li class="result">Unrecognized pokemon</li>';
|
||||
var id = toId(pokemon.species);
|
||||
if (Search.urlRoot) attrs += ' href="' + Search.urlRoot + 'pokemon/' + id + '" data-target="push"';
|
||||
var buf = '<li class="result"><a' + attrs + ' data-entry="pokemon|' + Tools.escapeHTML(pokemon.species) + '">';
|
||||
var buf = '<li class="result"><a' + attrs + ' data-entry="pokemon|' + BattleLog.escapeHTML(pokemon.species) + '">';
|
||||
|
||||
// number
|
||||
// buf += '<span class="col numcol">' + (pokemon.num >= 0 ? pokemon.num : 'CAP') + '</span> ';
|
||||
|
|
@ -1414,7 +1414,7 @@
|
|||
Search.prototype.renderTaggedPokemonRowInner = function (pokemon, tag, errorMessage) {
|
||||
var attrs = '';
|
||||
if (Search.urlRoot) attrs = ' href="' + Search.urlRoot + 'pokemon/' + toId(pokemon.species) + '" data-target="push"';
|
||||
var buf = '<a' + attrs + ' data-entry="pokemon|' + Tools.escapeHTML(pokemon.species) + '">';
|
||||
var buf = '<a' + attrs + ' data-entry="pokemon|' + BattleLog.escapeHTML(pokemon.species) + '">';
|
||||
|
||||
// tag
|
||||
buf += '<span class="col tagcol shorttagcol">' + tag + '</span> ';
|
||||
|
|
@ -1485,7 +1485,7 @@
|
|||
if (!item) return '<li class="result">Unrecognized item</li>';
|
||||
var id = toId(item.name);
|
||||
if (Search.urlRoot) attrs += ' href="' + Search.urlRoot + 'items/' + id + '" data-target="push"';
|
||||
var buf = '<li class="result"><a' + attrs + ' data-entry="item|' + Tools.escapeHTML(item.name) + '">';
|
||||
var buf = '<li class="result"><a' + attrs + ' data-entry="item|' + BattleLog.escapeHTML(item.name) + '">';
|
||||
|
||||
// icon
|
||||
buf += '<span class="col itemiconcol">';
|
||||
|
|
@ -1515,7 +1515,7 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
buf += '<span class="col itemdesccol">' + Tools.escapeHTML(desc) + '</span> ';
|
||||
buf += '<span class="col itemdesccol">' + BattleLog.escapeHTML(desc) + '</span> ';
|
||||
|
||||
buf += '</a></li>';
|
||||
|
||||
|
|
@ -1526,7 +1526,7 @@
|
|||
if (!ability) return '<li class="result">Unrecognized ability</li>';
|
||||
var id = toId(ability.name);
|
||||
if (Search.urlRoot) attrs += ' href="' + Search.urlRoot + 'abilities/' + id + '" data-target="push"';
|
||||
var buf = '<li class="result"><a' + attrs + ' data-entry="ability|' + Tools.escapeHTML(ability.name) + '">';
|
||||
var buf = '<li class="result"><a' + attrs + ' data-entry="ability|' + BattleLog.escapeHTML(ability.name) + '">';
|
||||
|
||||
// name
|
||||
var name = ability.name;
|
||||
|
|
@ -1541,7 +1541,7 @@
|
|||
return buf;
|
||||
}
|
||||
|
||||
buf += '<span class="col abilitydesccol">' + Tools.escapeHTML(ability.shortDesc || ability.desc) + '</span> ';
|
||||
buf += '<span class="col abilitydesccol">' + BattleLog.escapeHTML(ability.shortDesc || ability.desc) + '</span> ';
|
||||
|
||||
buf += '</a></li>';
|
||||
|
||||
|
|
@ -1552,7 +1552,7 @@
|
|||
if (!move) return '<li class="result">Unrecognized move</li>';
|
||||
var id = toId(move.name);
|
||||
if (Search.urlRoot) attrs += ' href="' + Search.urlRoot + 'moves/' + id + '" data-target="push"';
|
||||
var buf = '<li class="result"><a' + attrs + ' data-entry="move|' + Tools.escapeHTML(move.name) + '">';
|
||||
var buf = '<li class="result"><a' + attrs + ' data-entry="move|' + BattleLog.escapeHTML(move.name) + '">';
|
||||
|
||||
// name
|
||||
var name = move.name;
|
||||
|
|
@ -1614,7 +1614,7 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
buf += '<span class="col movedesccol">' + Tools.escapeHTML(desc) + '</span> ';
|
||||
buf += '<span class="col movedesccol">' + BattleLog.escapeHTML(desc) + '</span> ';
|
||||
|
||||
buf += '</a></li>';
|
||||
|
||||
|
|
@ -1623,7 +1623,7 @@
|
|||
Search.prototype.renderMoveRowInner = function (move, errorMessage) {
|
||||
var attrs = '';
|
||||
if (Search.urlRoot) attrs = ' href="' + Search.urlRoot + 'moves/' + toId(move.name) + '" data-target="push"';
|
||||
var buf = '<a' + attrs + ' data-entry="move|' + Tools.escapeHTML(move.name) + '">';
|
||||
var buf = '<a' + attrs + ' data-entry="move|' + BattleLog.escapeHTML(move.name) + '">';
|
||||
|
||||
// name
|
||||
var name = move.name;
|
||||
|
|
@ -1649,7 +1649,7 @@
|
|||
buf += '<span class="col pplabelcol"><em>PP</em><br />' + (move.pp === 1 || move.noPPBoosts ? move.pp : move.pp * 8 / 5) + '</span> ';
|
||||
|
||||
// desc
|
||||
buf += '<span class="col movedesccol">' + Tools.escapeHTML(move.shortDesc || move.desc) + '</span> ';
|
||||
buf += '<span class="col movedesccol">' + BattleLog.escapeHTML(move.shortDesc || move.desc) + '</span> ';
|
||||
|
||||
buf += '</a>';
|
||||
|
||||
|
|
@ -1658,7 +1658,7 @@
|
|||
Search.prototype.renderTaggedMoveRow = function (move, tag, errorMessage) {
|
||||
var attrs = '';
|
||||
if (Search.urlRoot) attrs = ' href="' + Search.urlRoot + 'moves/' + toId(move.name) + '" data-target="push"';
|
||||
var buf = '<li class="result"><a' + attrs + ' data-entry="move|' + Tools.escapeHTML(move.name) + '">';
|
||||
var buf = '<li class="result"><a' + attrs + ' data-entry="move|' + BattleLog.escapeHTML(move.name) + '">';
|
||||
|
||||
// tag
|
||||
buf += '<span class="col tagcol">' + tag + '</span> ';
|
||||
|
|
@ -1686,7 +1686,7 @@
|
|||
buf += '<span class="col pplabelcol"><em>PP</em><br />' + (move.pp !== 1 ? move.pp * 8 / 5 : move.pp) + '</span> ';
|
||||
|
||||
// desc
|
||||
buf += '<span class="col movedesccol">' + Tools.escapeHTML(move.shortDesc || move.desc) + '</span> ';
|
||||
buf += '<span class="col movedesccol">' + BattleLog.escapeHTML(move.shortDesc || move.desc) + '</span> ';
|
||||
|
||||
buf += '</a></li>';
|
||||
|
||||
|
|
@ -1696,7 +1696,7 @@
|
|||
Search.prototype.renderTypeRow = function (type, matchStart, matchLength, errorMessage) {
|
||||
var attrs = '';
|
||||
if (Search.urlRoot) attrs = ' href="' + Search.urlRoot + 'types/' + toId(type.name) + '" data-target="push"';
|
||||
var buf = '<li class="result"><a' + attrs + ' data-entry="type|' + Tools.escapeHTML(type.name) + '">';
|
||||
var buf = '<li class="result"><a' + attrs + ' data-entry="type|' + BattleLog.escapeHTML(type.name) + '">';
|
||||
|
||||
// name
|
||||
var name = type.name;
|
||||
|
|
@ -1723,7 +1723,7 @@
|
|||
Search.prototype.renderCategoryRow = function (category, matchStart, matchLength, errorMessage) {
|
||||
var attrs = '';
|
||||
if (Search.urlRoot) attrs = ' href="' + Search.urlRoot + 'categories/' + category.id + '" data-target="push"';
|
||||
var buf = '<li class="result"><a' + attrs + ' data-entry="category|' + Tools.escapeHTML(category.name) + '">';
|
||||
var buf = '<li class="result"><a' + attrs + ' data-entry="category|' + BattleLog.escapeHTML(category.name) + '">';
|
||||
|
||||
// name
|
||||
var name = category.name;
|
||||
|
|
@ -1752,7 +1752,7 @@
|
|||
if (Search.urlRoot) attrs = ' href="' + Search.urlRoot + 'articles/' + article.id + '" data-target="push"';
|
||||
var isSearchType = (article.id === 'pokemon' || article.id === 'moves');
|
||||
if (isSearchType) attrs = ' href="' + article.id + '/" data-target="replace"';
|
||||
var buf = '<li class="result"><a' + attrs + ' data-entry="article|' + Tools.escapeHTML(article.name) + '">';
|
||||
var buf = '<li class="result"><a' + attrs + ' data-entry="article|' + BattleLog.escapeHTML(article.name) + '">';
|
||||
|
||||
// name
|
||||
var name = article.name;
|
||||
|
|
@ -1781,7 +1781,7 @@
|
|||
Search.prototype.renderEggGroupRow = function (egggroup, matchStart, matchLength, errorMessage) {
|
||||
var attrs = '';
|
||||
if (Search.urlRoot) attrs = ' href="' + Search.urlRoot + 'egggroups/' + toId(egggroup.name) + '" data-target="push"';
|
||||
var buf = '<li class="result"><a' + attrs + ' data-entry="egggroup|' + Tools.escapeHTML(egggroup.name) + '">';
|
||||
var buf = '<li class="result"><a' + attrs + ' data-entry="egggroup|' + BattleLog.escapeHTML(egggroup.name) + '">';
|
||||
|
||||
// name
|
||||
var name = egggroup.name;
|
||||
|
|
@ -1803,7 +1803,7 @@
|
|||
Search.prototype.renderTierRow = function (tier, matchStart, matchLength, errorMessage) {
|
||||
var attrs = '';
|
||||
if (Search.urlRoot) attrs = ' href="' + Search.urlRoot + 'tiers/' + toId(tier.name) + '" data-target="push"';
|
||||
var buf = '<li class="result"><a' + attrs + ' data-entry="tier|' + Tools.escapeHTML(tier.name) + '">';
|
||||
var buf = '<li class="result"><a' + attrs + ' data-entry="tier|' + BattleLog.escapeHTML(tier.name) + '">';
|
||||
|
||||
// name
|
||||
var name = tier.name;
|
||||
|
|
|
|||
|
|
@ -486,10 +486,10 @@ Storage.initTestClient = function () {
|
|||
if (uri[0] === '/') { //relative URI
|
||||
uri = Tools.resourcePrefix + uri.substr(1);
|
||||
}
|
||||
var src = '<!DOCTYPE html><html><body><form action="' + Tools.escapeHTML(uri) + '" method="POST">';
|
||||
var src = '<!DOCTYPE html><html><body><form action="' + BattleLog.escapeHTML(uri) + '" method="POST">';
|
||||
src += '<input type="hidden" name="testclient">';
|
||||
for (var i in data) {
|
||||
src += '<input type=hidden name="' + i + '" value="' + Tools.escapeHTML(data[i]) + '">';
|
||||
src += '<input type=hidden name="' + i + '" value="' + BattleLog.escapeHTML(data[i]) + '">';
|
||||
}
|
||||
src += '<input type=submit value="Please click this button first."></form></body></html>';
|
||||
app.addPopup(ProxyPopup, {uri: "data:text/html;charset=UTF-8," + encodeURIComponent(src), callback: callback});
|
||||
|
|
@ -529,7 +529,7 @@ Storage.loadPackedTeams = function (buffer) {
|
|||
Storage.whenAppLoaded(function (app) {
|
||||
app.addPopup(Popup, {
|
||||
type: 'modal',
|
||||
htmlMessage: "Your teams are corrupt and could not be loaded. :( We may be able to recover a team from this data:<br /><textarea rows=\"10\" cols=\"60\">" + Tools.escapeHTML(buffer) + "</textarea>"
|
||||
htmlMessage: "Your teams are corrupt and could not be loaded. :( We may be able to recover a team from this data:<br /><textarea rows=\"10\" cols=\"60\">" + BattleLog.escapeHTML(buffer) + "</textarea>"
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -657,7 +657,7 @@ class BattleScene {
|
|||
pokemonhtml = '<div class="teamicons">' + pokemonhtml + '</div>';
|
||||
const $sidebar = (side.n ? this.$rightbar : this.$leftbar);
|
||||
if (side.name) {
|
||||
$sidebar.html('<div class="trainer"><strong>' + Tools.escapeHTML(side.name) + '</strong><div class="trainersprite" style="background-image:url(' + Tools.resolveAvatar(side.spriteid) + ')"></div>' + pokemonhtml + '</div>');
|
||||
$sidebar.html('<div class="trainer"><strong>' + BattleLog.escapeHTML(side.name) + '</strong><div class="trainersprite" style="background-image:url(' + Tools.resolveAvatar(side.spriteid) + ')"></div>' + pokemonhtml + '</div>');
|
||||
$sidebar.find('.trainer').css('opacity', 1);
|
||||
} else {
|
||||
$sidebar.find('.trainer').css('opacity', 0.4);
|
||||
|
|
@ -729,7 +729,7 @@ class BattleScene {
|
|||
}
|
||||
side.totalPokemon = side.pokemon.length;
|
||||
if (textBuf) {
|
||||
this.log('<div class="chat battle-history"><strong>' + Tools.escapeHTML(side.name) + '\'s team:</strong> <em style="color:#445566;display:block;">' + Tools.escapeHTML(textBuf) + '</em></div>');
|
||||
this.log('<div class="chat battle-history"><strong>' + BattleLog.escapeHTML(side.name) + '\'s team:</strong> <em style="color:#445566;display:block;">' + BattleLog.escapeHTML(textBuf) + '</em></div>');
|
||||
}
|
||||
this.$sprites[siden].html(buf + buf2);
|
||||
|
||||
|
|
@ -2270,7 +2270,7 @@ class PokemonSprite extends Sprite {
|
|||
|
||||
getStatbarHTML(pokemon: Pokemon) {
|
||||
let buf = '<div class="statbar' + (this.siden ? ' lstatbar' : ' rstatbar') + '" style="display: none">';
|
||||
buf += '<strong>' + (this.siden && (this.scene.battle.ignoreOpponent || this.scene.battle.ignoreNicks) ? pokemon.species : Tools.escapeHTML(pokemon.name));
|
||||
buf += '<strong>' + (this.siden && (this.scene.battle.ignoreOpponent || this.scene.battle.ignoreNicks) ? pokemon.species : BattleLog.escapeHTML(pokemon.name));
|
||||
let gender = pokemon.gender;
|
||||
if (gender) buf += ' <img src="' + Tools.resourcePrefix + 'fx/gender-' + gender.toLowerCase() + '.png" alt="' + gender + '" />';
|
||||
buf += (pokemon.level === 100 ? '' : ' <small>L' + pokemon.level + '</small>');
|
||||
|
|
|
|||
|
|
@ -89,55 +89,6 @@ if (window.soundManager) {
|
|||
// @ts-ignore
|
||||
window.nodewebkit = !!(typeof process !== 'undefined' && process.versions && process.versions['node-webkit']);
|
||||
|
||||
let colorCache = {} as {[userid: string]: string};
|
||||
|
||||
function hashColor(name: string) {
|
||||
if (colorCache[name]) return colorCache[name];
|
||||
let hash;
|
||||
if (window.Config && Config.customcolors && Config.customcolors[name]) {
|
||||
if (Config.customcolors[name].color) {
|
||||
return (colorCache[name] = 'color:' + Config.customcolors[name].color + ';');
|
||||
}
|
||||
hash = MD5(Config.customcolors[name]);
|
||||
} else {
|
||||
hash = MD5(name);
|
||||
}
|
||||
let H = parseInt(hash.substr(4, 4), 16) % 360; // 0 to 360
|
||||
let S = parseInt(hash.substr(0, 4), 16) % 50 + 40; // 40 to 89
|
||||
let L = Math.floor(parseInt(hash.substr(8, 4), 16) % 20 + 30); // 30 to 49
|
||||
|
||||
let C = (100 - Math.abs(2 * L - 100)) * S / 100 / 100;
|
||||
let X = C * (1 - Math.abs((H / 60) % 2 - 1));
|
||||
let m = L / 100 - C / 2;
|
||||
|
||||
let R1, G1, B1;
|
||||
switch (Math.floor(H / 60)) {
|
||||
case 1: R1 = X; G1 = C; B1 = 0; break;
|
||||
case 2: R1 = 0; G1 = C; B1 = X; break;
|
||||
case 3: R1 = 0; G1 = X; B1 = C; break;
|
||||
case 4: R1 = X; G1 = 0; B1 = C; break;
|
||||
case 5: R1 = C; G1 = 0; B1 = X; break;
|
||||
case 0: default: R1 = C; G1 = X; B1 = 0; break;
|
||||
}
|
||||
let R = R1 + m, G = G1 + m, B = B1 + m;
|
||||
let lum = R * R * R * 0.2126 + G * G * G * 0.7152 + B * B * B * 0.0722; // 0.013 (dark blue) to 0.737 (yellow)
|
||||
|
||||
let HLmod = (lum - 0.2) * -150; // -80 (yellow) to 28 (dark blue)
|
||||
if (HLmod > 18) HLmod = (HLmod - 18) * 2.5;
|
||||
else if (HLmod < 0) HLmod = (HLmod - 0) / 3;
|
||||
else HLmod = 0;
|
||||
// let mod = ';border-right: ' + Math.abs(HLmod) + 'px solid ' + (HLmod > 0 ? 'red' : '#0088FF');
|
||||
let Hdist = Math.min(Math.abs(180 - H), Math.abs(240 - H));
|
||||
if (Hdist < 15) {
|
||||
HLmod += (15 - Hdist) / 3;
|
||||
}
|
||||
|
||||
L += HLmod;
|
||||
|
||||
colorCache[name] = "color:hsl(" + H + "," + S + "%," + L + "%);";
|
||||
return colorCache[name];
|
||||
}
|
||||
|
||||
function getString(str: any) {
|
||||
if (typeof str === 'string' || typeof str === 'number') return '' + str;
|
||||
return '';
|
||||
|
|
@ -268,372 +219,9 @@ const Tools = {
|
|||
return Tools.resolveAvatar(sprites[Math.floor(Math.random() * sprites.length)]);
|
||||
},
|
||||
|
||||
escapeFormat(formatid: string): string {
|
||||
let atIndex = formatid.indexOf('@@@');
|
||||
if (atIndex >= 0) {
|
||||
return Tools.escapeFormat(formatid.slice(0, atIndex)) + '<br />Custom rules: ' + Tools.escapeHTML(formatid.slice(atIndex + 3));
|
||||
}
|
||||
if (window.BattleFormats && BattleFormats[formatid]) {
|
||||
return Tools.escapeHTML(BattleFormats[formatid].name);
|
||||
}
|
||||
return Tools.escapeHTML(formatid);
|
||||
sanitizeName(name: string) {
|
||||
return name.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
||||
},
|
||||
parseChatMessage(message: string, name: string, timestamp: string, isHighlighted?: boolean, $chatElem?: any) {
|
||||
let showMe = !((Tools.prefs('chatformatting') || {}).hideme);
|
||||
let group = ' ';
|
||||
if (!/[A-Za-z0-9]/.test(name.charAt(0))) {
|
||||
// Backwards compatibility
|
||||
group = name.charAt(0);
|
||||
name = name.substr(1);
|
||||
}
|
||||
let color = hashColor(toId(name));
|
||||
let clickableName = '<small>' + Tools.escapeHTML(group) + '</small><span class="username" data-name="' + Tools.escapeHTML(name) + '">' + Tools.escapeHTML(name) + '</span>';
|
||||
let hlClass = isHighlighted ? ' highlighted' : '';
|
||||
let mineClass = (window.app && app.user && app.user.get('name') === name ? ' mine' : '');
|
||||
|
||||
let cmd = '';
|
||||
let target = '';
|
||||
if (message.charAt(0) === '/') {
|
||||
if (message.charAt(1) === '/') {
|
||||
message = message.slice(1);
|
||||
} else {
|
||||
let spaceIndex = message.indexOf(' ');
|
||||
cmd = (spaceIndex >= 0 ? message.slice(1, spaceIndex) : message.slice(1));
|
||||
if (spaceIndex >= 0) target = message.slice(spaceIndex + 1);
|
||||
}
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case 'me':
|
||||
if (!showMe) return '<div class="chat chatmessage-' + toId(name) + hlClass + mineClass + '">' + timestamp + '<strong style="' + color + '">' + clickableName + ':</strong> <em>/me' + Tools.parseMessage(' ' + target) + '</em></div>';
|
||||
return '<div class="chat chatmessage-' + toId(name) + hlClass + mineClass + '">' + timestamp + '<strong style="' + color + '">•</strong> <em>' + clickableName + '<i>' + Tools.parseMessage(' ' + target) + '</i></em></div>';
|
||||
case 'mee':
|
||||
if (!showMe) return '<div class="chat chatmessage-' + toId(name) + hlClass + mineClass + '">' + timestamp + '<strong style="' + color + '">' + clickableName + ':</strong> <em>/me' + Tools.parseMessage(' ' + target).slice(1) + '</em></div>';
|
||||
return '<div class="chat chatmessage-' + toId(name) + hlClass + mineClass + '">' + timestamp + '<strong style="' + color + '">•</strong> <em>' + clickableName + '<i>' + Tools.parseMessage(' ' + target).slice(1) + '</i></em></div>';
|
||||
case 'invite':
|
||||
let roomid = toRoomid(target);
|
||||
return [
|
||||
'<div class="chat">' + timestamp + '<em>' + clickableName + ' invited you to join the room "' + roomid + '"</em></div>',
|
||||
'<div class="notice"><button name="joinRoom" value="' + roomid + '">Join ' + roomid + '</button></div>'
|
||||
];
|
||||
case 'announce':
|
||||
return '<div class="chat chatmessage-' + toId(name) + hlClass + mineClass + '">' + timestamp + '<strong style="' + color + '">' + clickableName + ':</strong> <span class="message-announce">' + Tools.parseMessage(target) + '</span></div>';
|
||||
case 'log':
|
||||
return '<div class="chat chatmessage-' + toId(name) + hlClass + mineClass + '">' + timestamp + '<span class="message-log">' + Tools.parseMessage(target) + '</span></div>';
|
||||
case 'data-pokemon':
|
||||
let buf = '<li class="result">';
|
||||
let template = Tools.getTemplate(target);
|
||||
if (!template.abilities || !template.baseStats) return '[not supported in replays]';
|
||||
buf += '<span class="col numcol">' + (template.tier || Tools.getTemplate(template.baseSpecies).tier) + '</span> ';
|
||||
buf += '<span class="col iconcol"><span style="' + Tools.getPokemonIcon(template) + '"></span></span> ';
|
||||
buf += '<span class="col pokemonnamecol" style="white-space:nowrap"><a href="https://pokemonshowdown.com/dex/pokemon/' + template.id + '" target="_blank">' + template.species + '</a></span> ';
|
||||
buf += '<span class="col typecol">';
|
||||
if (template.types) for (let i = 0; i < template.types.length; i++) {
|
||||
buf += Tools.getTypeIcon(template.types[i]);
|
||||
}
|
||||
buf += '</span> ';
|
||||
buf += '<span style="float:left;min-height:26px">';
|
||||
if (template.abilities['1']) {
|
||||
buf += '<span class="col twoabilitycol">' + template.abilities['0'] + '<br />' + template.abilities['1'] + '</span>';
|
||||
} else {
|
||||
buf += '<span class="col abilitycol">' + template.abilities['0'] + '</span>';
|
||||
}
|
||||
if (template.abilities['S']) {
|
||||
buf += '<span class="col twoabilitycol' + (template.unreleasedHidden ? ' unreleasedhacol' : '') + '"><em>' + template.abilities['H'] + '<br />' + template.abilities['S'] + '</em></span>';
|
||||
} else if (template.abilities['H']) {
|
||||
buf += '<span class="col abilitycol' + (template.unreleasedHidden ? ' unreleasedhacol' : '') + '"><em>' + template.abilities['H'] + '</em></span>';
|
||||
} else {
|
||||
buf += '<span class="col abilitycol"></span>';
|
||||
}
|
||||
buf += '</span>';
|
||||
buf += '<span style="float:left;min-height:26px">';
|
||||
buf += '<span class="col statcol"><em>HP</em><br />' + template.baseStats.hp + '</span> ';
|
||||
buf += '<span class="col statcol"><em>Atk</em><br />' + template.baseStats.atk + '</span> ';
|
||||
buf += '<span class="col statcol"><em>Def</em><br />' + template.baseStats.def + '</span> ';
|
||||
buf += '<span class="col statcol"><em>SpA</em><br />' + template.baseStats.spa + '</span> ';
|
||||
buf += '<span class="col statcol"><em>SpD</em><br />' + template.baseStats.spd + '</span> ';
|
||||
buf += '<span class="col statcol"><em>Spe</em><br />' + template.baseStats.spe + '</span> ';
|
||||
let bst = 0;
|
||||
for (const i in template.baseStats) bst += template.baseStats[i as StatName];
|
||||
buf += '<span class="col bstcol"><em>BST<br />' + bst + '</em></span> ';
|
||||
buf += '</span>';
|
||||
buf += '</li>';
|
||||
return '<div class="message"><ul class="utilichart">' + buf + '<li style=\"clear:both\"></li></ul></div>';
|
||||
case 'data-item':
|
||||
if (!window.BattleSearch) return '[not supported in replays]';
|
||||
return '<div class="message"><ul class="utilichart">' + BattleSearch.renderItemRow(Tools.getItem(target), 0, 0) + '<li style=\"clear:both\"></li></ul></div>';
|
||||
case 'data-ability':
|
||||
if (!window.BattleSearch) return '[not supported in replays]';
|
||||
return '<div class="message"><ul class="utilichart">' + BattleSearch.renderAbilityRow(Tools.getAbility(target), 0, 0) + '<li style=\"clear:both\"></li></ul></div>';
|
||||
case 'data-move':
|
||||
if (!window.BattleSearch) return '[not supported in replays]';
|
||||
return '<div class="message"><ul class="utilichart">' + BattleSearch.renderMoveRow(Tools.getMove(target), 0, 0) + '<li style=\"clear:both\"></li></ul></div>';
|
||||
case 'text':
|
||||
return '<div class="chat">' + Tools.parseMessage(target) + '</div>';
|
||||
case 'error':
|
||||
return '<div class="chat message-error">' + Tools.escapeHTML(target) + '</div>';
|
||||
case 'html':
|
||||
return '<div class="chat chatmessage-' + toId(name) + hlClass + mineClass + '">' + timestamp + '<strong style="' + color + '">' + clickableName + ':</strong> <em>' + Tools.sanitizeHTML(target) + '</em></div>';
|
||||
case 'uhtml':
|
||||
case 'uhtmlchange':
|
||||
let parts = target.split(',');
|
||||
let $elements = $chatElem.find('div.uhtml-' + toId(parts[0]));
|
||||
let html = parts.slice(1).join(',');
|
||||
if (!html) {
|
||||
$elements.remove();
|
||||
} else if (!$elements.length) {
|
||||
$chatElem.append('<div class="chat uhtml-' + toId(parts[0]) + '">' + Tools.sanitizeHTML(html) + '</div>');
|
||||
} else if (cmd === 'uhtmlchange') {
|
||||
$elements.html(Tools.sanitizeHTML(html));
|
||||
} else {
|
||||
$elements.remove();
|
||||
$chatElem.append('<div class="chat uhtml-' + toId(parts[0]) + '">' + Tools.sanitizeHTML(html) + '</div>');
|
||||
}
|
||||
return '';
|
||||
case 'raw':
|
||||
return '<div class="chat">' + Tools.sanitizeHTML(target) + '</div>';
|
||||
default:
|
||||
// Not a command or unsupported. Parsed as a normal chat message.
|
||||
if (!name) {
|
||||
return '<div class="chat' + hlClass + '">' + timestamp + '<em>' + Tools.parseMessage(message) + '</em></div>';
|
||||
}
|
||||
return '<div class="chat chatmessage-' + toId(name) + hlClass + mineClass + '">' + timestamp + '<strong style="' + color + '">' + clickableName + ':</strong> <em>' + Tools.parseMessage(message) + '</em></div>';
|
||||
}
|
||||
},
|
||||
|
||||
parseMessage(str: string) {
|
||||
// Don't format console commands (>>).
|
||||
if (str.substr(0, 3) === '>> ' || str.substr(0, 4) === '>>> ') return Tools.escapeHTML(str);
|
||||
// Don't format console results (<<).
|
||||
if (str.substr(0, 3) === '<< ') return Tools.escapeHTML(str);
|
||||
str = formatText(str);
|
||||
|
||||
let options = Tools.prefs('chatformatting') || {};
|
||||
|
||||
if (options.hidelinks) {
|
||||
str = str.replace(/<a[^>]*>/g, '<u>').replace(/<\/a>/g, '</u>');
|
||||
}
|
||||
if (options.hidespoiler) {
|
||||
str = str.replace(/<span class="spoiler">/g, '<span class="spoiler spoiler-shown">');
|
||||
}
|
||||
if (options.hidegreentext) {
|
||||
str = str.replace(/<span class="greentext">/g, '<span>');
|
||||
}
|
||||
|
||||
return str;
|
||||
},
|
||||
|
||||
escapeHTML(str: string, jsEscapeToo?: boolean) {
|
||||
str = getString(str).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
||||
if (jsEscapeToo) str = str.replace(/\\/g, '\\\\').replace(/'/g, '\\\'');
|
||||
return str;
|
||||
},
|
||||
|
||||
unescapeHTML(str: string) {
|
||||
str = (str ? '' + str : '');
|
||||
return str.replace(/"/g, '"').replace(/>/g, '>').replace(/</g, '<').replace(/&/g, '&');
|
||||
},
|
||||
|
||||
escapeRegExp(str: string) {
|
||||
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
|
||||
},
|
||||
|
||||
sanitizeHTML: (function () {
|
||||
if (!('html4' in window)) {
|
||||
return function () {
|
||||
throw new Error('sanitizeHTML requires caja');
|
||||
};
|
||||
}
|
||||
// Add <marquee> <blink> <psicon> to the whitelist.
|
||||
Object.assign(html4.ELEMENTS, {
|
||||
'marquee': 0,
|
||||
'blink': 0,
|
||||
'psicon': html4.eflags['OPTIONAL_ENDTAG'] | html4.eflags['EMPTY']
|
||||
});
|
||||
Object.assign(html4.ATTRIBS, {
|
||||
// See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/marquee
|
||||
'marquee::behavior': 0,
|
||||
'marquee::bgcolor': 0,
|
||||
'marquee::direction': 0,
|
||||
'marquee::height': 0,
|
||||
'marquee::hspace': 0,
|
||||
'marquee::loop': 0,
|
||||
'marquee::scrollamount': 0,
|
||||
'marquee::scrolldelay': 0,
|
||||
'marquee::truespeed': 0,
|
||||
'marquee::vspace': 0,
|
||||
'marquee::width': 0,
|
||||
'psicon::pokemon': 0,
|
||||
'psicon::item': 0
|
||||
});
|
||||
|
||||
let uriRewriter = function (urlData: any) {
|
||||
if (urlData.scheme_ === 'geo' || urlData.scheme_ === 'sms' || urlData.scheme_ === 'tel') return null;
|
||||
return urlData;
|
||||
};
|
||||
let tagPolicy = function (tagName: string, attribs: string[]) {
|
||||
if (html4.ELEMENTS[tagName] & html4.eflags['UNSAFE']) {
|
||||
return;
|
||||
}
|
||||
let targetIdx = 0, srcIdx = 0;
|
||||
if (tagName === 'a') {
|
||||
// Special handling of <a> tags.
|
||||
|
||||
for (let i = 0; i < attribs.length - 1; i += 2) {
|
||||
switch (attribs[i]) {
|
||||
case 'target':
|
||||
targetIdx = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
let dataUri = '';
|
||||
if (tagName === 'img') {
|
||||
for (let i = 0; i < attribs.length - 1; i += 2) {
|
||||
if (attribs[i] === 'src' && attribs[i + 1].substr(0, 11) === 'data:image/') {
|
||||
srcIdx = i;
|
||||
dataUri = attribs[i + 1];
|
||||
}
|
||||
if (attribs[i] === 'src' && attribs[i + 1].substr(0, 2) === '//') {
|
||||
if (location.protocol !== 'http:' && location.protocol !== 'https:') {
|
||||
attribs[i + 1] = 'http:' + attribs[i + 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (tagName === 'psicon') {
|
||||
// <psicon> is a custom element which supports a set of mutually incompatible attributes:
|
||||
// <psicon pokemon> and <psicon item>
|
||||
let classValueIndex = -1;
|
||||
let styleValueIndex = -1;
|
||||
let iconAttrib = null;
|
||||
for (let i = 0; i < attribs.length - 1; i += 2) {
|
||||
if (attribs[i] === 'pokemon' || attribs[i] === 'item') {
|
||||
// If declared more than once, use the later.
|
||||
iconAttrib = attribs.slice(i, i + 2);
|
||||
} else if (attribs[i] === 'class') {
|
||||
classValueIndex = i + 1;
|
||||
} else if (attribs[i] === 'style') {
|
||||
styleValueIndex = i + 1;
|
||||
}
|
||||
}
|
||||
tagName = 'span';
|
||||
|
||||
if (iconAttrib) {
|
||||
if (classValueIndex < 0) {
|
||||
attribs.push('class', '');
|
||||
classValueIndex = attribs.length - 1;
|
||||
}
|
||||
if (styleValueIndex < 0) {
|
||||
attribs.push('style', '');
|
||||
styleValueIndex = attribs.length - 1;
|
||||
}
|
||||
|
||||
// Prepend all the classes and styles associated to the custom element.
|
||||
if (iconAttrib[0] === 'pokemon') {
|
||||
attribs[classValueIndex] = attribs[classValueIndex] ? 'picon ' + attribs[classValueIndex] : 'picon';
|
||||
attribs[styleValueIndex] = attribs[styleValueIndex] ? Tools.getPokemonIcon(iconAttrib[1]) + '; ' + attribs[styleValueIndex] : Tools.getPokemonIcon(iconAttrib[1]);
|
||||
} else if (iconAttrib[0] === 'item') {
|
||||
attribs[classValueIndex] = attribs[classValueIndex] ? 'itemicon ' + attribs[classValueIndex] : 'itemicon';
|
||||
attribs[styleValueIndex] = attribs[styleValueIndex] ? Tools.getItemIcon(iconAttrib[1]) + '; ' + attribs[styleValueIndex] : Tools.getItemIcon(iconAttrib[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (attribs[targetIdx] === 'replace') {
|
||||
targetIdx = -targetIdx;
|
||||
}
|
||||
attribs = html.sanitizeAttribs(tagName, attribs, uriRewriter);
|
||||
if (targetIdx < 0) {
|
||||
targetIdx = -targetIdx;
|
||||
attribs[targetIdx - 1] = 'data-target';
|
||||
attribs[targetIdx] = 'replace';
|
||||
targetIdx = 0;
|
||||
}
|
||||
|
||||
if (dataUri && tagName === 'img') {
|
||||
attribs[srcIdx + 1] = dataUri;
|
||||
}
|
||||
if (tagName === 'a' || tagName === 'form') {
|
||||
if (targetIdx) {
|
||||
attribs[targetIdx] = '_blank';
|
||||
} else {
|
||||
attribs.push('target');
|
||||
attribs.push('_blank');
|
||||
}
|
||||
if (tagName === 'a') {
|
||||
attribs.push('rel');
|
||||
attribs.push('noopener');
|
||||
}
|
||||
}
|
||||
return {tagName: tagName, attribs: attribs};
|
||||
};
|
||||
let localizeTime = function (full: string, date: string, time: string, timezone?: string) {
|
||||
let parsedTime = new Date(date + 'T' + time + (timezone || 'Z').toUpperCase());
|
||||
// Very old (pre-ES5) web browsers may be incapable of parsing ISO 8601
|
||||
// dates. In such a case, gracefully continue without replacing the date
|
||||
// format.
|
||||
if (!parsedTime.getTime()) return full;
|
||||
|
||||
let formattedTime;
|
||||
// Try using Intl API if it exists
|
||||
if (window.Intl && Intl.DateTimeFormat) {
|
||||
formattedTime = new Intl.DateTimeFormat(undefined, {month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric'}).format(parsedTime);
|
||||
} else {
|
||||
// toLocaleString even exists in ECMAScript 1, so no need to check
|
||||
// if it exists.
|
||||
formattedTime = parsedTime.toLocaleString();
|
||||
}
|
||||
return '<time>' + Tools.escapeHTML(formattedTime) + '</time>';
|
||||
};
|
||||
return function (input: any) {
|
||||
// <time> parsing requires ISO 8601 time. While more time formats are
|
||||
// supported by most JavaScript implementations, it isn't required, and
|
||||
// how to exactly enforce ignoring user agent timezone setting is not obvious.
|
||||
// As dates come from the server which isn't aware of client timezone, a
|
||||
// particular timezone is required.
|
||||
//
|
||||
// This regular expression is split into three groups.
|
||||
//
|
||||
// Group 1 - date
|
||||
// Group 2 - time (seconds and milliseconds are optional)
|
||||
// Group 3 - optional timezone
|
||||
//
|
||||
// Group 1 and group 2 are split to allow using space as a separator
|
||||
// instead of T. Stricly speaking ECMAScript 5 specification only
|
||||
// allows T, however it's more practical to also allow spaces.
|
||||
return html.sanitizeWithPolicy(getString(input), tagPolicy)
|
||||
.replace(/<time>\s*([+-]?\d{4,}-\d{2}-\d{2})[T ](\d{2}:\d{2}(?::\d{2}(?:\.\d{3})?)?)(Z|[+-]\d{2}:\d{2})?\s*<\/time>/ig, localizeTime);
|
||||
};
|
||||
})(),
|
||||
|
||||
interstice: (function () {
|
||||
let patterns = (function (whitelist) {
|
||||
let patterns = [];
|
||||
for (let i = 0; i < whitelist.length; ++i) {
|
||||
patterns.push(new RegExp('^(https?:)?//([A-Za-z0-9-]*\\.)?' +
|
||||
whitelist[i] +
|
||||
'(/.*)?', 'i'));
|
||||
}
|
||||
return patterns;
|
||||
})((window.Config && Config.whitelist) ? Config.whitelist : []);
|
||||
return {
|
||||
isWhitelisted(uri: string) {
|
||||
if ((uri[0] === '/') && (uri[1] !== '/')) {
|
||||
// domain-relative URIs are safe
|
||||
return true;
|
||||
}
|
||||
for (let i = 0; i < patterns.length; ++i) {
|
||||
if (patterns[i].test(uri)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
getURI(uri: string) {
|
||||
return 'http://pokemonshowdown.com/interstice?uri=' + encodeURIComponent(uri);
|
||||
}
|
||||
};
|
||||
})(),
|
||||
|
||||
prefs(prop: string, value?: any, save?: boolean) {
|
||||
// @ts-ignore
|
||||
|
|
@ -685,7 +273,7 @@ const Tools = {
|
|||
effect.exists = true;
|
||||
}
|
||||
if (!effect.id) effect.id = id;
|
||||
if (!effect.name) effect.name = Tools.escapeHTML(name);
|
||||
if (!effect.name) effect.name = Tools.sanitizeName(name);
|
||||
if (!effect.category) effect.category = 'Effect';
|
||||
if (!effect.effectType) effect.effectType = 'Effect';
|
||||
}
|
||||
|
|
@ -717,7 +305,7 @@ const Tools = {
|
|||
}
|
||||
|
||||
if (!move.id) move.id = id;
|
||||
if (!move.name) move.name = Tools.escapeHTML(name);
|
||||
if (!move.name) move.name = Tools.sanitizeName(name);
|
||||
|
||||
if (!move.critRatio) move.critRatio = 1;
|
||||
if (!move.baseType) move.baseType = move.type;
|
||||
|
|
@ -759,7 +347,7 @@ const Tools = {
|
|||
item = (window.BattleItems && window.BattleItems[id]) || {};
|
||||
if (item.name) item.exists = true;
|
||||
if (!item.id) item.id = id;
|
||||
if (!item.name) item.name = Tools.escapeHTML(name);
|
||||
if (!item.name) item.name = Tools.sanitizeName(name);
|
||||
if (!item.category) item.category = 'Effect';
|
||||
if (!item.effectType) item.effectType = 'Item';
|
||||
if (!item.gen) {
|
||||
|
|
@ -784,7 +372,7 @@ const Tools = {
|
|||
ability = (window.BattleAbilities && window.BattleAbilities[id]) || {};
|
||||
if (ability.name) ability.exists = true;
|
||||
if (!ability.id) ability.id = id;
|
||||
if (!ability.name) ability.name = Tools.escapeHTML(name);
|
||||
if (!ability.name) ability.name = Tools.sanitizeName(name);
|
||||
if (!ability.category) ability.category = 'Effect';
|
||||
if (!ability.effectType) ability.effectType = 'Ability';
|
||||
if (!ability.gen) {
|
||||
|
|
@ -840,7 +428,7 @@ const Tools = {
|
|||
if (template.species) name = template.species;
|
||||
if (template.exists === undefined) template.exists = true;
|
||||
if (!template.id) template.id = id;
|
||||
if (!template.name) template.name = name = Tools.escapeHTML(name);
|
||||
if (!template.name) template.name = name = Tools.sanitizeName(name);
|
||||
if (!template.speciesid) template.speciesid = id;
|
||||
if (!template.species) template.species = name;
|
||||
if (!template.baseSpecies) template.baseSpecies = name;
|
||||
|
|
@ -1545,74 +1133,4 @@ const Tools = {
|
|||
let sanitizedType = type.replace(/\?/g, '%3f');
|
||||
return '<img src="' + Tools.resourcePrefix + 'sprites/types/' + sanitizedType + '.png" alt="' + type + '" height="14" width="32"' + (b ? ' class="b"' : '') + ' />';
|
||||
},
|
||||
|
||||
/*********************************************************
|
||||
* Replay files
|
||||
*********************************************************/
|
||||
|
||||
// Replay files are .html files that display a replay for a battle.
|
||||
|
||||
// The .html files mainly contain replay log data; the actual replay
|
||||
// player is downloaded online. Also included is a textual log and
|
||||
// some minimal CSS to make it look pretty, for offline viewing.
|
||||
|
||||
// This strategy helps keep the replay file reasonably small; of
|
||||
// the 30 KB or so for a 50-turn battle, around 10 KB is the log
|
||||
// data, and around 20 KB is the textual log.
|
||||
|
||||
// The actual replay player is downloaded from replay-embed.js,
|
||||
// which handles loading all the necessary resources for turning the log
|
||||
// data into a playable replay.
|
||||
|
||||
// Battle log data is stored in and loaded from a
|
||||
// <script type="text/plain" class="battle-log-data"> tag.
|
||||
|
||||
// replay-embed.js is loaded through a cache-buster that rotates daily.
|
||||
// This allows pretty much anything about the replay viewer to be
|
||||
// updated as desired.
|
||||
|
||||
createReplayFile(room: any) {
|
||||
let battle = room.battle;
|
||||
let replayid = room.id;
|
||||
if (replayid) {
|
||||
// battle room
|
||||
replayid = replayid.slice(7);
|
||||
if (Config.server.id !== 'showdown') {
|
||||
if (!Config.server.registered) {
|
||||
replayid = 'unregisteredserver-' + replayid;
|
||||
} else {
|
||||
replayid = Config.server.id + '-' + replayid;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// replay panel
|
||||
replayid = room.fragment;
|
||||
}
|
||||
battle.fastForwardTo(-1);
|
||||
let buf = '<!DOCTYPE html>\n';
|
||||
buf += '<meta charset="utf-8" />\n';
|
||||
buf += '<!-- version 1 -->\n';
|
||||
buf += '<title>' + Tools.escapeHTML(battle.tier) + ' replay: ' + Tools.escapeHTML(battle.p1.name) + ' vs. ' + Tools.escapeHTML(battle.p2.name) + '</title>\n';
|
||||
buf += '<style>\n';
|
||||
buf += 'html,body {font-family:Verdana, sans-serif;font-size:10pt;margin:0;padding:0;}body{padding:12px 0;} .battle-log {font-family:Verdana, sans-serif;font-size:10pt;} .battle-log-inline {border:1px solid #AAAAAA;background:#EEF2F5;color:black;max-width:640px;margin:0 auto 80px;padding-bottom:5px;} .battle-log .inner {padding:4px 8px 0px 8px;} .battle-log .inner-preempt {padding:0 8px 4px 8px;} .battle-log .inner-after {margin-top:0.5em;} .battle-log h2 {margin:0.5em -8px;padding:4px 8px;border:1px solid #AAAAAA;background:#E0E7EA;border-left:0;border-right:0;font-family:Verdana, sans-serif;font-size:13pt;} .battle-log .chat {vertical-align:middle;padding:3px 0 3px 0;font-size:8pt;} .battle-log .chat strong {color:#40576A;} .battle-log .chat em {padding:1px 4px 1px 3px;color:#000000;font-style:normal;} .chat.mine {background:rgba(0,0,0,0.05);margin-left:-8px;margin-right:-8px;padding-left:8px;padding-right:8px;} .spoiler {color:#BBBBBB;background:#BBBBBB;padding:0px 3px;} .spoiler:hover, .spoiler:active, .spoiler-shown {color:#000000;background:#E2E2E2;padding:0px 3px;} .spoiler a {color:#BBBBBB;} .spoiler:hover a, .spoiler:active a, .spoiler-shown a {color:#2288CC;} .chat code, .chat .spoiler:hover code, .chat .spoiler:active code, .chat .spoiler-shown code {border:1px solid #C0C0C0;background:#EEEEEE;color:black;padding:0 2px;} .chat .spoiler code {border:1px solid #CCCCCC;background:#CCCCCC;color:#CCCCCC;} .battle-log .rated {padding:3px 4px;} .battle-log .rated strong {color:white;background:#89A;padding:1px 4px;border-radius:4px;} .spacer {margin-top:0.5em;} .message-announce {background:#6688AA;color:white;padding:1px 4px 2px;} .message-announce a, .broadcast-green a, .broadcast-blue a, .broadcast-red a {color:#DDEEFF;} .broadcast-green {background-color:#559955;color:white;padding:2px 4px;} .broadcast-blue {background-color:#6688AA;color:white;padding:2px 4px;} .infobox {border:1px solid #6688AA;padding:2px 4px;} .infobox-limited {max-height:200px;overflow:auto;overflow-x:hidden;} .broadcast-red {background-color:#AA5544;color:white;padding:2px 4px;} .message-learn-canlearn {font-weight:bold;color:#228822;text-decoration:underline;} .message-learn-cannotlearn {font-weight:bold;color:#CC2222;text-decoration:underline;} .message-effect-weak {font-weight:bold;color:#CC2222;} .message-effect-resist {font-weight:bold;color:#6688AA;} .message-effect-immune {font-weight:bold;color:#666666;} .message-learn-list {margin-top:0;margin-bottom:0;} .message-throttle-notice, .message-error {color:#992222;} .message-overflow, .chat small.message-overflow {font-size:0pt;} .message-overflow::before {font-size:9pt;content:\'...\';} .subtle {color:#3A4A66;}\n';
|
||||
buf += '</style>\n';
|
||||
buf += '<div class="wrapper replay-wrapper" style="max-width:1180px;margin:0 auto">\n';
|
||||
buf += '<input type="hidden" name="replayid" value="' + replayid + '" />\n';
|
||||
buf += '<div class="battle"></div><div class="battle-log"></div><div class="replay-controls"></div><div class="replay-controls-2"></div>\n';
|
||||
buf += '<h1 style="font-weight:normal;text-align:center"><strong>' + Tools.escapeHTML(battle.tier) + '</strong><br /><a href="http://pokemonshowdown.com/users/' + toId(battle.p1.name) + '" class="subtle" target="_blank">' + Tools.escapeHTML(battle.p1.name) + '</a> vs. <a href="http://pokemonshowdown.com/users/' + toId(battle.p2.name) + '" class="subtle" target="_blank">' + Tools.escapeHTML(battle.p2.name) + '</a></h1>\n';
|
||||
buf += '<script type="text/plain" class="battle-log-data">' + battle.activityQueue.join('\n').replace(/\//g, '\\/') + '</script>\n'; // lgtm [js/incomplete-sanitization]
|
||||
buf += '</div>\n';
|
||||
buf += '<div class="battle-log battle-log-inline"><div class="inner">' + battle.scene.$log.html() + '</div></div>\n';
|
||||
buf += '</div>\n';
|
||||
buf += '<script>\n';
|
||||
buf += 'let daily = Math.floor(Date.now()/1000/60/60/24);document.write(\'<script src="https://play.pokemonshowdown.com/js/replay-embed.js?version\'+daily+\'"></\'+\'script>\');\n';
|
||||
buf += '</script>\n';
|
||||
return buf;
|
||||
},
|
||||
|
||||
createReplayFileHref(room: any) {
|
||||
// unescape(encodeURIComponent()) is necessary because btoa doesn't support Unicode
|
||||
// @ts-ignore
|
||||
return 'data:text/plain;base64,' + encodeURIComponent(btoa(unescape(encodeURIComponent(Tools.createReplayFile(room)))));
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,11 +1,7 @@
|
|||
/**
|
||||
* Pokemon Showdown Dex Misc
|
||||
* Pokemon Showdown Log Misc
|
||||
*
|
||||
* Some miscellaneous helper functions for battle-dex.ts, namely:
|
||||
*
|
||||
* - polyfills, which in combination with Babel lets us write ES2018
|
||||
* while targeting ES3 (we are in theory still IE7-compatible! I
|
||||
* haven't tested in IE7 for years, though)
|
||||
* Some miscellaneous helper functions for battle-log.ts, namely:
|
||||
*
|
||||
* - an MD5 hasher
|
||||
*
|
||||
486
src/battle-log.ts
Normal file
486
src/battle-log.ts
Normal file
|
|
@ -0,0 +1,486 @@
|
|||
/**
|
||||
* Battle log
|
||||
*
|
||||
* @author Guangcong Luo <guangcongluo@gmail.com>
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
class BattleLog {
|
||||
static escapeFormat(formatid: string): string {
|
||||
let atIndex = formatid.indexOf('@@@');
|
||||
if (atIndex >= 0) {
|
||||
return this.escapeFormat(formatid.slice(0, atIndex)) + '<br />Custom rules: ' + this.escapeHTML(formatid.slice(atIndex + 3));
|
||||
}
|
||||
if (window.BattleFormats && BattleFormats[formatid]) {
|
||||
return this.escapeHTML(BattleFormats[formatid].name);
|
||||
}
|
||||
return this.escapeHTML(formatid);
|
||||
}
|
||||
|
||||
static escapeHTML(str: string, jsEscapeToo?: boolean) {
|
||||
str = getString(str).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
||||
if (jsEscapeToo) str = str.replace(/\\/g, '\\\\').replace(/'/g, '\\\'');
|
||||
return str;
|
||||
}
|
||||
|
||||
static unescapeHTML(str: string) {
|
||||
str = (str ? '' + str : '');
|
||||
return str.replace(/"/g, '"').replace(/>/g, '>').replace(/</g, '<').replace(/&/g, '&');
|
||||
}
|
||||
|
||||
static colorCache = {} as {[userid: string]: string};
|
||||
|
||||
static hashColor(name: string) {
|
||||
if (this.colorCache[name]) return this.colorCache[name];
|
||||
let hash;
|
||||
if (window.Config && Config.customcolors && Config.customcolors[name]) {
|
||||
if (Config.customcolors[name].color) {
|
||||
return (this.colorCache[name] = 'color:' + Config.customcolors[name].color + ';');
|
||||
}
|
||||
hash = MD5(Config.customcolors[name]);
|
||||
} else {
|
||||
hash = MD5(name);
|
||||
}
|
||||
let H = parseInt(hash.substr(4, 4), 16) % 360; // 0 to 360
|
||||
let S = parseInt(hash.substr(0, 4), 16) % 50 + 40; // 40 to 89
|
||||
let L = Math.floor(parseInt(hash.substr(8, 4), 16) % 20 + 30); // 30 to 49
|
||||
|
||||
let C = (100 - Math.abs(2 * L - 100)) * S / 100 / 100;
|
||||
let X = C * (1 - Math.abs((H / 60) % 2 - 1));
|
||||
let m = L / 100 - C / 2;
|
||||
|
||||
let R1, G1, B1;
|
||||
switch (Math.floor(H / 60)) {
|
||||
case 1: R1 = X; G1 = C; B1 = 0; break;
|
||||
case 2: R1 = 0; G1 = C; B1 = X; break;
|
||||
case 3: R1 = 0; G1 = X; B1 = C; break;
|
||||
case 4: R1 = X; G1 = 0; B1 = C; break;
|
||||
case 5: R1 = C; G1 = 0; B1 = X; break;
|
||||
case 0: default: R1 = C; G1 = X; B1 = 0; break;
|
||||
}
|
||||
let R = R1 + m, G = G1 + m, B = B1 + m;
|
||||
let lum = R * R * R * 0.2126 + G * G * G * 0.7152 + B * B * B * 0.0722; // 0.013 (dark blue) to 0.737 (yellow)
|
||||
|
||||
let HLmod = (lum - 0.2) * -150; // -80 (yellow) to 28 (dark blue)
|
||||
if (HLmod > 18) HLmod = (HLmod - 18) * 2.5;
|
||||
else if (HLmod < 0) HLmod = (HLmod - 0) / 3;
|
||||
else HLmod = 0;
|
||||
// let mod = ';border-right: ' + Math.abs(HLmod) + 'px solid ' + (HLmod > 0 ? 'red' : '#0088FF');
|
||||
let Hdist = Math.min(Math.abs(180 - H), Math.abs(240 - H));
|
||||
if (Hdist < 15) {
|
||||
HLmod += (15 - Hdist) / 3;
|
||||
}
|
||||
|
||||
L += HLmod;
|
||||
|
||||
this.colorCache[name] = "color:hsl(" + H + "," + S + "%," + L + "%);";
|
||||
return this.colorCache[name];
|
||||
}
|
||||
|
||||
static parseChatMessage(message: string, name: string, timestamp: string, isHighlighted?: boolean, $chatElem?: any) {
|
||||
let showMe = !((Tools.prefs('chatformatting') || {}).hideme);
|
||||
let group = ' ';
|
||||
if (!/[A-Za-z0-9]/.test(name.charAt(0))) {
|
||||
// Backwards compatibility
|
||||
group = name.charAt(0);
|
||||
name = name.substr(1);
|
||||
}
|
||||
let color = this.hashColor(toId(name));
|
||||
let clickableName = '<small>' + this.escapeHTML(group) + '</small><span class="username" data-name="' + this.escapeHTML(name) + '">' + this.escapeHTML(name) + '</span>';
|
||||
let hlClass = isHighlighted ? ' highlighted' : '';
|
||||
let mineClass = (window.app && app.user && app.user.get('name') === name ? ' mine' : '');
|
||||
|
||||
let cmd = '';
|
||||
let target = '';
|
||||
if (message.charAt(0) === '/') {
|
||||
if (message.charAt(1) === '/') {
|
||||
message = message.slice(1);
|
||||
} else {
|
||||
let spaceIndex = message.indexOf(' ');
|
||||
cmd = (spaceIndex >= 0 ? message.slice(1, spaceIndex) : message.slice(1));
|
||||
if (spaceIndex >= 0) target = message.slice(spaceIndex + 1);
|
||||
}
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case 'me':
|
||||
if (!showMe) return '<div class="chat chatmessage-' + toId(name) + hlClass + mineClass + '">' + timestamp + '<strong style="' + color + '">' + clickableName + ':</strong> <em>/me' + this.parseMessage(' ' + target) + '</em></div>';
|
||||
return '<div class="chat chatmessage-' + toId(name) + hlClass + mineClass + '">' + timestamp + '<strong style="' + color + '">•</strong> <em>' + clickableName + '<i>' + this.parseMessage(' ' + target) + '</i></em></div>';
|
||||
case 'mee':
|
||||
if (!showMe) return '<div class="chat chatmessage-' + toId(name) + hlClass + mineClass + '">' + timestamp + '<strong style="' + color + '">' + clickableName + ':</strong> <em>/me' + this.parseMessage(' ' + target).slice(1) + '</em></div>';
|
||||
return '<div class="chat chatmessage-' + toId(name) + hlClass + mineClass + '">' + timestamp + '<strong style="' + color + '">•</strong> <em>' + clickableName + '<i>' + this.parseMessage(' ' + target).slice(1) + '</i></em></div>';
|
||||
case 'invite':
|
||||
let roomid = toRoomid(target);
|
||||
return [
|
||||
'<div class="chat">' + timestamp + '<em>' + clickableName + ' invited you to join the room "' + roomid + '"</em></div>',
|
||||
'<div class="notice"><button name="joinRoom" value="' + roomid + '">Join ' + roomid + '</button></div>'
|
||||
];
|
||||
case 'announce':
|
||||
return '<div class="chat chatmessage-' + toId(name) + hlClass + mineClass + '">' + timestamp + '<strong style="' + color + '">' + clickableName + ':</strong> <span class="message-announce">' + this.parseMessage(target) + '</span></div>';
|
||||
case 'log':
|
||||
return '<div class="chat chatmessage-' + toId(name) + hlClass + mineClass + '">' + timestamp + '<span class="message-log">' + this.parseMessage(target) + '</span></div>';
|
||||
case 'data-pokemon':
|
||||
let buf = '<li class="result">';
|
||||
let template = Tools.getTemplate(target);
|
||||
if (!template.abilities || !template.baseStats) return '[not supported in replays]';
|
||||
buf += '<span class="col numcol">' + (template.tier || Tools.getTemplate(template.baseSpecies).tier) + '</span> ';
|
||||
buf += '<span class="col iconcol"><span style="' + Tools.getPokemonIcon(template) + '"></span></span> ';
|
||||
buf += '<span class="col pokemonnamecol" style="white-space:nowrap"><a href="https://pokemonshowdown.com/dex/pokemon/' + template.id + '" target="_blank">' + template.species + '</a></span> ';
|
||||
buf += '<span class="col typecol">';
|
||||
if (template.types) for (let i = 0; i < template.types.length; i++) {
|
||||
buf += Tools.getTypeIcon(template.types[i]);
|
||||
}
|
||||
buf += '</span> ';
|
||||
buf += '<span style="float:left;min-height:26px">';
|
||||
if (template.abilities['1']) {
|
||||
buf += '<span class="col twoabilitycol">' + template.abilities['0'] + '<br />' + template.abilities['1'] + '</span>';
|
||||
} else {
|
||||
buf += '<span class="col abilitycol">' + template.abilities['0'] + '</span>';
|
||||
}
|
||||
if (template.abilities['S']) {
|
||||
buf += '<span class="col twoabilitycol' + (template.unreleasedHidden ? ' unreleasedhacol' : '') + '"><em>' + template.abilities['H'] + '<br />' + template.abilities['S'] + '</em></span>';
|
||||
} else if (template.abilities['H']) {
|
||||
buf += '<span class="col abilitycol' + (template.unreleasedHidden ? ' unreleasedhacol' : '') + '"><em>' + template.abilities['H'] + '</em></span>';
|
||||
} else {
|
||||
buf += '<span class="col abilitycol"></span>';
|
||||
}
|
||||
buf += '</span>';
|
||||
buf += '<span style="float:left;min-height:26px">';
|
||||
buf += '<span class="col statcol"><em>HP</em><br />' + template.baseStats.hp + '</span> ';
|
||||
buf += '<span class="col statcol"><em>Atk</em><br />' + template.baseStats.atk + '</span> ';
|
||||
buf += '<span class="col statcol"><em>Def</em><br />' + template.baseStats.def + '</span> ';
|
||||
buf += '<span class="col statcol"><em>SpA</em><br />' + template.baseStats.spa + '</span> ';
|
||||
buf += '<span class="col statcol"><em>SpD</em><br />' + template.baseStats.spd + '</span> ';
|
||||
buf += '<span class="col statcol"><em>Spe</em><br />' + template.baseStats.spe + '</span> ';
|
||||
let bst = 0;
|
||||
for (const i in template.baseStats) bst += template.baseStats[i as StatName];
|
||||
buf += '<span class="col bstcol"><em>BST<br />' + bst + '</em></span> ';
|
||||
buf += '</span>';
|
||||
buf += '</li>';
|
||||
return '<div class="message"><ul class="utilichart">' + buf + '<li style=\"clear:both\"></li></ul></div>';
|
||||
case 'data-item':
|
||||
if (!window.BattleSearch) return '[not supported in replays]';
|
||||
return '<div class="message"><ul class="utilichart">' + BattleSearch.renderItemRow(Tools.getItem(target), 0, 0) + '<li style=\"clear:both\"></li></ul></div>';
|
||||
case 'data-ability':
|
||||
if (!window.BattleSearch) return '[not supported in replays]';
|
||||
return '<div class="message"><ul class="utilichart">' + BattleSearch.renderAbilityRow(Tools.getAbility(target), 0, 0) + '<li style=\"clear:both\"></li></ul></div>';
|
||||
case 'data-move':
|
||||
if (!window.BattleSearch) return '[not supported in replays]';
|
||||
return '<div class="message"><ul class="utilichart">' + BattleSearch.renderMoveRow(Tools.getMove(target), 0, 0) + '<li style=\"clear:both\"></li></ul></div>';
|
||||
case 'text':
|
||||
return '<div class="chat">' + this.parseMessage(target) + '</div>';
|
||||
case 'error':
|
||||
return '<div class="chat message-error">' + this.escapeHTML(target) + '</div>';
|
||||
case 'html':
|
||||
return '<div class="chat chatmessage-' + toId(name) + hlClass + mineClass + '">' + timestamp + '<strong style="' + color + '">' + clickableName + ':</strong> <em>' + BattleLog.sanitizeHTML(target) + '</em></div>';
|
||||
case 'uhtml':
|
||||
case 'uhtmlchange':
|
||||
let parts = target.split(',');
|
||||
let $elements = $chatElem.find('div.uhtml-' + toId(parts[0]));
|
||||
let html = parts.slice(1).join(',');
|
||||
if (!html) {
|
||||
$elements.remove();
|
||||
} else if (!$elements.length) {
|
||||
$chatElem.append('<div class="chat uhtml-' + toId(parts[0]) + '">' + BattleLog.sanitizeHTML(html) + '</div>');
|
||||
} else if (cmd === 'uhtmlchange') {
|
||||
$elements.html(BattleLog.sanitizeHTML(html));
|
||||
} else {
|
||||
$elements.remove();
|
||||
$chatElem.append('<div class="chat uhtml-' + toId(parts[0]) + '">' + BattleLog.sanitizeHTML(html) + '</div>');
|
||||
}
|
||||
return '';
|
||||
case 'raw':
|
||||
return '<div class="chat">' + BattleLog.sanitizeHTML(target) + '</div>';
|
||||
default:
|
||||
// Not a command or unsupported. Parsed as a normal chat message.
|
||||
if (!name) {
|
||||
return '<div class="chat' + hlClass + '">' + timestamp + '<em>' + this.parseMessage(message) + '</em></div>';
|
||||
}
|
||||
return '<div class="chat chatmessage-' + toId(name) + hlClass + mineClass + '">' + timestamp + '<strong style="' + color + '">' + clickableName + ':</strong> <em>' + this.parseMessage(message) + '</em></div>';
|
||||
}
|
||||
}
|
||||
|
||||
static parseMessage(str: string) {
|
||||
// Don't format console commands (>>).
|
||||
if (str.substr(0, 3) === '>> ' || str.substr(0, 4) === '>>> ') return this.escapeHTML(str);
|
||||
// Don't format console results (<<).
|
||||
if (str.substr(0, 3) === '<< ') return this.escapeHTML(str);
|
||||
str = formatText(str);
|
||||
|
||||
let options = Tools.prefs('chatformatting') || {};
|
||||
|
||||
if (options.hidelinks) {
|
||||
str = str.replace(/<a[^>]*>/g, '<u>').replace(/<\/a>/g, '</u>');
|
||||
}
|
||||
if (options.hidespoiler) {
|
||||
str = str.replace(/<span class="spoiler">/g, '<span class="spoiler spoiler-shown">');
|
||||
}
|
||||
if (options.hidegreentext) {
|
||||
str = str.replace(/<span class="greentext">/g, '<span>');
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
static interstice = (() => {
|
||||
const whitelist: string[] = (window.Config && Config.whitelist) ? Config.whitelist : [];
|
||||
const patterns = whitelist.map(entry => new RegExp(
|
||||
`^(https?:)?//([A-Za-z0-9-]*\\.)?${entry}(/.*)?`,
|
||||
'i'));
|
||||
return {
|
||||
isWhitelisted(uri: string) {
|
||||
if (uri[0] === '/' && uri[1] !== '/') {
|
||||
// domain-relative URIs are safe
|
||||
return true;
|
||||
}
|
||||
for (const pattern of patterns) {
|
||||
if (pattern.test(uri)) return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
getURI(uri: string) {
|
||||
return 'http://pokemonshowdown.com/interstice?uri=' + encodeURIComponent(uri);
|
||||
},
|
||||
};
|
||||
})();
|
||||
|
||||
static tagPolicy: (tagName: string, attribs: string[]) => any = null!;
|
||||
static initSanitizeHTML() {
|
||||
if (this.tagPolicy) return;
|
||||
if (!('html4' in window)) {
|
||||
throw new Error('sanitizeHTML requires caja');
|
||||
}
|
||||
// Add <marquee> <blink> <psicon> to the whitelist.
|
||||
Object.assign(html4.ELEMENTS, {
|
||||
'marquee': 0,
|
||||
'blink': 0,
|
||||
'psicon': html4.eflags['OPTIONAL_ENDTAG'] | html4.eflags['EMPTY']
|
||||
});
|
||||
Object.assign(html4.ATTRIBS, {
|
||||
// See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/marquee
|
||||
'marquee::behavior': 0,
|
||||
'marquee::bgcolor': 0,
|
||||
'marquee::direction': 0,
|
||||
'marquee::height': 0,
|
||||
'marquee::hspace': 0,
|
||||
'marquee::loop': 0,
|
||||
'marquee::scrollamount': 0,
|
||||
'marquee::scrolldelay': 0,
|
||||
'marquee::truespeed': 0,
|
||||
'marquee::vspace': 0,
|
||||
'marquee::width': 0,
|
||||
'psicon::pokemon': 0,
|
||||
'psicon::item': 0
|
||||
});
|
||||
|
||||
this.tagPolicy = (tagName: string, attribs: string[]) => {
|
||||
if (html4.ELEMENTS[tagName] & html4.eflags['UNSAFE']) {
|
||||
return;
|
||||
}
|
||||
let targetIdx = 0, srcIdx = 0;
|
||||
if (tagName === 'a') {
|
||||
// Special handling of <a> tags.
|
||||
|
||||
for (let i = 0; i < attribs.length - 1; i += 2) {
|
||||
switch (attribs[i]) {
|
||||
case 'target':
|
||||
targetIdx = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
let dataUri = '';
|
||||
if (tagName === 'img') {
|
||||
for (let i = 0; i < attribs.length - 1; i += 2) {
|
||||
if (attribs[i] === 'src' && attribs[i + 1].substr(0, 11) === 'data:image/') {
|
||||
srcIdx = i;
|
||||
dataUri = attribs[i + 1];
|
||||
}
|
||||
if (attribs[i] === 'src' && attribs[i + 1].substr(0, 2) === '//') {
|
||||
if (location.protocol !== 'http:' && location.protocol !== 'https:') {
|
||||
attribs[i + 1] = 'http:' + attribs[i + 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (tagName === 'psicon') {
|
||||
// <psicon> is a custom element which supports a set of mutually incompatible attributes:
|
||||
// <psicon pokemon> and <psicon item>
|
||||
let classValueIndex = -1;
|
||||
let styleValueIndex = -1;
|
||||
let iconAttrib = null;
|
||||
for (let i = 0; i < attribs.length - 1; i += 2) {
|
||||
if (attribs[i] === 'pokemon' || attribs[i] === 'item') {
|
||||
// If declared more than once, use the later.
|
||||
iconAttrib = attribs.slice(i, i + 2);
|
||||
} else if (attribs[i] === 'class') {
|
||||
classValueIndex = i + 1;
|
||||
} else if (attribs[i] === 'style') {
|
||||
styleValueIndex = i + 1;
|
||||
}
|
||||
}
|
||||
tagName = 'span';
|
||||
|
||||
if (iconAttrib) {
|
||||
if (classValueIndex < 0) {
|
||||
attribs.push('class', '');
|
||||
classValueIndex = attribs.length - 1;
|
||||
}
|
||||
if (styleValueIndex < 0) {
|
||||
attribs.push('style', '');
|
||||
styleValueIndex = attribs.length - 1;
|
||||
}
|
||||
|
||||
// Prepend all the classes and styles associated to the custom element.
|
||||
if (iconAttrib[0] === 'pokemon') {
|
||||
attribs[classValueIndex] = attribs[classValueIndex] ? 'picon ' + attribs[classValueIndex] : 'picon';
|
||||
attribs[styleValueIndex] = attribs[styleValueIndex] ? Tools.getPokemonIcon(iconAttrib[1]) + '; ' + attribs[styleValueIndex] : Tools.getPokemonIcon(iconAttrib[1]);
|
||||
} else if (iconAttrib[0] === 'item') {
|
||||
attribs[classValueIndex] = attribs[classValueIndex] ? 'itemicon ' + attribs[classValueIndex] : 'itemicon';
|
||||
attribs[styleValueIndex] = attribs[styleValueIndex] ? Tools.getItemIcon(iconAttrib[1]) + '; ' + attribs[styleValueIndex] : Tools.getItemIcon(iconAttrib[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (attribs[targetIdx] === 'replace') {
|
||||
targetIdx = -targetIdx;
|
||||
}
|
||||
attribs = html.sanitizeAttribs(tagName, attribs, (urlData: any) => {
|
||||
if (urlData.scheme_ === 'geo' || urlData.scheme_ === 'sms' || urlData.scheme_ === 'tel') return null;
|
||||
return urlData;
|
||||
});
|
||||
if (targetIdx < 0) {
|
||||
targetIdx = -targetIdx;
|
||||
attribs[targetIdx - 1] = 'data-target';
|
||||
attribs[targetIdx] = 'replace';
|
||||
targetIdx = 0;
|
||||
}
|
||||
|
||||
if (dataUri && tagName === 'img') {
|
||||
attribs[srcIdx + 1] = dataUri;
|
||||
}
|
||||
if (tagName === 'a' || tagName === 'form') {
|
||||
if (targetIdx) {
|
||||
attribs[targetIdx] = '_blank';
|
||||
} else {
|
||||
attribs.push('target');
|
||||
attribs.push('_blank');
|
||||
}
|
||||
if (tagName === 'a') {
|
||||
attribs.push('rel');
|
||||
attribs.push('noopener');
|
||||
}
|
||||
}
|
||||
return {tagName: tagName, attribs: attribs};
|
||||
};
|
||||
}
|
||||
static localizeTime(full: string, date: string, time: string, timezone?: string) {
|
||||
let parsedTime = new Date(date + 'T' + time + (timezone || 'Z').toUpperCase());
|
||||
// Very old (pre-ES5) web browsers may be incapable of parsing ISO 8601
|
||||
// dates. In such a case, gracefully continue without replacing the date
|
||||
// format.
|
||||
if (!parsedTime.getTime()) return full;
|
||||
|
||||
let formattedTime;
|
||||
// Try using Intl API if it exists
|
||||
if (window.Intl && Intl.DateTimeFormat) {
|
||||
formattedTime = new Intl.DateTimeFormat(undefined, {month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric'}).format(parsedTime);
|
||||
} else {
|
||||
// toLocaleString even exists in ECMAScript 1, so no need to check
|
||||
// if it exists.
|
||||
formattedTime = parsedTime.toLocaleString();
|
||||
}
|
||||
return '<time>' + this.escapeHTML(formattedTime) + '</time>';
|
||||
}
|
||||
static sanitizeHTML(input: string) {
|
||||
this.initSanitizeHTML();
|
||||
const sanitized = html.sanitizeWithPolicy(getString(input), this.tagPolicy) as string;
|
||||
// <time> parsing requires ISO 8601 time. While more time formats are
|
||||
// supported by most JavaScript implementations, it isn't required, and
|
||||
// how to exactly enforce ignoring user agent timezone setting is not obvious.
|
||||
// As dates come from the server which isn't aware of client timezone, a
|
||||
// particular timezone is required.
|
||||
//
|
||||
// This regular expression is split into three groups.
|
||||
//
|
||||
// Group 1 - date
|
||||
// Group 2 - time (seconds and milliseconds are optional)
|
||||
// Group 3 - optional timezone
|
||||
//
|
||||
// Group 1 and group 2 are split to allow using space as a separator
|
||||
// instead of T. Stricly speaking ECMAScript 5 specification only
|
||||
// allows T, however it's more practical to also allow spaces.
|
||||
return sanitized.replace(
|
||||
/<time>\s*([+-]?\d{4,}-\d{2}-\d{2})[T ](\d{2}:\d{2}(?::\d{2}(?:\.\d{3})?)?)(Z|[+-]\d{2}:\d{2})?\s*<\/time>/ig,
|
||||
this.localizeTime);
|
||||
}
|
||||
|
||||
/*********************************************************
|
||||
* Replay files
|
||||
*********************************************************/
|
||||
|
||||
// Replay files are .html files that display a replay for a battle.
|
||||
|
||||
// The .html files mainly contain replay log data; the actual replay
|
||||
// player is downloaded online. Also included is a textual log and
|
||||
// some minimal CSS to make it look pretty, for offline viewing.
|
||||
|
||||
// This strategy helps keep the replay file reasonably small; of
|
||||
// the 30 KB or so for a 50-turn battle, around 10 KB is the log
|
||||
// data, and around 20 KB is the textual log.
|
||||
|
||||
// The actual replay player is downloaded from replay-embed.js,
|
||||
// which handles loading all the necessary resources for turning the log
|
||||
// data into a playable replay.
|
||||
|
||||
// Battle log data is stored in and loaded from a
|
||||
// <script type="text/plain" class="battle-log-data"> tag.
|
||||
|
||||
// replay-embed.js is loaded through a cache-buster that rotates daily.
|
||||
// This allows pretty much anything about the replay viewer to be
|
||||
// updated as desired.
|
||||
|
||||
static createReplayFile(room: any) {
|
||||
let battle = room.battle;
|
||||
let replayid = room.id;
|
||||
if (replayid) {
|
||||
// battle room
|
||||
replayid = replayid.slice(7);
|
||||
if (Config.server.id !== 'showdown') {
|
||||
if (!Config.server.registered) {
|
||||
replayid = 'unregisteredserver-' + replayid;
|
||||
} else {
|
||||
replayid = Config.server.id + '-' + replayid;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// replay panel
|
||||
replayid = room.fragment;
|
||||
}
|
||||
battle.fastForwardTo(-1);
|
||||
let buf = '<!DOCTYPE html>\n';
|
||||
buf += '<meta charset="utf-8" />\n';
|
||||
buf += '<!-- version 1 -->\n';
|
||||
buf += '<title>' + this.escapeHTML(battle.tier) + ' replay: ' + this.escapeHTML(battle.p1.name) + ' vs. ' + this.escapeHTML(battle.p2.name) + '</title>\n';
|
||||
buf += '<style>\n';
|
||||
buf += 'html,body {font-family:Verdana, sans-serif;font-size:10pt;margin:0;padding:0;}body{padding:12px 0;} .battle-log {font-family:Verdana, sans-serif;font-size:10pt;} .battle-log-inline {border:1px solid #AAAAAA;background:#EEF2F5;color:black;max-width:640px;margin:0 auto 80px;padding-bottom:5px;} .battle-log .inner {padding:4px 8px 0px 8px;} .battle-log .inner-preempt {padding:0 8px 4px 8px;} .battle-log .inner-after {margin-top:0.5em;} .battle-log h2 {margin:0.5em -8px;padding:4px 8px;border:1px solid #AAAAAA;background:#E0E7EA;border-left:0;border-right:0;font-family:Verdana, sans-serif;font-size:13pt;} .battle-log .chat {vertical-align:middle;padding:3px 0 3px 0;font-size:8pt;} .battle-log .chat strong {color:#40576A;} .battle-log .chat em {padding:1px 4px 1px 3px;color:#000000;font-style:normal;} .chat.mine {background:rgba(0,0,0,0.05);margin-left:-8px;margin-right:-8px;padding-left:8px;padding-right:8px;} .spoiler {color:#BBBBBB;background:#BBBBBB;padding:0px 3px;} .spoiler:hover, .spoiler:active, .spoiler-shown {color:#000000;background:#E2E2E2;padding:0px 3px;} .spoiler a {color:#BBBBBB;} .spoiler:hover a, .spoiler:active a, .spoiler-shown a {color:#2288CC;} .chat code, .chat .spoiler:hover code, .chat .spoiler:active code, .chat .spoiler-shown code {border:1px solid #C0C0C0;background:#EEEEEE;color:black;padding:0 2px;} .chat .spoiler code {border:1px solid #CCCCCC;background:#CCCCCC;color:#CCCCCC;} .battle-log .rated {padding:3px 4px;} .battle-log .rated strong {color:white;background:#89A;padding:1px 4px;border-radius:4px;} .spacer {margin-top:0.5em;} .message-announce {background:#6688AA;color:white;padding:1px 4px 2px;} .message-announce a, .broadcast-green a, .broadcast-blue a, .broadcast-red a {color:#DDEEFF;} .broadcast-green {background-color:#559955;color:white;padding:2px 4px;} .broadcast-blue {background-color:#6688AA;color:white;padding:2px 4px;} .infobox {border:1px solid #6688AA;padding:2px 4px;} .infobox-limited {max-height:200px;overflow:auto;overflow-x:hidden;} .broadcast-red {background-color:#AA5544;color:white;padding:2px 4px;} .message-learn-canlearn {font-weight:bold;color:#228822;text-decoration:underline;} .message-learn-cannotlearn {font-weight:bold;color:#CC2222;text-decoration:underline;} .message-effect-weak {font-weight:bold;color:#CC2222;} .message-effect-resist {font-weight:bold;color:#6688AA;} .message-effect-immune {font-weight:bold;color:#666666;} .message-learn-list {margin-top:0;margin-bottom:0;} .message-throttle-notice, .message-error {color:#992222;} .message-overflow, .chat small.message-overflow {font-size:0pt;} .message-overflow::before {font-size:9pt;content:\'...\';} .subtle {color:#3A4A66;}\n';
|
||||
buf += '</style>\n';
|
||||
buf += '<div class="wrapper replay-wrapper" style="max-width:1180px;margin:0 auto">\n';
|
||||
buf += '<input type="hidden" name="replayid" value="' + replayid + '" />\n';
|
||||
buf += '<div class="battle"></div><div class="battle-log"></div><div class="replay-controls"></div><div class="replay-controls-2"></div>\n';
|
||||
buf += '<h1 style="font-weight:normal;text-align:center"><strong>' + this.escapeHTML(battle.tier) + '</strong><br /><a href="http://pokemonshowdown.com/users/' + toId(battle.p1.name) + '" class="subtle" target="_blank">' + this.escapeHTML(battle.p1.name) + '</a> vs. <a href="http://pokemonshowdown.com/users/' + toId(battle.p2.name) + '" class="subtle" target="_blank">' + this.escapeHTML(battle.p2.name) + '</a></h1>\n';
|
||||
buf += '<script type="text/plain" class="battle-log-data">' + battle.activityQueue.join('\n').replace(/\//g, '\\/') + '</script>\n'; // lgtm [js/incomplete-sanitization]
|
||||
buf += '</div>\n';
|
||||
buf += '<div class="battle-log battle-log-inline"><div class="inner">' + battle.scene.$log.html() + '</div></div>\n';
|
||||
buf += '</div>\n';
|
||||
buf += '<script>\n';
|
||||
buf += 'let daily = Math.floor(Date.now()/1000/60/60/24);document.write(\'<script src="https://play.pokemonshowdown.com/js/replay-embed.js?version\'+daily+\'"></\'+\'script>\');\n';
|
||||
buf += '</script>\n';
|
||||
return buf;
|
||||
}
|
||||
|
||||
static createReplayFileHref(room: any) {
|
||||
// unescape(encodeURIComponent()) is necessary because btoa doesn't support Unicode
|
||||
// @ts-ignore
|
||||
return 'data:text/plain;base64,' + encodeURIComponent(btoa(unescape(encodeURIComponent(this.createReplayFile(room)))));
|
||||
}
|
||||
}
|
||||
110
src/battle.ts
110
src/battle.ts
|
|
@ -332,7 +332,7 @@ class Pokemon {
|
|||
}
|
||||
}
|
||||
htmlName() {
|
||||
return '<span class="battle-nickname' + (this.side.n === 0 ? '' : '-foe') + '" title="' + this.species + '">' + Tools.escapeHTML(this.name) + '</span>';
|
||||
return '<span class="battle-nickname' + (this.side.n === 0 ? '' : '-foe') + '" title="' + this.species + '">' + BattleLog.escapeHTML(this.name) + '</span>';
|
||||
}
|
||||
getName(shortName?: boolean) {
|
||||
if (this.side.n === 0) {
|
||||
|
|
@ -358,7 +358,7 @@ class Pokemon {
|
|||
return titlestring;
|
||||
}
|
||||
getFullName(plaintext?: boolean) {
|
||||
let name = this.side && this.side.n && (this.side.battle.ignoreOpponent || this.side.battle.ignoreNicks) ? this.species : Tools.escapeHTML(this.name);
|
||||
let name = this.side && this.side.n && (this.side.battle.ignoreOpponent || this.side.battle.ignoreNicks) ? this.species : BattleLog.escapeHTML(this.name);
|
||||
if (name !== this.species) {
|
||||
if (plaintext) {
|
||||
name += ' (' + this.species + ')';
|
||||
|
|
@ -787,7 +787,7 @@ class Side {
|
|||
if (pokemon.side.n === 0) {
|
||||
this.battle.message('Go! ' + pokemon.getFullName() + '!');
|
||||
} else {
|
||||
this.battle.message('' + Tools.escapeHTML(pokemon.side.name) + ' sent out ' + pokemon.getFullName() + '!');
|
||||
this.battle.message('' + BattleLog.escapeHTML(pokemon.side.name) + ' sent out ' + pokemon.getFullName() + '!');
|
||||
}
|
||||
|
||||
this.battle.scene.animSummon(pokemon, slot);
|
||||
|
|
@ -849,12 +849,12 @@ class Side {
|
|||
pokemon.removeVolatile('formechange' as ID);
|
||||
}
|
||||
if (pokemon.lastMove === 'uturn' || pokemon.lastMove === 'voltswitch') {
|
||||
this.battle.message('' + pokemon.getName() + ' went back to ' + Tools.escapeHTML(pokemon.side.name) + '!');
|
||||
this.battle.message('' + pokemon.getName() + ' went back to ' + BattleLog.escapeHTML(pokemon.side.name) + '!');
|
||||
} else if (pokemon.lastMove !== 'batonpass' && pokemon.lastMove !== 'zbatonpass') {
|
||||
if (pokemon.side.n === 0) {
|
||||
this.battle.message('' + pokemon.getName() + ', come back!');
|
||||
} else {
|
||||
this.battle.message('' + Tools.escapeHTML(pokemon.side.name) + ' withdrew ' + pokemon.getFullName() + '!');
|
||||
this.battle.message('' + BattleLog.escapeHTML(pokemon.side.name) + ' withdrew ' + pokemon.getFullName() + '!');
|
||||
}
|
||||
}
|
||||
pokemon.statusData.toxicTurns = 0;
|
||||
|
|
@ -1163,12 +1163,12 @@ class Battle {
|
|||
// activities
|
||||
//
|
||||
start() {
|
||||
this.scene.log('<div>Battle between ' + Tools.escapeHTML(this.p1.name) + ' and ' + Tools.escapeHTML(this.p2.name) + ' started!</div>');
|
||||
this.scene.log('<div>Battle between ' + BattleLog.escapeHTML(this.p1.name) + ' and ' + BattleLog.escapeHTML(this.p2.name) + ' started!</div>');
|
||||
if (this.startCallback) this.startCallback(this);
|
||||
}
|
||||
winner(winner?: string) {
|
||||
if (winner) this.message('' + Tools.escapeHTML(winner) + ' won the battle!');
|
||||
else this.message('Tie between ' + Tools.escapeHTML(this.p1.name) + ' and ' + Tools.escapeHTML(this.p2.name) + '!');
|
||||
if (winner) this.message('' + BattleLog.escapeHTML(winner) + ' won the battle!');
|
||||
else this.message('Tie between ' + BattleLog.escapeHTML(this.p1.name) + ' and ' + BattleLog.escapeHTML(this.p2.name) + '!');
|
||||
this.ended = true;
|
||||
}
|
||||
prematureEnd() {
|
||||
|
|
@ -1440,7 +1440,7 @@ class Battle {
|
|||
// for (let i = 0; i < 10; i++) {
|
||||
// let name = people[Math.floor(Math.random() * people.length)];
|
||||
// if (!button) button = buttons[Math.floor(Math.random() * buttons.length)];
|
||||
// this.scene.log('<div class="chat"><strong style="' + hashColor(toUserid(name)) + '" class="username" data-name="' + Tools.escapeHTML(name) + '">' + Tools.escapeHTML(name) + ':</strong> <em>' + button + '</em></div>');
|
||||
// this.scene.log('<div class="chat"><strong style="' + BattleLog.hashColor(toUserid(name)) + '" class="username" data-name="' + BattleLog.escapeHTML(name) + '">' + BattleLog.escapeHTML(name) + ':</strong> <em>' + button + '</em></div>');
|
||||
// button = (name === 'Diatom' ? "thanks diatom" : null);
|
||||
// }
|
||||
} else {
|
||||
|
|
@ -2268,7 +2268,7 @@ class Battle {
|
|||
actions += '' + ofpoke!.getName() + ' surrounded itself with a veil of petals!';
|
||||
break;
|
||||
default:
|
||||
let stat = Tools.escapeHTML(args[3]);
|
||||
let stat = BattleLog.escapeHTML(args[3]);
|
||||
actions += "" + poke.getName() + "'s " + (stat ? stat + " was" : "stats were") + " not lowered!";
|
||||
}
|
||||
break;
|
||||
|
|
@ -2899,10 +2899,10 @@ class Battle {
|
|||
let poke = this.getPokemon(args[1])!;
|
||||
let item = Tools.getItem(args[3]);
|
||||
if (args[2] === 'Rayquaza') {
|
||||
actions += "" + Tools.escapeHTML(poke.side.name) + "'s fervent wish has reached " + poke.getLowerName() + "!";
|
||||
actions += "" + BattleLog.escapeHTML(poke.side.name) + "'s fervent wish has reached " + poke.getLowerName() + "!";
|
||||
} else {
|
||||
poke.item = item.name;
|
||||
actions += "" + poke.getName() + "'s " + item.name + " is reacting to " + (this.gen >= 7 ? "the Key Stone" : Tools.escapeHTML(poke.side.name) + "'s Mega Bracelet") + "!";
|
||||
actions += "" + poke.getName() + "'s " + item.name + " is reacting to " + (this.gen >= 7 ? "the Key Stone" : BattleLog.escapeHTML(poke.side.name) + "'s Mega Bracelet") + "!";
|
||||
}
|
||||
actions += "<br />" + poke.getName() + " has Mega Evolved into Mega " + args[2] + "!";
|
||||
break;
|
||||
|
|
@ -2932,7 +2932,7 @@ class Battle {
|
|||
} else {
|
||||
switch (effect.id) {
|
||||
case 'typechange':
|
||||
const types = Tools.escapeHTML(args[3]);
|
||||
const types = BattleLog.escapeHTML(args[3]);
|
||||
poke.removeVolatile('typeadd' as ID);
|
||||
poke.addVolatile('typechange' as ID, types);
|
||||
if (kwargs.silent) {
|
||||
|
|
@ -2962,7 +2962,7 @@ class Battle {
|
|||
}).join(' '), 'neutral');
|
||||
break;
|
||||
case 'typeadd':
|
||||
const type = Tools.escapeHTML(args[3]);
|
||||
const type = BattleLog.escapeHTML(args[3]);
|
||||
poke.addVolatile('typeadd' as ID, type);
|
||||
if (kwargs.silent) break;
|
||||
actions += "" + type + " type was added to " + poke.getLowerName() + "!";
|
||||
|
|
@ -3032,7 +3032,7 @@ class Battle {
|
|||
ofpoke!.markAbility(fromeffect.name);
|
||||
}
|
||||
this.scene.resultAnim(poke, 'Disabled', 'bad');
|
||||
actions += "" + poke.getName() + "'s " + Tools.escapeHTML(args[3]) + " was disabled!";
|
||||
actions += "" + poke.getName() + "'s " + BattleLog.escapeHTML(args[3]) + " was disabled!";
|
||||
break;
|
||||
case 'embargo':
|
||||
this.scene.resultAnim(poke, 'Embargo', 'bad');
|
||||
|
|
@ -3166,7 +3166,7 @@ class Battle {
|
|||
actions += '' + poke.getName() + ' foresaw an attack!';
|
||||
break;
|
||||
case 'mimic':
|
||||
actions += '' + poke.getName() + ' learned ' + Tools.escapeHTML(args[3]) + '!';
|
||||
actions += '' + poke.getName() + ' learned ' + BattleLog.escapeHTML(args[3]) + '!';
|
||||
break;
|
||||
case 'laserfocus':
|
||||
actions += '' + poke.getName() + ' concentrated intensely!';
|
||||
|
|
@ -3455,7 +3455,7 @@ class Battle {
|
|||
actions += "" + poke.getName() + " snatched " + ofpoke!.getLowerName() + "'s move!";
|
||||
break;
|
||||
case 'grudge':
|
||||
actions += "" + poke.getName() + "'s " + Tools.escapeHTML(args[3]) + " lost all of its PP due to the grudge!";
|
||||
actions += "" + poke.getName() + "'s " + BattleLog.escapeHTML(args[3]) + " lost all of its PP due to the grudge!";
|
||||
poke.markMove(args[3], Infinity);
|
||||
break;
|
||||
case 'quickguard':
|
||||
|
|
@ -3512,7 +3512,7 @@ class Battle {
|
|||
actions += 'Everyone is caught up in the happy atmosphere!';
|
||||
break;
|
||||
case 'celebrate':
|
||||
actions += 'Congratulations, ' + Tools.escapeHTML(poke.side.name) + '!';
|
||||
actions += 'Congratulations, ' + BattleLog.escapeHTML(poke.side.name) + '!';
|
||||
break;
|
||||
|
||||
// move activations
|
||||
|
|
@ -3534,7 +3534,7 @@ class Battle {
|
|||
ofpoke!.side.removeSideCondition('LightScreen');
|
||||
break;
|
||||
case 'beatup':
|
||||
actions += "" + Tools.escapeHTML(kwargs.of) + "'s attack!";
|
||||
actions += "" + BattleLog.escapeHTML(kwargs.of) + "'s attack!";
|
||||
break;
|
||||
case 'pursuit':
|
||||
actions += "(" + poke.getName() + " is being withdrawn!)";
|
||||
|
|
@ -3561,7 +3561,7 @@ class Battle {
|
|||
break;
|
||||
case 'spite':
|
||||
let move = Tools.getMove(args[3]).name;
|
||||
let pp = Tools.escapeHTML(args[4]);
|
||||
let pp = BattleLog.escapeHTML(args[4]);
|
||||
actions += "It reduced the PP of " + poke.getLowerName() + "'s " + move + " by " + pp + "!";
|
||||
poke.markMove(move, Number(pp));
|
||||
break;
|
||||
|
|
@ -3572,16 +3572,16 @@ class Battle {
|
|||
this.scene.anim(poke, {time: 100});
|
||||
break;
|
||||
case 'magnitude':
|
||||
actions += "Magnitude " + Tools.escapeHTML(args[3]) + "!";
|
||||
actions += "Magnitude " + BattleLog.escapeHTML(args[3]) + "!";
|
||||
break;
|
||||
case 'sketch':
|
||||
actions += "" + poke.getName() + " sketched " + Tools.escapeHTML(args[3]) + "!";
|
||||
actions += "" + poke.getName() + " sketched " + BattleLog.escapeHTML(args[3]) + "!";
|
||||
break;
|
||||
case 'skillswap':
|
||||
actions += "" + poke.getName() + " swapped Abilities with its target!";
|
||||
if (this.gen <= 4) break;
|
||||
let pokeability = Tools.escapeHTML(args[3]) || ofpoke!.ability;
|
||||
let ofpokeability = Tools.escapeHTML(args[4]) || poke.ability;
|
||||
let pokeability = BattleLog.escapeHTML(args[3]) || ofpoke!.ability;
|
||||
let ofpokeability = BattleLog.escapeHTML(args[4]) || poke.ability;
|
||||
if (pokeability) {
|
||||
poke.ability = pokeability;
|
||||
if (!ofpoke!.baseAbility) ofpoke!.baseAbility = pokeability;
|
||||
|
|
@ -3646,7 +3646,7 @@ class Battle {
|
|||
actions += '' + poke.getName() + ' anchored itself with its roots!';
|
||||
break;
|
||||
case 'matblock':
|
||||
actions += '' + Tools.escapeHTML(args[3]) + ' was blocked by the kicked-up mat!';
|
||||
actions += '' + BattleLog.escapeHTML(args[3]) + ' was blocked by the kicked-up mat!';
|
||||
break;
|
||||
case 'powder':
|
||||
actions += 'When the flame touched the powder on the Pokémon, it exploded!';
|
||||
|
|
@ -3682,10 +3682,10 @@ class Battle {
|
|||
break;
|
||||
case 'forewarn':
|
||||
if (this.gen >= 5) {
|
||||
actions += "It was alerted to " + ofpoke!.getLowerName() + "'s " + Tools.escapeHTML(args[3]) + "!";
|
||||
actions += "It was alerted to " + ofpoke!.getLowerName() + "'s " + BattleLog.escapeHTML(args[3]) + "!";
|
||||
ofpoke!.markMove(args[3], 0);
|
||||
} else {
|
||||
actions += "" + poke.getName() + "'s Forewarn alerted it to " + Tools.escapeHTML(args[3]) + "!";
|
||||
actions += "" + poke.getName() + "'s Forewarn alerted it to " + BattleLog.escapeHTML(args[3]) + "!";
|
||||
let foeActive = [] as Pokemon[];
|
||||
for (const target of poke.side.foe.active) if (target) foeActive.push(target);
|
||||
if (foeActive.length === 1) {
|
||||
|
|
@ -3759,7 +3759,7 @@ class Battle {
|
|||
break;
|
||||
case 'leppaberry':
|
||||
case 'mysteryberry':
|
||||
actions += '' + poke.getName() + " restored PP to its " + Tools.escapeHTML(args[3]) + " move using " + effect.name + "!";
|
||||
actions += '' + poke.getName() + " restored PP to its " + BattleLog.escapeHTML(args[3]) + " move using " + effect.name + "!";
|
||||
poke.markMove(args[3], effect.id === 'leppaberry' ? -10 : -5);
|
||||
break;
|
||||
case 'focusband':
|
||||
|
|
@ -3768,7 +3768,7 @@ class Battle {
|
|||
break;
|
||||
case 'safetygoggles':
|
||||
poke.item = 'Safety Goggles';
|
||||
actions += '' + poke.getName() + " is not affected by " + Tools.escapeHTML(args[3]) + " thanks to its Safety Goggles!";
|
||||
actions += '' + poke.getName() + " is not affected by " + BattleLog.escapeHTML(args[3]) + " thanks to its Safety Goggles!";
|
||||
break;
|
||||
case 'protectivepads':
|
||||
poke.item = 'Protective Pads';
|
||||
|
|
@ -4037,7 +4037,7 @@ class Battle {
|
|||
break;
|
||||
|
||||
} case '-message': {
|
||||
actions += Tools.escapeHTML(args[1]);
|
||||
actions += BattleLog.escapeHTML(args[1]);
|
||||
break;
|
||||
|
||||
} case '-anim': {
|
||||
|
|
@ -4052,7 +4052,7 @@ class Battle {
|
|||
break;
|
||||
|
||||
} case '-hint': {
|
||||
this.message('', '<small>(' + Tools.escapeHTML(args[1]) + ')</small>');
|
||||
this.message('', '<small>(' + BattleLog.escapeHTML(args[1]) + ')</small>');
|
||||
break;
|
||||
|
||||
} default: {
|
||||
|
|
@ -4371,7 +4371,7 @@ class Battle {
|
|||
} case 'tier': {
|
||||
if (!args[1]) args[1] = '';
|
||||
for (let i in kwargs) args[1] += '[' + i + '] ' + kwargs[i];
|
||||
this.scene.log('<div style="padding:5px 0"><small>Format:</small> <br /><strong>' + Tools.escapeHTML(args[1]) + '</strong></div>');
|
||||
this.scene.log('<div style="padding:5px 0"><small>Format:</small> <br /><strong>' + BattleLog.escapeHTML(args[1]) + '</strong></div>');
|
||||
this.tier = args[1];
|
||||
if (this.tier.slice(-13) === 'Random Battle') {
|
||||
this.speciesClause = true;
|
||||
|
|
@ -4397,16 +4397,16 @@ class Battle {
|
|||
this.scene.updateGen();
|
||||
break;
|
||||
} case 'variation': {
|
||||
this.scene.log('<div><small>Variation: <em>' + Tools.escapeHTML(args[1]) + '</em></small></div>');
|
||||
this.scene.log('<div><small>Variation: <em>' + BattleLog.escapeHTML(args[1]) + '</em></small></div>');
|
||||
break;
|
||||
} case 'rule': {
|
||||
let ruleArgs = args[1].split(': ');
|
||||
this.scene.log('<div><small><em>' + Tools.escapeHTML(ruleArgs[0]) + (ruleArgs[1] ? ':' : '') + '</em> ' + Tools.escapeHTML(ruleArgs[1] || '') + '</div>');
|
||||
this.scene.log('<div><small><em>' + BattleLog.escapeHTML(ruleArgs[0]) + (ruleArgs[1] ? ':' : '') + '</em> ' + BattleLog.escapeHTML(ruleArgs[1] || '') + '</div>');
|
||||
if (ruleArgs[0] === 'Species Clause') this.speciesClause = true;
|
||||
break;
|
||||
} case 'rated': {
|
||||
this.rated = true;
|
||||
this.scene.log('<div class="rated"><strong>' + (Tools.escapeHTML(args[1]) || 'Rated battle') + '</strong></div>');
|
||||
this.scene.log('<div class="rated"><strong>' + (BattleLog.escapeHTML(args[1]) || 'Rated battle') + '</strong></div>');
|
||||
break;
|
||||
} case ':': {
|
||||
break;
|
||||
|
|
@ -4423,7 +4423,7 @@ class Battle {
|
|||
if (window.app && app.ignore && app.ignore[toUserid(name)] && (rank === ' ' || rank === '+' || rank === '\u2605' || rank === '\u2606')) break;
|
||||
let message = args[1].slice(pipeIndex + 1);
|
||||
let isHighlighted = window.app && app.rooms && app.rooms[this.roomid].getHighlight(message);
|
||||
let parsedMessage = Tools.parseChatMessage(message, name, '', isHighlighted);
|
||||
let parsedMessage = BattleLog.parseChatMessage(message, name, '', isHighlighted);
|
||||
if (!Array.isArray(parsedMessage)) parsedMessage = [parsedMessage];
|
||||
for (let i = 0; i < parsedMessage.length; i++) {
|
||||
if (!parsedMessage[i]) continue;
|
||||
|
|
@ -4435,19 +4435,19 @@ class Battle {
|
|||
}
|
||||
break;
|
||||
} case 'chatmsg': {
|
||||
this.scene.log('<div class="chat">' + Tools.escapeHTML(args[1]) + '</div>', preempt);
|
||||
this.scene.log('<div class="chat">' + BattleLog.escapeHTML(args[1]) + '</div>', preempt);
|
||||
break;
|
||||
} case 'chatmsg-raw': case 'raw': case 'html': {
|
||||
this.scene.log('<div class="chat">' + Tools.sanitizeHTML(args[1]) + '</div>', preempt);
|
||||
this.scene.log('<div class="chat">' + BattleLog.sanitizeHTML(args[1]) + '</div>', preempt);
|
||||
break;
|
||||
} case 'error': {
|
||||
this.scene.log('<div class="chat message-error">' + Tools.escapeHTML(args[1]) + '</div>', preempt);
|
||||
this.scene.log('<div class="chat message-error">' + BattleLog.escapeHTML(args[1]) + '</div>', preempt);
|
||||
break;
|
||||
} case 'pm': {
|
||||
this.scene.log('<div class="chat"><strong>' + Tools.escapeHTML(args[1]) + ':</strong> <span class="message-pm"><i style="cursor:pointer" onclick="selectTab(\'lobby\');rooms.lobby.popupOpen(\'' + Tools.escapeHTML(args[2], true) + '\')">(Private to ' + Tools.escapeHTML(args[3]) + ')</i> ' + Tools.parseMessage(args[4]) + '</span>');
|
||||
this.scene.log('<div class="chat"><strong>' + BattleLog.escapeHTML(args[1]) + ':</strong> <span class="message-pm"><i style="cursor:pointer" onclick="selectTab(\'lobby\');rooms.lobby.popupOpen(\'' + BattleLog.escapeHTML(args[2], true) + '\')">(Private to ' + BattleLog.escapeHTML(args[3]) + ')</i> ' + BattleLog.parseMessage(args[4]) + '</span>');
|
||||
break;
|
||||
} case 'askreg': {
|
||||
this.scene.log('<div class="broadcast-blue"><b>Register an account to protect your ladder rating!</b><br /><button name="register" value="' + Tools.escapeHTML(args[1]) + '"><b>Register</b></button></div>');
|
||||
this.scene.log('<div class="broadcast-blue"><b>Register an account to protect your ladder rating!</b><br /><button name="register" value="' + BattleLog.escapeHTML(args[1]) + '"><b>Register</b></button></div>');
|
||||
break;
|
||||
} case 'inactive': {
|
||||
if (!this.kickingInactive) this.kickingInactive = true;
|
||||
|
|
@ -4469,11 +4469,11 @@ class Battle {
|
|||
this.kickingInactive = parseInt(args[1].slice(hasIndex + 5), 10) || true;
|
||||
}
|
||||
}
|
||||
this.scene.log('<div class="chat message-error">' + Tools.escapeHTML(args[1]) + '</div>', preempt);
|
||||
this.scene.log('<div class="chat message-error">' + BattleLog.escapeHTML(args[1]) + '</div>', preempt);
|
||||
break;
|
||||
} case 'inactiveoff': {
|
||||
this.kickingInactive = false;
|
||||
this.scene.log('<div class="chat message-error">' + Tools.escapeHTML(args[1]) + '</div>', preempt);
|
||||
this.scene.log('<div class="chat message-error">' + BattleLog.escapeHTML(args[1]) + '</div>', preempt);
|
||||
break;
|
||||
} case 'timer': {
|
||||
break;
|
||||
|
|
@ -4490,7 +4490,7 @@ class Battle {
|
|||
room.userList.updateNoUsersOnline();
|
||||
}
|
||||
if (!this.ignoreSpects) {
|
||||
this.scene.log('<div class="chat"><small>' + Tools.escapeHTML(args[1]) + ' joined.</small></div>', preempt);
|
||||
this.scene.log('<div class="chat"><small>' + BattleLog.escapeHTML(args[1]) + ' joined.</small></div>', preempt);
|
||||
}
|
||||
break;
|
||||
} case 'leave': case 'l': {
|
||||
|
|
@ -4505,7 +4505,7 @@ class Battle {
|
|||
room.userList.updateNoUsersOnline();
|
||||
}
|
||||
if (!this.ignoreSpects) {
|
||||
this.scene.log('<div class="chat"><small>' + Tools.escapeHTML(args[1]) + ' left.</small></div>', preempt);
|
||||
this.scene.log('<div class="chat"><small>' + BattleLog.escapeHTML(args[1]) + ' left.</small></div>', preempt);
|
||||
}
|
||||
break;
|
||||
} case 'J': case 'L': case 'N': case 'n': case 'spectator': case 'spectatorleave': {
|
||||
|
|
@ -4637,16 +4637,16 @@ class Battle {
|
|||
this.cantUseMove(poke, effect, move, kwargs);
|
||||
break;
|
||||
} case 'message': {
|
||||
this.message(Tools.escapeHTML(args[1]));
|
||||
this.message(BattleLog.escapeHTML(args[1]));
|
||||
break;
|
||||
} case 'bigerror': {
|
||||
this.message('<div class="broadcast-red">' + Tools.escapeHTML(args[1]).replace(/\|/g, '<br />') + '</div>');
|
||||
this.message('<div class="broadcast-red">' + BattleLog.escapeHTML(args[1]).replace(/\|/g, '<br />') + '</div>');
|
||||
break;
|
||||
} case 'done': case '': {
|
||||
if (this.ended || this.endPrevAction()) return;
|
||||
break;
|
||||
} case 'warning': {
|
||||
this.message('<strong>Warning:</strong> ' + Tools.escapeHTML(args[1]));
|
||||
this.message('<strong>Warning:</strong> ' + BattleLog.escapeHTML(args[1]));
|
||||
this.message('Bug? Report it to <a href="http://www.smogon.com/forums/showthread.php?t=3453192">the replay viewer\'s Smogon thread</a>');
|
||||
this.scene.wait(1000);
|
||||
break;
|
||||
|
|
@ -4661,7 +4661,7 @@ class Battle {
|
|||
} case 'debug': {
|
||||
args.shift();
|
||||
const name = args.join(' ');
|
||||
this.scene.log('<div class="debug"><div class="chat"><small style="color:#999">[DEBUG] ' + Tools.escapeHTML(name) + '.</small></div></div>', preempt);
|
||||
this.scene.log('<div class="debug"><div class="chat"><small style="color:#999">[DEBUG] ' + BattleLog.escapeHTML(name) + '.</small></div></div>', preempt);
|
||||
break;
|
||||
} case 'seed': case 'choice': {
|
||||
break;
|
||||
|
|
@ -4671,13 +4671,13 @@ class Battle {
|
|||
break;
|
||||
} case 'fieldhtml': {
|
||||
this.playbackState = Playback.Seeking; // force seeking to prevent controls etc
|
||||
this.scene.setFrameHTML(Tools.sanitizeHTML(args[1]));
|
||||
this.scene.setFrameHTML(BattleLog.sanitizeHTML(args[1]));
|
||||
break;
|
||||
} case 'controlshtml': {
|
||||
this.scene.setControlsHTML(Tools.sanitizeHTML(args[1]));
|
||||
this.scene.setControlsHTML(BattleLog.sanitizeHTML(args[1]));
|
||||
break;
|
||||
} default: {
|
||||
this.scene.log('<div class="chat message-error">Unknown command: ' + Tools.escapeHTML(args[0]) + '</div>');
|
||||
this.scene.log('<div class="chat message-error">Unknown command: ' + BattleLog.escapeHTML(args[0]) + '</div>');
|
||||
if (this.errorCallback) this.errorCallback(this);
|
||||
break;
|
||||
}}
|
||||
|
|
@ -4691,7 +4691,7 @@ class Battle {
|
|||
if (!str) return;
|
||||
if (str.charAt(0) !== '|' || str.substr(0, 2) === '||') {
|
||||
if (str.charAt(0) === '|') str = str.substr(2);
|
||||
this.scene.log('<div class="chat">' + Tools.escapeHTML(str) + '</div>', preempt);
|
||||
this.scene.log('<div class="chat">' + BattleLog.escapeHTML(str) + '</div>', preempt);
|
||||
return;
|
||||
}
|
||||
let args = ['done'];
|
||||
|
|
@ -4751,9 +4751,9 @@ class Battle {
|
|||
this.runMajor(args, kwargs, preempt);
|
||||
}
|
||||
} catch (e) {
|
||||
this.scene.log('<div class="broadcast-red">Error parsing: ' + Tools.escapeHTML(str) + ' (' + Tools.escapeHTML('' + e) + ')</div>', preempt);
|
||||
this.scene.log('<div class="broadcast-red">Error parsing: ' + BattleLog.escapeHTML(str) + ' (' + BattleLog.escapeHTML('' + e) + ')</div>', preempt);
|
||||
if (e.stack) {
|
||||
let stack = Tools.escapeHTML('' + e.stack).split('\n');
|
||||
let stack = BattleLog.escapeHTML('' + e.stack).split('\n');
|
||||
for (let i = 0; i < stack.length; i++) {
|
||||
if (/\brun\b/.test(stack[i])) {
|
||||
stack.length = i;
|
||||
|
|
|
|||
2
src/globals.d.ts
vendored
2
src/globals.d.ts
vendored
|
|
@ -29,7 +29,7 @@ declare var BattleStatuses: any;
|
|||
declare var BattlePokemonSprites: any;
|
||||
declare var BattlePokemonSpritesBW: any;
|
||||
|
||||
// defined in battle-dex-misc
|
||||
// defined in battle-log-misc
|
||||
declare function MD5(input: string): string;
|
||||
declare function formatText(input: string): string;
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ window = global;
|
|||
|
||||
// Without making these modules, the best we can do is directly include them into this workspace.
|
||||
eval('' + fs.readFileSync(`js/battle-scene-stub.js`));
|
||||
eval('' + fs.readFileSync(`js/battle-log.js`));
|
||||
eval('' + fs.readFileSync(`js/battle-dex.js`));
|
||||
eval('' + fs.readFileSync(`js/battle-dex-data.js`));
|
||||
eval('' + fs.readFileSync(`js/battle.js`));
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user