Ich möchte eine einfache Funktion erstellen, die Text in einen Textbereich an der Cursorposition des Benutzers einfügt. Es muss eine saubere Funktion sein. Nur die Grundlagen. Ich kann den Rest herausfinden.
Ich möchte eine einfache Funktion erstellen, die Text in einen Textbereich an der Cursorposition des Benutzers einfügt. Es muss eine saubere Funktion sein. Nur die Grundlagen. Ich kann den Rest herausfinden.
Antworten:
function insertAtCursor(myField, myValue) {
//IE support
if (document.selection) {
myField.focus();
sel = document.selection.createRange();
sel.text = myValue;
}
//MOZILLA and others
else if (myField.selectionStart || myField.selectionStart == '0') {
var startPos = myField.selectionStart;
var endPos = myField.selectionEnd;
myField.value = myField.value.substring(0, startPos)
+ myValue
+ myField.value.substring(endPos, myField.value.length);
} else {
myField.value += myValue;
}
}
} else {
myField.selectionStart = startPos + myValue.length;
myField.selectionEnd = startPos + myValue.length;
Dieses Snippet könnte Ihnen dabei in einigen Zeilen von jQuery 1.9+ helfen: http://jsfiddle.net/4MBUG/2/
$('input[type=button]').on('click', function() {
var cursorPos = $('#text').prop('selectionStart');
var v = $('#text').val();
var textBefore = v.substring(0, cursorPos);
var textAfter = v.substring(cursorPos, v.length);
$('#text').val(textBefore + $(this).val() + textAfter);
});
Für das richtige Javascript
HTMLTextAreaElement.prototype.insertAtCaret = function (text) {
text = text || '';
if (document.selection) {
// IE
this.focus();
var sel = document.selection.createRange();
sel.text = text;
} else if (this.selectionStart || this.selectionStart === 0) {
// Others
var startPos = this.selectionStart;
var endPos = this.selectionEnd;
this.value = this.value.substring(0, startPos) +
text +
this.value.substring(endPos, this.value.length);
this.selectionStart = startPos + text.length;
this.selectionEnd = startPos + text.length;
} else {
this.value += text;
}
};
this.value = ...
. Gibt es eine Möglichkeit, es zu bewahren?
https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/setRangeText
Ich bin mir jedoch nicht sicher, ob der Browser dies unterstützt.
Getestet in Chrome 81.
function typeInTextarea(newText, el = document.activeElement) {
const [start, end] = [el.selectionStart, el.selectionEnd];
el.setRangeText(newText, start, end, 'select');
}
document.getElementById("input").onkeydown = e => {
if (e.key === "Enter") typeInTextarea("lol");
}
<input id="input" />
<br/><br/>
<div>Press Enter to insert "lol" at caret.</div>
<div>It'll replace a selection with the given text.</div>
Eine reine JS-Modifikation von Erik Pukinskis 'Antwort:
function typeInTextarea(newText, el = document.activeElement) {
const start = el.selectionStart
const end = el.selectionEnd
const text = el.value
const before = text.substring(0, start)
const after = text.substring(end, text.length)
el.value = (before + newText + after)
el.selectionStart = el.selectionEnd = start + newText.length
el.focus()
}
document.getElementById("input").onkeydown = e => {
if (e.key === "Enter") typeInTextarea("lol");
}
<input id="input" />
<br/><br/>
<div>Press Enter to insert "lol" at caret.</div>
Getestet in Chrome 47, 81 und Firefox 76.
Wenn Sie den Wert des aktuell ausgewählten Texts ändern möchten, während Sie in dasselbe Feld eingeben (für eine automatische Vervollständigung oder einen ähnlichen Effekt), übergeben Sie document.activeElement
als ersten Parameter.
Es ist nicht die eleganteste Art, dies zu tun, aber es ist ziemlich einfach.
Beispielverwendungen:
typeInTextarea('hello');
typeInTextarea('haha', document.getElementById('some-id'));
Version 54.0.2813.0 canary (64-bit)
Chrome Canary 54.0.2813.0. Wenn Sie möchten, dass es nach ID in das Textfeld eingefügt wird, verwenden Sie es document.getElementById('insertyourIDhere')
anstelle von el
in der Funktion.
Erik Pukinskis
. Ich werde die Antwort aktualisieren, um dies besser widerzuspiegeln.
Eine einfache Lösung, die auf Firefox, Chrome, Opera, Safari und Edge funktioniert, aber wahrscheinlich nicht auf alten IE-Browsern funktioniert.
var target = document.getElementById("mytextarea_id")
if (target.setRangeText) {
//if setRangeText function is supported by current browser
target.setRangeText(data)
} else {
target.focus()
document.execCommand('insertText', false /*no UI*/, data);
}
}
setRangeText
Mit dieser Funktion können Sie die aktuelle Auswahl durch den bereitgestellten Text ersetzen. Wenn keine Auswahl vorhanden ist, fügen Sie den Text an der Cursorposition ein. Soweit ich weiß, wird es nur von Firefox unterstützt.
Für andere Browser gibt es den Befehl "insertText", der sich nur auf das aktuell fokussierte HTML-Element auswirkt und dasselbe Verhalten wie hat setRangeText
Teilweise inspiriert von diesem Artikel
execCommand
es jedoch, weil es Insert-Text-Textarea unterstützt undo
und erstellt hat . Keine IE-Unterstützung, aber kleiner
execCommand
von MDN leider als veraltet angesehen: developer.mozilla.org/en-US/docs/Web/API/Document/execCommand Ich weiß nicht warum, es scheint wirklich nützlich zu sein!
Rabs Antwort funktioniert gut, aber nicht für Microsoft Edge. Deshalb habe ich auch eine kleine Anpassung für Edge hinzugefügt:
https://jsfiddle.net/et9borp4/
function insertAtCursor(myField, myValue) {
//IE support
if (document.selection) {
myField.focus();
sel = document.selection.createRange();
sel.text = myValue;
}
// Microsoft Edge
else if(window.navigator.userAgent.indexOf("Edge") > -1) {
var startPos = myField.selectionStart;
var endPos = myField.selectionEnd;
myField.value = myField.value.substring(0, startPos)+ myValue
+ myField.value.substring(endPos, myField.value.length);
var pos = startPos + myValue.length;
myField.focus();
myField.setSelectionRange(pos, pos);
}
//MOZILLA and others
else if (myField.selectionStart || myField.selectionStart == '0') {
var startPos = myField.selectionStart;
var endPos = myField.selectionEnd;
myField.value = myField.value.substring(0, startPos)
+ myValue
+ myField.value.substring(endPos, myField.value.length);
} else {
myField.value += myValue;
}
}
Ich mag einfaches Javascript und habe normalerweise jQuery in der Nähe. Folgendes habe ich mir ausgedacht , basierend auf mparkuk's :
function typeInTextarea(el, newText) {
var start = el.prop("selectionStart")
var end = el.prop("selectionEnd")
var text = el.val()
var before = text.substring(0, start)
var after = text.substring(end, text.length)
el.val(before + newText + after)
el[0].selectionStart = el[0].selectionEnd = start + newText.length
el.focus()
}
$("button").on("click", function() {
typeInTextarea($("textarea"), "some text")
return false
})
Hier ist eine Demo: http://codepen.io/erikpukinskis/pen/EjaaMY?editors=101
function insertAtCaret(text) {
const textarea = document.querySelector('textarea')
textarea.setRangeText(
text,
textarea.selectionStart,
textarea.selectionEnd,
'end'
)
}
setInterval(() => insertAtCaret('Hello'), 3000)
<textarea cols="60">Stack Overflow Stack Exchange Starbucks Coffee</textarea>
Wenn der Benutzer die Eingabe nach dem Einfügen von Text nicht berührt, wird das Ereignis "Eingabe" nie ausgelöst, und das Wertattribut spiegelt die Änderung nicht wider. Daher ist es wichtig, das Eingabeereignis nach dem programmgesteuerten Einfügen von Text auszulösen. Das Feld zu fokussieren reicht nicht aus.
Das Folgende ist eine Kopie von Snorvargs Antwort mit einem Eingabetrigger am Ende:
function insertAtCursor(myField, myValue) {
//IE support
if (document.selection) {
myField.focus();
sel = document.selection.createRange();
sel.text = myValue;
}
// Microsoft Edge
else if(window.navigator.userAgent.indexOf("Edge") > -1) {
var startPos = myField.selectionStart;
var endPos = myField.selectionEnd;
myField.value = myField.value.substring(0, startPos)+ myValue
+ myField.value.substring(endPos, myField.value.length);
var pos = startPos + myValue.length;
myField.focus();
myField.setSelectionRange(pos, pos);
}
//MOZILLA and others
else if (myField.selectionStart || myField.selectionStart == '0') {
var startPos = myField.selectionStart;
var endPos = myField.selectionEnd;
myField.value = myField.value.substring(0, startPos)
+ myValue
+ myField.value.substring(endPos, myField.value.length);
} else {
myField.value += myValue;
}
triggerEvent(myField,'input');
}
function triggerEvent(el, type){
if ('createEvent' in document) {
// modern browsers, IE9+
var e = document.createEvent('HTMLEvents');
e.initEvent(type, false, true);
el.dispatchEvent(e);
} else {
// IE 8
var e = document.createEventObject();
e.eventType = type;
el.fireEvent('on'+e.eventType, e);
}
}
Gutschrift an plainjs.com für die TriggerEvent-Funktion
Mehr zum oninput event auf w3schools.com
Ich habe dies entdeckt, als ich einen Emoji-Picker für einen Chat erstellt habe. Wenn der Benutzer nur einige Emojis auswählt und auf die Schaltfläche "Senden" klickt, wird das Eingabefeld vom Benutzer nie berührt. Bei der Überprüfung des Wertattributs war es immer leer, obwohl die eingefügten Emoji-Unicodes im Eingabefeld sichtbar waren. Es stellt sich heraus, dass, wenn der Benutzer das Feld nicht berührt, das Eingabeereignis nie ausgelöst wurde und die Lösung darin bestand, es so auszulösen. Es hat eine ganze Weile gedauert, um dies herauszufinden ... ich hoffe, es wird jemandem Zeit sparen.
Veröffentlichen einer geänderten Funktion als eigene Referenz. In diesem Beispiel wird ein ausgewähltes Element aus dem <select>
Objekt eingefügt und das Caret zwischen die Tags eingefügt:
//Inserts a choicebox selected element into target by id
function insertTag(choicebox,id) {
var ta=document.getElementById(id)
ta.focus()
var ss=ta.selectionStart
var se=ta.selectionEnd
ta.value=ta.value.substring(0,ss)+'<'+choicebox.value+'>'+'</'+choicebox.value+'>'+ta.value.substring(se,ta.value.length)
ta.setSelectionRange(ss+choicebox.value.length+2,ss+choicebox.value.length+2)
}
/**
* Usage "foo baz".insertInside(4, 0, "bar ") ==> "foo bar baz"
*/
String.prototype.insertInside = function(start, delCount, newSubStr) {
return this.slice(0, start) + newSubStr + this.slice(start + Math.abs(delCount));
};
$('textarea').bind("keydown keypress", function (event) {
var val = $(this).val();
var indexOf = $(this).prop('selectionStart');
if(event.which === 13) {
val = val.insertInside(indexOf, 0, "<br>\n");
$(this).val(val);
$(this).focus();
}
})
Der folgende Code ist eine TypeScript-Anpassung des Pakets https://github.com/grassator/insert-text-at-cursor von Dmitriy Kubyshkin.
/**
* Inserts the given text at the cursor. If the element contains a selection, the selection
* will be replaced by the text.
*/
export function insertText(input: HTMLTextAreaElement | HTMLInputElement, text: string) {
// Most of the used APIs only work with the field selected
input.focus();
// IE 8-10
if ((document as any).selection) {
const ieRange = (document as any).selection.createRange();
ieRange.text = text;
// Move cursor after the inserted text
ieRange.collapse(false /* to the end */);
ieRange.select();
return;
}
// Webkit + Edge
const isSuccess = document.execCommand("insertText", false, text);
if (!isSuccess) {
const start = input.selectionStart;
const end = input.selectionEnd;
// Firefox (non-standard method)
if (typeof (input as any).setRangeText === "function") {
(input as any).setRangeText(text);
} else {
if (canManipulateViaTextNodes(input)) {
const textNode = document.createTextNode(text);
let 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
let offset = 0;
let startNode = null;
let endNode = null;
// To make a change we just need a Range, not a Selection
const range = document.createRange();
while (node && (startNode === null || endNode === null)) {
const 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 :(
const 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
const e = document.createEvent("UIEvent");
e.initEvent("input", true, false);
input.dispatchEvent(e);
}
}
function canManipulateViaTextNodes(input: HTMLTextAreaElement | HTMLInputElement) {
if (input.nodeName !== "TEXTAREA") {
return false;
}
let browserSupportsTextareaTextNodes;
if (typeof browserSupportsTextareaTextNodes === "undefined") {
const textarea = document.createElement("textarea");
textarea.value = "1";
browserSupportsTextareaTextNodes = !!textarea.firstChild;
}
return browserSupportsTextareaTextNodes;
}
Es wurde in getElementById (myField) geändert.
function insertAtCursor(myField, myValue) {
//IE support
if (document.selection) {
document.getElementById(myField).focus();
sel = document.selection.createRange();
sel.text = myValue;
}
//MOZILLA and others
else if (document.getElementById(myField).selectionStart || document.getElementById(myField).selectionStart == '0') {
var startPos = document.getElementById(myField).selectionStart;
var endPos = document.getElementById(myField).selectionEnd;
document.getElementById(myField).value = document.getElementById(myField).value.substring(0, startPos)
+ myValue
+ document.getElementById(myField).value.substring(endPos, document.getElementById(myField).value.length);
} else {
document.getElementById(myField).value += myValue;
}
}
myfield
als Lokal ist viel besser für die Leistung
document.getElementById(myField)
! Tun Sie es einmal oben und verwenden Sie einen Variablennamen. Wie oft hintereinander möchten Sie dasselbe Element redundant nachschlagen?