[英]JavaScript: Scroll to selection after using textarea.setSelectionRange in Chrome
javascript 函數使用 .setSelectionRange() 在 textarea 中選擇某個單詞。 在 Firefox 中,文本區域會自動向下滾動以顯示所選文本。 在 Chrome (v14) 中,它沒有。 有沒有辦法讓 Chrome 將 textarea 向下滾動到新選擇的文本? 歡迎使用 jQuery 解決方案。
這是一個簡單有效的解決方案,純js:
//first of all, you ignore any bad english, as i'm french and had a funny evening
//get the textarea
var textArea = document.getElementById('myTextArea');
//define your selection
var selectionStart = 50;
var selectionEnd = 60;
textArea.setSelectionRange( selectionStart, selectionEnd);
// now lets do some math
// we need the number of chars in a row
var charsPerRow = textArea.cols;
// we need to know at which row our selection starts
var selectionRow = (selectionStart - (selectionStart % charsPerRow)) / charsPerRow;
// we need to scroll to this row but scrolls are in pixels,
// so we need to know a row's height, in pixels
var lineHeight = textArea.clientHeight / textArea.rows;
// scroll !!
textArea.scrollTop = lineHeight * selectionRow;
把它放在一個函數中,用它擴展 javascript 的 Element 對象的原型,你就很好了。
如果您需要任何進一步的幫助,請隨時詢問。
很多答案,但接受的沒有考慮換行, Matthew Flaschen沒有添加解決方案代碼, naXa答案有錯誤。 最簡單的解決代碼是:
textArea.focus();
const fullText = textArea.value;
textArea.value = fullText.substring(0, selectionEnd);
textArea.scrollTop = textArea.scrollHeight;
textArea.value = fullText;
textArea.setSelectionRange(selectionStart, selectionEnd);
您可以在 ProveIt 中看到我們是如何解決問題的(請參閱 highlightLengthAtIndex)。 基本上,訣竅是截斷textarea,滾動到末尾,然后恢復文本的第二部分。 我們還使用了 textSelection 插件來實現一致的跨瀏覽器行為。
這是一個受 Matthew Flaschen's answer啟發的代碼。
/**
* Scroll textarea to position.
*
* @param {HTMLInputElement} textarea
* @param {Number} position
*/
function scrollTo(textarea, position) {
if (!textarea) { return; }
if (position < 0) { return; }
var body = textarea.value;
if (body) {
textarea.value = body.substring(0, position);
textarea.scrollTop = position;
textarea.value = body;
}
}
基本上,訣竅是截斷textarea,滾動到末尾,然后恢復文本的第二部分。
使用方法如下
var textarea, start, end;
/* ... */
scrollTo(textarea, end);
textarea.focus();
textarea.setSelectionRange(start, end);
Valeriy Katkov 的優雅解決方案效果很好,但有兩個問題:
這是我的改進版本,適用於長字符串(使用至少 50,000 個單詞進行測試)並將選擇滾動到 textarea 的中心:
function setSelectionRange(textarea, selectionStart, selectionEnd) {
// First scroll selection region to view
const fullText = textarea.value;
textarea.value = fullText.substring(0, selectionEnd);
// For some unknown reason, you must store the scollHeight to a variable
// before setting the textarea value. Otherwise it won't work for long strings
const scrollHeight = textarea.scrollHeight
textarea.value = fullText;
let scrollTop = scrollHeight;
const textareaHeight = textarea.clientHeight;
if (scrollTop > textareaHeight){
// scroll selection to center of textarea
scrollTop -= textareaHeight / 2;
} else{
scrollTop = 0;
}
textarea.scrollTop = scrollTop;
// Continue to set selection range
textarea.setSelectionRange(selectionStart, selectionEnd);
}
適用於 Chrome 72、Firefox 65、Opera 58 和 Edge 42
有關使用此函數的示例,請參閱我的 GitHub 項目SmartTextarea 。
基於@naXa 和@Valeriy Katkov 的想法,我改進了這個函數,減少了錯誤。 它應該是開箱即用的(它是用 TypeScript 編寫的。對於 JavasCript,只需刪除類型聲明):
function scrollTo(textarea: HTMLTextAreaElement, offset: number) {
const txt = textarea.value;
if (offset >= txt.length || offset < 0)
return;
textarea.scrollTop = 0; // Important, so that scrollHeight will be adjusted
textarea.value = txt.substring(0, offset);
const height = textarea.scrollHeight;
textarea.value = txt;
textarea.scrollTop = height - 40; // Margin between selection and top of viewport
}
用法:
let textarea, start, end;
/* ... */
scrollTo(textarea, start);
textarea.focus();
textarea.setSelectionRange(start, end);
Chrome 的完整代碼
<script type="text/javascript">
var SAR = {};
SAR.find = function () {
debugger;
var parola_cercata = $("#text_box_1").val(); // the searched word
// make text lowercase if search is supposed to be case insensitive
var txt = $('#remarks').val().toLowerCase();
parola_cercata = parola_cercata.toLowerCase();
var posi = jQuery('#remarks').getCursorPosEnd(); // take the position of the word in the text
var termPos = txt.indexOf(parola_cercata, posi);
if (termPos !== -1) {
debugger;
var target = document.getElementById("remarks");
var parola_cercata2 = $("#text_box_1").val();
// select the textarea and the word
if (target.setSelectionRange) {
if ('selectionStart' in target) {
target.selectionStart = termPos;
target.selectionEnd = termPos;
this.selectionStart = this.selectionEnd = target.value.indexOf(parola_cercata2);
target.blur();
target.focus();
target.setSelectionRange(termPos, termPos + parola_cercata.length);
}
} else {
var r = target.createTextRange();
r.collapse(true);
r.moveEnd('character', termPos + parola_cercata);
r.moveStart('character', termPos);
r.select();
}
} else {
// not found from cursor pos, so start from beginning
termPos = txt.indexOf(parola_cercata);
if (termPos !== -1) {
var target = document.getElementById("remarks");
var parola_cercata2 = $("#text_box_1").val();
// select the textarea and the word
if (target.setSelectionRange) {
if ('selectionStart' in target) {
target.selectionStart = termPos;
target.selectionEnd = termPos;
this.selectionStart = this.selectionEnd = target.value.indexOf(parola_cercata2);
target.blur();
target.focus();
target.setSelectionRange(termPos, termPos + parola_cercata.length);
}
} else {
var r = target.createTextRange();
r.collapse(true);
r.moveEnd('character', termPos + parola_cercata);
r.moveStart('character', termPos);
r.select();
}
} else {
alert("not found");
}
}
};
$.fn.getCursorPosEnd = function () {
var pos = 0;
var input = this.get(0);
// IE Support
if (document.selection) {
input.focus();
var sel = document.selection.createRange();
pos = sel.text.length;
}
// Firefox support
else if (input.selectionStart || input.selectionStart === '0')
pos = input.selectionEnd;
return pos;
};
</script>
我在這里發布了一個答案:
http://blog.blupixelit.eu/scroll-textarea-to-selected-word-using-javascript-jquery/
它與 jsut 一個需要的規則完美配合:在 textarea 的 css 中設置行高!
它僅通過進行一些簡單的數學計算來計算要滾動到的單詞的位置,並且在我的所有實驗中都運行良好!
請隨時向我詢問有關代碼的任何問題!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.