Difference between revisions of "MediaWiki:PropertyEditor.js"

(Created page with "(function () { →‎globals console, propertyInfo, makehtml: "use strict"; var br = '<br>', div = 'div', input = 'input', legend = 'legend...")
 
m
 
(48 intermediate revisions by the same user not shown)
Line 1: Line 1:
(function () {
+
/* globals console, propertyInfo, stratics, $ */
    /* globals console, propertyInfo, makehtml */
+
/* jshint esversion: 6 */
 +
var loadEditor = function () {
 
     "use strict";
 
     "use strict";
  
Line 32: Line 33:
  
 
     /* Reads in info from the JSON object, populates a select with options */
 
     /* Reads in info from the JSON object, populates a select with options */
     var populateSelect = function ($select, arr) {
+
     var populateSelect = function ($select, arr, allOption = false) {
             var options = [makehtml('option', {
+
             var options = [stratics.f.util.makehtml('option', {
 
                 value: "none"
 
                 value: "none"
 
             })];
 
             })];
 
             $select.empty();
 
             $select.empty();
 +
            if (allOption) {
 +
            options.push(stratics.f.util.makehtml('option', {
 +
                value: "all"
 +
            }, 'All Properties'));           
 +
            }
 
             for (i = 0; i < arr.length; i++) {
 
             for (i = 0; i < arr.length; i++) {
                 options.push(makehtml('option', {
+
                 options.push(stratics.f.util.makehtml('option', {
 
                     value: i
 
                     value: i
 
                 }, arr[i].name));
 
                 }, arr[i].name));
Line 61: Line 67:
 
             }
 
             }
 
             if (typeof label === 'undefined') {
 
             if (typeof label === 'undefined') {
                 return makehtml(elem, args);
+
                 return stratics.f.util.makehtml(elem, args);
 
             } else {
 
             } else {
 
                 if (typeof after === 'undefined') {
 
                 if (typeof after === 'undefined') {
                     return makehtml('label', {}, label + nbsp + makehtml(elem, args));
+
                     return stratics.f.util.makehtml('label', {}, label + nbsp + stratics.f.util.makehtml(elem, args));
 
                 } else {
 
                 } else {
                     return makehtml('label', {}, makehtml(elem, args) + nbsp + label);
+
                     return stratics.f.util.makehtml('label', {}, stratics.f.util.makehtml(elem, args) + nbsp + label);
 
                 }
 
                 }
 
             }
 
             }
Line 75: Line 81:
 
                     id: 'fieldset' + id
 
                     id: 'fieldset' + id
 
                 })
 
                 })
                 .append(makehtml(legend, {
+
                 .append(stratics.f.util.makehtml(legend, {
 
                     style: 'color:#FFF;font-weight:bolder;'
 
                     style: 'color:#FFF;font-weight:bolder;'
 
                 }, name))
 
                 }, name))
Line 105: Line 111:
 
                 /* Set the pattern based on which template is being used. */
 
                 /* Set the pattern based on which template is being used. */
 
                 if (itemType === 'rare') {
 
                 if (itemType === 'rare') {
                     pattern = /{{RareItem([\s\S]*)}}/m;
+
                     pattern = /{{RareItem([\s\S]*)^}}/m;
 
                 } else if (itemType === 'common') {
 
                 } else if (itemType === 'common') {
                     pattern = /{{InfoBox[\s|_]UOItem([\s\S]*)}}/m;
+
                     pattern = /{{InfoBox[\s|_]UOItem([\s\S]*)^}}/m;
 
                 }
 
                 }
  
Line 132: Line 138:
 
                     paramLookup.push(paramPairs[i][0]);
 
                     paramLookup.push(paramPairs[i][0]);
 
                 }
 
                 }
                $mwtextarea.data('params', {
 
                    pairs: paramPairs,
 
                    lookup: paramLookup
 
                });
 
 
             }
 
             }
 +
            $mwtextarea.data('params', {
 +
                pairs: paramPairs,
 +
                lookup: paramLookup
 +
            });
 
         },
 
         },
 
         /* Get the index, if any, of a parameter in the parameter store */
 
         /* Get the index, if any, of a parameter in the parameter store */
Line 176: Line 182:
 
             }
 
             }
 
             if (typeof args.descriptor === 'undefined') {
 
             if (typeof args.descriptor === 'undefined') {
                return $(makeElem(input, counter++, $.extend(args, {
+
              return $('<span>' + makeElem(input, counter++, $.extend(args, {
 
                         type: 'text',
 
                         type: 'text',
 
                         value: val,
 
                         value: val,
 
                         style: 'width:' + width + '%;margin-left:1%;'
 
                         style: 'width:' + width + '%;margin-left:1%;'
                     })))
+
                     })) + '</span>')
 
                     .data('param', param);
 
                     .data('param', param);
 
             } else {
 
             } else {
Line 195: Line 201:
 
         /* Create a box to display a single property */
 
         /* Create a box to display a single property */
 
         makeNewPropertyBox = function (propNum) {
 
         makeNewPropertyBox = function (propNum) {
             return $(makehtml(div, {
+
             return $(stratics.f.util.makehtml(div, {
 
                 'data-propnum': propNum,
 
                 'data-propnum': propNum,
 
                 'class': 'ui-corner-all ui-widget-content',
 
                 'class': 'ui-corner-all ui-widget-content',
Line 203: Line 209:
 
         /* Fill a property box with a property's text */
 
         /* Fill a property box with a property's text */
 
         fillPropertyBox = function ($prop, arr) {
 
         fillPropertyBox = function ($prop, arr) {
             return $prop.append(makehtml(span, {}, arr.join(': ')));
+
             return $prop.append(stratics.f.util.makehtml(span, {}, arr.join(': ')));
 
         },
 
         },
 
         /* Add a button to remove a property */
 
         /* Add a button to remove a property */
 
         addRemovePropertyButton = function ($prop, arr) {
 
         addRemovePropertyButton = function ($prop, arr) {
             return $prop.append($(makehtml(input, {
+
             return $prop.append($(stratics.f.util.makehtml(input, {
 
                     'class': 'removePropButton',
 
                     'class': 'removePropButton',
 
                     style: 'color:brown;font-weight:900;padding:0 .2em;float:right;margin:-2px -3px;',
 
                     style: 'color:brown;font-weight:900;padding:0 .2em;float:right;margin:-2px -3px;',
Line 275: Line 281:
 
             $('#DisambigInfo')
 
             $('#DisambigInfo')
 
                 .append([
 
                 .append([
                     makehtml(span, {}, 'Often, multiple things in UO share the same name. To allow them to each have their own page, we use disambiguation pages.'), br, br,
+
                     stratics.f.util.makehtml(span, {}, 'Often, multiple things in UO share the same name. To allow them to each have their own page, we use disambiguation pages.'), br, br,
                     makehtml(span, {}, 'If you are trying to add an item, and find that a page already exists for an item with that name, do not change that page. Instead, create a new page with a descriptive and unique name in parenthesis.'), br, br,
+
                     stratics.f.util.makehtml(span, {}, 'If you are trying to add an item, and find that a page already exists for an item with that name, do not change that page. Instead, create a new page with a descriptive and unique name in parenthesis.'), br, br,
                     makehtml(span, {}, 'If you were adding an item from Sonoma named "A Fireworks Wand", you might instead create a page named "UO:A Fireworks Wand (Sonoma Item)".'), br, br,
+
                     stratics.f.util.makehtml(span, {}, 'If you were adding an item from Sonoma named "A Fireworks Wand", you might instead create a page named "UO:A Fireworks Wand (Sonoma Item)".'), br, br,
                     makehtml(span, {}, 'Then, on both pages, make sure to set this field. Using that same example, you would put "A Fireworks Wand" in this blank.'),
+
                     stratics.f.util.makehtml(span, {}, 'Then, on both pages, make sure to set this field. Using that same example, you would put "A Fireworks Wand" in this blank.'),
                     makehtml(span, {}, 'Then go to "UO:A Fireworks Wand (disambiguation)". If it does not yet exist, create it, and add this as the entire text of the page: "{{DisambiguationPage}}" (without the quotes).'), br, br,
+
                     stratics.f.util.makehtml(span, {}, 'Then go to "UO:A Fireworks Wand (disambiguation)". If it does not yet exist, create it, and add this as the entire text of the page: "{{DisambiguationPage}}" (without the quotes).'), br, br,
 
                     br, br,
 
                     br, br,
 
                     makeTextField('disambiguation_page', 79, {
 
                     makeTextField('disambiguation_page', 79, {
Line 292: Line 298:
 
                     val = (typeof val === 'undefined' || val.length === 0) ? '' : val[0][1];
 
                     val = (typeof val === 'undefined' || val.length === 0) ? '' : val[0][1];
 
                     switch (val.toLowerCase()) {
 
                     switch (val.toLowerCase()) {
                     case 1:
+
                     case '1':
 
                     case 'yes':
 
                     case 'yes':
 
                     case 'true':
 
                     case 'true':
 
                         val = 1;
 
                         val = 1;
 
                         break;
 
                         break;
                     case 0:
+
                     case '0':
 
                     case 'no':
 
                     case 'no':
 
                     case 'none':
 
                     case 'none':
Line 326: Line 332:
 
                             style: 'float:right;'
 
                             style: 'float:right;'
 
                         })),
 
                         })),
                         option1 = makehtml('option', {
+
                         option1 = stratics.f.util.makehtml('option', {
 
                             value: '-1'
 
                             value: '-1'
 
                         }, "Don't Know"),
 
                         }, "Don't Know"),
                         option2 = makehtml('option', {
+
                         option2 = stratics.f.util.makehtml('option', {
 
                             value: '0'
 
                             value: '0'
 
                         }, "No"),
 
                         }, "No"),
                         option3 = makehtml('option', {
+
                         option3 = stratics.f.util.makehtml('option', {
 
                             value: '1'
 
                             value: '1'
 
                         }, "Yes"),
 
                         }, "Yes"),
                         $label = $(makehtml('label', {
+
                         $label = $(stratics.f.util.makehtml('label', {
 
                             style: 'text-align:center;line-height:24px;padding-right:7px;'
 
                             style: 'text-align:center;line-height:24px;padding-right:7px;'
 
                         }, descriptor + nbsp))
 
                         }, descriptor + nbsp))
Line 352: Line 358:
 
                         options = [];
 
                         options = [];
 
                     for (var i = 0; i < itemTypes.length; i++) {
 
                     for (var i = 0; i < itemTypes.length; i++) {
                         options.push(makehtml('option', {
+
                         options.push(stratics.f.util.makehtml('option', {
 
                             value: itemTypes[i]
 
                             value: itemTypes[i]
 
                         }, itemTypes[i]));
 
                         }, itemTypes[i]));
Line 421: Line 427:
 
                     }),
 
                     }),
 
                     br, br,
 
                     br, br,
                     makeTextField('quantity', 10, {
+
                     makeTextField('quantity', 12, {
 
                         placeholder: '(Quantity)',
 
                         placeholder: '(Quantity)',
 
                         descriptor: 'Quantity:'
 
                         descriptor: 'Quantity:'
 
                     }),
 
                     }),
                     $(makehtml('label', {
+
                     $(stratics.f.util.makehtml('label', {
 
                         style: 'text-align:center;line-height: 24px;float:right;'
 
                         style: 'text-align:center;line-height: 24px;float:right;'
 
                     }, 'Type(s) of item:' + nbsp))
 
                     }, 'Type(s) of item:' + nbsp))
Line 431: Line 437:
 
                     .append([
 
                     .append([
 
                         makeTypeSelect(),
 
                         makeTypeSelect(),
                         $(makehtml(input, {
+
                         $(stratics.f.util.makehtml(input, {
 
                             style: 'color:#f58400;font-weight:900;padding:0 .4em;margin-top:3px;',
 
                             style: 'color:#f58400;font-weight:900;padding:0 .4em;margin-top:3px;',
 
                             type: 'button',
 
                             type: 'button',
Line 448: Line 454:
 
                     ]),
 
                     ]),
 
                     br, br,
 
                     br, br,
                     makehtml(div, {
+
                     stratics.f.util.makehtml(div, {
 
                         style: 'margin:-8px 0;'
 
                         style: 'margin:-8px 0;'
 
                     }, "When was this item available? (If just for one day, leave the end date empty.)"),
 
                     }, "When was this item available? (If just for one day, leave the end date empty.)"),
Line 462: Line 468:
 
                         placeholder: 'DD'
 
                         placeholder: 'DD'
 
                     }), nbsp,
 
                     }), nbsp,
                     makehtml(span, {}, '-'), nbsp,
+
                     stratics.f.util.makehtml(span, {}, '-'), nbsp,
 
                     makeTextField('year_end', 12, {
 
                     makeTextField('year_end', 12, {
 
                         placeholder: 'YYYY',
 
                         placeholder: 'YYYY',
Line 478: Line 484:
 
                         descriptor: 'Season(s):'
 
                         descriptor: 'Season(s):'
 
                     }),
 
                     }),
                     $(makehtml(div, {
+
                     $(stratics.f.util.makehtml(div, {
 
                         style: 'display:inline-block;padding: 0em 0 1em 1em;line-height: 1.5em;transform: translateY(11px);'
 
                         style: 'display:inline-block;padding: 0em 0 1em 1em;line-height: 1.5em;transform: translateY(11px);'
 
                     }))
 
                     }))
 
                     .append([
 
                     .append([
                         makehtml(span, {}, nbsp + "If multiple seasons, separate with commas. Example: '12,13'"), br,
+
                         stratics.f.util.makehtml(span, {}, nbsp + "If multiple seasons, separate with commas. Example: '12,13'"), br,
 
                         makeCheckboxField('noseason', 'Check this box if the term "season" would not apply to this item.')
 
                         makeCheckboxField('noseason', 'Check this box if the term "season" would not apply to this item.')
 
                     ]),
 
                     ]),
 
                     br,
 
                     br,
                     makehtml(div, {
+
                     stratics.f.util.makehtml(div, {
 
                         style: 'color: brown;font-weight: 900;padding-top:6px;'
 
                         style: 'color: brown;font-weight: 900;padding-top:6px;'
 
                     }, nbsp + "This item was available on which shards?"), br,
 
                     }, nbsp + "This item was available on which shards?"), br,
Line 521: Line 527:
 
                     $('<div style="float:left;padding-top:7px;">')
 
                     $('<div style="float:left;padding-top:7px;">')
 
                     .append([
 
                     .append([
                         makehtml(div, {
+
                         stratics.f.util.makehtml(div, {
 
                             style: 'color: brown;font-weight: 900;'
 
                             style: 'color: brown;font-weight: 900;'
 
                         }, nbsp + "Is the item..."), br,
 
                         }, nbsp + "Is the item..."), br,
Line 535: Line 541:
 
                     $('<div style="float:right;padding-top:7px;">')
 
                     $('<div style="float:right;padding-top:7px;">')
 
                     .append([
 
                     .append([
                         makehtml(div, {
+
                         stratics.f.util.makehtml(div, {
 
                             style: 'color: brown;font-weight: 900;'
 
                             style: 'color: brown;font-weight: 900;'
 
                         }, nbsp + "Does the item..."), br,
 
                         }, nbsp + "Does the item..."), br,
Line 556: Line 562:
 
                     }),
 
                     }),
 
                     br, br,
 
                     br, br,
                     makehtml(span, {}, "What is the name of this item when the client is set to use Japanese?"),
+
                     stratics.f.util.makehtml(span, {}, "What is the name of this item when the client is set to use Japanese?"),
 
                     br,
 
                     br,
                     makehtml(div, {}, "(If the name is not localized, copy the English name here.)"),
+
                     stratics.f.util.makehtml(div, {}, "(If the name is not localized, copy the English name here.)"),
 
                     br,
 
                     br,
 
                     makeTextField('japanesename', 88, {
 
                     makeTextField('japanesename', 88, {
Line 564: Line 570:
 
                     }),
 
                     }),
 
                     br, br,
 
                     br, br,
                     makehtml(div, {}, "Is there an unofficial name this is known by?"),
+
                     stratics.f.util.makehtml(div, {}, "Is there an unofficial name this is known by?"),
 
                     br,
 
                     br,
 
                     makeTextField('aka', 100, {
 
                     makeTextField('aka', 100, {
Line 570: Line 576:
 
                     }),
 
                     }),
 
                     br, br,
 
                     br, br,
                     makehtml(div, {}, "List any minor variations in the name of this item (due to typos, etc.):"),
+
                     stratics.f.util.makehtml(div, {}, "List any minor variations in the name of this item (due to typos, etc.):"),
 
                     br,
 
                     br,
 
                     makeTextField('altname1', 49, {
 
                     makeTextField('altname1', 49, {
Line 604: Line 610:
 
                 def = [].concat(option.defaultval),
 
                 def = [].concat(option.defaultval),
 
                 elems = [],
 
                 elems = [],
                 i, j, select, options;
+
                 i, j, select, options, contStrings;
 
             for (i = 0; i < type.length; i++) {
 
             for (i = 0; i < type.length; i++) {
 
                 switch (type[i]) {
 
                 switch (type[i]) {
Line 614: Line 620:
 
                     break;
 
                     break;
 
                 case 'container':
 
                 case 'container':
                     elems.push(makehtml(span, {}, nbsp + 'Value:' + nbsp));
+
                     elems.push(stratics.f.util.makehtml(span, {}, nbsp + 'Value:' + nbsp));
                     var contStrings = ['/', 'items' + nbsp + nbsp, '/', 'stones'];
+
                     contStrings = ['/', 'items' + nbsp + nbsp, '/', 'stones'];
 
                     for (j = 0; j < 4;) {
 
                     for (j = 0; j < 4;) {
 
                         elems.push(makeNumber(j, def[j]));
 
                         elems.push(makeNumber(j, def[j]));
                         elems.push(makehtml(span, {}, nbsp + contStrings[j++] + nbsp));
+
                         elems.push(stratics.f.util.makehtml(span, {}, nbsp + contStrings[j++] + nbsp));
 
                     }
 
                     }
 
                     break;
 
                     break;
 +
                case 'elementGroup':
 +
                    contStrings = ['Physical', 'Fire', 'Cold', 'Poison', 'Energy'];
 +
                    for (j = 0; j < 5;) {
 +
                        elems.push(makeNumber(j, def[j]));
 +
                        elems.push(stratics.f.util.makehtml(span, {}, nbsp + contStrings[j++] + '<br>'));
 +
                    }
 +
                    break;                   
 
                 case 'range':
 
                 case 'range':
                     elems.push(makehtml(span, {}, nbsp + 'Value:' + nbsp));
+
                     elems.push(stratics.f.util.makehtml(span, {}, nbsp + 'Value:' + nbsp));
 
                     elems.push(makeNumber(i, def[i]));
 
                     elems.push(makeNumber(i, def[i]));
                     elems.push(makehtml(span, {}, nbsp + '-' + nbsp));
+
                     elems.push(stratics.f.util.makehtml(span, {}, nbsp + '-' + nbsp));
 
                     elems.push(makeNumber(i, def[i]));
 
                     elems.push(makeNumber(i, def[i]));
 
                     break;
 
                     break;
 
                 case 'int':
 
                 case 'int':
 
                     if (def != 'varies') {
 
                     if (def != 'varies') {
                         elems.push(makehtml(span, {}, nbsp + 'Value:' + nbsp));
+
                         elems.push(stratics.f.util.makehtml(span, {}, nbsp + 'Value:' + nbsp));
 
                         elems.push(makeNumber(i, def[i]));
 
                         elems.push(makeNumber(i, def[i]));
 
                         break;
 
                         break;
Line 635: Line 648:
 
                     /* falls through */
 
                     /* falls through */
 
                 case 'text':
 
                 case 'text':
                     elems.push(makehtml(span, {}, nbsp + 'Value:' + nbsp));
+
                     elems.push(stratics.f.util.makehtml(span, {}, nbsp + 'Value:' + nbsp));
 
                     elems.push(makeElem(input, i, {
 
                     elems.push(makeElem(input, i, {
 
                         type: 'text',
 
                         type: 'text',
Line 642: Line 655:
 
                     break;
 
                     break;
 
                 case 'state':
 
                 case 'state':
                     elems.push(makehtml(span, {}, nbsp + 'Value:' + nbsp));
+
                     elems.push(stratics.f.util.makehtml(span, {}, nbsp + 'Value:' + nbsp));
 
                     var states = option.states;
 
                     var states = option.states;
 
                     select = makeElem('select', i, {});
 
                     select = makeElem('select', i, {});
                     options = [makehtml('option', {
+
                     options = [stratics.f.util.makehtml('option', {
 
                         value: "none"
 
                         value: "none"
 
                     })];
 
                     })];
 
                     for (j = 0; j < states.length; j++) {
 
                     for (j = 0; j < states.length; j++) {
                         options.push(makehtml('option', {
+
                         options.push(stratics.f.util.makehtml('option', {
 
                             value: states[j].output
 
                             value: states[j].output
 
                         }, states[j].name));
 
                         }, states[j].name));
Line 658: Line 671:
 
                     break;
 
                     break;
 
                 case 'list':
 
                 case 'list':
                     elems.push(makehtml(span, {}, nbsp + 'Value:' + nbsp));
+
                     elems.push(stratics.f.util.makehtml(span, {}, nbsp + 'Value:' + nbsp));
 
                     var values = option.values;
 
                     var values = option.values;
 
                     select = makeElem('select', i, {});
 
                     select = makeElem('select', i, {});
                     options = [makehtml('option', {
+
                     options = [stratics.f.util.makehtml('option', {
 
                         value: "none"
 
                         value: "none"
 
                     })];
 
                     })];
 
                     for (j = 0; j < values.length; j++) {
 
                     for (j = 0; j < values.length; j++) {
                         options.push(makehtml('option', {
+
                         options.push(stratics.f.util.makehtml('option', {
 
                             value: values[j]
 
                             value: values[j]
 
                         }, values[j]));
 
                         }, values[j]));
Line 680: Line 693:
  
 
     /* Create popup dialog, tab structure, and data fieldsets */
 
     /* Create popup dialog, tab structure, and data fieldsets */
     var $toolmenu = $(makehtml('div', {
+
     var $toolmenu = $(stratics.f.util.makehtml('div', {
 
             id: 'toolmenu'
 
             id: 'toolmenu'
 
         })),
 
         })),
Line 693: Line 706:
 
         $btndiv = $('<div id="button-wrapper">')
 
         $btndiv = $('<div id="button-wrapper">')
 
         .append([
 
         .append([
             $(makehtml(input, {
+
             $(stratics.f.util.makehtml(input, {
 
                 id: 'saveButton',
 
                 id: 'saveButton',
 
                 style: 'background:#111!important;color:#e0ac43;font-weight:900;padding:3px 15px;position:absolute;right:30%;bottom:0;',
 
                 style: 'background:#111!important;color:#e0ac43;font-weight:900;padding:3px 15px;position:absolute;right:30%;bottom:0;',
Line 706: Line 719:
 
             })
 
             })
 
             .hide(),
 
             .hide(),
             $(makehtml(input, {
+
             $(stratics.f.util.makehtml(input, {
 
                 id: 'cancelButton',
 
                 id: 'cancelButton',
 
                 style: 'background:#111!important;color:salmon;font-weight:900;padding:3px 15px;position:absolute;left:30%;bottom:0;',
 
                 style: 'background:#111!important;color:salmon;font-weight:900;padding:3px 15px;position:absolute;left:30%;bottom:0;',
Line 728: Line 741:
 
         .append('<div id="propDisplay">'),
 
         .append('<div id="propDisplay">'),
 
         $field6 = makeFieldset(4, 'Item Disambiguation'),
 
         $field6 = makeFieldset(4, 'Item Disambiguation'),
         tab1 = makehtml('li', {}, makehtml('a', {
+
         tab1 = stratics.f.util.makehtml('li', {}, stratics.f.util.makehtml('a', {
             href: loc + '#RareInfo1'
+
             href: loc + '#RareInfo1',
 +
            id: 'tab1'
 
         }, 'Rare Item Information 1')),
 
         }, 'Rare Item Information 1')),
         tab3 = makehtml('li', {}, makehtml('a', {
+
         tab3 = stratics.f.util.makehtml('li', {}, stratics.f.util.makehtml('a', {
             href: loc + '#RareInfo2'
+
             href: loc + '#RareInfo2',
 +
            id: 'tab3'
 
         }, 'Rare Item Information 2')),
 
         }, 'Rare Item Information 2')),
         tab2 = makehtml('li', {}, makehtml('a', {
+
         tab2 = stratics.f.util.makehtml('li', {}, stratics.f.util.makehtml('a', {
             href: loc + '#PropInfo'
+
             href: loc + '#PropInfo',
 +
            id: 'tab2'
 
         }, 'Property Info')),
 
         }, 'Property Info')),
         tab4 = makehtml('li', {}, makehtml('a', {
+
         tab4 = stratics.f.util.makehtml('li', {}, stratics.f.util.makehtml('a', {
             href: loc + '#DisambigInfo'
+
             href: loc + '#DisambigInfo',
 +
            id: 'tab4'
 
         }, 'Item Disambiguation')),
 
         }, 'Item Disambiguation')),
 
         $tabsInfo = $('<div>', {
 
         $tabsInfo = $('<div>', {
Line 745: Line 762:
 
         .hide();
 
         .hide();
  
     var $tabsList = $('<ul>')
+
     var $tabsList = $('<ul>');
         .append([tab1, tab3, tab2, tab4]);
+
    if ($mwtextarea.data('type') == 'rare') {
 +
         $tabsList.append([tab1, tab3, tab2, tab4]);
 +
    } else if ($mwtextarea.data('type') == 'common') {
 +
        $tabsList.append([tab2, tab4]);
 +
    }
  
 
     $propertyBox.append($field5);
 
     $propertyBox.append($field5);
Line 760: Line 781:
  
 
     /* Initialize type of item section buttons */
 
     /* Initialize type of item section buttons */
     var typeQuestion = makehtml(span, {}, 'Is this a rare item?'),
+
     var typeQuestion = stratics.f.util.makehtml(span, {}, 'Is this a rare item?'),
 
         $typeBtnCommon = $(makeElem(input, 'CommonItem', {
 
         $typeBtnCommon = $(makeElem(input, 'CommonItem', {
 
             type: 'button',
 
             type: 'button',
Line 786: Line 807:
 
         var $mwtextarea = $('.wikiEditor-ui-text textarea');
 
         var $mwtextarea = $('.wikiEditor-ui-text textarea');
 
         $mwtextarea.data('type', 'common');
 
         $mwtextarea.data('type', 'common');
         $('#fieldset1,#PropInfo,#DisambigInfo,#buttonSubmitProp')
+
         $('#fieldset1,#PropInfo,#DisambigInfo,#buttonSubmitProp,#tabs')
 
             .toggle();
 
             .toggle();
 +
        $tabsList.append([tab2, tab4]);
 +
        $("#toolmenu")
 +
            .tabs();
 
     });
 
     });
 
     $typeBtnRare.click(function () {
 
     $typeBtnRare.click(function () {
Line 794: Line 818:
 
         $('#fieldset1,#RareInfo1,#RareInfo2,#PropInfo,#DisambigInfo,#buttonSubmitProp,#tabs')
 
         $('#fieldset1,#RareInfo1,#RareInfo2,#PropInfo,#DisambigInfo,#buttonSubmitProp,#tabs')
 
             .toggle();
 
             .toggle();
 +
        $tabsList.append([tab1, tab3, tab2, tab4]);
 
         $("#toolmenu")
 
         $("#toolmenu")
 
             .tabs();
 
             .tabs();
Line 802: Line 827:
 
     var $select1 = populateSelect($('<select>', {
 
     var $select1 = populateSelect($('<select>', {
 
             id: 'select1'
 
             id: 'select1'
         }), propertyInfo.category),
+
         }), propertyInfo.category, true),
 
         $propinfo = makeFieldset('propInfo', ''),
 
         $propinfo = makeFieldset('propInfo', ''),
 
         $proptext = $('<div>', {
 
         $proptext = $('<div>', {
Line 817: Line 842:
 
         .button()
 
         .button()
 
         .hide();
 
         .hide();
 
  
 
     /* Add selects and info collection area for item property section to the page */
 
     /* Add selects and info collection area for item property section to the page */
Line 839: Line 863:
 
         .dialog({
 
         .dialog({
 
             title: 'Item Template Editor',
 
             title: 'Item Template Editor',
             autoOpen: true,
+
             autoOpen: false,
 
             position: {
 
             position: {
 
                 my: 'center',
 
                 my: 'center',
Line 862: Line 886:
 
         });
 
         });
 
     $propertyBox.dialog({
 
     $propertyBox.dialog({
 +
            autoOpen: false,
 
             height: 700,
 
             height: 700,
 
             width: 250,
 
             width: 250,
Line 967: Line 992:
 
             types.push($('#addTypeSelect option:selected')
 
             types.push($('#addTypeSelect option:selected')
 
                 .val());
 
                 .val());
             $.unique(types)
+
             $typeDisplay.val([...new Set(types)].join(', '));
                .sort();
 
            $typeDisplay.val(types.join(', '));
 
 
         });
 
         });
  
Line 1,002: Line 1,025:
 
         $propinfo.empty();
 
         $propinfo.empty();
 
         if (selected !== "none") {
 
         if (selected !== "none") {
             var type = getOptionType($this, selected);
+
             if (selected === "all") {
            if (type == 'option') {
+
            let allOpt = [];
                $select2.show();
+
$('#select1').data('source').forEach(group => {
                populateSelect($select2, thisOption.options);
+
    if (group.hasOwnProperty('options')) {
 +
        allOpt.push(...group.options);
 +
}
 +
});
 +
allOpt = allOpt.sort((a, b) => (a.name > b.name) ? 1 : -1);
 +
              populateSelect($select2, allOpt);
 
             } else {
 
             } else {
                $select2.hide();
+
            var type = getOptionType($this, selected);
                $propinfo.append(handleOption(thisOption));
+
            if (type == 'option') {
 +
                $select2.show();
 +
                populateSelect($select2, thisOption.options);
 +
            } else {
 +
                $select2.hide();
 +
                $propinfo.append(handleOption(thisOption));
 +
            }
 
             }
 
             }
 
         } else {
 
         } else {
Line 1,036: Line 1,070:
 
             showError = function (err) {
 
             showError = function (err) {
 
                 $('#propText')
 
                 $('#propText')
                     .html(makehtml('span', {
+
                     .html(stratics.f.util.makehtml('span', {
 
                         style: 'color:red;'
 
                         style: 'color:red;'
 
                     }, err));
 
                     }, err));
Line 1,156: Line 1,190:
 
         }
 
         }
 
     });
 
     });
}());
+
    $('.namespace')
 +
        .after($('<a>')
 +
            .addClass('buttonTrigger')
 +
            .text('Open Item Editor')
 +
            .click(function (e) {
 +
                e.preventDefault();
 +
                $('#toolmenu')
 +
                    .dialog('open');
 +
            }));
 +
};

Latest revision as of 03:11, 12 January 2020

/* globals console, propertyInfo, stratics, $ */
/* jshint esversion: 6 */
var loadEditor = function () {
    "use strict";

    var br = '<br>',
        div = 'div',
        input = 'input',
        legend = 'legend',
        nbsp = '&nbsp;',
        number = 'number',
        span = 'span',
        loc = location.href.toString(),
        counter = 0,
        arrays,
        i;

    /* Determine what type of item is being edited. */
    var $mwtextarea = $('.wikiEditor-ui-text textarea, #editform textarea'),
        itemType;
    var mwtext = $mwtextarea.val();
    switch (true) {
    case /^{{RareItem/m.test(mwtext):
        itemType = 'rare';
        break;
    case /^{{InfoBox[\s|_]UOItem/m.test(mwtext):
        itemType = 'common';
        break;
    default:
        itemType = 'new';
    }
    $mwtextarea.data('type', itemType);

    /* Reads in info from the JSON object, populates a select with options */
    var populateSelect = function ($select, arr, allOption = false) {
            var options = [stratics.f.util.makehtml('option', {
                value: "none"
            })];
            $select.empty();
            if (allOption) {
            	options.push(stratics.f.util.makehtml('option', {
                	value: "all"
            	}, 'All Properties'));            
            }
            for (i = 0; i < arr.length; i++) {
                options.push(stratics.f.util.makehtml('option', {
                    value: i
                }, arr[i].name));
            }
            return $select.append(options)
                .sortOptions()
                .val("")
                .data('source', arr);
        },
        /* Reads the select's source array, returns the type of the element at [value] */
        getOptionType = function ($select, value) {
            return $select.data('source')[value].type;
        },
        /* Creates an arbitrary element */
        makeElem = function (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 stratics.f.util.makehtml(elem, args);
            } else {
                if (typeof after === 'undefined') {
                    return stratics.f.util.makehtml('label', {}, label + nbsp + stratics.f.util.makehtml(elem, args));
                } else {
                    return stratics.f.util.makehtml('label', {}, stratics.f.util.makehtml(elem, args) + nbsp + label);
                }
            }
        },
        /* Creates an arbitrary element */
        makeFieldset = function (id, name) {
            return $('<fieldset>', {
                    id: 'fieldset' + id
                })
                .append(stratics.f.util.makehtml(legend, {
                    style: 'color:#FFF;font-weight:bolder;'
                }, name))
                .append(br);
        },
        /* Creates an input[type=number] element */
        makeNumber = function (j, val) {
            return makeElem(input, j, {
                type: number,
                min: 0,
                step: 1,
                style: 'width: 6em;',
                value: val
            });
        },
        /* Parse existing data from template */
        readTemplate = function () {
            var itemType = $mwtextarea.data('type'),
                linePattern = /\s*\|\s*(\S+\s*=\s*.+)/mg,
                argPattern = /([a-zA-Z\s_]+)+=\s*(.+)/,
                templateBody = '',
                paramLines,
                paramPairs = [],
                paramLookup = [],
                pattern,
                result;

            if (itemType !== 'new') {
                /* Set the pattern based on which template is being used. */
                if (itemType === 'rare') {
                    pattern = /{{RareItem([\s\S]*)^}}/m;
                } else if (itemType === 'common') {
                    pattern = /{{InfoBox[\s|_]UOItem([\s\S]*)^}}/m;
                }

                /* Extract the template's contents */
                mwtext = $mwtextarea.val();
                mwtext.replace(pattern, function (match, p1) {
                    templateBody = p1; // Store the contents of the template
                    return ''; // Remove the template from the page's text
                });

                /* Extract the parameters from the template */
                paramLines = templateBody.split(linePattern)
                    .filter(function (el) {
                        return el.trim()
                            .length !== 0;
                    });

                /* Split each parameter into argument+value pairs */
                for (i = 0; i < paramLines.length; i++) {
                    result = paramLines[i].match(argPattern)
                        .slice(1);
                    result[0] = result[0].trim();
                    paramPairs.push(result);
                    paramLookup.push(paramPairs[i][0]);
                }
            }
            $mwtextarea.data('params', {
                pairs: paramPairs,
                lookup: paramLookup
            });
        },
        /* Get the index, if any, of a parameter in the parameter store */
        lookupParamIndex = function (paramName) {
            return $mwtextarea.data('params')
                .lookup.indexOf(paramName);
        },
        /* Retrieve a stored parameter, removing it from the both the parameter lookup and the parameter store */
        spliceParam = function (num) {
            arrays = $mwtextarea.data('params');
            i = arrays.pairs.splice(num, 1);
            arrays.lookup.splice(num, 1);
            $mwtextarea.data('params', arrays);
            return i;
        },
        /* Retrieve a stored param pair, removing it from the param store */
        getStoredParam = function (match) {
            var index = lookupParamIndex(match);
            if (index > -1) {
                var storedVal = spliceParam(index);
                return storedVal;
            }
            return '';
        },
        /* Retrieve a stored param pair, removing it from the param store */
        addParamToStore = function (arr) {
            arrays = $mwtextarea.data('params');
            arrays.pairs.push(arr);
            arrays.lookup.push(arr[0]);
            $mwtextarea.data('params', arrays);
            return;
        },
        /* Create a text input field */
        makeTextField = function (param, width, args) {
            var val = getStoredParam(param);
            val = (val.length === 0) ? '' : val[0][1];
            if (typeof args.placeholder === 'undefined') {
                args.placeholder = '';
            }
            if (typeof args.descriptor === 'undefined') {
              return $('<span>' + makeElem(input, counter++, $.extend(args, {
                        type: 'text',
                        value: val,
                        style: 'width:' + width + '%;margin-left:1%;'
                    })) + '</span>')
                    .data('param', param);
            } else {
                var descriptor = args.descriptor;
                delete args.descriptor;
                return $(makeElem(input, counter++, $.extend(args, {
                        type: 'text',
                        value: val,
                        style: 'width:' + width + '%;'
                    }), descriptor))
                    .data('param', param);
            }
        },
        /* Create a box to display a single property */
        makeNewPropertyBox = function (propNum) {
            return $(stratics.f.util.makehtml(div, {
                'data-propnum': propNum,
                'class': 'ui-corner-all ui-widget-content',
                style: 'background:#101010;padding:4px;margin:1px;'
            }));
        },
        /* Fill a property box with a property's text */
        fillPropertyBox = function ($prop, arr) {
            return $prop.append(stratics.f.util.makehtml(span, {}, arr.join(': ')));
        },
        /* Add a button to remove a property */
        addRemovePropertyButton = function ($prop, arr) {
            return $prop.append($(stratics.f.util.makehtml(input, {
                    'class': 'removePropButton',
                    style: 'color:brown;font-weight:900;padding:0 .2em;float:right;margin:-2px -3px;',
                    type: 'button',
                    value: '✗'
                }))
                .button());
        },
        /* Attach a property box to the property fieldset */
        attachPropertyBox = function ($prop) {
            $('#propDisplay')
                .append($prop);
            return;
        },
        /* Process a single property into the property list */
        addToPropList = function (propNum, arr) {
            var $prop = makeNewPropertyBox(propNum);
            $prop = fillPropertyBox($prop, arr);
            $prop = addRemovePropertyButton($prop);
            attachPropertyBox($prop);
            return;
        },
        /* Cleans the property array (Basically, a chance to remove/change depricated parameters) */
        cleanPropArray = function () {
            getStoredParam('crafted'); // This has the effect of deleting the depricated 'crafted' param from the storage arrays
            return;
        },
        /* Process an array of properties into the property list, and into the property store, if needed */
        addArrayToPropertyList = function (arr) {
            var goodData = [],
                startNum = $('#propDisplay')
                .children()
                .length;

            /* Validate the new data */
            if (!Array.isArray(arr)) { // Not passed an array
                if (typeof console !== 'undefined') {
                    console.log('Expected an array, received ' + arr + ' instead.');
                }
                return;
            }
            if (arr.length === 0) { // Passed an empty array
                return;
            }
            if (!Array.isArray(arr[0])) { // Passed a one-dimensional array
                arr = [arr]; // Convert to a two-dimensional array
            }
            for (i = 0; i < arr.length; i++) { // Test that each parameter has a definition
                if (arr[i].length == 2 && arr[i][1].length !== 0) {
                    goodData.push(arr[i]);
                }
            }

            /* Process the new data */
            for (i = 0; i < goodData.length; i++) {
                addToPropList(startNum++, goodData[i]); // Display the new property
                if ($mwtextarea.data('params')
                    .lookup.length < startNum) // If this is a new property,
                    addParamToStore(goodData[i]); // then add it to the data store
            }
            cleanPropArray();
            return;

        },
        /* Create the disambiguation tab */
        buildDisambigTab = function (option) {
            $('#DisambigInfo')
                .append([
                    stratics.f.util.makehtml(span, {}, 'Often, multiple things in UO share the same name. To allow them to each have their own page, we use disambiguation pages.'), br, br,
                    stratics.f.util.makehtml(span, {}, 'If you are trying to add an item, and find that a page already exists for an item with that name, do not change that page. Instead, create a new page with a descriptive and unique name in parenthesis.'), br, br,
                    stratics.f.util.makehtml(span, {}, 'If you were adding an item from Sonoma named "A Fireworks Wand", you might instead create a page named "UO:A Fireworks Wand (Sonoma Item)".'), br, br,
                    stratics.f.util.makehtml(span, {}, 'Then, on both pages, make sure to set this field. Using that same example, you would put "A Fireworks Wand" in this blank.'),
                    stratics.f.util.makehtml(span, {}, 'Then go to "UO:A Fireworks Wand (disambiguation)". If it does not yet exist, create it, and add this as the entire text of the page: "{{DisambiguationPage}}" (without the quotes).'), br, br,
                    br, br,
                    makeTextField('disambiguation_page', 79, {
                        placeholder: '(Disambiguation Wikipage)',
                        descriptor: 'Disambiguation Wikipage:'
                    })
                ]);
        },
        /* Create the rare item fields for the dialog */
        buildRareFields = function (option) {
            var getBoolValue = function (val) {
                    val = (typeof val === 'undefined' || val.length === 0) ? '' : val[0][1];
                    switch (val.toLowerCase()) {
                    case '1':
                    case 'yes':
                    case 'true':
                        val = 1;
                        break;
                    case '0':
                    case 'no':
                    case 'none':
                    case 'false':
                        val = 0;
                        break;
                    default:
                        val = -1;
                    }
                    return val;
                },
                makeCheckboxField = function (param, descriptor) {
                    var val = getStoredParam(param),
                        $elem = $(makeElem(input, counter++, {
                            type: 'checkbox',
                        }, descriptor, 1))
                        .data('param', param);
                    val = getBoolValue(val);
                    if (val > 0) {
                        $elem.find('input')
                            .prop('checked', true);
                    }
                    return $elem;
                },
                makeTriStateField = function (param, descriptor) {
                    var val = getStoredParam(param),
                        $select = $(makeElem('select', counter++, {
                            style: 'float:right;'
                        })),
                        option1 = stratics.f.util.makehtml('option', {
                            value: '-1'
                        }, "Don't Know"),
                        option2 = stratics.f.util.makehtml('option', {
                            value: '0'
                        }, "No"),
                        option3 = stratics.f.util.makehtml('option', {
                            value: '1'
                        }, "Yes"),
                        $label = $(stratics.f.util.makehtml('label', {
                            style: 'text-align:center;line-height:24px;padding-right:7px;'
                        }, descriptor + nbsp))
                        .data('param', param);

                    $select.append([option1, option2, option3])
                        .val(getBoolValue(val));
                    return $label.append($select);
                },
                makeTypeSelect = function () {
                    var $select = $(makeElem('select', counter++, {
                            id: 'addTypeSelect',
                            type: 'typeSelect',
                            style: 'padding-left:3px;'
                        })),
                        options = [];
                    for (var i = 0; i < itemTypes.length; i++) {
                        options.push(stratics.f.util.makehtml('option', {
                            value: itemTypes[i]
                        }, itemTypes[i]));
                    }
                    return $select.append(options);
                };

            var brclear = '<br style="clear:both;"/>',
                fourColumnCSS = [
                    'column-count: 4;',
                    'column-gap: 20px;',
                    '-moz-column-count: 4;',
                    '-moz-column-gap: 20px;',
                    '-webkit-column-count: 4;',
                    '-webkit-column-gap: 20px;>'
                ];
            var fourColumnDiv = '<div style="' + fourColumnCSS.join() + '">',
                itemTypes = [
                    'Advanced Character Program',
                    'Beta',
                    'Bug',
                    'Christmas',
                    'Cleanup Britannia',
                    'Cornucopia',
                    'Craftable',
                    'Daily',
                    'Developer',
                    'EM',
                    'Exploit',
                    'Faction',
                    'Gift',
                    'GM',
                    'Halloween',
                    'Hourly',
                    'IGM',
                    'Khaldun',
                    'Khaldun Birth',
                    'Loot',
                    'Magic Moments',
                    'Mesanna',
                    'Monthly',
                    'New Player',
                    'NPC Vendor',
                    'Original Necromancy',
                    'Plague Of Despair',
                    'Prepatch',
                    'Quest',
                    'SA Birth',
                    'Seer',
                    'Server Birth',
                    'Sigil',
                    'Stacking Bug',
                    'Store',
                    'Stratics',
                    'T2A Birth',
                    'Trammel Birth',
                    'Trick Or Treat',
                    'Trinsic Invasion',
                    'Unapproved EM',
                    'Weekly'
                ];

            $('#fieldset2')
                .append([
                    makeTextField('name', 86, {
                        placeholder: '(Item name)',
                        descriptor: 'Item Name:'
                    }),
                    br, br,
                    makeTextField('quantity', 12, {
                        placeholder: '(Quantity)',
                        descriptor: 'Quantity:'
                    }),
                    $(stratics.f.util.makehtml('label', {
                        style: 'text-align:center;line-height: 24px;float:right;'
                    }, 'Type(s) of item:' + nbsp))
                    .data('param', 'type')
                    .append([
                        makeTypeSelect(),
                        $(stratics.f.util.makehtml(input, {
                            style: 'color:#f58400;font-weight:900;padding:0 .4em;margin-top:3px;',
                            type: 'button',
                            id: 'addTypeButton',
                            value: '➤'
                        }))
                        .button(),
                        makeTextField('type', 30, {
                            id: 'addTypeDisplay',
                            placeholder: '(Item type)'
                        })
                        .css({
                            backgroundColor: 'rgb(187, 187, 187)',
                            color: '#101010'
                        })
                    ]),
                    br, br,
                    stratics.f.util.makehtml(div, {
                        style: 'margin:-8px 0;'
                    }, "When was this item available? (If just for one day, leave the end date empty.)"),
                    br,
                    makeTextField('year', 12, {
                        placeholder: 'YYYY',
                        descriptor: 'Start date:'
                    }),
                    makeTextField('month', 9, {
                        placeholder: 'MM'
                    }),
                    makeTextField('day', 9, {
                        placeholder: 'DD'
                    }), nbsp,
                    stratics.f.util.makehtml(span, {}, '-'), nbsp,
                    makeTextField('year_end', 12, {
                        placeholder: 'YYYY',
                        descriptor: 'End date:'
                    }),
                    makeTextField('month_end', 9, {
                        placeholder: 'MM'
                    }),
                    makeTextField('day_end', 9, {
                        placeholder: 'DD'
                    }),
                    br,
                    makeTextField('season', 20, {
                        placeholder: 'Season',
                        descriptor: 'Season(s):'
                    }),
                    $(stratics.f.util.makehtml(div, {
                        style: 'display:inline-block;padding: 0em 0 1em 1em;line-height: 1.5em;transform: translateY(11px);'
                    }))
                    .append([
                        stratics.f.util.makehtml(span, {}, nbsp + "If multiple seasons, separate with commas. Example: '12,13'"), br,
                        makeCheckboxField('noseason', 'Check this box if the term "season" would not apply to this item.')
                    ]),
                    br,
                    stratics.f.util.makehtml(div, {
                        style: 'color: brown;font-weight: 900;padding-top:6px;'
                    }, nbsp + "This item was available on which shards?"), br,
                    $(fourColumnDiv)
                    .append([
                        makeCheckboxField('Arirang', 'Arirang'), br,
                        makeCheckboxField('Asuka', 'Asuka'), br,
                        makeCheckboxField('Atlantic', 'Atlantic'), br,
                        makeCheckboxField('Baja', 'Baja'), br,
                        makeCheckboxField('Balhae', 'Balhae'), br,
                        makeCheckboxField('Catskills', 'Catskills'), br,
                        makeCheckboxField('Chesapeake', 'Chesapeake'), br,
                        makeCheckboxField('Drachenfels', 'Drachenfels'), br,
                        makeCheckboxField('Europa', 'Europa'), br,
                        makeCheckboxField('Formosa', 'Formosa'), br,
                        makeCheckboxField('GL', 'Great Lakes'), br,
                        makeCheckboxField('Hokuto', 'Hokuto'), br,
                        makeCheckboxField('Izumo', 'Izumo'), br,
                        makeCheckboxField('LA', 'Lake Austin'), br,
                        makeCheckboxField('LS', 'Lake Superior'), br,
                        makeCheckboxField('Legends', 'Legends'), br,
                        makeCheckboxField('Mizuho', 'Mizuho'), br,
                        makeCheckboxField('Mugen', 'Mugen'), br,
                        makeCheckboxField('Napa', 'Napa Valley'), br,
                        makeCheckboxField('Oceania', 'Oceania'), br,
                        makeCheckboxField('Origin', 'Origin'), br,
                        makeCheckboxField('Pacific', 'Pacific'), br,
                        makeCheckboxField('Sakura', 'Sakura'), br,
                        makeCheckboxField('Sonoma', 'Sonoma'), br,
                        makeCheckboxField('SP', 'Siege Perilous'), br,
                        makeCheckboxField('Wakoku', 'Wakoku'), br,
                        makeCheckboxField('Yamato', 'Yamato'), br
                    ]),
                    $('<div style="float:left;padding-top:7px;">')
                    .append([
                        stratics.f.util.makehtml(div, {
                            style: 'color: brown;font-weight: 900;'
                        }, nbsp + "Is the item..."), br,
                        makeTriStateField('spawning', 'Currently spawning'), brclear,
                        makeTriStateField('legal', 'Legal to own'), brclear,
                        makeTriStateField('animated', 'Animated'), brclear,
                        makeTriStateField('dyable', 'Dyable'), brclear,
                        makeTriStateField('newbie', 'Newbiefied'), brclear,
                        makeTriStateField('translucent', 'Translucent'), brclear,
                        makeTriStateField('wearable', 'Wearable'), brclear,
                        makeTriStateField('wieldable', 'Wieldable')
                    ]),
                    $('<div style="float:right;padding-top:7px;">')
                    .append([
                        stratics.f.util.makehtml(div, {
                            style: 'color: brown;font-weight: 900;'
                        }, nbsp + "Does the item..."), br,
                        makeTriStateField('stackable', 'Stack'), brclear,
                        makeTriStateField('container', 'Work as a container'), brclear,
                        makeTriStateField('doubleclick', 'Have an effect when double-clicked'), brclear,
                        makeTriStateField('eatable', 'Disapear when eaten'), brclear,
                        makeTriStateField('turnable', 'Rotate with a deco tool'), brclear,
                        makeTriStateField('runebook', 'Work like a runebook'), brclear,
                        makeTriStateField('sound', 'Make sounds'), brclear,
                        makeTriStateField('spellbook', 'Work like a spellbook'), brclear,
                        makeTriStateField('walkover', 'Have an effect when walked on')
                    ])
                ]);
            $('#fieldset4')
                .append([
                    makeTextField('engraving', 80, {
                        placeholder: '(Item engraving)',
                        descriptor: 'Item Engraving:'
                    }),
                    br, br,
                    stratics.f.util.makehtml(span, {}, "What is the name of this item when the client is set to use Japanese?"),
                    br,
                    stratics.f.util.makehtml(div, {}, "(If the name is not localized, copy the English name here.)"),
                    br,
                    makeTextField('japanesename', 88, {
                        placeholder: '(Japanese localized name)'
                    }),
                    br, br,
                    stratics.f.util.makehtml(div, {}, "Is there an unofficial name this is known by?"),
                    br,
                    makeTextField('aka', 100, {
                        placeholder: '(Unofficial name)'
                    }),
                    br, br,
                    stratics.f.util.makehtml(div, {}, "List any minor variations in the name of this item (due to typos, etc.):"),
                    br,
                    makeTextField('altname1', 49, {
                        placeholder: '(Alternate name 1)'
                    }),
                    makeTextField('altname4', 49, {
                        placeholder: '(Alternate name 4)'
                    }),
                    makeTextField('altname2', 49, {
                        placeholder: '(Alternate name 2)'
                    }),
                    makeTextField('altname5', 49, {
                        placeholder: '(Alternate name 5)'
                    }),
                    makeTextField('altname3', 49, {
                        placeholder: '(Alternate name 3)'
                    }),
                    makeTextField('altname6', 49, {
                        placeholder: '(Alternate name 6)'
                    }),
                    br
                ]);
            /* At this point, all that is left in the textarea's stored params is item parameters. */
            cleanPropArray();
            addArrayToPropertyList($mwtextarea.data('params')
                .pairs);
        },
        /* Reads the selected option's JSON source, builds the appropriate data fields */
        handleOption = function (option) {
            $proptext.html(propertyInfo.descriptions[0][option.description]);

            var type = [].concat(option.type),
                def = [].concat(option.defaultval),
                elems = [],
                i, j, select, options, contStrings;
            for (i = 0; i < type.length; i++) {
                switch (type[i]) {
                case 'bool':
                    elems.push(makeElem(input, i, {
                        type: 'checkbox',
                        style: 'width:2em;height:2em;margin-left:4em;'
                    }));
                    break;
                case 'container':
                    elems.push(stratics.f.util.makehtml(span, {}, nbsp + 'Value:' + nbsp));
                    contStrings = ['/', 'items' + nbsp + nbsp, '/', 'stones'];
                    for (j = 0; j < 4;) {
                        elems.push(makeNumber(j, def[j]));
                        elems.push(stratics.f.util.makehtml(span, {}, nbsp + contStrings[j++] + nbsp));
                    }
                    break;
                case 'elementGroup':
                    contStrings = ['Physical', 'Fire', 'Cold', 'Poison', 'Energy'];
                    for (j = 0; j < 5;) {
                        elems.push(makeNumber(j, def[j]));
                        elems.push(stratics.f.util.makehtml(span, {}, nbsp + contStrings[j++] + '<br>'));
                    }
                    break;                    
                case 'range':
                    elems.push(stratics.f.util.makehtml(span, {}, nbsp + 'Value:' + nbsp));
                    elems.push(makeNumber(i, def[i]));
                    elems.push(stratics.f.util.makehtml(span, {}, nbsp + '-' + nbsp));
                    elems.push(makeNumber(i, def[i]));
                    break;
                case 'int':
                    if (def != 'varies') {
                        elems.push(stratics.f.util.makehtml(span, {}, nbsp + 'Value:' + nbsp));
                        elems.push(makeNumber(i, def[i]));
                        break;
                    }
                    /* falls through */
                case 'text':
                    elems.push(stratics.f.util.makehtml(span, {}, nbsp + 'Value:' + nbsp));
                    elems.push(makeElem(input, i, {
                        type: 'text',
                        value: def[i]
                    }));
                    break;
                case 'state':
                    elems.push(stratics.f.util.makehtml(span, {}, nbsp + 'Value:' + nbsp));
                    var states = option.states;
                    select = makeElem('select', i, {});
                    options = [stratics.f.util.makehtml('option', {
                        value: "none"
                    })];
                    for (j = 0; j < states.length; j++) {
                        options.push(stratics.f.util.makehtml('option', {
                            value: states[j].output
                        }, states[j].name));
                    }
                    elems.push($(select)
                        .append(options)
                        .data('type', 'state'));
                    break;
                case 'list':
                    elems.push(stratics.f.util.makehtml(span, {}, nbsp + 'Value:' + nbsp));
                    var values = option.values;
                    select = makeElem('select', i, {});
                    options = [stratics.f.util.makehtml('option', {
                        value: "none"
                    })];
                    for (j = 0; j < values.length; j++) {
                        options.push(stratics.f.util.makehtml('option', {
                            value: values[j]
                        }, values[j]));
                    }
                    elems.push($(select)
                        .append(options)
                        .data('type', 'list'));
                    break;
                }
            }
            $toolmenu.data('option', option);
            return elems;
        };

    /* Create popup dialog, tab structure, and data fieldsets */
    var $toolmenu = $(stratics.f.util.makehtml('div', {
            id: 'toolmenu'
        })),
        $div2 = $('<div id="RareInfo1">')
        .hide(),
        $div4 = $('<div id="RareInfo2">')
        .hide(),
        $div3 = $('<div id="PropInfo">')
        .hide(),
        $div5 = $('<div id="DisambigInfo">')
        .hide(),
        $btndiv = $('<div id="button-wrapper">')
        .append([
            $(stratics.f.util.makehtml(input, {
                id: 'saveButton',
                style: 'background:#111!important;color:#e0ac43;font-weight:900;padding:3px 15px;position:absolute;right:30%;bottom:0;',
                type: 'button',
                value: 'Save all changes',
            }))
            .button()
            .hover(function () {
                this.style.backgroundColor = '#666!important';
            }, function () {
                this.style.backgroundColor = '#111!important';
            })
            .hide(),
            $(stratics.f.util.makehtml(input, {
                id: 'cancelButton',
                style: 'background:#111!important;color:salmon;font-weight:900;padding:3px 15px;position:absolute;left:30%;bottom:0;',
                type: 'button',
                value: 'Cancel editing'
            }))
            .button()
            .hover(function () {
                this.style.backgroundColor = '#666!important';
            }, function () {
                this.style.backgroundColor = '#111!important';
            })
        ]),
        $propertyBox = $('<div id="PropBox">'),
        $field1 = makeFieldset(1, 'Type of item'),
        $field2 = makeFieldset(2, ''),
        $field4 = makeFieldset(4, ''),
        $field3 = makeFieldset(3, 'Select a property to add to this item'),
        $field5 = makeFieldset(5, 'Item Properties')
        .css('margin', '0 -10px')
        .append('<div id="propDisplay">'),
        $field6 = makeFieldset(4, 'Item Disambiguation'),
        tab1 = stratics.f.util.makehtml('li', {}, stratics.f.util.makehtml('a', {
            href: loc + '#RareInfo1',
            id: 'tab1'
        }, 'Rare Item Information 1')),
        tab3 = stratics.f.util.makehtml('li', {}, stratics.f.util.makehtml('a', {
            href: loc + '#RareInfo2',
            id: 'tab3'
        }, 'Rare Item Information 2')),
        tab2 = stratics.f.util.makehtml('li', {}, stratics.f.util.makehtml('a', {
            href: loc + '#PropInfo',
            id: 'tab2'
        }, 'Property Info')),
        tab4 = stratics.f.util.makehtml('li', {}, stratics.f.util.makehtml('a', {
            href: loc + '#DisambigInfo',
            id: 'tab4'
        }, 'Item Disambiguation')),
        $tabsInfo = $('<div>', {
            id: 'tabs'
        })
        .hide();

    var $tabsList = $('<ul>');
    if ($mwtextarea.data('type') == 'rare') {
        $tabsList.append([tab1, tab3, tab2, tab4]);
    } else if ($mwtextarea.data('type') == 'common') {
        $tabsList.append([tab2, tab4]);
    }

    $propertyBox.append($field5);
    $toolmenu.append([
        $field1,
        $div2.append($field2),
        $div4.append($field4),
        $div3.append($field3),
        $div5.append($field6),
        $btndiv
    ]);
    $field1.before($tabsInfo.append($tabsList));

    /* Initialize type of item section buttons */
    var typeQuestion = stratics.f.util.makehtml(span, {}, 'Is this a rare item?'),
        $typeBtnCommon = $(makeElem(input, 'CommonItem', {
            type: 'button',
            value: 'No'
        }))
        .button(),
        $typeBtnRare = $(makeElem(input, 'RareItem', {
            type: 'button',
            value: 'Yes'
        }))
        .button();

    /* Add type of item section buttons to the page */
    $field1.append(
        [br,
            typeQuestion,
            br, br, br,
            $typeBtnCommon,
            nbsp, nbsp, nbsp,
            $typeBtnRare
        ]);

    /* Add click handlers to the type of item section buttons */
    $typeBtnCommon.click(function () {
        var $mwtextarea = $('.wikiEditor-ui-text textarea');
        $mwtextarea.data('type', 'common');
        $('#fieldset1,#PropInfo,#DisambigInfo,#buttonSubmitProp,#tabs')
            .toggle();
        $tabsList.append([tab2, tab4]);
        $("#toolmenu")
            .tabs();
    });
    $typeBtnRare.click(function () {
        var $mwtextarea = $('.wikiEditor-ui-text textarea');
        $mwtextarea.data('type', 'rare');
        $('#fieldset1,#RareInfo1,#RareInfo2,#PropInfo,#DisambigInfo,#buttonSubmitProp,#tabs')
            .toggle();
        $tabsList.append([tab1, tab3, tab2, tab4]);
        $("#toolmenu")
            .tabs();
        buildRareFields();
    });

    /* Initialize selects and info collection area for item property section */
    var $select1 = populateSelect($('<select>', {
            id: 'select1'
        }), propertyInfo.category, true),
        $propinfo = makeFieldset('propInfo', ''),
        $proptext = $('<div>', {
            id: 'propText'
        }),
        $select2 = $('<select>', {
            id: 'select2'
        }),
        $submitProp = $(makeElem(input, 'SubmitProp', {
            style: 'position: absolute;bottom: 7%;right: 3%;color:rgb(224, 172, 67);',
            type: 'button',
            value: 'Add this property'
        }))
        .button()
        .hide();

    /* Add selects and info collection area for item property section to the page */
    $field3.append(
            [$select1,
                nbsp,
                $select2.hide(),
                br, br,
                $proptext,
                br, br,
                $propinfo
            ])
        .after($submitProp)
        .after(br + br + br + br + br + br);

    /* Parse existing template data */
    readTemplate();

    /* Initialize popup dialog */
    $toolmenu.appendTo('body')
        .dialog({
            title: 'Item Template Editor',
            autoOpen: false,
            position: {
                my: 'center',
                at: 'center-125',
                of: window
            },
            modal: true,
            width: 890,
            height: 900,
            close: function () {
                $('#PropBox')
                    .dialog('close');
            },
            open: function () {
                if ($('#PropBox')
                    .length > 0 && !$('#PropBox')
                    .dialog("isOpen")) {
                    $('#PropBox')
                        .dialog('open');
                }
            }
        });
    $propertyBox.dialog({
            autoOpen: false,
            height: 700,
            width: 250,
            position: {
                my: 'left bottom',
                at: 'right bottom',
                of: $('#toolmenu')
                    .parent()
            }
        })
        .siblings('div.ui-dialog-titlebar')
        .remove();
    buildDisambigTab();
    switch ($('.wikiEditor-ui-text textarea')
        .data('type')) {
    case 'common':
        $('#fieldset1')
            .hide();
        $('#PropInfo,#DisambigInfo,#buttonSubmitProp')
            .show();
        break;
    case 'rare':
        $('#fieldset1')
            .hide();
        $('#RareInfo1,#RareInfo2,#PropInfo,#DisambigInfo,#buttonSubmitProp,#tabs')
            .show();
        $("#toolmenu")
            .tabs();
        buildRareFields();
    }

    /* Click handler for the 'save edits' button */
    $('#saveButton')
        .click(function () {
            var rareData = [],
                $parents = $('#RareInfo1, #RareInfo2, #DisambigInfo');

            $parents.find('input[type=text]')
                .filter(function () {
                    return !!this.value;
                })
                .each(function () {
                    var $this = $(this);
                    rareData.push([$this.parent()
                        .data('param'), $this.val()
                    ]);
                });
            $parents.find('input[type=checkbox]:checked')
                .each(function () {
                    var $this = $(this);
                    rareData.push([$this.parent()
                        .data('param'), 1
                    ]);
                });
            $parents.find('select:not(#addTypeSelect)')
                .filter(function () {
                    return this.value > -1;
                })
                .each(function () {
                    var $this = $(this);
                    rareData.push([$this.parent()
                        .data('param'), $this.val()
                    ]);
                });

            var outputArr = $.merge(rareData, $mwtextarea
                .data('params')
                .pairs);

            var disambig = outputArr.indexOf('disambiguation_page'),
                outputStr = '';

            if ($mwtextarea.data('type') == 'common' && disambig > -1) {
                disambig = outputArr.splice(disambig, 1);
                disambig = '\n{{UO Disambiguation Header\n| ' + disambig.join(' = ') + '\n}}';
            } else {
                disambig = '';
            }

            for (i = 0; i < outputArr.length; i++) {
                outputStr += '| ' + outputArr[i].join(' = ') + '\n';
            }
            outputStr = '{{' + ($mwtextarea.data('type') == 'common' ? 'InfoBox_UOItem' : 'RareItem') + '\n' + outputStr + '}}' + disambig;
            $mwtextarea.val(outputStr + $mwtextarea.val()
                .replace(/{{(?:RareItem|InfoBox[\s|_]UOItem)[\s\S]*}}/, ''));
            $toolmenu.dialog("close");
            $('#wpSave')
                .trigger('click');
        });

    /* Click handler for the 'cancel editing' button */
    $('#cancelButton')
        .click(function () {
            $toolmenu.dialog("close");
        });

    /* Click handler for the 'add type' button */
    $('#addTypeButton')
        .click(function () {
            $('#saveButton')
                .show();
            var $typeDisplay = $('#addTypeDisplay');
            var types = $typeDisplay.val()
                .split(/,\s?/g);
            types.push($('#addTypeSelect option:selected')
                .val());
            $typeDisplay.val([...new Set(types)].join(', '));
        });

    /* Click handler for the 'delete property' button */
    $('#propDisplay')
        .on('click', '.removePropButton', function () {
            $('#saveButton')
                .show();
            var $parent = $(this)
                .parent();
            spliceParam($parent.attr('data-propnum'));
            $('#propDisplay')
                .empty();
            addArrayToPropertyList($mwtextarea.data('params')
                .pairs);
        });

    /* Show the 'save edits' button whenever any edit has been made */
    $('#toolmenu')
        .on('change keyup', 'select, input', function () {
            $('#saveButton')
                .show();
        });

    /* Change handler for select 1 */
    $select1.change(function () {
        var $this = $(this);
        var selected = $this.find(':selected')
            .val();
        var thisOption = $select1.data('source')[selected];
        $proptext.empty();
        $propinfo.empty();
        if (selected !== "none") {
            if (selected === "all") {
	            let allOpt = [];
				$('#select1').data('source').forEach(group => {
    				if (group.hasOwnProperty('options')) {
				        allOpt.push(...group.options);
					}
				});
				allOpt = allOpt.sort((a, b) => (a.name > b.name) ? 1 : -1);
               	populateSelect($select2, allOpt);
            } else {
            	var type = getOptionType($this, selected);
            	if (type == 'option') {
	                $select2.show();
    	            populateSelect($select2, thisOption.options);
        	    } else {
            	    $select2.hide();
                	$propinfo.append(handleOption(thisOption));
            	}
            }
        } else {
            $select2.hide();
        }
    });

    /* Change handler for select 2 */
    $select2.change(function () {
        var $this = $(this);
        var selected = $this.find(':selected')
            .val();
        var thisOption = $select2.data('source')[selected];
        $proptext.empty();
        $propinfo.empty();
        if (selected !== "none") {
            handleOption(thisOption);
            $propinfo.append(handleOption(thisOption));
        }
    });

    /* Save Property button handler */
    $submitProp.click(function () {
        var $propField = $('#fieldsetpropInfo');
        var $children = $propField.children(':not(span)');
        var childCount = $children.length,
            showError = function (err) {
                $('#propText')
                    .html(stratics.f.util.makehtml('span', {
                        style: 'color:red;'
                    }, err));
                errorcount++;
            },
            highlightField = function ($obj) {
                $obj.css('background', 'brown')
                    .addClass('lastError');
            };

        $('#propText')
            .empty();
        $('.lastError')
            .css('background', '#101010')
            .removeClass('lastError');

        /* Check that any property fields exist */
        if (childCount === 0) {
            showError("You don't have any property selected!");
        } else {

            var option = $('#toolmenu')
                .data('option'),
                values = [],
                errorcount = 0,
                val;

            if (option === 'undefined') {
                showError("You don't have any property selected!");
            } else {
                var output = [].concat(option.output);

                for (var i = 0; i < childCount; i++) {
                    var $thisChild = $children.eq(i);
                    var eletype = $thisChild.prop('nodeName');
                    if (eletype === 'SELECT') {
                        var type = $thisChild.data('type');
                        val = $thisChild.val();
                        if (val === 'none') {
                            highlightField($thisChild);
                            showError("You haven't set a value for this property!");
                        } else {
                            if (type === 'list') {
                                if (/#/.test(output[i])) {
                                    values.push(output[i].replace('#', val.replace("Just 'Mana Burst'", ''))
                                        .split('='));
                                } else {
                                    values.push([output[i], val]);
                                }
                            } else if (type === 'state') {
                                values.push(val.split('='));
                            }
                        }
                    } else if (eletype === 'INPUT') {
                        switch ($thisChild.attr('type')) {
                        case 'checkbox':
                            val = $thisChild.is(':checked');
                            if (val === false) {
                                highlightField($thisChild);
                                showError("Only add this property if it is true (ie, the checkbox is checked).");
                            } else {
                                values.push([output[i], 1]);
                            }
                            break;
                        case 'number':
                            /* falls through */
                        case 'text':
                            val = $thisChild.val();
                            if (val.length === 0) {
                                highlightField($thisChild);
                                showError("You haven't set a value for this property!");
                            } else {
                                if (/#/.test(output[i])) {
                                    values.push(output[i].replace('#', val)
                                        .split('='));
                                } else {
                                    output[i] = output[i].split('|');
                                    if (output[i].length == 2) {
                                        values.push(output[i][0].split('='));
                                        values.push([output[i][1], val]);
                                    } else {
                                        values.push([output[i][0], val]);
                                    }
                                }

                            }
                        }
                    } else {
                        /* This should be unreachable. */
                    }
                }
                /* Check for any redundant properties */
                var errCnt = 0,
                    matchIndex;

                for (var v = 0; v < values.length; v++) {
                    matchIndex = lookupParamIndex(values[v][0]);
                    if (matchIndex > -1) {
                        errCnt++;
                        highlightField($('#propDisplay div:eq(' + matchIndex + ')'));
                    }
                }
                if (errCnt == 1) {
                    showError("This property already exists.");
                } else if (errCnt > 1) {
                    showError("These properties already exist.");
                }

                if (errorcount === 0) {
                    $('#saveButton')
                        .show();
                    addArrayToPropertyList(values);
                    $proptext.empty();
                    $propinfo.empty();
                    $select1.val('none')
                        .trigger('change');
                }
            }
        }
    });
    $('.namespace')
        .after($('<a>')
            .addClass('buttonTrigger')
            .text('Open Item Editor')
            .click(function (e) {
                e.preventDefault();
                $('#toolmenu')
                    .dialog('open');
            }));
};