开发者

Use jQuery to auto select text inside a span tag when clicked

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.

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.

Does jQuery have an easy means to do this?

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.


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:

Given the 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:

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:

$(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/.

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).

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


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.


use DOM ranges: 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);


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

I took the liberty to change the code a bit so that it accepts the element node as argument instead of an element 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();
}


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:

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

and then your jQuery would look something like this

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

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


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").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. 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.

  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.

  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).


Check the select() event :)


$("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.


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

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜