Difference between revisions of "MediaWiki:Mob Editor.js"

m
m
Line 187: Line 187:
 
     }
 
     }
 
     cleanerRE = new RegExp(`\\|\\s?${cleanerRE.join('|')}((?![\r\n]+\|)[\\W\\w](?!}}))+`, 'gm'); // http://stackoverflow.com/questions/43290667
 
     cleanerRE = new RegExp(`\\|\\s?${cleanerRE.join('|')}((?![\r\n]+\|)[\\W\\w](?!}}))+`, 'gm'); // http://stackoverflow.com/questions/43290667
 +
console.log(cleanerRE)
 
     stratics.wiki.markup = stratics.wiki.markup.replace(/\n\s*\|/g, '\n|');
 
     stratics.wiki.markup = stratics.wiki.markup.replace(/\n\s*\|/g, '\n|');
 
     stratics.wiki.markup = stratics.wiki.markup.replace(cleanerRE, '');
 
     stratics.wiki.markup = stratics.wiki.markup.replace(cleanerRE, '');

Revision as of 02:38, 9 April 2017

/* globals stratics, mw, $, jQuery */
"use strict";

let i,
    elementCounter = 0,
    tabcounter = 20;
const br = '<br>',
    input = 'input',
    label = 'label',
    legend = 'legend',
    loc = location.href.split('#')[0].toString(),
    makehtml = stratics.f.util.makehtml,
    nbsp = '&nbsp;',
    number = 'number',
    span = 'span',
    logs = [],
    tabs = {},
    fields = {},
    boolFields = [
        ['Autodispel', 'autoDispel'],
        ['Bardable', 'bardable'],
        ['Paragon', 'disableParagon'],
        ['Polymorphable', 'polymorphable'],
        ['Spawning', 'spawning'],
        ['Statue', 'statue'],
        ['Subdue', 'subdueRequired'],
        ['Summonable', 'summonable'],
        ['Tameable', 'tameable']
    ],
    textFields = [
        ['','abilities'], // Deprecated parameter; this removes it from the markup
        ['abilities', 'specialAttack'],
        ['added', 'firstSeen'],
        ['alignment', 'alignment'],
        ['bardNotes', 'bardingNotes'],
        ['carved', 'loot_carved'],
        ['combatNotes', 'combatStrategy'],
        ['commonItems', 'loot_base'],
        ['fame', 'fame'],
        ['generalInfo', 'body_text'],
        ['gold', 'loot_gold'],
        ['harvester', 'loot_harvester'],
        ['karma', 'karma'],
        ['loyalty', 'loyaltyPoints'],
        ['magicLevel', 'magicLevel'],
        ['minMount', 'mountskill'],
        ['minTame', 'taming'],
        ['name','name'],
        ['poisonLevel', 'poisonLevel'],
        ['polyItem', 'polymorphPage'],
        ['quest', 'questPage'],
        ['ranged', 'rangedAttack'],
        ['slayer', 'slayer'],
        ['spawn', 'found'],
        ['specialItems', 'loot_special'],
        ['speed', 'speed'],
        ['statue', 'statuePage'],
        ['stealing', 'loot_stealing'],
        ['summonItem', 'summonPage'],
        ['tameNotes', 'taming_notes'],
        ['trivia', 'trivia_text']
    ];

/* Script-specific localization */
const lstrings = [];

const l = (str, id) => {
    lstrings.push([id, str]);
    let translatedStr = stratics.f.util.l(str);
    if (undefined !== translatedStr) {
        return translatedStr;
    } else {
        stratics.f.util.log(3, `New string: ${str}`);
        return str;
    }
};

const tabsUpdate = () => {
    $('#tabControlAL2 li').each(function() {
        let a = $(this).find('a');
        a.text(stratics.f.util.l(a.data('value')));
    });
};

const lupdate = () => {
    for (let x of lstrings) {
        let $ele = $(`#${x[0]}`);
        if ($ele.is('input[type=button]')) {
            $ele.prop('value', stratics.f.util.l(x[1]));
        } else if ($ele.is('input[type=text]')) {
            $ele.prop('placeholder', stratics.f.util.l(x[1]));
        } else {
            $ele.text(stratics.f.util.l(x[1]));
        }
    }
    tabsUpdate();
    if ($('#editToolMenuLangSelect').val() !== stratics.f.util.getLang) {
        $('#editToolMenuLangSelect').val(stratics.f.util.getLang);
    }
};

/* Logs a message to the debug console. */
/* 3 for status, 4 for text dump. */
stratics.f.util.log = (i, msg) => {
    const $console = $('#debugConsole' + i);
    if (i === 3) {
        logs.push(msg);
    }
    if ($('#debugConsole3').length > 0) {
        for (let logmsg of logs) {
            $console.html(i === 4 ? logmsg : `${$console.html()}${stratics.f.util.getTime()}: ${logmsg}${br}`);
        }
        logs.length = 0;
    }
};
stratics.f.util.log(3, 'Starting script.');

/* Returns the maximum value from an array. */
stratics.f.util.getMax = (arr) => Math.max(...arr);

/* Returns the minimum value from an array, ignoring null values. */
stratics.f.util.getMin = (arr) => Math.min(...arr);

/* Event handler for markup AJAX request */
$('body').on('markupArrived', () => {
    const log = stratics.f.util.log,
        makeBoolean = a => /[1yot]/i.test(`${a}`[0]) ? true : a.length > 0 && /[0nf]/i.test(`${a}`[0]) ? false : 'unknown',
        getVal = (str) => {
            try {
                let x = new RegExp(`\\|\\s?${str}((?![\r\n]+\\|)[\\W\\w])+`, 'gm');
                stratics.data[str] = stratics.wiki.markup.match(x)[0].split(/=\s/)[1].trim();
            } catch (e) { // requested parameter does not exist in the markup, or does not have a value in the markup
                if (str === 'name') {
                    stratics.data[str] = loc.split(':')[2].split('(')[0]; // Get the name from the URL
                } else if (str === 'alignment' || str === 'speed') {
                    stratics.data[str] = 'unknown';
                } else {
                    stratics.data[str] = '';
                }
            }
            return stratics.data[str];
        },
        getNum = (str) => {
            switch (str) {
                case 'none'     : return 0;
                case 'lesser'   : return 1;
                case 'standard' : return 2;
                case 'greater'  : return 3;
                case 'deadly'   : return 4;
                case 'lethal'   : return 5;
                default         : return str;
            }
        };

    log(3, 'Markup has been received.');
    log(4, stratics.wiki.markup);
    stratics.wiki.markup = stratics.wiki.markup.replace(/<!--.+-->\n/g, '');

    log(3, 'Storing old info from markup.');
    for (let x of textFields) {
        if (x[0] === 'magicLevel' || x[0] === 'poisonLevel') {
            $(`#${fields[x[0]]}`).val(getNum(getVal(x[1])));
        } else {
            $(`#${fields[x[0]]}`).val(getVal(x[1]));
        }
    }
    for (let x of boolFields) {
        stratics.data[x[1]] = makeBoolean(getVal(x[1]));
        if (stratics.data[x[1]] === true) {
            $(`#editToolMenu${x[0]}`).val(true);
        } else if (stratics.data[x[1]] === 'unknown') {
            $(`#editToolMenu${x[0]}`)[0].indeterminate = true;
        }
    }
    log(3, 'Old info has been stored.');

    log(3, 'Selecting the selectables.');
    for (let x of ['alignment','speed']) {
        $(`#${fields[x]}`).find(`[value="${stratics.data[x]}"]`).addClass("ui-selecting");
        $(`#${fields[x]}`).selectable('refresh').data("selectable")._mouseStop(null);
    }

    log(3, 'Clearing old info from markup.');
    let cleanerRE = [];
    for (var x of [...textFields,...boolFields]) {
        cleanerRE.push(x[1]);
    }
    cleanerRE = new RegExp(`\\|\\s?${cleanerRE.join('|')}((?![\r\n]+\|)[\\W\\w](?!}}))+`, 'gm'); // http://stackoverflow.com/questions/43290667
console.log(cleanerRE)
    stratics.wiki.markup = stratics.wiki.markup.replace(/\n\s*\|/g, '\n|');
    stratics.wiki.markup = stratics.wiki.markup.replace(cleanerRE, '');
    log(3, 'Markup has been cleaned.');

    log(4, stratics.wiki.markup);
    $('body').trigger('markupReady');
});

/* Event handler for when form is ready to be submitted. */
$('body').on('markupReady', function() {
    $('#editToolMenuSubmit').button('enable');
});

/* Event handler for when form is submitted. */
$('body').on('formSubmit', () => {
    let data = [],
        thisData,
        foods = [],
        instincts = [];
    const log = stratics.f.util.log;

    log(3, 'Retriving stored data from the markup.');
    stratics.wiki.markup = stratics.wiki.markup.replace(/-->(?!-->)(?:\n<!--storedLores = (.+)-->[\w\W]+)/gm, (match, storedLores) => {
        data = JSON.parse(storedLores);
        return '-->\n';
    });
    log(4, stratics.wiki.markup);

    log(3, 'Collecting data for new record.');
    thisData = data[data.length] = [];
    for (let j = 0; j <= 44; j++) {
        thisData.push(parseInt($('#number' + j).val()));
        if (isNaN(thisData[j])) {
            thisData[j] = null; // Empty string would convert the field to a string; we specifically want it to stay an int.
        }
    }
    $('#ul45 .ui-selected').each(function() {
        foods.push($(this).prop('value'));
    });
    $('#ul46 .ui-selected').each(function() {
        instincts.push($(this).prop('value'));
    });
    thisData.push(foods, instincts);

    log(3, 'Re-adding new+stored data to the markup.');
    stratics.wiki.markup += '<!-- Everything below this point is generated from Animal Lore readings.  Do not edit.  -->\n<!--storedLores = ' + JSON.stringify(data) + '-->\n';
    log(4, stratics.wiki.markup);
    stratics.data.lores = data;

    log(3, 'Forming new parameter values.');
    let fields = '',
        fieldnum = 0;

    const flatten = list => list.reduce(
            (a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), []
        ),
        getCurrData = (i = fieldnum) => {
            return [...new Set(flatten(data.map(curr => curr[i])).filter(n => n !== undefined))];
        },
        buildMinMax = (names) => {
            const checkNan = (arg) => arg = isNaN(arg) ? '' : arg;
            for (var name of names) {
                let min = checkNan(stratics.f.util.getMin(getCurrData())),
                    max = checkNan(stratics.f.util.getMax(getCurrData(fieldnum++)));
                if (min === Infinity) min = '';
                if (max === -Infinity) max = '';
                fields += `|min_${name} = ${min}\n|max_${name} = ${max}\n`;
            }
        },
        buildParam = (name, j = fieldnum++) => {
            let info = getCurrData(j);
            if (info.length === 0) {
                log(3, `Field ${name} has no useable data stored.`);
            }
            fields += `|${name} = ${0 < info.length ? info.pop() : ''}\n`;
        };

    buildMinMax(['hits', 'stam', 'mana', 'str', 'dex', 'int']); // Data array values 0-5
    buildParam('bardingDifficulty'); // Data array value 6 
    buildMinMax(['hpr', 'stamRegen', 'manaRegen']); // Data array values 7-9
    buildMinMax(['resistPhysical', 'resistFire', 'resistCold', 'resistPoison', 'resistEnergy']); // Data array values 10-14
    buildParam('damagePhysical'); // Data array value 15 
    buildParam('damageFire'); // Data array value 16 
    buildParam('damageCold'); // Data array value 17 
    buildParam('damagePoison'); // Data array value 18 
    buildParam('damageEnergy'); // Data array value 19 
    let baseD1 = getCurrData(fieldnum++),
        baseD2 = getCurrData(fieldnum++);
    fields += `|baseDamage = ${baseD1.pop()}-${baseD2.pop()}\n`; // Data array values 20-21
    buildMinMax(['wrestling', 'tactics', 'resist', 'anatomy', 'healing', 'poison', 'detectingHidden', 'hiding', 'parrying']); // Data array values 22-30
    buildMinMax(['magery', 'eval', 'med', 'necro', 'spiritSpeak', 'mysticism', 'focus', 'spellweaving', 'discordance']); // Data array values 31-39
    buildMinMax(['bushido', 'ninjitsu', 'chivalry']); // Data array values 40-42
    let foodlist = getCurrData(45); // Data array value 45 = Foods
    log(3, 'Foods array:' + JSON.stringify(foodlist));
    fields += `|eats_BlackrockStew = ${-1 !== foodlist.indexOf('Blackrock Stew') ? 'Yes' : 'No'}\n`;
    for (var food of ['Crops', 'Eggs', 'Fish', 'Fruit & Vegetables', 'Gold', 'Grain', 'Hay', 'Leather', 'Meat', 'Metal']) {
        fields += `|eats_${food === 'Fruit & Vegetables' ? 'FruitVeg' : food} = ${-1 !== foodlist.indexOf(food) ? 'Yes' : 'No'}\n`;
    }
    buildParam('packInstinct', 46); // Data array value 46 = Pack Instincts
    buildParam('controlslots'); // Data array value 43 = Pet Slots min
    buildParam('maxcontrolslots'); // Data array value 44 = Pet Slots max

    fields += `|readings = ${data.length}\n}}`;

    stratics.wiki.markup = stratics.wiki.markup + fields;
    log(3, 'New parameter values have been formed and stored.');
    log(4, stratics.wiki.markup);

    log(3, 'Submitting changed markup.');
    stratics.f.wiki.submitMarkup('Adding a new Animal Lore reading.', stratics.wiki.markup);
});

/* Handle a successful markup submission. */
$('body').on('submitMarkupSuccess', () => {
    $('#editToolMenuNotification').text('Saved. Reloading the page...');
    //        stratics.f.util.reloadPage();
});

/* Handle a failed markup submission. */
$('body').on('submitMarkupFailure', () => {
    $('#editToolMenuNotification').text('An error has occurred submitting the data. Please try again.');
});

/* Creates an arbitrary element */
const makeElem = (elem, num, args, label, after) => {
    if (typeof args.id === 'undefined') { // Allow for defined element ids
        if (typeof args.type === 'undefined') {
            args.id = elem + num;
        } else {
            args.id = args.type + num;
        }
    }
    if (typeof label === 'undefined') {
        return makehtml(elem, args);
    } else {
        if (typeof after === 'undefined') {
            return makehtml('label', {}, label + nbsp + makehtml(elem, args));
        } else {
            return makehtml('label', {}, makehtml(elem, args) + nbsp + label);
        }
    }
};

/* Creates an arbitrary element */
const makeFieldset = (id, name) => $('<fieldset>', {
        id: 'fieldset' + id
    })
    .append(makehtml(legend, {
        style: 'color:#FFF;font-weight:bolder;padding-bottom: 1em;',
        id: `fieldsetLegend${id}`
    }, name));

/* Creates a dl element */
const makeDL = (str) => makehtml('dl', {
    id: `dl${elementCounter}`,
    style: "margin-bottom: 1em"
}, str);

/* Creates a dt element */
const makeDT = (str) => makehtml('dt', {
    id: `dt${elementCounter}`,
    style: "font-weight: 700;margin-left: 2em;color: goldenrod"
}, str);

/* Creates a dd element */
const makeDD = (str) => makehtml('dd', {
    id: `dd${elementCounter}`,
    style: "margin-left: 4em"
}, str);

/* Creates a span element */
const makeSpan = (str) => makehtml(span, {
    id: `span${elementCounter}`
}, str);

/* Creates an input[type=number] element */
const makeNumber = (j, val) => makeElem(input, j, {
    type: number,
    min: 0,
    step: 1,
    style: 'width: 9em;',
    value: val
});

/* Create popup dialog, tab structure, and data fieldsets */
const $editToolMenu = $(makehtml('div', {
        id: 'editToolMenu'
    })),
    $tabsInfo = $('<div>', {
        id: 'tabs2'
    }),
    $tabsList = $('<ul id="tabControlAL2">'),
    makeTab = (i, name) => {
        const $div1 = $('<div style="float:left;width: 100%;" id="container' + i + '">').append(makeFieldset(i, l(name, `fieldsetLegend${i}`))),
            $div2 = $('<div style="float:right;display: flex;">');
        $(`<div id="ALMenu${i}">`).append([$div1, $div2])
            .appendTo($editToolMenu);
        $(makehtml('li', {}, makehtml('a', {
            href: `${loc}#ALMenu${i}`,
            id: `tab${i}`
        }, name))).appendTo($tabsList);
    };

$editToolMenu.append([
    '<div id="editToolMenuLanguageBox" style="position: absolute; bottom: 2px; left: 1em;">',
    '<div id="editToolMenuButtons" style="position: absolute; bottom: 2px; right: 1em;">'
]);

for (let x of ['basicStats', 'skills', 'trivia', 'loot', 'combat', 'credits', 'debug', 'tamer', 'bard']) {
    tabs[x] = tabcounter++;
}

makeTab(tabs.basicStats, 'Basic Stats');
makeTab(tabs.skills, 'Skills');
makeTab(tabs.trivia, 'Trivia');
makeTab(tabs.loot, 'Loot');
makeTab(tabs.combat, 'Combat');
makeTab(tabs.debug, 'Debug');
makeTab(tabs.credits, 'Credits');

$editToolMenu.appendTo('body').prepend($tabsInfo.append($tabsList));

$(`#fieldset${tabs.skills}`).append([
    makeFieldset(tabs.tamer, l('Tamer', `fieldsetLegend${tabs.tamer}`)),
    makeFieldset(tabs.bard, l('Bard', `fieldsetLegend${tabs.bard}`))
]);

const addNumberInput = (field, name, skipBreak) => {
        let $div = $('<div style="display: block;margin-top: 4px;">'),
            num = elementCounter;
        $(`#fieldset${field}`).append($div.append([
            $(makeNumber(num, "")).prop("name", name + 1),
            stratics.f.util.makehtml(label, {
                id: `label${elementCounter}`,
                for: `number${num}`,
                style: "padding-left:0.5em;"
            }, l(name, `label${elementCounter++}`)),
            skipBreak ? '' : br
        ]));
        return `number${num}`;
    },
    addNumberInputs = (i, arr) => {
        for (var item of arr) {
            addNumberInput(i, item);
        }
    },
    addRangeInput = (field, name) => {
        $(`#fieldset${field}`).append([
            $(makeNumber(elementCounter++, "")).prop("name", name + 2),
            " - ",
        ]);
        addNumberInput(field, name);
    },
    addButtonInput = (field, name, text, disabled) => {
        $(`#${field}`).append($(makehtml(input, {
                type: 'button',
                value: text,
                id: `editToolMenu${name}2`,
            })).text(l(text, `editToolMenu${name}2`))
            .button()
            .button(disabled ? 'disable' : 'enable'));
    },
    addBreak = (field) => {
        $(`#fieldset${field}`).append(br);
    },
    addCheckboxInput = (field, name, text, checked) => {
        let $div = $('<div style="display: flex;margin-top: 4px;">');
        let checkbox = $(makehtml(input, {
            type: 'checkbox',
            id: `editToolMenu${name}`
        }));
        if (checked) {
            checkbox.prop('checked', true);
        }
        $(`#fieldset${field}`).append($div.append([checkbox,
            makehtml(label, {
                style: 'color:#FFF; padding-left: 0.4em; padding-right: 1em;',
                for: `editToolMenu${name}`,
                id: `inputLabel${elementCounter}`
            }, l(text, `inputLabel${elementCounter++}`)),
        ]));
    },
    addTextInput = (field, text, placeholder = '') => {
        let id = `editToolMenu${elementCounter}`;
        let $div = $('<div style="display: flex; margin-top: 3px; margin-bottom: 1.4em;">').append([
            makehtml(label, {
                for: id,
                id: `inputLabel${elementCounter}`,
                style: 'flex: 0 1 auto; color:#FFF; padding-top: 5px;'
            }, l(text, `inputLabel${elementCounter}`)),
            makehtml(input, {
                id: id,
                placeholder: l(placeholder, `editToolMenu${elementCounter++}`),
                style: 'flex: 1 1 auto; margin-left:0.5em; min-height: 28px;',
                type: 'text'
            })
        ]);
        $(`#fieldset${field}`).append($div);
        return id;
    },
    addTextareaInput = (field, text, height = 8) => {
        let id = `editToolMenu${elementCounter}`;
        let $div = $('<div style="display: flex; margin-top: 3px; margin-bottom: 1.4em;">').append([
            makehtml(label, {
                for: id,
                id: `textareaLabel${elementCounter}`,
                style: 'flex: 0 1 auto; color:#FFF; padding-top: 5px;'
            }, l(text, `textareaLabel${elementCounter++}`)),
            makehtml('textarea', {
                id: id,
                style: `flex: 1 1 auto; margin-left:0.5em; min-height: 28px;height:${height}em;`
            })
        ]);
        $(`#fieldset${field}`).append($div);
        return id;
    },
    addSelect = (field, name, options) => {
        let id = `editToolMenu${elementCounter}`;
        const liArr = [],
            $ul = $(`<ul class="selectable" id="${id}">`);
        for (i = 0; options.length > i; i++) {
            liArr.push(`<li id="option${elementCounter}" style="cursor:pointer;" value="${options[i]}">${l(options[i], `select${elementCounter++}`)}</li>`);
        }
        $ul.append(liArr);
        $(`#fieldset${field}`).append($ul);
        $ul.selectable();
        return id;
    };

/* Populate tabs */
fields.name = addTextInput(tabs.basicStats, 'What is the name of this mob?');
$(`#fieldset${tabs.basicStats}`).append(makehtml(label, {
    style: 'color:#FFF;padding-left: 0.4em;padding-right: 1em;',
    id: `inputLabel${elementCounter}`
}, l('Alignment:', `inputLabel${elementCounter}`), `inputLabel${elementCounter++}`));
fields.alignment = addSelect(tabs.basicStats, 'alignment', ['Good (blue)', 'Neutral (grey)', 'Evil (red)', 'unknown']);
$(`#fieldset${tabs.basicStats}`).append([br, br]);
fields.magicLevel = addNumberInput(tabs.basicStats, 'Magic Level');
fields.poisonLevel = addNumberInput(tabs.basicStats, 'Poison Level', true);
$(`#${fields.poisonLevel}`).parent().append('<span> (</span>', makeSpan(l('0 = none, 1 = lesser, 2 = standard, 3 = greater, 4 = deadly, 5 = lethal', `span${++elementCounter}`)), '<span>)</span>');
fields.loyalty = addNumberInput(tabs.basicStats, 'Loyalty Points');
fields.fame = addNumberInput(tabs.basicStats, 'Fame');
fields.karma = addNumberInput(tabs.basicStats, 'Karma');
fields.generalInfo = addTextareaInput(tabs.basicStats, 'Write any text with general info for this mob.', 15);

addCheckboxInput(tabs.tamer, 'Tameable', 'Check this box if this mob can be tamed.');
addCheckboxInput(tabs.tamer, 'Subdue', 'Check this box if this mob must be subdued before it can be tamed.');
fields.minTame = addNumberInput(tabs.tamer, 'Minimum required taming skill to tame this mob');
fields.minMount = addNumberInput(tabs.tamer, 'Minimum required taming skill to mount this mob, if it can be mounted.');
fields.tameNotes = addTextareaInput(tabs.tamer, 'Write any text with notes about taming this mob.', 9);

addCheckboxInput(tabs.bard, 'Bardable', 'Check this box if this mob can be barded.');
fields.bardNotes = addTextareaInput(tabs.bard, 'Write any text with notes about barding this mob.', 9);

fields.added = addTextInput(tabs.trivia, 'When was this mob added to the game?', 'YYYY-MM-DD: Patch #/Publish #/Release');
addCheckboxInput(tabs.trivia, 'Spawning', 'Check this box if this mob is currently spawning.');
addCheckboxInput(tabs.trivia, 'Paragon', 'Check this box if there is no way for this mob to spawn as a paragon.');
fields.spawn = addTextInput(tabs.trivia, 'Where does it spawn?');
addCheckboxInput(tabs.trivia, 'Summonable', 'Check this box if this mob can be summoned in any way. This includes ethereal statues, spells, talismans, etc.');
fields.summonItem = addTextInput(tabs.trivia, 'What item or spell is used?');
addCheckboxInput(tabs.trivia, 'Polymorphable', 'Check this box if a player can take on the appearance of this mob. This includes polymorph spells, costumes, or any other means.');
fields.polyItem = addTextInput(tabs.trivia, 'What item or spell is used?');
addCheckboxInput(tabs.trivia, 'Statue', 'Check this box if a statue of this mob exists. This includes ethereals, veteran rewards, etc. (Do not include rare items.)');
fields.statue = addTextInput(tabs.trivia, 'What item(s)?');
fields.quest = addTextInput(tabs.trivia, 'If this mob only appears during a quest, what is the name of that quest?');
fields.trivia = addTextareaInput(tabs.trivia, 'Write any random trivia for this mob.');

fields.gold = addTextInput(tabs.loot, 'Roughly how much gold does this mob drop?', 'example: 100 - 200');
fields.commonItems = addTextInput(tabs.loot, 'What common items does this mob drop?', 'example: magery reagents, robe, magery scroll');
fields.specialItems = addTextInput(tabs.loot, 'What special items does this mob have a chance to drop?', 'example: daemon bone armor');
fields.carved = addTextInput(tabs.loot, 'What items, and how many of each, are given when carved (by a human)?', 'example: 10 ribs, 20 horned hides, 8 dragon blood, 3 fur');
fields.harvester = addTextInput(tabs.loot, 'Same question as above, but when using a harvester\'s blade?', 'example: 20 ribs, 30 horned hides, 10 dragon blood, 4 fur');
fields.stealing = addTextInput(tabs.loot, 'What items can be obtained when stealing from this mob?', 'example: none');

$(`#fieldset${tabs.combat}`).append(makehtml(label, {
    style: 'color:#FFF;padding-left: 0.4em;padding-right: 1em;',
    id: `inputLabel${elementCounter}`
}, l('Speed:', `inputLabel${elementCounter}`), `inputLabel${elementCounter++}`));
fields.speed = addSelect(tabs.combat, 'speed', ['Slow', 'Medium', 'Fast', 'Paragon', 'unknown']);
addBreak(tabs.combat);
addBreak(tabs.combat);
fields.abilities = addTextInput(tabs.combat, 'What special abilities does this mob have?');
fields.ranged = addTextInput(tabs.combat, 'If this mob can use ranged attacks, what types of attacks?', 'example: Arrows, Fireball, Energy Bolt');
addCheckboxInput(tabs.combat, 'Autodispel', 'Check this box if this mob can auto-dispel summoned creatures.');
fields.slayer = addTextInput(tabs.combat, 'What slayers is this mob vulnerable to?');
fields.combatNotes = addTextareaInput(tabs.combat, 'Write any text with advice for fighting this mob.', 15);

$(`#editToolMenu`).append(makehtml('div', {
    id: `div${elementCounter}`,
    style: 'position:absolute; bottom: 6em;'
}, l('For all questions, separate multiple items with commas. Please use only English item or spell names.', `div${elementCounter++}`)));

$(`#fieldset${tabs.debug}`).append('<div id="debugConsole3"></div><br/><textarea style="width:825px;height:300px;" wrap="off" id="debugConsole4"></textarea>');

$(`#tab${tabs.debug}`).parent().hide(); // Debug tab

/* Populate Credits tab */
let translations = [];
for (let k of stratics.f.util.getLangList()) {
    if (k[0] != 'en') {
        translations.push(makeDL([
            makeDT(makeSpan(l('Translation', `span${++elementCounter}`)) + makeSpan(` (${stratics.i18n[k[0]]["{language name}"]})`)),
            makeDD(stratics.i18n[k[0]]["{translators}"])
        ].join('')));
    }
}
$(`#fieldset${tabs.credits}`).append(makeDL([
    makeDT(l('Programming', `dt${++elementCounter}`)),
    makeDD('BrianFreud')
].join('')) + translations.join(''));

/* Create button controls */
$('#editToolMenuButtons').append('<span id="editToolMenuNotification">');
addButtonInput('editToolMenuButtons', 'Edit', 'Edit the raw wiki markup', false);
addButtonInput('editToolMenuButtons', 'Submit', 'Submit', true);
addButtonInput('editToolMenuButtons', 'Cancel', 'Cancel', false);

/* Create language selector */
$('#editToolMenuLanguageBox').append('<select id="editToolMenuLangSelect" style="float: right;margin-bottom: 1em;border-radius: 10px;">');
let $options = [];
for (let k of stratics.f.util.getLangList()) {
    let selected = (k[0] == stratics.i18n.current) ? 'selected' : '';
    $options.push(`<option value="${k[0]}" ${selected}>${k[1]}</option>`);
}
$('#editToolMenuLangSelect').append($options).selectmenu({
    style: 'dropdown'
});

/* Handle a changed language selection */
$('#editToolMenuLangSelect').on('change', function() {
    stratics.f.util.setLang($(this).val());
});

/* Handle notification of a changed language selection */
$('body').on('languageChanged', () => {
    lupdate();
});

/* Handle a click on the raw mode edit button. */
$('#editToolMenuEdit2').click(function() {
    window.location.search = `${window.location.search}&action=edit`;
});

/* Handle a click on the cancel button. */
$('#editToolMenuCancel2').click(function() {
    $editToolMenu.dialog('close');
});

/* Handle a click on the submit button. */
$('#editToolMenuSubmit2').click(function() {
    $('#editToolMenuNotification').text('Thanks! Saving...');
    $('body').trigger('formSubmit');
});

/* Allow the debug menu to be seen. */
$(document).bind('keydown', function(event) {
    if (event.which === 68 && event.altKey) {
        $(`#tab${tabs.debug}`).parent().toggle();
    }
});

/* Start fetching the page's markup. ASYNCH */
stratics.f.wiki.getMarkup();

/* Initialize popup dialog */
stratics.f.util.log(3, 'Initializing dialog.');
$editToolMenu.tabs()
    .dialog({
        title: l('Mob Editor', 'ui-id-1'),
        autoOpen: false,
        position: {
            my: 'center',
            at: 'center-125',
            of: window
        },
        modal: true,
        width: 1000,
        height: 800,
        close: function() {
            $('#PropBox')
                .dialog('close');
        },
        open: function() {
            if ($('#PropBox')
                .length > 0 && !$('#PropBox')
                .dialog("isOpen")) {
                $('#PropBox')
                    .dialog('open');
            }
        }
    });

/* Create Trigger link. */
stratics.f.util.log(3, 'Creating trigger link.');
$('a[title="Edit this page [alt-shift-e]"]').click(e => {
    e.preventDefault();
    $('#editToolMenu').dialog('open');
});

/* Store tabs' text */
$('#tabControlAL2 li').each(function() {
    let a = $(this).find('a');
    a.data('value', a.text());
});
$('body').trigger('languageChanged');