最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

jquery - How to wrap highlighted text with a span and place a div positioned relative to it in javascript? - Stack Overflow

programmeradmin0浏览0评论

My end goal is for the user to be able to :

  • select text from a paragraph
  • wrap the text in a span
  • place an action button / div at the end of the selection that they could click to take further action

Here is my code so far:

function Discussion(){       
    var $this = this;
    $(document).bind("mouseup",function(){
        $this.selectText($this);
    });
}
Discussion.prototype.selectText = function($this){
    var selection = $this.getSelectedText();
    if(selection.length > 3){
        console.log(selection);
        var spn = '<span class="selected">' + selection + '</span>';
        $(this).html($(this).html().replace(selection, spn)); 
        //ERROR here; it says that it can't replace() on undefined $(this).html()
    }
}
Discussion.prototype.getSelectedText = function(){
    if(window.getSelection){
        return window.getSelection().toString();
    }
    else if(document.getSelection){
        return document.getSelection();
    }
    else if(document.selection){
        return document.selection.createRange().text;
    }
}

As you might expect, so far I can get the text of the selection with window.getSelection().toString(). If I remove the .toString(), I get a Selection object. With this I can use window.getSelection().anchorNode.parentNode to get most of the information I need.

I also see that Selection.anchorOffset and Selection.extentOffset will give me the range of characters I've selected. Is there a way I can use this information to place the span?

I guess my questions would be:

  • Why isn't this code wrapping the selection in divs?
  • Will this fail with multiple instances of the same text?
  • After wrapping the selection with a span or inline-block div or something, will I be able to get (and use) its position for positioning an additional button / div?

Phew, thanks for your time!

Edit: I added a JS fiddle here : /

My end goal is for the user to be able to :

  • select text from a paragraph
  • wrap the text in a span
  • place an action button / div at the end of the selection that they could click to take further action

Here is my code so far:

function Discussion(){       
    var $this = this;
    $(document).bind("mouseup",function(){
        $this.selectText($this);
    });
}
Discussion.prototype.selectText = function($this){
    var selection = $this.getSelectedText();
    if(selection.length > 3){
        console.log(selection);
        var spn = '<span class="selected">' + selection + '</span>';
        $(this).html($(this).html().replace(selection, spn)); 
        //ERROR here; it says that it can't replace() on undefined $(this).html()
    }
}
Discussion.prototype.getSelectedText = function(){
    if(window.getSelection){
        return window.getSelection().toString();
    }
    else if(document.getSelection){
        return document.getSelection();
    }
    else if(document.selection){
        return document.selection.createRange().text;
    }
}

As you might expect, so far I can get the text of the selection with window.getSelection().toString(). If I remove the .toString(), I get a Selection object. With this I can use window.getSelection().anchorNode.parentNode to get most of the information I need.

I also see that Selection.anchorOffset and Selection.extentOffset will give me the range of characters I've selected. Is there a way I can use this information to place the span?

I guess my questions would be:

  • Why isn't this code wrapping the selection in divs?
  • Will this fail with multiple instances of the same text?
  • After wrapping the selection with a span or inline-block div or something, will I be able to get (and use) its position for positioning an additional button / div?

Phew, thanks for your time!

Edit: I added a JS fiddle here : http://jsfiddle/nn62G/

Share Improve this question edited May 11, 2013 at 15:56 Keith asked May 11, 2013 at 15:41 KeithKeith 4,2247 gold badges28 silver badges43 bronze badges 5
  • I'm not professional in Jquery. However, are you sure that this code is used monly with Jquery?! – SaidbakR Commented May 11, 2013 at 15:45
  • 1 Hmm, it was my attempt at OOP JS code using jQuery to make things easier. Does it look funky? – Keith Commented May 11, 2013 at 15:47
  • 1 Could you please include HTML and CSS part as well, probably encapsulated in jsfiddle? That will help. Rgds, – Alexander Bell Commented May 11, 2013 at 15:52
  • @AlexBell I've created a simple JSFiddle: jsfiddle/QDFZA/1 – Alfred Xing Commented May 11, 2013 at 15:53
  • here's a fiddle: jsfiddle/nn62G – Keith Commented May 11, 2013 at 15:55
Add a ment  | 

3 Answers 3

Reset to default 2

I'm going to post my js fiddle here with the solution for posterity. Thanks for all the help, everyone!

http://jsfiddle/prodikl/mP8KT/

function Discussion(){       
    var $this = this;
    $(document).bind("mouseup",function(){
        $this.selectText($this);
    });
}
Discussion.prototype.selectText = function($this){
    $("mark").contents().unwrap();
    $("mark").remove();
    var selection = $this.getSelection(); 
    var range = selection.getRangeAt(0);
    var cssclass = $(selection.anchorNode.parentNode).attr("class");
    if(selection.toString().length > 2){
        $this.startPoint = selection.anchorOffset;
        $this.endPoint = selection.extentOffset;
        var newNode = document.createElement("mark");
        range.surroundContents(newNode);
        $("mark").attr('title', ' ');
        $("mark").tooltip({
            content : "<a class='content' href='http://www.google.' target='_blank'>Here's a link.</a>"
        });
        $("mark").on('mouseleave',function(event){
            event.stopImmediatePropagation();
        }).tooltip("open");
    }
}
Discussion.prototype.getSelection = function(){
    if(window.getSelection){
        return window.getSelection();
    }
    else if(document.getSelection){
        return document.getSelection();
    }
    else if(document.selection){
        return document.selection.createRange().text;
    }
}
var discussion = new Discussion();

The value returned by getSelectedText is a selection not an element in the DOM. That is why your cal to the html function is failing, selection has no such property.

You can do what you want as follows, set the part of the document you want to process as contentEditable for example a <p> or <div>. When you select within that area then you can get the HTML element using document.activeElement. If you select outside a contentEdiatble area then activeElement returns the body element. The activeElement you CAN process :

document.activeElement.innerHTML = 
    document.activeElement.innerHTML.replace (selection, spn);

However, if you make parts of your document editable other things happen which you may not want. More seriously, if the selected text occurs multiple times you cannot determine which one has actually been selected so this may not be a solution to your problem.

Updated fiddle here

Ok well, a possible solution could be to find the element that contains the current selection and replace it's html something like:

// this get's you all the elements (including the top parent) that contain the selection
var existsInElements = $('*:contains("' + selection + '")');

// the exact element match is in the last one
var exactElement = existsInElements[existsInElements.length - 1];

Here is a fiddle that works.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论