Difference between revisions of "MediaWiki:Gadget-SkillForm.js"
Jump to navigation
Jump to search
(Fixed edit link handling and reference) |
|||
(173 intermediate revisions by 4 users not shown) | |||
Line 1: | Line 1: | ||
− | + | RLQ.push(['jquery', function () { | |
− | $(document).ready(function() { | + | $(document).ready(function() { |
− | + | var skillforms = $('.skillform'); | |
− | + | if (skillforms.length > 0) {// Only 1 on normal pages | |
− | + | skillforms.each(function(idx, element) { | |
− | + | initButtons($(element).find('.tabButtonLane'), function(tabs) { | |
− | + | initSkillForm(element, tabs); | |
− | + | $(element).find('.tabButtonLane button').first().click(); | |
− | + | }); | |
− | + | }); | |
− | + | } | |
− | }); | + | }); |
+ | }]); | ||
+ | |||
− | var | + | function initButtons(buttonContainer, finishedHandler) { |
+ | var skillform = buttonContainer.closest('.skillform'); | ||
+ | |||
+ | // Remove any existence of another button | ||
+ | buttonContainer.empty(); | ||
+ | |||
+ | var skillCount = skillform.find('.skilldataraw').length; | ||
+ | |||
+ | for (var idx=1; idx<=skillCount; idx++) { | ||
+ | var idxNameAddOn = idx === 1 ? "" : ""+idx; | ||
+ | var skillDataRawElement = skillform.find('.skilldataraw[data-skilldata-content="skill' + idxNameAddOn + 'data"]'); | ||
+ | var skillElement = skillDataRawElement.find('div'); | ||
+ | if (skillElement.length === 1) { | ||
+ | var buttonData = convertSkillData(skillElement); | ||
+ | var button = $('<button></button>'); | ||
+ | button.data('skilldata', buttonData); | ||
+ | |||
+ | var skillEditLinks = skillDataRawElement.find('.skilleditlinksraw'); | ||
+ | if (skillEditLinks.length === 1) { | ||
+ | button.data('skilleditlinks', skillEditLinks.html()); | ||
+ | } | ||
+ | |||
+ | //Special tab names in Template:PNCHero | ||
+ | if (skillform.hasClass('pnchero')){ | ||
+ | switch(idx){ | ||
+ | case 1:button.text('Passive'); break; | ||
+ | case 2:button.text('Auto'); break; | ||
+ | case 3:button.text('Ultimate'); break; | ||
+ | default:button.text('Skill' + idx); | ||
+ | } | ||
+ | }else{ | ||
+ | button.text('Skill' + idx); | ||
+ | } | ||
+ | |||
+ | buttonContainer.append(button); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | finishedHandler(buttonContainer.find('button')); | ||
+ | } | ||
− | function | + | function initSkillForm(element, tabs) { |
− | + | var skillform = $(element); | |
− | + | ||
− | + | // selector is not possible in Wiki so we have to create it :/ | |
− | + | var levelSelector = skillform.find('.skilllevel select'); | |
− | + | if (levelSelector.length < 1) { | |
− | + | levelSelector = $('<select></select>'); | |
− | + | levelSelector.addClass("gf-droplist"); | |
− | + | skillform.find('.skilllevel').append(levelSelector); | |
− | + | } | |
− | + | //The skilldata object will be properly bound to .skilllevel>select during display_data() | |
− | + | levelSelector.on('change', function() { display_data(skillform, $(this).data('skilldata'), $(this).data('skilleditlinks')); }); | |
− | + | ||
− | + | if (skillform.hasClass('assimilated')) { | |
− | + | // Add checkbox for max analysis (visibility is controlled from display_data()) | |
− | + | var anamax = $('<label><input type="checkbox"> Max Analysis</label>'); | |
− | + | skillform.find('.maxanalysis').append(anamax); | |
− | + | //The skilldata object will be properly bound to .maxanalysis>input during display_data() | |
− | + | anamax.find('input').on('change', function() { display_data(skillform, $(this).data('skilldata'), $(this).data('skilleditlinks')); }); | |
− | + | } | |
− | + | ||
− | + | tabs.click(function(evt) { | |
− | + | skillformButtonHandler(evt.target); | |
+ | }); | ||
+ | } | ||
+ | |||
+ | function skillformButtonHandler(element) { | ||
+ | var currentButton = $(element); | ||
+ | var skillform = currentButton.closest('.skillform'); | ||
+ | |||
+ | skillform.find('.tabButtonLane button').removeClass('tabButton-active'); | ||
+ | currentButton.addClass('tabButton-active'); | ||
+ | |||
+ | var convertedData = currentButton.data('skilldata'); | ||
+ | var skillEditLinks = currentButton.data('skilleditlinks'); | ||
+ | |||
+ | display_data(skillform, convertedData, skillEditLinks); | ||
+ | } | ||
+ | |||
+ | function convertSkillData(dataElement) { | ||
+ | skill_data = {}; | ||
+ | var key; | ||
+ | |||
+ | dataElement.find('tbody tr').each(function(index, row) { | ||
+ | var key = $(row).find('th').text().trim(); | ||
+ | var tds = $(row).find('td'); | ||
+ | if (tds.length === 1) { | ||
+ | skill_data[key] = tds.first().html().trim(); | ||
+ | } else { | ||
+ | var lines = tds.map(function(index, td) { | ||
+ | return $(td).text().trim(); | ||
+ | }); | ||
+ | skill_data[key] = lines; | ||
+ | } | ||
+ | }); | ||
+ | |||
+ | return skill_data; | ||
+ | } | ||
+ | |||
+ | function calculateDescriptionText(data, chosenLevelIdx) { | ||
+ | var regex = /\(\$\w+\)/g; | ||
+ | var resultText = data.text; | ||
+ | |||
+ | if (!data.text || typeof data.text.match !== "function") { | ||
+ | //console.log("debug", data); | ||
+ | return resultText; | ||
+ | } | ||
+ | |||
+ | var vars = data.text.match(regex); | ||
+ | //No parameters defined | ||
+ | if(vars === null) { | ||
+ | return resultText; | ||
+ | } | ||
+ | |||
+ | var i; // For i not being global :) | ||
+ | |||
+ | if($('.maxanalysis input').is(':checked')) { | ||
+ | for (i = 0; i < vars.length; i++) { | ||
+ | var_name = vars[i].substring(2, vars[i].length - 1);// Trim beginning $( and trailing ) | ||
+ | var_name_max = var_name + '_4'; | ||
+ | if (typeof data[var_name_max] !== 'undefined'){// If defined, use max analysis data instead of base data | ||
+ | resultText = resultText.replace(vars[i], "<span class='skill-value'>" + data[var_name_max][chosenLevelIdx] + "</span>"); | ||
+ | } else { | ||
+ | resultText = resultText.replace(vars[i], "<span class='skill-value'>" + data[var_name][chosenLevelIdx] + "</span>"); | ||
+ | } | ||
+ | } | ||
+ | } else { | ||
+ | for (i = 0; i < vars.length; i++) { | ||
+ | var_name = vars[i].substring(2, vars[i].length - 1);// Trim beginning $( and trailing ) | ||
+ | resultText = resultText.replace(vars[i], "<span class='skill-value'>" + data[var_name][chosenLevelIdx] + "</span>"); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | return resultText; | ||
+ | } | ||
+ | |||
+ | function calculateConditionText(data, chosenLevelIdx) { | ||
+ | /* Passive for skilldata without special properties. */ | ||
+ | var result = "Passive"; | ||
+ | /* Use support points for fairies by default, if this is an assimilated unit use action points instead */ | ||
+ | var pointsToUse = $('.skillform').hasClass('assimilated') ? ' action' : ' support'; | ||
+ | if (data.hasOwnProperty('skill_cost')) { | ||
+ | /* Fairys hav turn_cooldown and skill_cost. */ | ||
+ | if (Array.isArray(data.skill_cost) || typeof data.skill_cost === 'object') { | ||
+ | result = data.skill_cost[chosenLevelIdx] + pointsToUse + ' point(s) per use'; | ||
+ | } else { | ||
+ | result = data.skill_cost + pointsToUse + ' point(s) per use'; | ||
+ | } | ||
+ | if (data.hasOwnProperty('turn_cooldown')) { | ||
+ | if (Array.isArray(data.turn_cooldown) || typeof data.turn_cooldown === 'object') { | ||
+ | result += ', ' + data.turn_cooldown[chosenLevelIdx] + ' turn cooldown'; | ||
+ | } else { | ||
+ | result += ', ' + data.turn_cooldown + ' turn cooldown'; | ||
+ | } | ||
} | } | ||
+ | } else if (data.hasOwnProperty('cooldown')) { | ||
+ | /* cooldown and initial are used for T-Doll Skills. */ | ||
+ | result = data.cooldown[chosenLevelIdx] + 's cooldown'; | ||
+ | if (data.hasOwnProperty('initial')) { | ||
+ | result += ', ' + data.initial + 's initial cooldown'; | ||
+ | } | ||
+ | } else if (data.hasOwnProperty('activation')) { | ||
+ | /* Skills/Buffs activated with a certain chance are defined by 'activation' */ | ||
+ | result = data.activation[chosenLevelIdx] + '% chance to activate'; | ||
+ | } | ||
+ | return result; | ||
} | } | ||
− | function display_data() { | + | function display_data(skillDataContainer, data, skilleditlinks) { |
− | + | if (data == null) { | |
− | + | console.log("Skill called without data", data); | |
− | + | return; | |
− | + | } | |
− | + | ||
− | + | // Make sure skillcontainer is visible, as it is display:none by default | |
− | + | skillDataContainer.find('.skillcontent').show(); | |
− | + | ||
− | + | // Make sure Level Selector shows the fitting amount of levels | |
− | + | var idx = 0; | |
− | + | var skillLevels = 10; | |
− | + | var levelSelector = skillDataContainer.find('.skilllevel select'); | |
− | + | ||
− | + | if (data.hasOwnProperty('skilllevelcount')) { | |
− | + | try { | |
− | + | skillLevels = parseInt(data.skilllevelcount, 10); | |
− | + | } catch (e) { | |
− | + | console.log("Error parsing 'skilllevelcount'", e); | |
− | + | } | |
− | + | } | |
− | + | ||
− | + | if (levelSelector.find('option').length != skillLevels) { | |
− | + | levelSelector.empty(); | |
− | + | for (idx=0; idx<skillLevels; idx++) { | |
− | + | var opt = $('<option></option>'); | |
− | + | opt.text('Lv. ' + (idx+1)); | |
− | + | opt.attr('value', idx); | |
− | + | if (idx == skillLevels-1) opt.prop('selected', true); | |
− | + | levelSelector.append(opt); | |
} | } | ||
+ | } | ||
+ | |||
+ | // We have to remember skilldata for the levelSelector | ||
+ | levelSelector.data('skilldata', data); | ||
+ | |||
+ | var name = skillDataContainer.find('.skillname'); | ||
+ | name.text(data.name); | ||
+ | |||
+ | if (skilleditlinks) { | ||
+ | var skilleditlinksDestination = skillDataContainer.find('.skilleditlinks'); | ||
+ | skilleditlinksDestination.html(skilleditlinks); | ||
+ | } | ||
+ | |||
+ | var iconImg = skillDataContainer.find('.skillicon img'); | ||
+ | var iconId = data.icon || ""; | ||
+ | var iconFilename = "Icon_Skill_" + iconId + ".png"; | ||
+ | if (iconImg.attr('alt') != iconFilename) { | ||
+ | iconImg.attr('alt', iconFilename); | ||
+ | var wikiPath = "/images/" + gfUtils.createWikiPathPart(iconFilename) + iconFilename; | ||
+ | var fallbackPath = "/images/thumb/5/5b/skill_backup.png/75px-skill_backup.png 1.5x, /images/5/5b/skill_backup.png 2x" | ||
+ | iconImg.attr('src', wikiPath); | ||
+ | if (iconId == '' || iconId == null) { | ||
+ | iconImg.attr('srcset', fallbackPath); | ||
+ | } else { | ||
+ | // Check if icon actually exists as a file | ||
+ | var img = new Image(); | ||
+ | img.src = wikiPath; | ||
+ | img.onload = function(){ iconImg.attr('srcset', wikiPath + " 1.5x"); } | ||
+ | img.onerror = function(){ iconImg.attr('srcset', fallbackPath); } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | if (skillDataContainer.hasClass('assimilated')) { | ||
+ | // Show checkbox for max analysis only for assimilated first skill, else hide (hidden by default) | ||
+ | var anamax = skillDataContainer.find('.maxanalysis'); | ||
+ | anamax.find('input').data('skilldata', data); | ||
+ | if (skillDataContainer.find('.tabButton-active').text() == 'Skill1') { | ||
+ | anamax.show(); | ||
+ | } else { | ||
+ | anamax.hide(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | var chosenLevelIdx = skillDataContainer.find('.skilllevel select').val(); | ||
+ | var formatted_text = calculateDescriptionText(data, chosenLevelIdx); | ||
+ | var description = skillDataContainer.find('.skilldesc'); | ||
+ | description.html(formatted_text); | ||
+ | |||
+ | var conditions = skillDataContainer.find('.skillconditions'); | ||
+ | if (data.hasOwnProperty('cost')) { | ||
+ | conditions.addClass('cost'); | ||
+ | } else { | ||
+ | conditions.removeClass('cost'); | ||
+ | } | ||
+ | if (data.hasOwnProperty('cooldown')) { | ||
+ | conditions.addClass('cooldown'); | ||
+ | } else { | ||
+ | conditions.removeClass('cooldown'); | ||
+ | } | ||
+ | |||
+ | var conditionText = calculateConditionText(data, chosenLevelIdx); | ||
+ | conditions.text(conditionText); | ||
} | } |
Latest revision as of 03:55, 25 February 2024
RLQ.push(['jquery', function () {
$(document).ready(function() {
var skillforms = $('.skillform');
if (skillforms.length > 0) {// Only 1 on normal pages
skillforms.each(function(idx, element) {
initButtons($(element).find('.tabButtonLane'), function(tabs) {
initSkillForm(element, tabs);
$(element).find('.tabButtonLane button').first().click();
});
});
}
});
}]);
function initButtons(buttonContainer, finishedHandler) {
var skillform = buttonContainer.closest('.skillform');
// Remove any existence of another button
buttonContainer.empty();
var skillCount = skillform.find('.skilldataraw').length;
for (var idx=1; idx<=skillCount; idx++) {
var idxNameAddOn = idx === 1 ? "" : ""+idx;
var skillDataRawElement = skillform.find('.skilldataraw[data-skilldata-content="skill' + idxNameAddOn + 'data"]');
var skillElement = skillDataRawElement.find('div');
if (skillElement.length === 1) {
var buttonData = convertSkillData(skillElement);
var button = $('<button></button>');
button.data('skilldata', buttonData);
var skillEditLinks = skillDataRawElement.find('.skilleditlinksraw');
if (skillEditLinks.length === 1) {
button.data('skilleditlinks', skillEditLinks.html());
}
//Special tab names in Template:PNCHero
if (skillform.hasClass('pnchero')){
switch(idx){
case 1:button.text('Passive'); break;
case 2:button.text('Auto'); break;
case 3:button.text('Ultimate'); break;
default:button.text('Skill' + idx);
}
}else{
button.text('Skill' + idx);
}
buttonContainer.append(button);
}
}
finishedHandler(buttonContainer.find('button'));
}
function initSkillForm(element, tabs) {
var skillform = $(element);
// selector is not possible in Wiki so we have to create it :/
var levelSelector = skillform.find('.skilllevel select');
if (levelSelector.length < 1) {
levelSelector = $('<select></select>');
levelSelector.addClass("gf-droplist");
skillform.find('.skilllevel').append(levelSelector);
}
//The skilldata object will be properly bound to .skilllevel>select during display_data()
levelSelector.on('change', function() { display_data(skillform, $(this).data('skilldata'), $(this).data('skilleditlinks')); });
if (skillform.hasClass('assimilated')) {
// Add checkbox for max analysis (visibility is controlled from display_data())
var anamax = $('<label><input type="checkbox"> Max Analysis</label>');
skillform.find('.maxanalysis').append(anamax);
//The skilldata object will be properly bound to .maxanalysis>input during display_data()
anamax.find('input').on('change', function() { display_data(skillform, $(this).data('skilldata'), $(this).data('skilleditlinks')); });
}
tabs.click(function(evt) {
skillformButtonHandler(evt.target);
});
}
function skillformButtonHandler(element) {
var currentButton = $(element);
var skillform = currentButton.closest('.skillform');
skillform.find('.tabButtonLane button').removeClass('tabButton-active');
currentButton.addClass('tabButton-active');
var convertedData = currentButton.data('skilldata');
var skillEditLinks = currentButton.data('skilleditlinks');
display_data(skillform, convertedData, skillEditLinks);
}
function convertSkillData(dataElement) {
skill_data = {};
var key;
dataElement.find('tbody tr').each(function(index, row) {
var key = $(row).find('th').text().trim();
var tds = $(row).find('td');
if (tds.length === 1) {
skill_data[key] = tds.first().html().trim();
} else {
var lines = tds.map(function(index, td) {
return $(td).text().trim();
});
skill_data[key] = lines;
}
});
return skill_data;
}
function calculateDescriptionText(data, chosenLevelIdx) {
var regex = /\(\$\w+\)/g;
var resultText = data.text;
if (!data.text || typeof data.text.match !== "function") {
//console.log("debug", data);
return resultText;
}
var vars = data.text.match(regex);
//No parameters defined
if(vars === null) {
return resultText;
}
var i; // For i not being global :)
if($('.maxanalysis input').is(':checked')) {
for (i = 0; i < vars.length; i++) {
var_name = vars[i].substring(2, vars[i].length - 1);// Trim beginning $( and trailing )
var_name_max = var_name + '_4';
if (typeof data[var_name_max] !== 'undefined'){// If defined, use max analysis data instead of base data
resultText = resultText.replace(vars[i], "<span class='skill-value'>" + data[var_name_max][chosenLevelIdx] + "</span>");
} else {
resultText = resultText.replace(vars[i], "<span class='skill-value'>" + data[var_name][chosenLevelIdx] + "</span>");
}
}
} else {
for (i = 0; i < vars.length; i++) {
var_name = vars[i].substring(2, vars[i].length - 1);// Trim beginning $( and trailing )
resultText = resultText.replace(vars[i], "<span class='skill-value'>" + data[var_name][chosenLevelIdx] + "</span>");
}
}
return resultText;
}
function calculateConditionText(data, chosenLevelIdx) {
/* Passive for skilldata without special properties. */
var result = "Passive";
/* Use support points for fairies by default, if this is an assimilated unit use action points instead */
var pointsToUse = $('.skillform').hasClass('assimilated') ? ' action' : ' support';
if (data.hasOwnProperty('skill_cost')) {
/* Fairys hav turn_cooldown and skill_cost. */
if (Array.isArray(data.skill_cost) || typeof data.skill_cost === 'object') {
result = data.skill_cost[chosenLevelIdx] + pointsToUse + ' point(s) per use';
} else {
result = data.skill_cost + pointsToUse + ' point(s) per use';
}
if (data.hasOwnProperty('turn_cooldown')) {
if (Array.isArray(data.turn_cooldown) || typeof data.turn_cooldown === 'object') {
result += ', ' + data.turn_cooldown[chosenLevelIdx] + ' turn cooldown';
} else {
result += ', ' + data.turn_cooldown + ' turn cooldown';
}
}
} else if (data.hasOwnProperty('cooldown')) {
/* cooldown and initial are used for T-Doll Skills. */
result = data.cooldown[chosenLevelIdx] + 's cooldown';
if (data.hasOwnProperty('initial')) {
result += ', ' + data.initial + 's initial cooldown';
}
} else if (data.hasOwnProperty('activation')) {
/* Skills/Buffs activated with a certain chance are defined by 'activation' */
result = data.activation[chosenLevelIdx] + '% chance to activate';
}
return result;
}
function display_data(skillDataContainer, data, skilleditlinks) {
if (data == null) {
console.log("Skill called without data", data);
return;
}
// Make sure skillcontainer is visible, as it is display:none by default
skillDataContainer.find('.skillcontent').show();
// Make sure Level Selector shows the fitting amount of levels
var idx = 0;
var skillLevels = 10;
var levelSelector = skillDataContainer.find('.skilllevel select');
if (data.hasOwnProperty('skilllevelcount')) {
try {
skillLevels = parseInt(data.skilllevelcount, 10);
} catch (e) {
console.log("Error parsing 'skilllevelcount'", e);
}
}
if (levelSelector.find('option').length != skillLevels) {
levelSelector.empty();
for (idx=0; idx<skillLevels; idx++) {
var opt = $('<option></option>');
opt.text('Lv. ' + (idx+1));
opt.attr('value', idx);
if (idx == skillLevels-1) opt.prop('selected', true);
levelSelector.append(opt);
}
}
// We have to remember skilldata for the levelSelector
levelSelector.data('skilldata', data);
var name = skillDataContainer.find('.skillname');
name.text(data.name);
if (skilleditlinks) {
var skilleditlinksDestination = skillDataContainer.find('.skilleditlinks');
skilleditlinksDestination.html(skilleditlinks);
}
var iconImg = skillDataContainer.find('.skillicon img');
var iconId = data.icon || "";
var iconFilename = "Icon_Skill_" + iconId + ".png";
if (iconImg.attr('alt') != iconFilename) {
iconImg.attr('alt', iconFilename);
var wikiPath = "/images/" + gfUtils.createWikiPathPart(iconFilename) + iconFilename;
var fallbackPath = "/images/thumb/5/5b/skill_backup.png/75px-skill_backup.png 1.5x, /images/5/5b/skill_backup.png 2x"
iconImg.attr('src', wikiPath);
if (iconId == '' || iconId == null) {
iconImg.attr('srcset', fallbackPath);
} else {
// Check if icon actually exists as a file
var img = new Image();
img.src = wikiPath;
img.onload = function(){ iconImg.attr('srcset', wikiPath + " 1.5x"); }
img.onerror = function(){ iconImg.attr('srcset', fallbackPath); }
}
}
if (skillDataContainer.hasClass('assimilated')) {
// Show checkbox for max analysis only for assimilated first skill, else hide (hidden by default)
var anamax = skillDataContainer.find('.maxanalysis');
anamax.find('input').data('skilldata', data);
if (skillDataContainer.find('.tabButton-active').text() == 'Skill1') {
anamax.show();
} else {
anamax.hide();
}
}
var chosenLevelIdx = skillDataContainer.find('.skilllevel select').val();
var formatted_text = calculateDescriptionText(data, chosenLevelIdx);
var description = skillDataContainer.find('.skilldesc');
description.html(formatted_text);
var conditions = skillDataContainer.find('.skillconditions');
if (data.hasOwnProperty('cost')) {
conditions.addClass('cost');
} else {
conditions.removeClass('cost');
}
if (data.hasOwnProperty('cooldown')) {
conditions.addClass('cooldown');
} else {
conditions.removeClass('cooldown');
}
var conditionText = calculateConditionText(data, chosenLevelIdx);
conditions.text(conditionText);
}