2

I'd like to implement such a function on a web page: When called, it checks whether there are some text selection(often displayed as inverted colored text) on the page, if yes, insert an element <img src="my.png"/> just before the first word of the selection.

Pure JavaScript or jQuery code are both welcome, jQuery preferable. Thank you.

Ry-
  • 218,210
  • 55
  • 464
  • 476
Jimm Chen
  • 3,411
  • 3
  • 35
  • 59
  • So what have you tried? – Selvakumar Arumugam Jun 27 '13 at 14:47
  • Maybe this [discussion](http://stackoverflow.com/questions/5379120/get-the-highlighted-selected-text) can help. Replace the alert by the [jQuery .append](http://api.jquery.com/append/) function. – MrSo Jun 27 '13 at 14:49
  • The problem is that a selection can weave in and out of multiple DOM elements and hierarchies. Think of a case where a selection starts in the middle of some div, selects the rest of that div, some text in the parent div, then down into a nested list, and then maybe a div that's in the flow but has been absolutely positioned to the top of the page. What does "before the selection" mean in this case? – George Mauer Jun 27 '13 at 15:00
  • Another thought, if the text is right-to-left (eg Hebrew) wouldn't "before" mean actually "insert after but on the same line"? Isn't Chinese written top-to-bottom? There are different implications for al of these. – George Mauer Jun 27 '13 at 15:34
  • Yes, I've been aware of this. So I just want to place my ```` just at the **starting point** of the selection. This should be no ambiguation. – Jimm Chen Jun 28 '13 at 11:46

2 Answers2

5

I can propose you this solution :

$('#butt').click(function(){
  var sel = window.getSelection();
  if (sel.toString().length>0) { 
     var key = sel.anchorNode.compareDocumentPosition(sel.focusNode) & Node.DOCUMENT_POSITION_PRECEDING
        ? 'focus' : 'anchor';
     var $elem = $(sel[key+'Node']), txt = $elem.text(), offset = sel[key+'Offset'];
     var $f = $(document.createTextNode(txt.slice(0, offset)));
     $elem.replaceWith($f);
     $(document.createTextNode(txt.slice(offset))).insertAfter($f);
     $('<img src=http://dystroy.org/flore/icon.png>').insertAfter($f);
  }
});

Demonstration

Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
  • 1
    In addition, it should be checked, which comes first - the anchor node or the focus node: http://stackoverflow.com/questions/10710733/dom-determine-if-the-anchornode-or-focusnode-is-on-the-left-side A selection can be made from left to right and from right to left. That determines the anchor and focus nodes. Quite tricky ... – Simon Steinberger Jun 27 '13 at 14:56
  • Not much you can do but situations with text removed from the flow will break with this: http://jsbin.com/ilisay/1/edit – George Mauer Jun 27 '13 at 15:09
  • @GeorgeMauer Right but it's like the entire selection process which is weird and hard if you remove the elements from the flow. I think we can assume it won't happen in a real use case. – Denys Séguret Jun 27 '13 at 15:11
  • So you work primarily with good layouts made by people who know their css and don't use tables, huh? :P – George Mauer Jun 27 '13 at 15:16
  • @GeorgeMauer No, but I suppose this is dedicated to a kind of document, not a random web page. – Denys Séguret Jun 27 '13 at 15:17
  • Another thought, if the text is right-to-left (eg Hebrew) wouldn't "before" mean actually "insert after but on the same line"? – George Mauer Jun 27 '13 at 15:31
  • @GeorgeMauer You're questioning details of the specification. It would be easier to handle if you commented the question, not this answer. But I fear OP totally forgot he asked a question... – Denys Séguret Jun 27 '13 at 15:32
  • That's fair, and I think your answer is likely good enough, just that people often forget about globalization and I wanted to point it out for posterity. – George Mauer Jun 27 '13 at 15:37
  • Thank you dystroy, your solution works quite well on Chrome v27. But I really hope it can work in IE8. After replacing ``window.getSelection`` with a cross-browser one(provided by http://mark.koli.ch/2009/09/use-javascript-and-jquery-to-get-user-selected-text.html), I'm stuck in ``anchorNode`` not supported in IE8 problem. Could you help improve it? – Jimm Chen Jun 28 '13 at 12:21
  • @JimmChen As I have no IE8 (in fact I have no Windows), I can't do that. Maybe you could have more luck using the [Range](https://developer.mozilla.org/en-US/docs/Web/API/range?redirectlocale=en-US&redirectslug=DOM%2Frange) object but I personally think there isn't any good reason to support IE8 today : it's too much expensive for the few not caring users... – Denys Séguret Jun 28 '13 at 12:23
0
    <div id="test">
    <span class="spanthatcontainstext">test</span>
    </div>
$(function(){
    var checkfortext = $('.spanthatcontainstext').length;
    if(checkfortext){
    $(checkfortext).prepend('<img src="" />');
    } else {
    //do something if there is no text
    }
});
Ali Demirci
  • 5,302
  • 7
  • 39
  • 66