如何在用户文本选择旁边放置元素?

我需要在用户所选文本旁边放置一个绝对定位按钮。 就像IE8在内部做的那样。

我正在将一个jQuery mouseup事件绑定到Document,并获取所选文本,但我目前没有关于如何知道实际选择位置的想法,而没有将其包装在某个元素中,因为选择文本可以是跨越几个元素,如果我将其包装,它会弄乱结构。

您可以在选区的末尾放置标记范围,使用jQuery获取其坐标,将按钮放在这些坐标处并删除标记范围。

以下内容应该让您入门:

var markSelection = (function() { var markerTextChar = "\ufeff"; var markerTextCharEntity = ""; var markerEl, markerId = "sel_" + new Date().getTime() + "_" + Math.random().toString().substr(2); var selectionEl; return function() { var sel, range; if (document.selection && document.selection.createRange) { // Clone the TextRange and collapse range = document.selection.createRange().duplicate(); range.collapse(false); // Create the marker element containing a single invisible character by creating literal HTML and insert it range.pasteHTML('' + markerTextCharEntity + ''); markerEl = document.getElementById(markerId); } else if (window.getSelection) { sel = window.getSelection(); if (sel.getRangeAt) { range = sel.getRangeAt(0).cloneRange(); } else { // Older WebKit doesn't have getRangeAt range = document.createRange(); range.setStart(sel.anchorNode, sel.anchorOffset); range.setEnd(sel.focusNode, sel.focusOffset); // Handle the case when the selection was selected backwards (from the end to the start in the // document) if (range.collapsed !== sel.isCollapsed) { range.setStart(sel.focusNode, sel.focusOffset); range.setEnd(sel.anchorNode, sel.anchorOffset); } } range.collapse(false); // Create the marker element containing a single invisible character using DOM methods and insert it markerEl = document.createElement("span"); markerEl.id = markerId; markerEl.appendChild( document.createTextNode(markerTextChar) ); range.insertNode(markerEl); } if (markerEl) { // Lazily create element to be placed next to the selection if (!selectionEl) { selectionEl = document.createElement("div"); selectionEl.style.border = "solid darkblue 1px"; selectionEl.style.backgroundColor = "lightgoldenrodyellow"; selectionEl.innerHTML = "<- selection"; selectionEl.style.position = "absolute"; document.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); } }; })(); 

当我需要内容保持不受干扰时,我使用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://sofzh.miximages.com/javascript/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); } }