获取选定的文本位置并在其旁边放置一个元素

问题描述 投票:24回答:3

tl; dr

其想法是允许用户标记任何文本,并在所选内容旁边看到菜单弹出窗口,并可以将操作应用于所选文本。


我需要在用户选择的文本旁边放置一个绝对定位的按钮。

我正在将mouseup事件绑定到文档,并获取选定的文本,但是我目前对如何知道实际选择的位置(不将其包装在某些元素中)缺乏主意,因为文本的选择可能跨越多个元素,如果我将其包装,则会使结构混乱。

javascript dom
3个回答
27
投票
您可以将标记范围放置在选择的末尾,使用jQuery获取其坐标,将按钮置于这些坐标处并删除标记范围。

以下内容将帮助您入门:

var markSelection = (function() { var markerTextChar = "\ufeff"; var markerTextCharEntity = "&#xfeff;"; var markerEl, markerId = "sel_" + new Date().getTime() + "_" + Math.random().toString().substr(2); var selectionEl; return function(win) { win = win || window; var doc = win.document; var sel, range; // Branch for IE <= 8 if (doc.selection && doc.selection.createRange) { // Clone the TextRange and collapse range = doc.selection.createRange().duplicate(); range.collapse(false); // Create the marker element containing a single invisible character by creating literal HTML and insert it range.pasteHTML('<span id="' + markerId + '" style="position: relative;">' + markerTextCharEntity + '</span>'); markerEl = doc.getElementById(markerId); } else if (win.getSelection) { sel = win.getSelection(); range = sel.getRangeAt(0).cloneRange(); range.collapse(false); // Create the marker element containing a single invisible character using DOM methods and insert it markerEl = doc.createElement("span"); markerEl.id = markerId; markerEl.appendChild( doc.createTextNode(markerTextChar) ); range.insertNode(markerEl); } if (markerEl) { // Lazily create element to be placed next to the selection if (!selectionEl) { selectionEl = doc.createElement("div"); selectionEl.style.border = "solid darkblue 1px"; selectionEl.style.backgroundColor = "lightgoldenrodyellow"; selectionEl.innerHTML = "&lt;- selection"; selectionEl.style.position = "absolute"; doc.body.appendChild(selectionEl); } // Find markerEl position http://www.quirksmode.org/js/findpos.html var obj = markerEl; var left = 0, top = 0; do { left += obj.offsetLeft; top += obj.offsetTop; } while (obj = obj.offsetParent); // Move the button into place. // Substitute your jQuery stuff in here selectionEl.style.left = left + "px"; selectionEl.style.top = top + "px"; markerEl.parentNode.removeChild(markerEl); } }; })();


15
投票
当我需要使内容保持不受干扰的同时在其附近放置其他内容时,我使用getBoundingClientRect()。>

var r=window.getSelection().getRangeAt(0).getBoundingClientRect(); var relative=document.body.parentNode.getBoundingClientRect(); ele.style.top =(r.bottom -relative.top)+'px';//this will place ele below the selection ele.style.right=-(r.right-relative.right)+'px';//this will align the right edges together

这可以在Chrome中使用,但是IE喜欢给人奇怪的东西,所以这是一个跨浏览器的解决方案:(在Chrome和IE中经过测试,可能在其他地方也可以使用)]

https://jsfiddle.net/joktrpkz/7/

您可能应该在“范围”的末尾插入绝对位置元素。在不同的浏览器中,此方法的工作方式有所不同,因此最好的选择是嗅探。

而且您问过:这是纽约时间在其'altClickToSearch.js'文件中的处理方式:

function insertButton() { selectionButton = new Element( 'span', { 'className':'nytd_selection_button', 'id':'nytd_selection_button', 'title':'Lookup Word', 'style': 'margin:-20px 0 0 -20px; position:absolute; background:url(http://graphics8.nytimes.com/images/global/word_reference/ref_bubble.png);width:25px;height:29px;cursor:pointer;_background-image: none;filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="http://graphics8.nytimes.com/images/global/word_reference/ref_bubble.png", sizingMethod="image");' } ) if (Prototype.Browser.IE) { var tmp = new Element('div'); tmp.appendChild(selectionButton); newRange = selection.duplicate(); newRange.setEndPoint( "StartToEnd", selection); newRange.pasteHTML(tmp.innerHTML); selectionButton = $('nytd_selection_button'); } else { var range = selection.getRangeAt(0); newRange = document.createRange(); newRange.setStart(selection.focusNode, range.endOffset); newRange.insertNode(selectionButton); } }


2
投票
您可能应该在“范围”的末尾插入绝对位置元素。在不同的浏览器中,此方法的工作方式有所不同,因此最好的选择是嗅探。
© www.soinside.com 2019 - 2024. All rights reserved.