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 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); }); } //