Tôi muốn tạo một chức năng đơn giản để thêm văn bản vào vùng văn bản tại vị trí con trỏ của người dùng. Nó cần phải là một chức năng sạch. Chỉ những điều căn bản. Tôi có thể tìm ra phần còn lại.
Tôi muốn tạo một chức năng đơn giản để thêm văn bản vào vùng văn bản tại vị trí con trỏ của người dùng. Nó cần phải là một chức năng sạch. Chỉ những điều căn bản. Tôi có thể tìm ra phần còn lại.
Câu trả lời:
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;
Đoạn mã này có thể giúp bạn với nó trong một vài dòng của jQuery 1.9+: 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);
});
Vì lợi ích của Javascript phù hợp
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 = ...
. Có cách nào để bảo quản không?
https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/setRangeText
Tôi không chắc về sự hỗ trợ của trình duyệt cho việc này.
Đã thử nghiệm trong 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>
Một sửa đổi JS thuần túy cho câu trả lời của Erik Pukinskis:
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>
Đã thử nghiệm trong Chrome 47, 81 và Firefox 76.
Nếu bạn muốn thay đổi giá trị của văn bản hiện đang được chọn trong khi bạn đang nhập trong cùng một trường (để có hiệu ứng tự động hoàn thành hoặc tương tự), hãy chuyển document.activeElement
làm tham số đầu tiên.
Đây không phải là cách thanh lịch nhất để làm điều này, nhưng nó khá đơn giản.
Cách sử dụng ví dụ:
typeInTextarea('hello');
typeInTextarea('haha', document.getElementById('some-id'));
Version 54.0.2813.0 canary (64-bit)
, về cơ bản là Chrome Canary 54.0.2813.0. Cuối cùng, nếu bạn muốn nó chèn vào hộp văn bản bằng ID, hãy sử dụng document.getElementById('insertyourIDhere')
thay el
cho hàm.
Erik Pukinskis
. Tôi sẽ cập nhật câu trả lời để phản ánh điều đó tốt hơn.
Một giải pháp đơn giản hoạt động trên firefox, chrome, opera, safari và edge nhưng có thể sẽ không hoạt động trên các trình duyệt IE cũ.
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
chức năng cho phép bạn thay thế lựa chọn hiện tại bằng văn bản được cung cấp hoặc nếu không có lựa chọn nào thì chèn văn bản vào vị trí con trỏ. Nó chỉ được hỗ trợ bởi firefox theo như tôi biết.
Đối với các trình duyệt khác, có lệnh "insertText" chỉ ảnh hưởng đến phần tử html hiện được tập trung và có hành vi tương tự như setRangeText
Lấy cảm hứng một phần từ bài viết này
execCommand
vì nó hỗ trợ undo
và tạo chèn-văn bản-văn bản . Không hỗ trợ IE nhưng nhỏ hơn
execCommand
được coi là lỗi thời bởi MDN: developer.mozilla.org/en-US/docs/Web/API/Document/execCommand Tôi không biết tại sao, nó có vẻ thực sự hữu ích!
Câu trả lời của Rab hoạt động tốt, nhưng không phù hợp với Microsoft Edge, vì vậy tôi cũng đã thêm một bản điều chỉnh nhỏ cho Edge:
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;
}
}
Tôi thích javascript đơn giản và tôi thường có jQuery xung quanh. Đây là những gì tôi nghĩ ra, dựa trên 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
})
Đây là bản 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>
Nếu người dùng không chạm vào đầu vào sau khi chèn văn bản, thì sự kiện 'đầu vào' sẽ không bao giờ được kích hoạt và thuộc tính giá trị sẽ không phản ánh thay đổi. Do đó, điều quan trọng là phải kích hoạt sự kiện đầu vào sau khi chèn văn bản theo chương trình. Tập trung lĩnh vực là không đủ.
Sau đây là bản sao câu trả lời của Snorvarg với một trình kích hoạt đầu vào ở cuối:
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);
}
}
Tín dụng để plainjs.com cho hàm triggerEvent
Thông tin thêm về sự kiện oninput tại w3schools.com
Tôi đã phát hiện ra điều này trong khi tạo bộ chọn biểu tượng cảm xúc cho một cuộc trò chuyện. Nếu người dùng chỉ cần chọn một vài biểu tượng cảm xúc và nhấn nút "gửi", trường nhập liệu sẽ không bao giờ được người dùng chạm vào. Khi kiểm tra thuộc tính giá trị, thuộc tính này luôn trống, mặc dù các mã đơn biểu tượng cảm xúc được chèn vẫn hiển thị trong trường nhập. Hóa ra rằng nếu người dùng không chạm vào trường, sự kiện 'đầu vào' sẽ không bao giờ được kích hoạt và giải pháp là kích hoạt nó như thế này. Phải mất khá nhiều thời gian để tìm ra điều này ... hy vọng nó sẽ giúp ai đó tiết kiệm thời gian.
Đăng chức năng đã sửa đổi để tham khảo riêng. Ví dụ này chèn một mục đã chọn từ <select>
đối tượng và đặt dấu mũ giữa các thẻ:
//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();
}
})
Đoạn mã dưới đây là bản chuyển thể TypeScript của gói https://github.com/grassator/insert-text-at-cursor của 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;
}
Đã thay đổi nó thành getElementById (myField)
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
dưới dạng cục bộ sẽ tốt hơn nhiều cho hiệu suất
document.getElementById(myField)
! Làm điều đó một lần ở trên cùng và sử dụng một tên biến. Bạn định tìm kiếm dư thừa cùng một phần tử bao nhiêu lần liên tiếp?