JavaScript:在 Chrome 中使用 textarea.setSelectionRange 后滚动到选择
Posted
技术标签:
【中文标题】JavaScript:在 Chrome 中使用 textarea.setSelectionRange 后滚动到选择【英文标题】:JavaScript: Scroll to selection after using textarea.setSelectionRange in Chrome 【发布时间】:2011-11-19 19:50:46 【问题描述】:javascript 函数使用 .setSelectionRange() 选择文本区域中的某个单词。在 Firefox 中,文本区域会自动向下滚动以显示选定的文本。在 Chrome (v14) 中,它没有。有没有办法让 Chrome 将文本区域向下滚动到新选择的文本?欢迎使用 jQuery 解决方案。
【问题讨论】:
【参考方案1】:这里有一个简单高效的解决方案,纯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对象的原型,就可以了。
如果您需要任何进一步的帮助,请随时询问。
【讨论】:
charsPerRow
逻辑忽略换行符,软(单词之间换行)和硬(实际换行)。
你完全正确!我目前正在检查您的解决方案【参考方案2】:
很多答案,但是accepted one 没有考虑换行,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);
【讨论】:
所有聪明的操作都发生在一个“集中”的texarea上是非常重要的。textArea.focus()
应该在顶部【参考方案3】:
您可以看到我们如何解决问题in ProveIt(请参阅 highlightLengthAtIndex)。基本上,诀窍是截断文本区域,滚动到末尾,然后恢复文本的第二部分。我们还使用 textSelection 插件来实现一致的跨浏览器行为。
【讨论】:
嗨,马特,只是建议,将代码放入您的答案中,以便我们可以在 SO 而不是链接中看到它们。 对您的代码添加一些 cmets,以防您还没有遇到它。而不是 document.getElementById("my_textarea") ,你可以做 jQuery('#my_textarea').get(0)【参考方案4】:这是受 Matthew Flaschen 的 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;
基本上,诀窍是截断文本区域,滚动到末尾,然后恢复文本的第二部分。
如下使用
var textarea, start, end;
/* ... */
scrollTo(textarea, end);
textarea.focus();
textarea.setSelectionRange(start, end);
【讨论】:
变量position
既用作子字符串索引,又用作采用像素的scrollTop 是没有意义的。【参考方案5】:
Valeriy Katkov 的 elegant solution 效果很好,但有两个问题:
-
不适用于长字符串
所选内容会滚动到文本区域的底部,因此很难看到围绕所选内容的上下文
这是我的改进版本,适用于长字符串(测试至少 50,000 个单词)并将选择滚动到文本区域的中心:
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。
【讨论】:
【参考方案6】:基于@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);
【讨论】:
【参考方案7】: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>
【讨论】:
对我来说非常有效,请检查并恢复已解决的问题,以便在 textarea 上滚动以进行单词搜索【参考方案8】:我在这里发表了一个答案:
http://blog.blupixelit.eu/scroll-textarea-to-selected-word-using-javascript-jquery/
它与 jsut 一个需要的规则完美配合:在 textarea 的 css 中设置一个 line-height!
它仅通过一些简单的数学计算来计算要滚动到的单词的位置,并且在我的所有实验中都能完美运行!
如果您对代码有任何需要,请随时问我!
【讨论】:
虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接的答案可能会失效。以上是关于JavaScript:在 Chrome 中使用 textarea.setSelectionRange 后滚动到选择的主要内容,如果未能解决你的问题,请参考以下文章
new Date() 在 Chrome 和 Firefox 中的工作方式不同
在 Javascript 中使用 appendChild 和 IE
使用JavaScript / JQuery导出 html table 数据至 Excel 兼容IE/Chrome/Firefox