4

我的最终目标是让用户能够:

  • 从段落中选择文本
  • 将文本包装在一个跨度中
  • 在选择的末尾放置一个操作按钮/ div,他们可以单击以采取进一步的操作

到目前为止,这是我的代码:

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;
    }
}

如您所料,到目前为止,我可以使用window.getSelection().toString(). 如果我删除.toString(),我会得到一个Selection对象。有了这个,我可以window.getSelection().anchorNode.parentNode用来获取我需要的大部分信息。

我也看到了这一点Selection.anchorOffsetSelection.extentOffset并将给我我选择的字符范围。有没有办法可以使用这些信息来放置跨度?

我想我的问题是:

  • 为什么这段代码不将选择包装在 div 中?
  • 这会因同一文本的多个实例而失败吗?
  • 在用 span 或 inline-block div 或其他东西包装选择之后,我能否获得(并使用)它的位置来定位额外的按钮/div?

唷,谢谢你的时间!

编辑:我在这里添加了一个 JS 小提琴:http: //jsfiddle.net/nn62G/

4

3 回答 3

2

我将在这里发布我的 js fiddle 以及后代的解决方案。谢谢各位的帮助!

http://jsfiddle.net/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.com' 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();
于 2013-05-12T16:18:05.000 回答
1

好吧,一个可能的解决方案可能是找到包含当前选择的元素并将其替换为 html,例如:

// 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];

这是一个有效的小提琴

于 2013-05-11T18:26:43.983 回答
1

返回的值getSelectedText是选择而不是 DOM 中的元素。这就是为什么您对html函数的校准失败,选择没有这样的属性。

您可以按照以下方式进行操作,将要处理的文档部分设置contentEditable为例如 a<p><div>。当您在该区域内选择时,您可以使用document.activeElement. 如果您在contentEdiatble区域外选择,则activeElement返回该body元素。activeElement你可以处理:

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

但是,如果您使文档的某些部分可编辑,则会发生您可能不希望发生的其他事情。更严重的是,如果所选文本多次出现,您将无法确定实际选择了哪个文本,因此这可能无法解决您的问题。

在这里更新小提琴

于 2013-05-11T18:33:52.110 回答