Editing.js – MediaWiki

From Bohemia Interactive Community
Jump to navigation Jump to search
m (Some JS formatting)
(Add allowLineMove function)
Line 101: Line 101:
ecb.appendChild(cb);
ecb.appendChild(cb);
ecb.appendChild(label);
ecb.appendChild(label);
}
/*****************************************************************************************
* Allow moving source's selected line(s) with Alt+Up / Alt+Down (no Ctrl+Z, though)
* Maintainer: [[User:Lou Montana]]
*/
function allowLineMove() {
editingTextbox.addEventListener('keydown', (ev) => {
if (!ev.altKey || ev.ctrlKey || ev.shiftKey)
return;
let moveUp = ev.key == 'ArrowUp';
if (!moveUp && ev.key != 'ArrowDown')
return;
let lines = editingTextbox.value.split('\n');
let linesCount = lines.length;
if (linesCount == 0)
return;
let cursorStart = editingTextbox.selectionStart;
let cursorEnd = editingTextbox.selectionEnd;
let firstHighlightedLine = -1;
let lastHighlightedLine = -1;
let cursorStartColumn = -1;
let cursorEndColumn = -1;
let calcLength = 0;
let lineLength;
for (let i = 0; i < linesCount; ++i) {
lineLength = lines[i].length;
if (cursorStartColumn == -1 && cursorStart <= calcLength + lineLength) {
firstHighlightedLine = i;
cursorStartColumn = cursorStart - calcLength;
}
if (cursorEndColumn == -1 && cursorEnd <= calcLength + lineLength) {
lastHighlightedLine = i;
cursorEndColumn = cursorStart - calcLength;
}
if (cursorEndColumn != -1 && cursorEndColumn != -1)
break;
calcLength += lineLength + 1; // "\n"
}
if (cursorStartColumn == -1 || cursorEndColumn == -1)
return;
if (firstHighlightedLine > lastHighlightedLine)
[firstHighlightedLine, lastHighlightedLine] = [lastHighlightedLine, firstHighlightedLine];
if ((moveUp && firstHighlightedLine == 0) || (!moveUp && lastHighlightedLine == linesCount - 1))
return;
if (moveUp)
{
let movedLine = lines[firstHighlightedLine - 1];
lines.splice(firstHighlightedLine - 1, 1);
lines.splice(lastHighlightedLine, 0, movedLine);
cursorStart -= movedLine.length + 1;
cursorEnd -= movedLine.length + 1;
}
else
{
let movedLine = lines[lastHighlightedLine + 1];
lines.splice(lastHighlightedLine + 1, 1);
lines.splice(firstHighlightedLine, 0, movedLine);
cursorStart += movedLine.length + 1;
cursorEnd += movedLine.length + 1;
}
editingTextbox.value = lines.join('\n');
editingTextbox.selectionStart = cursorStart;
editingTextbox.selectionEnd = cursorEnd;
});
}
}


Line 108: Line 192:


allowTabs();
allowTabs();
allowLineMove();
darkModePreview();
darkModePreview();


}()); // END WRAPPER
}()); // END WRAPPER

Revision as of 01:00, 10 June 2024

/*****************************************************************************************
 * JavaScript here will be loaded by MediaWiki:Common.js when "editing mode" is detected.
 *
 *****************************************************************************************/

(function() { // BEGIN WRAPPER

	/*****************************************************************************************
	 * Variables required by all functions below
	 */

	var editingTextbox = document.getElementById("wpTextbox1");

	/*****************************************************************************************
	 * Add checkbox toggle of allowance to use TAB key in editing textarea to insert TAB chars
	 * Maintainer: [[User:Fred Gandt]]
	 */
	function allowTabs() {
		var ecb = document.getElementsByClassName("editCheckboxes")[0],
			cb = document.createElement("input"),
			cb_lbl = document.createElement("label"),
			tabsAllowed = function(evt) {
				if (evt.keyCode == 9) {
					evt.preventDefault();
					var ss = editingTextbox.selectionStart;
					editingTextbox.value = editingTextbox.value.substr(0, ss) + String.fromCharCode(evt.keyCode) + editingTextbox.value.substr(editingTextbox.selectionEnd);
					editingTextbox.setSelectionRange(ss + 1, ss + 1);
				}
			}

		initTabsAllowed = function() {
			editingTextbox.addEventListener("keydown", tabsAllowed, false);
			editingTextbox.form.action += "&allowTabs";
		};
		cb.setAttribute("id", "allowTabs");
		cb.setAttribute("type", "checkbox");
		cb.setAttribute("style", "margin-left: 3em");
		cb_lbl.setAttribute("for", "allowTabs");
		cb_lbl.setAttribute("title", "Allows insertion of Tab characters when and where the Tab key is pressed");
		cb_lbl.innerHTML = "&nbsp;Allow tabulations usage";
		cb.addEventListener("change", function() {
			if (this.checked) {
				initTabsAllowed();
			} else {
				editingTextbox.removeEventListener("keydown", tabsAllowed, false);
				editingTextbox.form.action = editingTextbox.form.action.replace("&allowTabs", "");
			}
		}, false);

		if (~window.location.search.indexOf("&allowTabs")) {
			cb.checked = true;
			initTabsAllowed();
		}

		ecb.appendChild(cb);
		ecb.appendChild(cb_lbl);
	}

	/*****************************************************************************************
	 * Prevents page body scrolling when scrolling of the editing textarea reaches the top or bottom.
	 * Maintainer: [[User:Fred Gandt]]
	 */
	function holdStill() {
		editingTextbox.addEventListener("mousewheel", function(evt) {
			evt.preventDefault();
			editingTextbox.scrollTop -= evt.wheelDelta / 3;
		}, false);
	}

	/*****************************************************************************************
	 * Add a checkbox to preview darkmode (?useskin=darkvector)
	 * Maintainer: [[User:Lou Montana]]
	 */
	function darkModePreview() {
		var ecb = document.getElementsByClassName("editCheckboxes")[0],
			cb = document.createElement("input"),
			label = document.createElement("label"),
			actionDarkAdd = "&useskin=darkvector";
			actionLightAdd = "&useskin=vector";

		cb.setAttribute("id", "previewDarkMode");
		cb.setAttribute("type", "checkbox");
		cb.setAttribute("style", "margin-left: 3em");
		label.setAttribute("for", "previewDarkMode");
		label.setAttribute("title", "Preview Dark Mode render (next preview)");
		label.innerHTML = "&nbsp;Preview Dark Mode";
		cb.addEventListener("change", function() {
			if (this.checked) {
				editingTextbox.form.action = editingTextbox.form.action.replace(actionLightAdd, "")
				editingTextbox.form.action += actionDarkAdd;
			} else {
				editingTextbox.form.action = editingTextbox.form.action.replace(actionDarkAdd, "");
				editingTextbox.form.action += actionLightAdd;
			}
		}, false);

		cb.checked = document.getElementsByTagName("body")[0].classList.contains("skin-darkvector");
		let event = new Event("change");
		cb.dispatchEvent(event);

		ecb.appendChild(cb);
		ecb.appendChild(label);
	}

	/*****************************************************************************************
	 * Allow moving source's selected line(s) with Alt+Up / Alt+Down (no Ctrl+Z, though)
	 * Maintainer: [[User:Lou Montana]]
	 */
	function allowLineMove() {

		editingTextbox.addEventListener('keydown', (ev) => {

			if (!ev.altKey || ev.ctrlKey || ev.shiftKey)
				return;

			let moveUp = ev.key == 'ArrowUp';
			if (!moveUp && ev.key != 'ArrowDown')
				return;

			let lines = editingTextbox.value.split('\n');
			let linesCount = lines.length;
			if (linesCount == 0)
				return;

			let cursorStart = editingTextbox.selectionStart;
			let cursorEnd = editingTextbox.selectionEnd;

			let firstHighlightedLine = -1;
			let lastHighlightedLine = -1;
			let cursorStartColumn = -1;
			let cursorEndColumn = -1;
			let calcLength = 0;
			let lineLength;
			for (let i = 0; i < linesCount; ++i) {

				lineLength = lines[i].length;

				if (cursorStartColumn == -1 && cursorStart <= calcLength + lineLength) {

					firstHighlightedLine = i;
					cursorStartColumn = cursorStart - calcLength;
				}

				if (cursorEndColumn == -1 && cursorEnd <= calcLength + lineLength) {

					lastHighlightedLine = i;
					cursorEndColumn = cursorStart - calcLength;
				}

				if (cursorEndColumn != -1 && cursorEndColumn != -1)
					break;

				calcLength += lineLength + 1; // "\n"
			}

			if (cursorStartColumn == -1 || cursorEndColumn == -1)
				return;

			if (firstHighlightedLine > lastHighlightedLine)
				[firstHighlightedLine, lastHighlightedLine] = [lastHighlightedLine, firstHighlightedLine];

			if ((moveUp && firstHighlightedLine == 0) || (!moveUp && lastHighlightedLine == linesCount - 1))
				return;

			if (moveUp)
			{
				let movedLine = lines[firstHighlightedLine - 1];
				lines.splice(firstHighlightedLine - 1, 1);
				lines.splice(lastHighlightedLine, 0, movedLine);
				cursorStart -= movedLine.length + 1;
				cursorEnd -= movedLine.length + 1;
			}
			else
			{
				let movedLine = lines[lastHighlightedLine + 1];
				lines.splice(lastHighlightedLine + 1, 1);
				lines.splice(firstHighlightedLine, 0, movedLine);
				cursorStart += movedLine.length + 1;
				cursorEnd += movedLine.length + 1;
			}

			editingTextbox.value = lines.join('\n');

			editingTextbox.selectionStart = cursorStart;
			editingTextbox.selectionEnd = cursorEnd;
		});
	}

	/*****************************************************************************************
	 * Call the required functions from those above
	 */

	allowTabs();
	allowLineMove();
	darkModePreview();

}()); // END WRAPPER