User:Alexis Jazz/Inline-editor.js

/*

Extremely minimalist editor for small edits like fixing typos. Triple click the paragraph and (if nothing goes wrong) its elements become editable and buttons appear to publish/cancel.

Todo:

Edit summary field/minor edit checkbox

Translations (import from MediaWiki)

Maybe check for duplicate paragraphs?

Show diff function?

Known/suspected limitations:

Cannot introduce new elements, only intended for plain text editing

Cannot alter link targets, references, markup, etc

Can only alter text that exists within a

If you enter wikitext it'll probably save the wikitext but you'd continue to see the unparsed wikitext until you reload the page

Possible bugs if you introduce new elements anyway

Won't work if templates or tags are used that transclude text that doesn't exist in the wikitext. For example, generates supertext "[1]" which breaks this script. As is very common, the script has been made to ignore references.

If the whole textContent of an element isn't unique in wikitext it might replace the wrong instance (Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo)

  • /

//This script is public domain, irrevocably released as WTFPL Version 2[www.wtfpl.net/about/] by its author, Alexis Jazz.

/*globals $:false,mw:false*/

window.AJQE={};

var AJQE=window.AJQE;

AJQE.msg = {

fail: 'failed to load inline editor',

save: 'Publish changes',

cancel: 'Cancel',

savefailregexp: 'failed to save changes (not found in wikitext)',

savefailapi: 'failed to save changes (API error: $ARG)', //do not translate "$ARG"

summary: 'inline-editor]',

success: 'Your edit was saved.'

};

AJQE.findTarget=function(target,wikitext,int){

if ( target.detail != 3 ) {

return;

}

if ( $('.AJIE')[0] ) { //only allow one editor instance at a time

return;

}

if ( ! wikitext ) {

AJQE.api.get( {action: 'query', prop: 'revisions', format: 'json', titles: mw.config.get('wgPageName'), rvlimit: 1, rvprop: 'timestamp|content|ids', rvslots: '*',

} ).then( function ( data ) {

AJQE.pageData=data;

if ( data.query && data.query.pages && data.query.pages[ Object.keys(data.query.pages)[0] ] && data.query.pages[ Object.keys(data.query.pages)[0] ].revisions && data.query.pages[ Object.keys(data.query.pages)[0] ].revisions[0] ) {

AJQE.pageRevisionCurrentText = data.query.pages[ Object.keys(data.query.pages)[0] ].revisions[0].slots.main['*'];

AJQE.revid=data.query.pages[ Object.keys(data.query.pages)[0] ].revisions[0].revid;

AJQE.findTarget(target,AJQE.pageRevisionCurrentText);

}

});

return;

}

AJQE.target=target.target;

AJQE.innerHTML=AJQE.target.innerHTML; //used to restore content upon cancel

AJQE.regexArr='(.*)';

for(int=0;int<4;int++){

if ( AJQE.target.tagName != 'P' ) {

AJQE.target = AJQE.target.parentElement;

}

}

if ( AJQE.target.tagName != 'P' ) { //we want to work on a paragraph as a single element may not have enough unique content to locate in wikitext

return;

} else {

AJQE.target.classList.add('AJIE');

}

for(int=0;int

if (AJQE.target.childNodes[int].nodeName == '#text' ) {

AJQE.newSpan=document.createElement('span');

AJQE.newSpan.innerText=AJQE.target.childNodes[int].textContent;

$('.AJIE')[0].childNodes[int].replaceWith(AJQE.newSpan);

}

}

AJQE.int2=2;

for(int=0;int

if ( ! AJQE.target.childNodes[int].classList.contains('reference') && getComputedStyle(AJQE.target.childNodes[int]).display == 'inline' ) {

AJQE.target.childNodes[int].contentEditable='true'; //make every element of the paragraph editable. Do NOT make the

editable as that would (more often) allow introduction of new elements (by pressing ) which will trip things up

AJQE.regexArr+=mw.util.escapeRegExp(AJQE.target.childNodes[int].textContent)+'(.*)';

AJQE.int2++;

}

}

AJQE.checkRegEx=new RegExp(AJQE.regexArr);

AJQE.checkWikitextMatch=AJQE.pageRevisionCurrentText.match(AJQE.checkRegEx);

if ( AJQE.checkWikitextMatch ) {

AJQE.saveBtn=document.createElement('input');

AJQE.saveBtn.type='submit';

AJQE.saveBtn.id='AJQEsaveBtn';

AJQE.saveBtn.classList='cdx-button cdx-button--action-progressive cdx-button--weight-primary';

AJQE.saveBtn.style.display='inline-block'; //prevents the button from being inserted in wikitext

AJQE.saveBtn.value=AJQE.msg.save;

AJQE.target.append(AJQE.saveBtn);

$('#AJQEsaveBtn').on('click',AJQE.saveEdit);

AJQE.cancelBtn=document.createElement('input');

AJQE.cancelBtn.type='submit';

AJQE.cancelBtn.id='AJQEcancelBtn';

AJQE.cancelBtn.classList='cdx-button cdx-button--action-destructive';

AJQE.cancelBtn.style.display='inline-block'; //prevents the button from being inserted in wikitext

AJQE.cancelBtn.style.margin='0 1em 0 1em';

AJQE.cancelBtn.value=AJQE.msg.cancel;

AJQE.target.append(AJQE.cancelBtn);

$('#AJQEcancelBtn').on('click',AJQE.cancelEdit);

AJQE.target.childNodes[0].focus();

} else {

mw.notify(AJQE.msg.savefailregexp,{type:'error'});

}

};

AJQE.saveEdit=function(int){

AJQE.regexReplacement='$1';

AJQE.int2=2;

for(int=0;int

if ( ! AJQE.target.childNodes[int].classList.contains('reference') && getComputedStyle(AJQE.target.childNodes[int]).display == 'inline' ) {

AJQE.regexReplacement+=AJQE.target.childNodes[int].textContent+'$'+AJQE.int2;

AJQE.int2++;

}

}

AJQE.newWikitext=AJQE.pageRevisionCurrentText.replace(AJQE.checkRegEx,AJQE.regexReplacement);

if ( AJQE.newWikitext == AJQE.pageRevisionCurrentText ) {

mw.notify(AJQE.msg.savefailregexp,{type:'error'});

return;

}

AJQE.params = {format: 'json', assert:'user', action: 'edit', title: mw.config.get('wgPageName'), baserevid: AJQE.revid, watchlist: 'nochange', text: AJQE.newWikitext, summary: AJQE.msg.summary};

AJQE.api.postWithEditToken( AJQE.params ).then( function ( data ) {

mw.notify(AJQE.msg.success);

AJQE.removeEditor();

}, function ( code, data ) {

AJQE.removeEditor();

mw.notify(AJQE.msg.savefailapi.replace('$ARG',code),{type:'error'});

});

};

AJQE.removeEditor = function(int) {

for(int=0;int

if ( ! AJQE.target.childNodes[int].classList.contains('reference') && getComputedStyle(AJQE.target.childNodes[int]).display == 'inline' ) {

AJQE.target.childNodes[int].contentEditable='false';

}

}

$('#AJQEsaveBtn,#AJQEcancelBtn').remove();

AJQE.target.classList.remove('AJIE');

};

AJQE.cancelEdit = function() {

$('.AJIE')[0].innerHTML = AJQE.innerHTML;

$('.AJIE').removeClass('AJIE');

};

if ( mw.config.get('wgIsProbablyEditable') ) {

mw.loader.using(['mediawiki.api','mediawiki.util'], function(){

AJQE.api = new mw.Api();

$('#mw-content-text').on('click',AJQE.findTarget);

});

}

//