jQuery - 选择覆盖在图像上的不可见文本,ala GMail PDF查看器

时间:2010-11-09 04:01:17

标签: javascript jquery jquery-ui jquery-plugins jquery-selectors

我在图像上方覆盖了不可见的文字。是否有一个jQuery插件(或类似的)允许用户选择图像上的区域(也选择重叠的文本),并能够复制内容。

现在,我已将每个角色放在自己的<span />标记中。问题是当用户选择时,它有时会选择所有重叠的文本(除非用户对他/她的鼠标非常精确),有时图像本身会被选中等等。

类似于GMail的PDF查看器的解决方案会很不错。建议?

2 个答案:

答案 0 :(得分:8)

Google似乎从PDF文件中了解文件中的各种x,y文本偏移量。当您选择一堆行时,它会在“text”所在的图像上放置一组绝对定位的“selection”div(它们具有类highlight-pane)。当您选择文字时,它会在#selection-content textarea中填入您选择的内容,并选择其中的文字(例如,尝试使用Chrome中的window.getSelection().anchorNode)。除了那些选择叠加层之外,还有一个图像.page-image。我敢打赌他们实际上使用窗口捕获他们关心的所有鼠标手势(我假设mousedownmouseup)。 (Here's an example pdf document

如果您绝对定位元素,则可以检测到mousedownmousemovemouseup,找出鼠标位于(或最近)的span元素,并填写在textarea中,包含这两个元素之间所有内容的内容。如果你只想使用单词粒度,我怀疑有人会抱怨(用一个跨度而不是每个字母围绕每个单词)。

编辑:昨晚我有点好奇并编写了一个真正的天真版本。它只有mousedownmouseup,它在IE中不起作用(我不想调试它:)

Check it out on jsfiddle.

您可能想要添加的功能:

  1. 检查基于位置的匹配的更好方法;我只是把它包含在盒子里。
  2. mousemove
  3. 上的动态更新
  4. 基于行而非基于跨度
  5. 您仍然可以按背景颜色进行选择,但根据元素的排列方式,它可能看起来不太好。还需要支持透明度。

答案 1 :(得分:1)

以下是使用我对上一个问题的回答的简单示例:http://www.jsfiddle.net/yijiang/83W7X/2/embedded/result

var selected = [];

function drawSelection(){
    if(selected.length){
        selected.sort(function(a, b){
            if(a.sourceIndex){
                return a.sourceIndex - b.sourceIndex;
            } else if(a.compareDocumentPosition){
                if(a.compareDocumentPosition(b) == Node.DOCUMENT_POSITION_PRECEDING){
                    return 1;
                } else {
                    return -1;
                }
            }
        });
        var range = rangy.createRange(),
            sel = rangy.getSelection();

        range.setStart(selected[0].children[0], 0);
        range.setEnd(selected[selected.length - 1].children[0], 1);
        sel.setSingleRange(range);
    }
}

$('ul').selectable({
    delay: 100,
    selecting: function(event, ui) {
        if(ui.selecting.getAttribute('class').indexOf('wrapper') !== -1 && $.inArray(ui.selecting, selected) === -1) {
            selected.push(ui.selecting);
            drawSelection();
        }
    },
    unselecting: function(event, ui){
        if(ui.unselecting.getAttribute('class').indexOf('wrapper') !== -1 && $.inArray(ui.unselecting, selected) > -1){
            selected.splice($.inArray(ui.unselecting, selected), 1);
            drawSelection();
        }
    }
});

它将jQuery UI的Selectable与Tim Down优秀的Rangy库混合在一起,创造出类似于你所要求的东西。我认为。你要求的并不完全清楚。

代码保留一组当前选定的li元素。代码的第二部分添加了相关的事件处理程序和选项。每次选择或取消选择元素时,都会调用drawSelection函数。该函数首先按DOM中的位置对所有元素进行排序,然后从第一个选定的li到最后一个选择。

代码,如theazureshadow's,只是概念验证,因为我正在抽象选择li到相当重的Rangy库的简单任务。它也表现不佳,可以进行一些重构。