Note: After publishing, you may have to bypass your browser's cache to see the changes.
- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
- Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
- Opera: Press Ctrl-F5.
/**
* Autocomplete/Dropdown list
* Uses https://yuku-t.com/textcomplete/
*
* Notes:
* - Won't work with CodeEditor since it doesn't use a textarea but that's fine
* since CodeEditor won't be used for wikitext
* - $.getScript() is used since mw.loader.load() doesn't wait for the code to load
* mw.loader.load('https://unpkg.com/textcomplete@0.13.1/dist/textcomplete.min.js');
* Bugs:
*
*/
if (mw.config.get("wgAction") == 'edit') {
/* Make the strategies to add */
var templates = {};
templates.Color = {};
$.get( "https://zelda.gamepedia.com/Template:Color?action=raw", function( data ) {
var colorsArray = [];
data.split("</includeonly>")[0]
.split("#switch:{{{1\|}}}")[1]
.split("\|#default")[0]
.match(/\|[a-zA-Z0-9 ]*/g)
.forEach(function(value, index){
var name = value.slice(1).trim();
colorArray.push(name);
});
templates.Color = {
"1": colorsArray
};
});
templates.KSTest = {
"1": ["testparam1value1","testparam1value2","testparam1value3"],
"2": ["testparam2value1","testparam2value2","testparam2value3"],
"3": ["testparam3value1","testparam3value2","testparam3value3"]
};
templates.Icon = {};
$.get( "https://zelda.gamepedia.com/Template:Icon?action=raw", function( data ) {
var iconsArray = [];
data.split("</includeonly>")[0]
.split("\|#default")[0]
.match(/\n\|[a-zA-Z0-9-+ ]*/g)
.forEach(function(value, index){
var name = value.slice(2).trim();
iconsArray.push(name);
});
templates.Icon = {
"1": iconsArray
};
});
var initialismsArray = [];
var readInitialisms = function(callback) {
$.get( "https://zelda.gamepedia.com/Template:Zelda?action=raw", function( data ) {
var initialisms = [];
data.split("<noinclude>")[1]
.match(/\|\|[a-zA-Z0-9-+& ]*\n/g)
.forEach(function(value, index){
var name = value.slice(2).trim();
initialisms.push(name);
});
initialismsArray = initialisms;
callback();
});
};
/** Initialisms-dependent templates: */
templates["Exp Game"] = {};
readInitialisms(function() {
templates["Exp Game"] = {
"1": initialismsArray
};
});
// Getting a list of every template in the wiki is non-trivial...
/* Load Textcomplete then register the strategies */
$(document).ready(getTextcompleteScript);
var getTextcompleteScript = function() {
console.log( "Loading textcomplete..." );
$.getScript( "https://unpkg.com/textcomplete/dist/textcomplete.min.js", function( data, textStatus, jqxhr ) {
console.log( [ data, textStatus, jqxhr.status ] ); // Data returned, Success, 200
console.log( "Loaded textcomplete. (Warning: May not be executed yet)" );
// Textarea object: https://github.com/yuku-t/textcomplete/issues/114#issuecomment-318352383
Textarea = Textcomplete.editors.Textarea; // Global variable
registerStrategies();
});
};
/* Note: The param arrays need ont exist before strategy is registered */
var registerStrategies = function() {
var editor = new Textarea(document.getElementById('wpTextbox1'))
, options = {
dropdown: {
maxCount: 500,
style: { 'margin-top': (-parseFloat($('body').css('margin-top')))+'px' }
}
}
, textcomplete = new Textcomplete(editor, options);
/** Register strategies */
textcomplete.register(templateStrategy);
};
var getBeforeCursor = function(el) { // Borrowed from https://github.com/yuku-t/textcomplete/blob/6f07195c47ace5e787cf7b46604b37a8bd5c6d30/src/textarea.js#L82
if (el === null) el = document.getElementById('wpTextbox1');
return el.selectionStart !== el.selectionEnd ? null : el.value.substring(0, el.selectionEnd);
};
var getTemplateStartPos = function(text) { // Assumes no "{{{" and "}}}" (perhaps ok even with these, anyway?), nor <nowiki> tags that would render "{{" or "}}" escaped/inactive,
var count = 0;
var index = text.length-2;
while (index >= 0) {
var char1 = text.charAt(index);
var char2 = text.charAt(index+1);
if (char1 === '}' && char2 === '}') {
count++;
index -= 2;
} else if (char1 === '{' && char2 === '{') {
count--;
index -= 2;
} else {
index -= 1;
}
if (count < 0) return index;
}
return -1;
};
var templateStrategy =
{
id: "Templates",
match: /(\|)([^\|]*)$/,
search: function (term, callback) {
// term should be the stuff after the latest "|"
var text = getBeforeCursor(el); //the text before the cursor
text = text.slice(0,text.length-term.length); //stuff before the term but including the "|"
var templateStartPos = getTemplateStartPos(text);
var templateName = text.slice(templateStartPos + 2);
//loop regex to remove the templates and tables (there should be no unmatched braces?) OR assume none
templateName = templateName.slice(0,text.indexOf("|"));
//count the number of "|" in text to determine which parameter (since it's e.g. "{{templateName|param1|param2|currentparam" )
var paramNum = 0;
for (var i=0; i<templateName.length; i++) if (templateName.charAt(i) == '|') paramNum++;
paramArray = templates[templateName][paramNum];
var nameArray = paramArray.filter(function(currentValue) { return currentValue.startsWith(term); });
callback(nameArray); // List of possible completions ('names')
},
template: function (name) {
var displayName = name;
return displayName; // What to display in the list
},
replace: function (name) {
var replacementString = "$1" + name;
return replacementString; // What to replace the matched typed text with
}
};
}