/**
* Allows for one click modification of list items when viewing a page
* add importScript('User:The Evil IP address/liedit.js'); to your .js file to use it
* @author Janko Hoener (The Evil IP address)
* @version 0.9.9 (beta)
*/
mw.loader.load('mediawiki.api');
window.liedit = {
REGEX_WIKI: /^\s*(\*+)[^\*]*/,
REGEX_HTML: /^\s*<li>.+(<\/li>)?\s*$/,
SIBLING: -1,
PARENT: 1,
EDIT_SUM_LIMIT: 170,
arraysEqual: function(a, b) {
// stolen from StackOverflow
if (a === b) return true;
if (a === null || b === null) return false;
if (a.length != b.length) return false;
// If you don't care about the order of the elements inside
// the array, you should sort both arrays here.
for (var i = 0; i < a.length; ++i) {
if (a[i] !== b[i]) return false;
}
return true;
},
onclick: function (event, $e) {
if ($e.is('table.infobox li')) {
liedit.set_error_msg('Sorry, cannot edit list items in infoboxes using this script.');
return;
}
if ($e.is('#toc li') || $e.has('form').length) {
return;
}
if (liedit.$e) {
liedit.cancel(event);
}
liedit.pagename = mw.config.get('wgPageName');
liedit.api = new mw.Api();
liedit.$e = $e;
liedit.api.get( {
action: 'parse',
page: liedit.pagename,
prop: 'sections',
format: 'json'
}).done( function (data) {
liedit.sections = {};
$.each(data.parse.sections, function (i, v) {
if (v.byteoffset) {
liedit.sections[v.anchor] = v.index;
}
}
);
cur_elem = liedit.$e[0];
liedit.index = 0;
abort = false;
last_move = liedit.SIBLING;
liedit.position = [0, 0];
for (i = 0; i < 10000 && !abort; i++) {
$cur_elem = $(cur_elem);
switch (cur_elem.localName) {
case 'li':
if (last_move == liedit.SIBLING) {
liedit.position[1]++;
}
if (last_move == liedit.PARENT) {
liedit.position.unshift(0);
}
break;
case 'ul':
liedit.position[0]++;
break;
case 'dl':
case 'dd':
if (last_move == liedit.PARENT) {
liedit.set_error_msg('Cannot edit this list item using this script.');
return;
}
break;
case 'h1':
case 'h2':
case 'h3':
case 'h4':
case 'h5':
case 'h6':
if ($cur_elem.attr('class') == 'firstHeading') {
liedit.index = 0;
abort = true;
break;
}
liedit.anchor = $cur_elem.find('span.mw-headline').first().attr('id');
if (liedit.anchor in liedit.sections) {
liedit.index = liedit.sections[liedit.anchor];
abort = true;
}
break;
}
if (cur_elem.previousElementSibling) {
cur_elem = cur_elem.previousElementSibling;
last_move = liedit.SIBLING;
}
else {
cur_elem = cur_elem.parentNode;
last_move = liedit.PARENT;
}
}
liedit.api.get( {
action: 'parse',
page: liedit.pagename,
section: liedit.index,
prop: 'wikitext',
format: 'json'
}).done( function (obj) {
liedit.wikitext = obj.parse.wikitext['*'];
liedit.wikitext = liedit.wikitext.replace(/([^\n])(<li>)/mgi, "$1\n$2");
liedit.lines = liedit.wikitext.split('\n');
currently_in_list = false;
current_list_wiki = false;
current_list_html = false;
cur_pos = [];
depth = liedit.position.length-1;
for (i = 0; i < liedit.position.length; i++) {
cur_pos.push(0);
}
for (i = 0; i < liedit.lines.length; i++) {
line = liedit.lines[i];
line_match_wiki = line.match(liedit.REGEX_WIKI);
line_match_html = line.match(liedit.REGEX_HTML);
if (line_match_html || line_match_wiki) {
if (!currently_in_list) {
currently_in_list = true;
if (line_match_wiki) {
current_list_wiki = true;
current_list_html = false;
}
else if (line_match_html) {
current_list_wiki = false;
current_list_html = true;
}
cur_pos[0]++;
cur_pos[1] = 1;
for (j = 2; j < cur_pos.length; j++) {
cur_pos[j] = 0;
}
}
else if (line_match_wiki && currently_in_list && current_list_html) {
cur_pos[0]++;
cur_pos[1] = 1;
for (j = 2; j < cur_pos.length; j++) {
cur_pos[j] = 0;
}
current_list_wiki = true;
current_list_html = false;
}
else if (line_match_html && currently_in_list && current_list_wiki) {
cur_pos[0]++;
cur_pos[1] = 1;
for (j = 2; j < cur_pos.length; j++) {
cur_pos[j] = 0;
}
current_list_wiki = false;
current_list_html = true;
}
else if (currently_in_list && current_list_wiki && line_match_wiki) {
line_depth = line.replace(liedit.REGEX_WIKI, '$1').length;
if (line_depth > depth) {
continue;
}
for (j = 1; j < line_depth; j++) {
if (cur_pos[j] === 0) {
cur_pos[j] = 1;
}
}
cur_pos[line_depth]++;
for (j = line_depth + 1; j < cur_pos.length; j++) {
cur_pos[j] = 0;
}
}
else if (currently_in_list && current_list_html && line_match_html) {
cur_pos[1]++;
}
liedit.li_index = i;
if (liedit.arraysEqual(liedit.position, cur_pos)) {
liedit.li_wikitext = line;
liedit.inputsize = liedit.li_wikitext.length*1.5;
var form = $('<form>').css('display', 'inline').submit(liedit.save);
var input = $('<input>').attr('id', 'liedit_input').attr('size', liedit.inputsize).val(liedit.li_wikitext);
var button1 = $('<button>').attr('id', 'liedit_submit').attr('type', 'submit').text('Save');
var button2 = $('<button>').attr('type', 'button').attr('id', 'liedit_cancel').text('Cancel').click(liedit.cancel);
$(form).append(input).append(button1).append(button2);
liedit.form = form;
$e.append(form);
return false;
}
}
else if (currently_in_list) {
currently_in_list = false;
}
}
liedit.set_error_msg('Sorry, this script could not identify the list item in the wikitext.')
liedit.li_wikitext = null;
liedit.li_index = null;
return false;
}
);
}
);
},
save: function () {
liedit.newwikitext = $(this).parent().find('input').val();
if (liedit.newwikitext == liedit.li_wikitext) return false;
if (liedit.newwikitext == '') {
liedit.lines.splice(liedit.li_index, 1);
liedit.line_removed = true;
}
else {
liedit.lines[liedit.li_index] = liedit.newwikitext;
liedit.line_removed = false;
}
liedit.wikitext = liedit.lines.join('\n');
$('#liedit_input, #liedit_submit, #liedit_cancel').attr('disabled', 'disabled');
liedit.summary = '';
if (liedit.anchor) {
liedit.summary += '/* ' + liedit.anchor + ' */ ';
}
if (liedit.line_removed) {
liedit.summary += 'List item removal using a [[User:The Evil IP address/liedit|script]] [beta]: ' + liedit.li_wikitext;
}
else {
liedit.summary += 'List item amendment using a [[User:The Evil IP address/liedit|script]] [beta]';
fullsum = liedit.summary + ': ' + liedit.li_wikitext + ' → ' + liedit.newwikitext;
if (fullsum.length < liedit.EDIT_SUM_LIMIT) {
liedit.summary = fullsum;
}
}
liedit.api.edit(liedit.pagename, function () {
return {
action: 'edit',
format: 'json',
minor: true,
section: liedit.index,
summary: liedit.summary,
text: liedit.wikitext,
};
}).then( function (resp) {
if (resp.result == 'Success') {
window.location.reload();
}
else if (resp.result == 'Failure') {
liedit.set_error_msg('API returned error code ' + data.error.code + ': ' + data.error.info);
}
else {
liedit.set_error_msg('Unknown API error.');
}
});
return false;
},
set_error_msg: function (msg) {
mw.notify(msg, {title: 'Error!', autoHide: false});
},
cancel: function (event) {
if (liedit.form) {
liedit.$e.show();
liedit.form.remove();
event.stopPropagation();
}
}
};
if (mw.config.get('wgNamespaceNumber') >= 0 && mw.config.get('wgAction') == 'view' && mw.config.get('wgIsProbablyEditable')) {
$('#mw-content-text ul li').click(function ( event ) {
liedit.onclick(event, $(this));
event.stopPropagation();
}
);
}