如何在textarea中的选定文本下方显示一个div?
Posted
技术标签:
【中文标题】如何在textarea中的选定文本下方显示一个div?【英文标题】:how to show a div below selected text in textarea? 【发布时间】:2018-07-07 20:31:37 【问题描述】:我有一个场景,我需要在文本区域中选择文本时显示一个 div(如弹出窗口)。但是,我使用了鼠标向下键,有时 div 的位置并不完全低于文本.
function getSel()
// obtain the object reference for the textarea>
var txtarea = document.getElementById("mytextarea");
// obtain the index of the first selected character
var start = txtarea.selectionStart;
// obtain the index of the last selected character
var finish = txtarea.selectionEnd;
//obtain all Text
var allText = txtarea.value;
// obtain the selected text
var sel = allText.substring(start, finish);
sel = sel.replace(/[\S]/g, "*");
//append te text;
var newText = allText.substring(0, start) + sel + allText.substring(finish, allText.length);
txtarea.value = newText;
$('#newpost').offset( top: 0, left: 0 ).hide();
$(document).ready(function ()
var position;
$('#newpost').hide();
$('#mytextarea').on('select', function (e)
var str = $('#mytextarea').val();
$('#newpost').offset(position).show();
var txtarea = document.getElementById("mytextarea");
var start = txtarea.selectionStart;
var finish = txtarea.selectionEnd;
$('#newpost div').text('Replace with stars');
).on('select', function (e)
position = top: e.pageY+10, left: e.pageX ;
);
$('#newpost').hide();
);
function closePopUp()
$('#newpost').hide();
这是我的plunker 链接
这里我的要求是在文本选择时显示一个 div。但是当我使用 on-select 而不是鼠标按下时,div 显示在文本区域下方。
提前致谢。
【问题讨论】:
任何人都可以提供帮助 【参考方案1】:几天前在this answer 中,我提出了一种方法,即当用户选择一些文本时,找到光标位置并在textarea
上显示div
。
但是,正如@anub 所提到的,这种方法有效,div
有时不会显示在所选文本的正下方,而是向上或向下显示几个像素 - 因为它的位置是根据第一个用户的点击确定的。
经过短暂的搜索,我找到了this post,它描述了如何通过创建给定文本区域的临时div
克隆来查找选定文本在文本区域中的位置。
我从那里采用了getCursorXY
方法并用它来定位弹出窗口。
试一试!
function getSel()
// obtain the object reference for the textarea>
var txtarea = document.getElementById("mytextarea");
// obtain the index of the first selected character
var start = txtarea.selectionStart;
// obtain the index of the last selected character
var finish = txtarea.selectionEnd;
//obtain all Text
var allText = txtarea.value;
// obtain the selected text
var sel = Array(finish - start + 1).join("*");
//append te text;
var newText = allText.substring(0, start) + sel + allText.substring(finish, allText.length);
txtarea.value = newText;
$('#newpost').offset(top: 0, left: 0).hide();
function closePopUp()
$('#newpost').offset(top: 0, left: 0).hide();
$(document).ready(function ()
closePopUp();
var newpost = $('#newpost');
$('#mytextarea').on('select', function (e)
var txtarea = document.getElementById("mytextarea");
var start = txtarea.selectionStart;
var finish = txtarea.selectionEnd;
newpost.offset(getCursorXY(txtarea, start, 20)).show();
newpost.find('div').text(Array(finish - start + 1).join("*"));
);
);
const getCursorXY = (input, selectionPoint, offset) =>
const
offsetLeft: inputX,
offsetTop: inputY,
= input
// create a dummy element that will be a clone of our input
const div = document.createElement('div')
// get the computed style of the input and clone it onto the dummy element
const copyStyle = getComputedStyle(input)
for (const prop of copyStyle)
div.style[prop] = copyStyle[prop]
// we need a character that will replace whitespace when filling our dummy element
// if it's a single line <input/>
const swap = '.'
const inputValue = input.tagName === 'INPUT' ? input.value.replace(/ /g, swap) : input.value
// set the div content to that of the textarea up until selection
const textContent = inputValue.substr(0, selectionPoint)
// set the text content of the dummy element div
div.textContent = textContent
if (input.tagName === 'TEXTAREA') div.style.height = 'auto'
// if a single line input then the div needs to be single line and not break out like a text area
if (input.tagName === 'INPUT') div.style.width = 'auto'
// create a marker element to obtain caret position
const span = document.createElement('span')
// give the span the textContent of remaining content so that the recreated dummy element
// is as close as possible
span.textContent = inputValue.substr(selectionPoint) || '.'
// append the span marker to the div
div.appendChild(span)
// append the dummy element to the body
document.body.appendChild(div)
// get the marker position, this is the caret position top and left relative to the input
const offsetLeft: spanX, offsetTop: spanY = span
// lastly, remove that dummy element
// NOTE:: can comment this out for debugging purposes if you want to see where that span is rendered
document.body.removeChild(div)
// return an object with the x and y of the caret. account for input positioning
// so that you don't need to wrap the input
return
left: inputX + spanX,
top: inputY + spanY + offset,
#mytextarea width: 600px; height: 200px; overflow:hidden; position:fixed
#newpost
position:absolute;
background-color:#ffffdc;
border:1px solid #DCDCDC;
border-radius:10px;
padding-right:5px;
width: auto;
height: 30px;
#newpost span
cursor:pointer;
position: absolute;
top: 0;
right: 5px;
font-size: 22px;
#newpost div
color:#0000ff;
padding:10px;
margin-right:10px;
width: auto;
cursor:pointer;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<head>
</head>
<body>
<textArea id="mytextarea"></textArea>
<div id="newpost">
<span onclick="closePopUp();">˟</span>
<div onclick="getSel()"></div>
</div>
</body>
</html>
【讨论】:
非常感谢..它对我有用..但是在替换文本后,像 (Ctrl+z) 这样的默认操作不起作用..你能帮我吗.. @anub 如果这个答案有帮助,请接受它。然后你可以问一个关于capturing ctr+z key event in javascript 的新问题。如果您在此处发布新问题的链接,我将很乐意为您提供帮助。 @anub 似乎已作为副本关闭。实际上,您应该按照该答案中描述的步骤进行操作:侦听关键事件并检查代码:evtobj.keyCode == 90 && evtobj.ctrlKey
。如果匹配,请执行类似var newText = allText.substring(0, start) + text+ allText.substring(finish, allText.length);
的操作,但使用之前保存的start
、finish
和text
别忘了打电话e.preventDefault();
防止默认Ctr+Z
我找不到你..我会再发一个问题..你可以回答【参考方案2】:
我在关闭弹出窗口并重新选择另一个区域时遇到了这个问题,我解决了这个问题
function closePopUp()
$('#newpost').offset( top: 0, left: 0 ).hide();
看看这个
【讨论】:
但这里我的问题是显示,onselect popup 而不是 mousedown @anub 但我认为你只能通过使用鼠标事件来获得偏移量,我遇到的问题是弹出窗口向下移动,因为我继续关闭并重新选择一个区域,当时的位置弹出窗口未重置,这就是为什么我要求您在隐藏弹出窗口时更改偏移量以上是关于如何在textarea中的选定文本下方显示一个div?的主要内容,如果未能解决你的问题,请参考以下文章
如何通过javascript获取textarea元素内的选定文本?