Get selected text position and place an element next to it

前端 未结 3 1399
挽巷
挽巷 2020-11-27 02:49

tl;dr

The idea is to allow a user to mark any text and see menu pop-up just next to the selection, with possible actions to apply to the selected text.


<
相关标签:
3条回答
  • 2020-11-27 03:01

    You should probably insert an absolutely position element at the end of the 'range.' This works differently in different browsers, so your best bet might be to sniff.

    And since you asked: this is how the new york times does it in their 'altClickToSearch.js' file:

    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);
    }
    }
    
    0 讨论(0)
  • 2020-11-27 03:06

    I use getBoundingClientRect() when I need the content to remain undisturbed, while placing additional content near it.

        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
    

    this works in Chrome, but IE likes to give weird things, so here's a cross-browser solution: (Tested in Chrome and IE, probably works elsewhere)

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

    0 讨论(0)
  • 2020-11-27 03:09

    You could position a marker span at the end of the selection, get its coordinates using jQuery, place your button at those coordinates and remove the marker span.

    The following should get you started:

    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);
            }
        };
    })();
    
    0 讨论(0)
提交回复
热议问题