0

I am trying to insert some HTML after the user has selected some text on the page. I have it working but not optimally and there is one problem in particular:

It relies on the element being on the page, but I don't want it to be. I want to do it all in the code, I am sure it's something relatively simple but need some help :)

I also welcome any other tips/suggestions/feedback!

The code canbe seen working here: http://jsfiddle.net/shE58/ (The selectionchange library is to make this work in FF).

document.addEventListener('selectionchange', function (event) {
    var sel = this.getSelection();

    // If text is being selected by drag, to wait for them to finish selecting.
    jQuery("body").mouseup(function() {
      // Ensure there is some text selected and that it is more than one character.
      if (sel.toString().length > 1) {
        // We only want one #element on the page at a time.
        $("#element").remove();

        // @TODO: Remove dependency on this:
        var el = document.getElementById('selection');
        el.innerHTML = '<div id="element"></div>';
        var frag = document.createDocumentFragment(), node;
        frag.appendChild(el.firstChild);

        var range = sel.getRangeAt(0)
        var startNode = range.startContainer, startOffset = range.startOffset;
        var boundaryRange = range.cloneRange();
        boundaryRange.collapse(false);
        boundaryRange.insertNode(frag);
        boundaryRange.setStart(startNode, startOffset);
        boundaryRange.collapse(true);
        // Clean up
        sel = '';
      }
    });
  });
klidifia
  • 1,415
  • 1
  • 12
  • 18
  • Its not clear at all on what you are trying to achieve. I can see what is happening by watching the html code on the fiddle.. but I'm still not clear on where you are going. Question: What is this line of code: `var frag = document.createDocumentFragment(), node;` I don't understand the comma node thing... is that just another empty variable, one that is never called? – zipzit Jul 09 '14 at 05:29
  • I guess you get it now :) yes that node variable was unused and shouldn't have been there. – klidifia Jul 09 '14 at 07:00

1 Answers1

1

Solution 1

Remove frag variable and directly add value in insertNode function like this :

boundaryRange.insertNode($('<div id="element"></div>')[0]);

http://jsfiddle.net/N6zz8/

Fix issue when to select right to left :

With a condition check if endOffset is smaller than startOffset.

var startNode = range.startContainer, startOffset = range.startOffset;
if (range.endOffset < range.startOffset) {
    startNode = range.endContainer;
    startOffset = range.endOffset;
}

http://jsfiddle.net/2c4qw/

Solution 2

Remove unnecessary code, remove 'el' variable like this :

// @TODO: Remove dependency on this:
var frag = document.createDocumentFragment(), node;
$(frag).append($('<div id="element"></div>'));

http://jsfiddle.net/zYSH4/

Solution 3

Declare your variable like this var el = $("<div></div>")[0];. To get this :

// @TODO: Remove dependency on this:
var el = $("<div></div>")[0];
el.innerHTML = '<div id="element"></div>';
var frag = document.createDocumentFragment(), node;
frag.appendChild(el.firstChild);

http://jsfiddle.net/7L3Kf/

user2226755
  • 12,494
  • 5
  • 50
  • 73
  • Hors, nicely done. Solution 1 seems simple and complete.. but I'm not getting the why on Solution #2. Why the $("
    ")[0] notation? What is that, and why would you use that technique? I can see its some sort of jQuery selector, its not clear on which one... why the [0]?
    – zipzit Jul 09 '14 at 06:05
  • $("#element")[0] return javascript node (document.getElementById("element")). `$("body")[0] === document.body // true` – user2226755 Jul 09 '14 at 06:08
  • ooops.. you inserted a solution #2 on me. There were only two solutions before.. The new #2 makes sense. I understand we want to cast an object that will work with .insertNode() .. What I'm not getting is the new #3 with the $("
    ")[0] notation? What is that, and why would you use that technique? I can see its some sort of jQuery selector, its not clear on which one... why the [0]? Is that just a code obfuscation technique. (Its working! I'm obfuscated :^)
    – zipzit Jul 09 '14 at 06:22
  • $("
    ")[0] is [$("
    ").get()](http://api.jquery.com/get/), [get a DOM Element from a JQuery Selector](http://stackoverflow.com/questions/1677880/how-to-get-a-dom-element-from-a-jquery-selector).
    – user2226755 Jul 09 '14 at 06:26
  • Apologies for driving this into the ground.. but
    doesn't really exist. Is that a catch all for a DOM phantom element identifier? How did you know that would even work? (Note: I tried `

    ` and that totally worked because the fiddle had those elements.. but this example doesn't have any `
    's` in the body of the html (or are we relying that somewhere else in the jsfiddle management system there is a `
    `?) Oh, and many thanks for the links on the .get() to [0] translation. Never seen that before...
    – zipzit Jul 09 '14 at 06:39
  • It is like to use `document.createElement("p").textContent` the element doesn't exist but you can set text content. – user2226755 Jul 09 '14 at 06:46
  • Thank you! :) You've left an r off container inside that if statement - was getting an error. – klidifia Jul 09 '14 at 07:12