单击时,使用jQuery自动选择span标记内的文本

时间:2022-11-04 17:55:56

I have a div which contains a series of span tags, each containing a string of text. I'd like to attach a jQuery click event to all of the spans so that when the text inside any span is clicked, the entire line of text (dom > innerText object) will be auto selected to facilitate the drag/drop or copy/paste of the text string.

我有一个包含一系列span标签的div,每个标签包含一串文本。我想将jQuery单击事件附加到所有跨度,以便在单击任何跨度内的文本时,将自动选择整行文本(dom> innerText对象)以方便拖放或复制/粘贴文本字符串。

For example, my content is...

例如,我的内容是......

<div id="mySpans">
  <span>&nbsp;This is my text&nbsp;</span>
  <span>&nbsp;This is my text&nbsp;</span>
</div>

If the cursor is clicked on any text inside a span, I want to select the text within that span, so that it can be drag/dropped (without the span tags, just the innerText of the span) as a copy.

如果在跨度内的任何文本上单击光标,我想选择该跨度内的文本,以便可以将其拖放(没有span标记,只是跨度的innerText)作为副本。

Does jQuery have an easy means to do this?

jQuery有一个简单的方法吗?

EDIT: A more detailed explanation of what I'm trying to accomplish:

编辑:我正在努力完成的更详细的解释:

Without aid of script, in order to copy a block of text, the user has to manually drag select a selection rectangle across the text block. The text then becomes selected signaling that a click & drag event will pick up all of the selected text. So I'm trying to create script that allows a single click on the text to automatically select the text for the user so they don't have to manually do it themselves.

在没有脚本帮助的情况下,为了复制文本块,用户必须手动拖动选择文本块中的选择矩形。然后,文本被选中,表示点击和拖动事件将拾取所有选定的文本。因此,我正在尝试创建脚本,允许单击文本以自动为用户选择文本,这样他们就不必自己手动执行。

8 个解决方案

#1


16  

Right. The short answer is: you can't.

对。简短的回答是:你做不到。

That, however, isn't really very helpful. So, if you're prepared to accept a slightly hacky approach, with at least one caveat, you can:

然而,这并不是非常有用。所以,如果你准备接受一种略带hacky的方法,至少有一个警告,你可以:

Given the html:

鉴于html:

<div id="wrap">
    <span class="copyText">This is some text to copy.</span>
    <span>Can't copy <em>this</em> (automatically...)!</span>
    <span class="copyText">And this is yet more text.</span>
</div>

And the CSS:

而CSS:

span.copyText {
    position: relative;
    display: block;
}
textarea {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    border: 0 none transparent;
    margin: 0;
    padding: 0;
    outline: none;
    resize: none;
    overflow: hidden;
    font-family: inherit;
    font-size: 1em;
}

You can use the following jQuery:

您可以使用以下jQuery:

$(document).ready(
    function() {
        $('.copyText').click(
            function() {
                if ($('#tmp').length) {
                    $('#tmp').remove();
                }
                var clickText = $(this).text();
                $('<textarea id="tmp" />')
                    .appendTo($(this))
                    .val(clickText)
                    .focus()
                    .select();
        return false;
    });
$(':not(.copyText)').click(
    function(){
        $('#tmp').remove();
    });

});

With the requisite JS Fiddle demo, at: http://jsfiddle.net/davidThomas/ZmYBh/.

有了必要的JS Fiddle演示,请访问:http://jsfiddle.net/davidThomas/ZmYBh/。

The main caveat is that the element you want to copy cannot (with this approach at least) wrap from one line to the next (unless it's also display: block), I suspect it has something to do with how native form elements are rendered as 'solid' rectangles, unlike most other inline elements, such as html which form a more...'fluid'(?) rectangle when wrapping).

主要的警告是你要复制的元素不能(至少用这种方法)从一行换行到下一行(除非它也显示:block),我怀疑它与本机表单元素的呈现方式有关“实心”矩形,与大多数其他内联元素不同,例如html,在包装时形成更“......流畅”(?)的矩形。

There may be others, however.

但是,可能还有其他人。

JS Fiddle demo to show that it does work with wrapping text, so long as the parent container element (span) is still display: block;.

JS Fiddle演示,表明它可以处理包装文本,只要父容器元素(span)仍然显示:block;。


Edited: to add that I tried using inputs instead of textarea which, predictably, failed to work any differently/better than textarea, and also <span contenteditable>, which (again, predictably) didn't select the text at all, but did insert the caret at the beginning of the text.

Sigh. I think there should be a far easier answer to this question, but I can't see it for the life of me.

叹。我认为这个问题应该有一个更容易的答案,但我不能在我的生活中看到它。

#2


8  

use DOM ranges: http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html

使用DOM范围:http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html

var span = ...
var range = document.createRange();
range.setStartBefore(span.firstChild);
range.setEndAfter(span.lastChild);
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);

#3


5  

Found this core-javascript solution that works well and is hack-free: http://coderzone.org/library/Select-text-in-a-DIV-SPAN-or-table-cell_1047.htm

找到了这个核心-javascript解决方案,该解决方案运行良好且无黑客攻击:http://coderzone.org/library/Select-text-in-a-DIV-SPAN-or-table-cell_1047.htm

I took the liberty to change the code a bit so that it accepts the element node as argument instead of an element id.

我冒昧地改变了代码,以便它接受元素节点作为参数而不是元素id。

// Selects text inside an element node.
function selectElementText(el) {
    removeTextSelections();
    if (document.selection) {
        var range = document.body.createTextRange();
        range.moveToElementText(el);
        range.select();
    }
    else if (window.getSelection) {
        var range = document.createRange();
        range.selectNode(el);
        window.getSelection().addRange(range);
    }
}

// Deselects all text in the page.
function removeTextSelections() {
    if (document.selection) document.selection.empty(); 
    else if (window.getSelection) window.getSelection().removeAllRanges();
}

#4


1  

tbleckert is on the right track. The .select() event is only available for inputs though, so you'd need to have your <span> become an input and then style it with no background, no border, and no focus ring. Then, you can do this:

tbleckert走在正确的轨道上。 .select()事件仅适用于输入,因此您需要将变为输入,然后将其设置为没有背景,没有边框和没有聚焦环的样式。然后,你可以这样做:

<input type="text" style="border:none; background:transparent; outline: none;" class="selectOnClick" />

and then your jQuery would look something like this

然后你的jQuery看起来像这样

$('input.selectOnClick').click(function(){ $(this).select(); });

This is untested code but should point you in the right direction.

这是未经测试的代码,但应指向正确的方向。

#5


1  

I wanted to do something similar. My website has quotes that I wanted users to be able to easily copy. I also wanted to add the author's name to the string.

我想做类似的事情。我的网站有引号,我希望用户能够轻松复制。我还想将作者的名字添加到字符串中。

Normally, I have user-select set to none, so I created a class that is programmatically applied when needed...

通常,我有用户选择设置为无,所以我创建了一个在需要时以编程方式应用的类...

.editable {
    user-select: text;
    -webkit-user-select: text;
    -moz-user-select: text;
    -ms-user-select: text;
    -o-user-select: text;
}

All of the quotes are in a class called "paragraph_quote". When a site visitor clicks on a quote, the follow sequence occurs:

所有引号都在一个名为“paragraph_quote”的类中。当站点访问者单击引号时,将发生以下序列:

$(".paragraph_quote").on("click", function() {
    var addendum = " [by Author]";

    if (! $(this).attr("contenteditable") || $(this).html().indexOf(addendum) === -1) {     
            $(this).removeData("quote")
            .data("quote", $(this).html())
            .html($(this).html() + addendum)
            .attr("contenteditable", true)
            .addClass("editable")
            .focus()
        ;
    }
    document.execCommand('selectAll', false, null);
}).on("blur", function() {
    $(this).removeClass("editable").html($(this).data("quote"));
});
  1. Look to see if the following steps have already been executed (i.e., whether the user is clicking for a second time inside the same paragraph). If it's the first time, execute steps 2 through 7. If not, just step 8.

    查看是否已执行以下步骤(即,用户是否在同一段落内第二次点击)。如果是第一次,请执行步骤2到7.如果不是,请执行步骤8。

  2. Remove any data that might have been stored if this isn't the first time that quote was clicked.

    如果这不是第一次单击引用,则删除可能已存储的所有数据。

  3. Store the quote's HTML as data. This allow you to modify the HTML for the copy (if you would like) and then easily return it to its original state.

    将报价的HTML存储为数据。这允许您修改副本的HTML(如果您愿意),然后轻松将其返回到其原始状态。

  4. Add any additional text (e.g., the author's name) to the HTML. Not shown below: I also use .replace() to remove any special HTML characters like non-breaking spaces, em-dashes, etc.

    将任何其他文本(例如,作者的姓名)添加到HTML。下面没有显示:我还使用.replace()删除任何特殊的HTML字符,如非破坏空格,em-dashes等。

  5. Make the paragraph editable.

    使段落可编辑。

  6. Add the editable class.

    添加可编辑的类。

  7. Set the focus to the paragraph. The editable class ensures the appearance of the focus outline.

    将焦点设置为段落。可编辑类确保焦点轮廓的外观。

  8. Select the entire content of the editable paragraph. Not that this step is useful, even if the other steps have already been taken, because it causes the entire selection to be re-highlighted if the user clicks within the selection.

    选择可编辑段落的完整内容。并非此步骤很有用,即使已经采取了其他步骤,因为如果用户在选择内单击,则会导致整个选择重新突出显示。

  9. When the user clicks outside of the paragraph, remove the editable class and...

    当用户点击段落外部时,删除可编辑的类并...

  10. Restore the HTML to its previous state (if you modified as indicated in step 4, above).

    将HTML还原到以前的状态(如果您按照上面的步骤4中的说明进行了修改)。

#6


0  

Check the select() event :)

检查select()事件:)

#7


0  

$("span").click(function(){
var mytext  = $(this).text()
})

will put the text in a javascript variable ... but it may be quicker to have a look at jQuery Ui, specifically draggable.

将文本放在一个javascript变量中...但是看看jQuery Ui可能会更快,特别是可拖动的。

#8


0  

Try something like

尝试类似的东西

$('#mySpans span').hover(function() {
    $(this).addClass('spanhover');
}, function() {
    $(this).removeClass('spanhover');
});

where you dynamically add a class "spanhover" you defined in your CSS section like

你动态添加你在CSS部分中定义的类“spanhover”的地方

#mySpans.spanhover {background-color:yellow;}

#1


16  

Right. The short answer is: you can't.

对。简短的回答是:你做不到。

That, however, isn't really very helpful. So, if you're prepared to accept a slightly hacky approach, with at least one caveat, you can:

然而,这并不是非常有用。所以,如果你准备接受一种略带hacky的方法,至少有一个警告,你可以:

Given the html:

鉴于html:

<div id="wrap">
    <span class="copyText">This is some text to copy.</span>
    <span>Can't copy <em>this</em> (automatically...)!</span>
    <span class="copyText">And this is yet more text.</span>
</div>

And the CSS:

而CSS:

span.copyText {
    position: relative;
    display: block;
}
textarea {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    border: 0 none transparent;
    margin: 0;
    padding: 0;
    outline: none;
    resize: none;
    overflow: hidden;
    font-family: inherit;
    font-size: 1em;
}

You can use the following jQuery:

您可以使用以下jQuery:

$(document).ready(
    function() {
        $('.copyText').click(
            function() {
                if ($('#tmp').length) {
                    $('#tmp').remove();
                }
                var clickText = $(this).text();
                $('<textarea id="tmp" />')
                    .appendTo($(this))
                    .val(clickText)
                    .focus()
                    .select();
        return false;
    });
$(':not(.copyText)').click(
    function(){
        $('#tmp').remove();
    });

});

With the requisite JS Fiddle demo, at: http://jsfiddle.net/davidThomas/ZmYBh/.

有了必要的JS Fiddle演示,请访问:http://jsfiddle.net/davidThomas/ZmYBh/。

The main caveat is that the element you want to copy cannot (with this approach at least) wrap from one line to the next (unless it's also display: block), I suspect it has something to do with how native form elements are rendered as 'solid' rectangles, unlike most other inline elements, such as html which form a more...'fluid'(?) rectangle when wrapping).

主要的警告是你要复制的元素不能(至少用这种方法)从一行换行到下一行(除非它也显示:block),我怀疑它与本机表单元素的呈现方式有关“实心”矩形,与大多数其他内联元素不同,例如html,在包装时形成更“......流畅”(?)的矩形。

There may be others, however.

但是,可能还有其他人。

JS Fiddle demo to show that it does work with wrapping text, so long as the parent container element (span) is still display: block;.

JS Fiddle演示,表明它可以处理包装文本,只要父容器元素(span)仍然显示:block;。


Edited: to add that I tried using inputs instead of textarea which, predictably, failed to work any differently/better than textarea, and also <span contenteditable>, which (again, predictably) didn't select the text at all, but did insert the caret at the beginning of the text.

Sigh. I think there should be a far easier answer to this question, but I can't see it for the life of me.

叹。我认为这个问题应该有一个更容易的答案,但我不能在我的生活中看到它。

#2


8  

use DOM ranges: http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html

使用DOM范围:http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html

var span = ...
var range = document.createRange();
range.setStartBefore(span.firstChild);
range.setEndAfter(span.lastChild);
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);

#3


5  

Found this core-javascript solution that works well and is hack-free: http://coderzone.org/library/Select-text-in-a-DIV-SPAN-or-table-cell_1047.htm

找到了这个核心-javascript解决方案,该解决方案运行良好且无黑客攻击:http://coderzone.org/library/Select-text-in-a-DIV-SPAN-or-table-cell_1047.htm

I took the liberty to change the code a bit so that it accepts the element node as argument instead of an element id.

我冒昧地改变了代码,以便它接受元素节点作为参数而不是元素id。

// Selects text inside an element node.
function selectElementText(el) {
    removeTextSelections();
    if (document.selection) {
        var range = document.body.createTextRange();
        range.moveToElementText(el);
        range.select();
    }
    else if (window.getSelection) {
        var range = document.createRange();
        range.selectNode(el);
        window.getSelection().addRange(range);
    }
}

// Deselects all text in the page.
function removeTextSelections() {
    if (document.selection) document.selection.empty(); 
    else if (window.getSelection) window.getSelection().removeAllRanges();
}

#4


1  

tbleckert is on the right track. The .select() event is only available for inputs though, so you'd need to have your <span> become an input and then style it with no background, no border, and no focus ring. Then, you can do this:

tbleckert走在正确的轨道上。 .select()事件仅适用于输入,因此您需要将变为输入,然后将其设置为没有背景,没有边框和没有聚焦环的样式。然后,你可以这样做:

<input type="text" style="border:none; background:transparent; outline: none;" class="selectOnClick" />

and then your jQuery would look something like this

然后你的jQuery看起来像这样

$('input.selectOnClick').click(function(){ $(this).select(); });

This is untested code but should point you in the right direction.

这是未经测试的代码,但应指向正确的方向。

#5


1  

I wanted to do something similar. My website has quotes that I wanted users to be able to easily copy. I also wanted to add the author's name to the string.

我想做类似的事情。我的网站有引号,我希望用户能够轻松复制。我还想将作者的名字添加到字符串中。

Normally, I have user-select set to none, so I created a class that is programmatically applied when needed...

通常,我有用户选择设置为无,所以我创建了一个在需要时以编程方式应用的类...

.editable {
    user-select: text;
    -webkit-user-select: text;
    -moz-user-select: text;
    -ms-user-select: text;
    -o-user-select: text;
}

All of the quotes are in a class called "paragraph_quote". When a site visitor clicks on a quote, the follow sequence occurs:

所有引号都在一个名为“paragraph_quote”的类中。当站点访问者单击引号时,将发生以下序列:

$(".paragraph_quote").on("click", function() {
    var addendum = " [by Author]";

    if (! $(this).attr("contenteditable") || $(this).html().indexOf(addendum) === -1) {     
            $(this).removeData("quote")
            .data("quote", $(this).html())
            .html($(this).html() + addendum)
            .attr("contenteditable", true)
            .addClass("editable")
            .focus()
        ;
    }
    document.execCommand('selectAll', false, null);
}).on("blur", function() {
    $(this).removeClass("editable").html($(this).data("quote"));
});
  1. Look to see if the following steps have already been executed (i.e., whether the user is clicking for a second time inside the same paragraph). If it's the first time, execute steps 2 through 7. If not, just step 8.

    查看是否已执行以下步骤(即,用户是否在同一段落内第二次点击)。如果是第一次,请执行步骤2到7.如果不是,请执行步骤8。

  2. Remove any data that might have been stored if this isn't the first time that quote was clicked.

    如果这不是第一次单击引用,则删除可能已存储的所有数据。

  3. Store the quote's HTML as data. This allow you to modify the HTML for the copy (if you would like) and then easily return it to its original state.

    将报价的HTML存储为数据。这允许您修改副本的HTML(如果您愿意),然后轻松将其返回到其原始状态。

  4. Add any additional text (e.g., the author's name) to the HTML. Not shown below: I also use .replace() to remove any special HTML characters like non-breaking spaces, em-dashes, etc.

    将任何其他文本(例如,作者的姓名)添加到HTML。下面没有显示:我还使用.replace()删除任何特殊的HTML字符,如非破坏空格,em-dashes等。

  5. Make the paragraph editable.

    使段落可编辑。

  6. Add the editable class.

    添加可编辑的类。

  7. Set the focus to the paragraph. The editable class ensures the appearance of the focus outline.

    将焦点设置为段落。可编辑类确保焦点轮廓的外观。

  8. Select the entire content of the editable paragraph. Not that this step is useful, even if the other steps have already been taken, because it causes the entire selection to be re-highlighted if the user clicks within the selection.

    选择可编辑段落的完整内容。并非此步骤很有用,即使已经采取了其他步骤,因为如果用户在选择内单击,则会导致整个选择重新突出显示。

  9. When the user clicks outside of the paragraph, remove the editable class and...

    当用户点击段落外部时,删除可编辑的类并...

  10. Restore the HTML to its previous state (if you modified as indicated in step 4, above).

    将HTML还原到以前的状态(如果您按照上面的步骤4中的说明进行了修改)。

#6


0  

Check the select() event :)

检查select()事件:)

#7


0  

$("span").click(function(){
var mytext  = $(this).text()
})

will put the text in a javascript variable ... but it may be quicker to have a look at jQuery Ui, specifically draggable.

将文本放在一个javascript变量中...但是看看jQuery Ui可能会更快,特别是可拖动的。

#8


0  

Try something like

尝试类似的东西

$('#mySpans span').hover(function() {
    $(this).addClass('spanhover');
}, function() {
    $(this).removeClass('spanhover');
});

where you dynamically add a class "spanhover" you defined in your CSS section like

你动态添加你在CSS部分中定义的类“spanhover”的地方

#mySpans.spanhover {background-color:yellow;}