User:Alexis Jazz/Inline-editor.js
Appearance
Code that you insert on this page could contain malicious content capable of compromising your account. If you import a script from another page with "importScript", "mw.loader.load", "iusc", or "lusc", take note that this causes you to dynamically load a remote script, which could be changed by others. Editors are responsible for all edits and actions they perform, including by scripts. User scripts are not centrally supported and may malfunction or become inoperable due to software changes. A guide to help you find broken scripts is available. If you are unsure whether code you are adding to this page is safe, you can ask at the appropriate village pump. This code will be executed when previewing this page. |
This user script seems to have a documentation page at User:Alexis Jazz/Inline-editor. |
/*<nowiki>
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 <p>
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, <ref> generates supertext "[1]" which breaks this script. As <ref> 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: '[[[User:Alexis Jazz/Inline-editor|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<AJQE.target.childNodes.length;int++){ //we can't make textnodes editable, so we make them into spans
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<AJQE.target.childNodes.length;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 <p> editable as that would (more often) allow introduction of new elements (by pressing <enter>) 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<AJQE.target.childNodes.length;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<AJQE.target.childNodes.length;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);
});
}
//</nowiki>