User:NguoiDungKhongDinhDanh/CodeAjaxEditor.js
Appearance
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)
- Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
/**
* CodeAjaxEditor: Make the code you see on JS/CSS/Lua pages editable without loading CodeEditor.
*
* Skin tested: Vector, Vector 2022, Monobook, Timeless.
*
* After clicking the link that activates it in the "More" menu, you will see a button to submit
* whatever you typed. Two prompts will then appear to ask for edit summary and minor marking.
* If you want to abort the submitting progress, cancel the first prompt. In the case of failing
* to make the edit, all codes will be copied to your clipboard; a notification will then appear.
* Click it before it disappear will take you to the edit page where you can paste your codes
* and save manually.
*
* Please note that CodeAjaxEditor is not supposed to be a real editor and may be buggy;
* The CodeEditor extension should be preferred for syntaxhighlighting and other features.
*
* License: CC BY-SA.
**/
mw.loader.using(['oojs-ui-core', 'mediawiki.util']).done(function() {
if (!['javascript', 'css', 'sanitized-css', 'Scribunto'].includes(mw.config.get('wgPageContentModel'))) {
return;
}
mw.util.addPortletLink('p-cactions', '', 'CAE', 'ca-cae', 'Initialize CodeAjaxEditor');
$('#ca-cae').click(function(e) {
e.preventDefault();
if ($('#CAE-pre').length) {
mw.notify('CodeAjaxEditor has already been enabled!', {
type: 'warn',
autoHide: true,
autoHideSeconds: 10,
tag: 'CAE-ready'
});
return;
}
var CAE = {};
window.CAE = CAE;
/ For attribution: /stackoverflow.com/q/16580841
CAE.insert = function(v) {
var sel, range;
if (window.getSelection) {
sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
range = sel.getRangeAt(0);
range.deleteContents();
var el = document.createElement('div');
el.innerText = v;
var frag = document.createDocumentFragment(), node, lastNode;
while ((node = el.firstChild)) {
lastNode = frag.appendChild(node);
}
range.insertNode(frag);
if (lastNode) {
range = range.cloneRange();
range.setStartAfter(lastNode);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
}
}
}
};
var css = `
#CAE-submit {
position: fixed;
bottom: 2em;
right: 2em;
}
#CAE-pre:focus {
outline: 0;
}
`;
try {
mw.util.addCSS(css);
} catch(e) {
mw.util.addStyleTag(css);
}
CAE.confirm = false;
onbeforeunload = function() { / Alert when user attempt to leave.
if (!CAE.confirm) return 'You have unsaved changes. Do you really want to leave?';
};
CAE.submit = new OO.ui.ButtonWidget({
label: 'Submit',
flags: [
'primary',
'progressive'
],
id: 'CAE-submit'
});
$('body').append(CAE.submit.$element);
var selector = $('.mw-highlight > pre').length > 0 ? '.mw-highlight > pre' : '#mw-content-text pre.mw-code';
$(selector)
.attr('id', 'CAE-pre') / Give it an id for ease of select.
.prop('contenteditable', true); / Main feature.
mw.notify('Content is now editable. Please note that CodeAjaxEditor is not supposed to be a real editor and may be buggy. ' +
'The CodeEditor extension should be preferred for syntaxhighlighting and other features.', {
title: 'Initialized.',
autoHide: true,
autoHideSecond: 10
});
$('#CAE-pre').on('keydown', function(e) {
if (e.which == 9) {
e.preventDefault();
CAE.insert('\t');
} else if (e.which == 13) {
e.preventDefault();
CAE.insert('\n');
} else return;
});
$('#CAE-submit').click(function() {
/ UX.
CAE.submit.setLabel('Submitting...');
CAE.submit.setDisabled(true);
/ Prompt for summary.
var es, me;
try {
es = prompt('Edit summary (cancel to abort):').trim();
es += ' (via [[:m:User:NguoiDungKhongDinhDanh/CodeAjaxEditor.js|CAE]])';
} catch (e) {
CAE.submit.setDisabled(false);
CAE.submit.setLabel('Submit');
return console.log('CodeAjaxEditor: Aborted.');
}
me = confirm('Mark this edit as minor?');
/ Turn off event handler (i.e. this one).
$(this).off();
/ Dirty but works.
$('#CAE-pre').html($('#CAE-pre').html().replace(/<br ?\/?>/g, '\n'));
/ API request.
(new mw.Api()).postWithToken('csrf', {
action: 'edit',
title: mw.config.get('wgPageName'),
text: $('#CAE-pre').text(),
summary: es,
minor: me,
nocreate: true,
format: 'json',
formatversion: 2
}).done(function(response) {
CAE.submit.setLabel('Submitted.');
mw.notify('Changes made successfully. Reloading...', {
title: 'Saved!',
type: 'success',
autoHide: false,
tag: 'CAE-notification'
});
CAE.confirm = true;
location.reload();
}).fail(function(response) {
/ Old browsers support.
/ For attribution: [[:en:User:Qwerfjkl/scripts/copy.js]]
var ta = document.createElement('textarea');
ta.textContent = $('#CAE-pre').text();
ta.style.position = 'fixed';
document.body.appendChild(ta);
ta.select();
document.execCommand('copy');
document.body.removeChild(ta);
CAE.submit.setLabel('Submitted.');
var e;
if ($($('#ca-edit > a')[0]).attr('href')) e = $($('#ca-edit > a')[0]).attr('href');
else if ($($('#ca-viewsource > a')[0]).attr('href')) e = $($('#ca-viewsource > a')[0]).attr('href');
mw.notify('Could not edit the page. Changes has been copied to your clipboard. ' + (e ? 'Click to edit manually.' : ''), {
title: 'Failed!',
type: 'error',
autoHide: true,
autoHideSecond: 10,
tag: 'CAE-notification'
});
if (e) {
CAE.confirm = true;
$('.mw-notification-tag-CAE-notification').click(function() {
location.assign(e);
});
}
});
});
});
});