-5

The problem:

Let's say I have a div with a text like this

<div id=”bla”>One Two Three Four Five</div>

I want to be able programmatically take any substring and wrap it into a <div> with some handler attached to it (say onlick). I want to be able to do it multiple times to different part of the text so in the end my div can end up looking like this:

<div id=”bla”>One <div id=”bla2”>Two</div> Three <div id=”bla4”>Four</div> Five</div>

The problem is how to do it?

Some thoughts:

Potentially, if I want to wrap the string Two into div, then if I just take whole div content using html(), do substring before and after Two, then do .empty() on the div and .append(beforeSubstring, <Two wrapper with some handler>, afterString) – it looks good, but it will put the beforeSubstring and afterSubstring into “” and remove all previous handlers. But I want to keep previous handlers and I don’t need “” since it messes things up for me.

Any thoughts? :)

Lucas
  • 1,359
  • 7
  • 16
Pinny
  • 206
  • 2
  • 10
  • 1
    Does your HTML document validates using `”` (instead of `"`) quotes? – Roko C. Buljan Sep 25 '15 at 20:54
  • Also... `
    ` you got that ID automagically?
    – Roko C. Buljan Sep 25 '15 at 21:04
  • are there event handlers existing within the html that will be affected already before any of this manipulation? If so will have to iterate text nodes, otherwise can use event delegation on new ones – charlietfl Sep 25 '15 at 21:12
  • @Pinny I think it would have been easier to understand you if you wrote your algorithm with code instead of writing it in English. – Andrea Casaccia Sep 25 '15 at 21:14
  • 1. [edit] & improve your question, 2. participate in comments and answers. – Roko C. Buljan Sep 25 '15 at 21:18
  • @RokoC.Buljan: Thanks for edits :). To answer two of your questions: No I use regular " quotes, it's just editing... And I can programatically create and ID if I need to. – Pinny Sep 28 '15 at 17:00
  • @AndreaCasaccia, that is what I am trying to do - I am trying to come up with the code that solves the issue I described in English, not fixing the existing one, as I don't have one that works :) – Pinny Sep 28 '15 at 17:01
  • @Pinny would be more helpful that you commented on an answer describing why it's not what you were looking for - and again click > [edit] and improve your question cause it's still not exactly understandable what you're after. – Roko C. Buljan Sep 28 '15 at 18:08
  • 1
    @RokoC.Buljan. I was out for two days and now I am trying to apply the two solutions I have here. I don't want to spam the thread. As soon as I get pos/neg answer - I will post here. – Pinny Sep 28 '15 at 18:15
  • Here is the quick view of my original "quick and dirty" first take at this problem. http://jsfiddle.net/Pinny/mzt2fh0g/ Clearly it has some issues (like selecting text second time outputs the markup...) but at least it will give the idea of what I am trying to do. Now I will apply the solutions people posted here. Bear with me. It' a busy Monday... – Pinny Sep 28 '15 at 22:29
  • So here is the version that does not "lose" handlers after new selections are added: http://jsfiddle.net/Pinny/mzt2fh0g/3/. I basically recreate them. Now the only remaining issue is how to make the correct selection. In this example everything works as long as you keep selecting to the left of the leftmost existing selection. This is because we select the visible text but html() and later substring() deal with actual innerHTML that includes tags, attrs, etc... – Pinny Sep 29 '15 at 00:44

2 Answers2

0

You first need to cache your element's content like var cont = $("#bla").text();
than always use that cont before inserting your wrappers (using RegExp I suppose...) and placing the result back into that element like $("#bla").html(regexModifiedCont);

Example:

var $contentEl = $("#bla");
var content = $contentEl.text(); // Cache the original content!

$("#query").on("input", function(){
  var reg = new RegExp("("+  $.trim(this.value) +")", "ig");
  $contentEl.html( content.replace(reg, "<span class='clickable'>$1</span>") );
});

$("body").on("click", ".clickable", function(){
  alert( $(this).text() );
});
.clickable{
  background:gold;
  cursor:pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Write a text to take <input id=query type=text>
<div id=bla>One Two Three Four Five</div>
Roko C. Buljan
  • 196,159
  • 39
  • 305
  • 313
  • This solution has the same issue I am having right now. Steps to repro: Click F12 to see the source; Type "Tw"; See the new "source" of the
    As you can see dealing with text()/html() puts "" around parts that were split. And while this does not effect how things look like in browser, in my case I will be doing text selections based on start and end position, which will be skewed because of "invisible" quotes. My guess is that I would need to do something like the Las suggesting below - putting things into tags (probably ) to avoid issues like that.
    – Pinny Sep 28 '15 at 22:52
  • @Pinny yes, my example places `` tags so that you can style them using CSS adn make the clickable (logical, isn't it?). Now why that's an issue you fail to explain I don't understand what invisible quotes you're talking about and why those are an issue in my example. – Roko C. Buljan Sep 29 '15 at 00:26
  • @Pinny for example have you tried to Right click and Copy HTML of the parent and than paste the clipboard in a text editor? Can you see any ghost quotes? If you have not tried you really should. And after you try that, please come back and tell me what's the **real** issue with the above example. Can't wait to hear from you. – Roko C. Buljan Sep 29 '15 at 00:31
  • dude, I am not sure what's your problem with this thread, but if it is so annoying to you - you do know you can stop responding to it, right? You really not being helpful, but quite the opposite. – Pinny Sep 29 '15 at 00:38
  • @Pinny no, it's not annoying, actually quite the opposite :) – Roko C. Buljan Sep 29 '15 at 08:36
0

Perhaps you're looking for something like this? =)

  function wrapTag(string, tag) {
    return '<'+tag+'>' + string + '</'+tag+'>';
  }

  // http://stackoverflow.com/questions/5379120/get-the-highlighted-selected-text
  function getSelectionText() {
      var text = "";
      if (window.getSelection) {
          text = window.getSelection().toString();
      } else if (document.selection && document.selection.type != "Control") {
          text = document.selection.createRange().text;
      }
      return text;
  }      

  function highlightSelection(tag) {
    var highlighted = getSelectionText();
    var newContent = $('#paragraph').html()
                      .replace(/\s+/g,' ').trim()
                      .replace(highlighted, wrapTag(highlighted, tag));
    $('#paragraph').html(newContent);
  } 

Working example: http://plnkr.co/edit/VCpGScPR9TEjuY3mtP2j?p=preview

Lucas
  • 1,359
  • 7
  • 16
  • You solution is much closer to the desired one, but has the second issue I am having and that is - after you make a next selection, the handler(s) for the previously selected text(s) are gone. – Pinny Sep 28 '15 at 23:22