User:KokoroSenshi/common.js
Jump to navigation
Jump to search
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:
*
*/
var registerStrategiesFunctionDefault = function() {
var self = this;///
var params = self.params;
var strategies = self.strategies;
var templateName = self.templateName;
/** Validate parameters */
console.log("params: ");
console.log(params);
/**
* Turn each parameter into a strategy; assume no named parameters for now
*/
for (var paramName in params) {
if (params.hasOwnProperty(paramName)) {
console.log(paramName + " -> " + params[paramName]);
// Assume paramName is a number (as a String)
var precedingParamRegex = "";
var paramNum = parseInt(paramName);
for (var i = 1; i < paramNum; i++) {
precedingParamRegex += "\\|[^\\|\\}]*";
}
var strategy = self.createStrategy(
templateName,
paramName,
new RegExp("({{" + templateName + precedingParamRegex + "\\|)([^\\|\\}]*)$",""),
params[paramName],
function(name) { return name; },
function(name) { return "$1" + name; } // Removed the '}}' for generality for now; maybe will make exceptions for single or no parameter templates?
);
strategies.push(strategy);
}
}
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);
textcomplete.register(strategies);
};
var registerStrategiesFunctionInfinite = function() {
var self = this;///
var params = self.params;
var strategies = self.strategies;
var templateName = self.templateName;
/** Validate parameters */
console.log("params: ");
console.log(params);
/**
* Turn "1" in params into a strategy for all parameters; assume only one paramset for all params, which are all numbered
*/
var strategy = self.createStrategy(
templateName,
"",
new RegExp("({{" + templateName + "[^\\}]*\\|)([^\\|\\}]*)$",""),
params["1"],
function(name) { return name; },
function(name) { return "$1" + name; } // Removed the '}}' for generality for now; maybe will make exceptions for single or no parameter templates?
);
strategies.push(strategy);
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);
textcomplete.register(strategies);
};
if (mw.config.get("wgAction") == 'edit') {
/* Make the strategy/ies to add */
var Strategies = {};
Strategies.Templates = [];
Strategies.Templates.push(new TemplateStrategy(
"Color",
function() {
var self = this;
$.get( "https://zelda.gamepedia.com/Template:Color?action=raw", function( data ) {
/** Store parameter options in instance variable */
self.params["1"] = readArrayFromString(data);
/** Callback */
self.registerStrategies();
});
var readArrayFromString = function(text) {
var array = [];
text.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();
array.push(name);
});
return array;
};
},
registerStrategiesFunctionDefault
));
Strategies.Templates.push(new TemplateStrategy(
"KSTest",
function() { // Need to have self/this for params and registerStrategies()
var self = this;
/** Store parameter options in instance variable */
self.params["1"] = ["testparam1value1","testparam1value2","testparam1value3"];
self.params["2"] = ["testparam2value1","testparam2value2","testparam2value3"];
self.params["3"] = ["testparam3value1","testparam3value2","testparam3value3"];
/** Callback */
self.registerStrategies();
},
registerStrategiesFunctionDefault
));
Strategies.Templates.push(new TemplateStrategy(
"Icon",
function() {
var self = this;
$.get( "https://zelda.gamepedia.com/Template:Icon?action=raw", function( data ) {
/** Store parameter options in instance variable */
self.params["1"] = readArrayFromString(data);
/** Callback */
self.registerStrategies();
});
var readArrayFromString = function(text) {
var array = [];
text.split("</includeonly>")[0]
.split("\|#default")[0]
.match(/\n\|[a-zA-Z0-9-+ ]*/g)
.forEach(function(value, index){
var name = value.slice(2).trim();
array.push(name);
});
return array;
};
},
registerStrategiesFunctionDefault
));
var readInitialismsArrayFromString = function(callback) {
$.get( "https://zelda.gamepedia.com/Template:Zelda?action=raw", function( data ) {
var initialismsArray = [];
data.split("<noinclude>")[1]
.match(/\|\|[a-zA-Z0-9-+& ]*\n/g)
.forEach(function(value, index){
var name = value.slice(2).trim();
initialismsArray.push(name);
});
callback(initialismsArray);
});
};
readInitialismsArrayFromString(function(initialismsArray) {
Strategies.Templates.push(new TemplateStrategy(
"Exp Game",
function() {
var self = this;
/** Store parameter options in instance variable */
self.params["1"] = initialismsArray;
/** Callback */
self.registerStrategies();
},
registerStrategiesFunctionInfinite
));
});
// Getting a list of every template in the wiki is non-trivial...
/* Load Textcomplete then register the strategy/ies */
$(document).ready(function() {
getTextcompleteScript(
Strategies.Templates // Array of TemplateStrategy objects to register each of
);
} );
}
function getTextcompleteScript(templateStrategyArray) {
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)" );
// (Global) Textarea object: https://github.com/yuku-t/textcomplete/issues/114#issuecomment-318352383
Textarea = Textcomplete.editors.Textarea;
templateStrategyArray.forEach(function(templateStrategy){ templateStrategy.register(); });
});
}
// Been going over OOP in JavaScript: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain#Example
/**
* Strategy Object
*/
/**
* Constructor (and non-prototype definitions)
* (instance variables can't be accessed without "this." etc.)
*/
function TemplateStrategy(templateName, getParametersFunction, registerStrategiesFunction) {
var self = this;
/*********************
** Public variables **
**********************/
this.templateName = templateName;
this.params = {}; // params.<name_of_param> = array of options // should each param have a 'description' variable too? applicable to both preset options and open-ended
this.strategies = [];
/********************
** Public methods **
********************/
/**
* register method
*/
this.register = function() {
self.getParameters(); // Must have callback to registerStrategies()
};
this.getParameters = getParametersFunction;
this.registerStrategies = registerStrategiesFunction;
this.createStrategy = function(name, param, match, paramArray, template, replace) {
var strategy =
{
id: "Template:" + name + "_" + param,
match: /(\|)([^\|\}]*)$/,
search: function (term, callback) {
// term should be the stuff after the latest "|"
var text = getBeforeCursor(el); //the text before the cursor
var templateStartPos = getTemplateStartPos(text);
var nameArray = paramArray.filter(function(currentValue) { return currentValue.startsWith(term); });
callback(nameArray); // List of possible completions ('names')
},
template: function (name) {
var displayName = template(name);
return displayName; // What to display in the list
},
replace: function (name) {
var replacementString = replace(name);
return replacementString; // What to replace the matched typed text with
}
};
return strategy;
};
}
function getBeforeCursor(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));
}
function getTemplateStartPos(text) {
var count = 0;
var index = text.length-2;
while (i >= 0) {
var char1 = text.charAt(i);
var char2 = text.charAt(i+1);
if (char1 == "}" && char2 == "}") {
count++;
index -= 2;
} else if (char1 == "{" && char2 == "{") {
count--;
index -= 2;
} else {
index -= 1;
}
if (count < 0) return index;
}
return -1;
}