如何将 textarea 的插入符号始终保持在视口内?
Posted
技术标签:
【中文标题】如何将 textarea 的插入符号始终保持在视口内?【英文标题】:How do I keep a textarea's caret always within the viewport? 【发布时间】:2012-10-15 00:33:17 【问题描述】:我有一个用于编辑大量文本的文本区域很长的页面。通常,当您键入时,当插入符号接近文本区域的底部时,页面会自动滚动以使插入符号始终保持在视口内(Firefox 一次滚动一行,Chrome 会将插入符号滚动到视口)。
我的问题来自这样一个事实,即我正在根据用户键入的内容以编程方式更改文本区域的内容。在某些情况下,这涉及添加额外的内容,从而将插入符号推到视野之外。
只要用户点击一个键,自动滚动就会启动,插入符号会滚动到视图中——但不是之前,所以当用户键入时,他们会看不到插入符号。我曾希望我可以简单地触发 textarea 上的关键事件让浏览器自动滚动,但触发的事件并不能完全模拟用户行为,我也没有得到响应。
我现在能看到的唯一解决方案是尝试通过以下方式获取插入符号的 XY 坐标:
-
查找插入符号的字符位置。
构建一个 div,在插入符号位置使用标记来镜像 textarea 的内容。
测量标记的位置。
有没有更简单的方法来做到这一点?
【问题讨论】:
可能相关:***.com/a/12738472/1615483 【参考方案1】:我不想建议为一个问题添加整个库,但请考虑查看 CodeMirror。它为您处理所有这些事情,而且使用起来相当简单。
http://codemirror.net/
【讨论】:
【参考方案2】:[之前的解决方案不兼容 Chrome (WebKit?)]
如果,一个 BIG if,额外的内容被附加到输入的末尾,下面的练习可能会提供解决方案:
<html>
<head>
<script>
function btnGoOnClick(ctrl)
//-- For this POC the text content is reset to 160 lines of dummy text -
//----------------------------------------------------------------------
ctrl.value = "";
for (var i = 0; i < 160; ++i)
ctrl.value += "dummy!\n";
//-- Then the carret is set to the last position -----------------------
//----------------------------------------------------------------------
if (ctrl.createTextRange)
//-- IE specific methods to move the carret to the last position
var textRange = ctrl.createTextRange();
textRange.moveStart("character", ctrl.value.length);
textRange.moveEnd("character", 0);
textRange.select();
else
//-- Mozilla and WebKit methods to move the carret
ctrl.setSelectionRange(ctrl.value.length, ctrl.value.length);
//-- For WebKit, the scroll bar has to be explicitly set ---------------
//----------------------------------------------------------------------
ctrl.scrollTop = ctrl.scrollHeight;
//-- Almost there: make sure the control has fucos and is into view ----
//----------------------------------------------------------------------
ctrl.focus();
ctrl.scrollIntoView(false);
</script>
</head>
<body>
<form name="form">
<input type="button" name="btnGo" value="Go!" onClick="btnGoOnClick(document.form.text);" />
<div style="height: 1000px"></div>
<textarea name="text" rows="80"></textarea>
</form>
</body>
</html>
【讨论】:
我看到的是 scrollIntoView() 将视口滚动到 textarea 的顶部,但这与插入符号的位置没有任何关联(我的 textarea 的高度大于视口高度,因此插入符号仍然可以看不见)。 对不起,我的错!我对 Mozilla 和 IE 进行了测试,跳过了 Chrome (WebKit)。我设计了一个更广泛的、失败证明的解决方案,并将编辑我的帖子。请即使您已经满足了您的需求,也请评估一下,如果证明是正确的,请将我的帖子标记为有效。我(我们)需要这些学分:-)【参考方案3】:由于您已经在 javascript 路径上,并且假设动态 textarea 高度会造成设计问题,您可以尝试按内容自动调整 textarea 的大小:
function resizeTextarea(textarea)
var lines = textarea.value.split('\n');
var width = textarea.cols;
var height = 1;
for (var i = 0; i < lines.length; i++)
var linelength = lines[i].length;
if (linelength >= width)
height += Math.ceil(linelength / width);
height += lines.length;
textarea.rows = height;
我知道这并不能回答您帖子中概述的细节,但它提供了一种适合您问题标题的替代方法。因此,即使它对您没有用,也可能对访问此问题的其他人有用。
我个人讨厌太小的文本区域,并且视情况而定,希望它们自动调整大小。
【讨论】:
感谢您的想法,我想这是解决不同问题的方法。在我的情况下,我已经使用 jquery-elastic 自动扩展了 textarea 的大小(尽管它的默认大小已经大于视口),我相信这与您提供的代码相同。以上是关于如何将 textarea 的插入符号始终保持在视口内?的主要内容,如果未能解决你的问题,请参考以下文章
您如何以编程方式将 Flex TextArea 的插入符号移到末尾?
JavaFX:在进入 TextArea 时将插入符号/光标放在 TextArea 的末尾