5

I have a situation that when I click on a button, I need the current selection before the click. Example code goes like

$('div#test').on('click', 'span', function () {
    sel = window.getSelection();
    $('div#out p').text(sel.toString());
});

The expected behavior is shown here - http://jsfiddle.net/yvondtm/NH2DW/

Things goes right when the image button is clicked. If you make a selection before clicking the image, then you get the output - here it's just a copy of your selection.

But if you click on a text button, the selection gets lost, and the result isn't as expected. It seems like clicking on the text will move the cursor and hence change the selection.

I have checked CSS solutions like this one to disable the selection, as I have put in the fiddle, -webkit-user-select: none;. It does what it says, but doesn't make any help - even though "range" selection is not allowed, the caret still moves!

How can I solve this problem? Do I have to find some way to convert the text button to as if it were an image?

(No problem to use either js or jquery or css to achieve that. )

Community
  • 1
  • 1
Yvon
  • 2,814
  • 1
  • 11
  • 33

3 Answers3

4

The problem here is that the mousedown event that precedes the click event clears any existing selection - after which point window.getSelection() returns empty. To counter this, simply disable text-selection on the clickable <span>, in your case #sp

#sp {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}

Demo: http://jsfiddle.net/NH2DW/3/


A round about way that'll ensure the selection stays even if the user accidentally drags his mouse a little after pressing down on the span. Involves JavaScript but.

$('div#di').on('click', 'span', function () {
    $('div#out p').text(selection);
});

var selection = '', onSelect = function(_event) {
    if($(_event.target).is(':not(div#di span)'))
        selection = window.getSelection().toString();
    else return false;
};
$(document).mouseup(onSelect).keyup(onSelect).mousedown(onSelect);

Demo: http://jsfiddle.net/NH2DW/7/

techfoobar
  • 61,046
  • 13
  • 104
  • 127
  • Your solution helps a lot! So I have to set the css for the ``, but not `

    `. Now the button works correctly when it's clicked. But when you drag on it, the selection still gets lost. It happens in real as users often make accidental operations. They may move mouse while clicking, turning the operation into drag. Could you give any solution?

    – Yvon Jul 17 '14 at 06:42
  • 1
    See my edit, might fix the accidental dragging issue. – techfoobar Jul 17 '14 at 06:46
  • Adding a global variable to store the selection might not be good in my case, because other scripts may interfere with mouse clicking events, and I don't know at all what's inside those scripts. But I have learned a lot. Your first answer really helps. However, the css does not work in my script, although it does in the fiddle. Have to figure out why.... – Yvon Jul 17 '14 at 07:30
  • Just a feedback - I believe in my case the mouse events are interfered by other scripts, which I have no chance to get rid of. Have to think more 'hacky' ways. – Yvon Jul 17 '14 at 07:41
  • 1
    Debug hint: Put your span directly under the body, give it position absolute and bring it up using a large z-index. If the script works in that case, you can be sure that the rest of the event binding code is where you need to look. – techfoobar Jul 17 '14 at 07:46
  • Good hint! I created a DOM exactly the same as in the fiddle, inserted it, and then found things behave differently in the fiddle page and my target page. The css does not work at all with any of `div` or `span` or `p`. I will try alternative solution. – Yvon Jul 17 '14 at 14:46
0
$('div#di').on('click', 'span', function (e) {
    $('div#out p').html($(e.currentTarget).html());
});
chf
  • 727
  • 4
  • 14
  • Thanks for your help, but it may not be the answer, because the expected should be previously selected content (acutally I need more than `.toString()`), instead of the text inside the button itself. – Yvon Jul 17 '14 at 06:44
0

Overlay a transparent image over the text. So when you click, you are doing on an image, as if it were an image button.

<div id="container">
    <span id="wrapper">
        <img src="transparent image" id="overlay_img" />
        <p id="button_text"> Or you can use transparent property </p>
    </span>
</div>

And make the CSS style of 'img#overlay_img' as

position: absolute;
width: 100%; /* strech image to cover entire span */
height: 100%;
top: -1px; /* minor adjustments if the span has padding */
left: -1px;

A possible reference - CONTENT OVERLAY WITH CSS

The js should be like

$('div#container').on('click', 'span', function () {
    sel = window.getSelection();
    $('div#out p').text(sel.toString());
});

Working fiddle (the overlay image looks ugly but works) - http://jsfiddle.net/yvondtm/NH2DW/8/

Yvon
  • 2,814
  • 1
  • 11
  • 33