react-mde
Version:
React Markdown Editor
98 lines (97 loc) • 4.03 kB
JavaScript
;
/*!
* The MIT License
Copyright (c) 2018 Dmitriy Kubyshkin
Copied from https://github.com/grassator/insert-text-at-cursor
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.insertText = void 0;
/**
* Inserts the given text at the cursor. If the element contains a selection, the selection
* will be replaced by the text.
*/
function insertText(input, text) {
// Most of the used APIs only work with the field selected
input.focus();
// IE 8-10
if (document.selection) {
var ieRange = document.selection.createRange();
ieRange.text = text;
// Move cursor after the inserted text
ieRange.collapse(false /* to the end */);
ieRange.select();
return;
}
// Webkit + Edge
var isSuccess = document.execCommand("insertText", false, text);
if (!isSuccess) {
var start = input.selectionStart;
var end = input.selectionEnd;
// Firefox (non-standard method)
if (typeof input.setRangeText === "function") {
input.setRangeText(text);
}
else {
if (canManipulateViaTextNodes(input)) {
var textNode = document.createTextNode(text);
var node = input.firstChild;
// If textarea is empty, just insert the text
if (!node) {
input.appendChild(textNode);
}
else {
// Otherwise we need to find a nodes for start and end
var offset = 0;
var startNode = null;
var endNode = null;
// To make a change we just need a Range, not a Selection
var range = document.createRange();
while (node && (startNode === null || endNode === null)) {
var nodeLength = node.nodeValue.length;
// if start of the selection falls into current node
if (start >= offset && start <= offset + nodeLength) {
range.setStart((startNode = node), start - offset);
}
// if end of the selection falls into current node
if (end >= offset && end <= offset + nodeLength) {
range.setEnd((endNode = node), end - offset);
}
offset += nodeLength;
node = node.nextSibling;
}
// If there is some text selected, remove it as we should replace it
if (start !== end) {
range.deleteContents();
}
// Finally insert a new node. The browser will automatically
// split start and end nodes into two if necessary
range.insertNode(textNode);
}
}
else {
// For the text input the only way is to replace the whole value :(
var value = input.value;
input.value = value.slice(0, start) + text + value.slice(end);
}
}
// Correct the cursor position to be at the end of the insertion
input.setSelectionRange(start + text.length, start + text.length);
// Notify any possible listeners of the change
var e = document.createEvent("UIEvent");
e.initEvent("input", true, false);
input.dispatchEvent(e);
}
}
exports.insertText = insertText;
function canManipulateViaTextNodes(input) {
if (input.nodeName !== "TEXTAREA") {
return false;
}
var browserSupportsTextareaTextNodes;
if (typeof browserSupportsTextareaTextNodes === "undefined") {
var textarea = document.createElement("textarea");
textarea.value = "1";
browserSupportsTextareaTextNodes = !!textarea.firstChild;
}
return browserSupportsTextareaTextNodes;
}