views:

73

answers:

4

Consider following DOM fragment:

<div id="div-1">foo</div>
<div id="div-2">bar</div>

Is it possible to insert HTML string (EDIT: that contains tags to render) between divs without wrapping it in another div (EDIT: or some other tag) created via document.createElement and setting its innerHTML property?

A: 
var neuB = document.createElement("b");
var neuBText = document.createTextNode("mit fettem Text ");
neuB.appendChild(neuBText);
document.getElementById("derText").insertBefore(neuB, document.getElementById("derKursiveText"));

You search for: insertBefore

Floyd
+4  A: 

This does it for straight text, which is how I read your original question (see below for an update for strings that include tags):

var div = document.getElementById('div-2');
var textNode = document.createTextNode('your text');
div.parentNode.insertBefore(textNode, div);

Live example

If you start with:

<div id="div-1">foo</div>div id="div-2">bar</div>

(note that there's no whitespace between them) then the result of the above is exactly what you would get with this HTML:

<div id="div-1">foo</div>your text<div id="div-2">bar</div>

If you really have that whitespace between the divs, you'll already have a text node there and the above will insert another one next to it. For virtually all intents and purposes, that doesn't matter, but if that bothers you, you can append to the existing text node instead if you like:

var text = 'your text';
var div = document.getElementById('div-2');
var prev = div.previousSibling;
if (prev && prev.nodeType == 3) { // 3 == TEXT_NODE
  // Prev is a text node, append to it
  prev.nodeValue = prev.nodeValue + text;
}
else {
  // Prev isn't a text node, insert one
  var textNode = document.createTextNode(text);
  div.parentNode.insertBefore(textNode, div);
}

Live example

Links to W3C docs: insertBefore, createTextNode

Including HTML tags

In your revised question you've said you want to include tags to be interpreted in doing all this. It's possible, but it's roundabout. First you put the HTML string into an element, then you move the stuff over, like this:

var text, div, tempdiv, node, next, parent;

// The text
text = 'your text <em>with</em> <strong>tags</strong> in it';

// Get the element to insert in front of, and its parent
div = document.getElementById('div-2');
parent = div.parentNode;

// Create a temporary container and render the HTML to it
tempdiv = document.createElement('div');
tempdiv.innerHTML = text;

// Walk through the children of the container, moving them
// to the desired target. Note that we have to be sure to
// grab the node's next sibling *before* we move it, because
// these things are live and when we moev it, well, the next
// sibling will become div-2!
node = tempdiv.firstChild;
next = node.nextSibling;
while (node) {
  parent.insertBefore(node, div);
  node = next;
  next = node ? node.nextSibling : undefined;
}

Live example

But here there be dragons, you have to select the container element as appropriate to the content you're inserting. For instance, we couldn't use a <tr> in your text with the code above because we're inserting it into a div, not a tbody, and so that's invalid and the results are implementation-specific. These sorts of complexities are why we have libraries to help us out. You've asked for a raw DOM answer and that's what the above is, but I really would check out jQuery, Closure, Prototype, YUI, or any of several others. They'll smooth a lot of stuff over for you.

T.J. Crowder
Maybe I do not understand you but this is exactly that I'm trying to avoid, wrapping HTML string into tag.
actual
"without wrapping it in another div created via document.createElement"
mplungjan
@actual: Sorry, will edit. I actually read "with"! :-)
T.J. Crowder
@actual: Fixed, sorry for misreading. It's exactly the same concept, it's just with a text node rather than an element.
T.J. Crowder
Unfortunately, HTML tags are [not working](http://jsfiddle.net/H3SLn/) inside text node.
actual
@actual: No, they won't -- that's part of what a text node is for. I see you've edited your question. Okay, third edit coming, it *is* possible, it's just a pain.
T.J. Crowder
@T.J. Crowder: sorry for edits, it is hard to ask questions ;)
actual
@actual: Not a problem, example above although Andy's `insertAdjacentHTML` looks cool.
T.J. Crowder
@T.J. Crowder: I wish I could accept multiple answers...
actual
Would the downvoter like to share some useful feedback?
T.J. Crowder
@actual: *"I wish I could accept multiple answers..."* Worry not! :-)
T.J. Crowder
Impressive work. I already +1ed before your first edit, but I wish I could give another for the effort put in since then.
Andy E
@Andy: LOL, thanks!
T.J. Crowder
A: 

Using jquery it is very simple:

$("#div-1").after("Other tag here!!!");

See: jquery.after

It is obvious that javascript is not a pure javascript solution.

angelcervera
How that could be translated into pure JS + DOM?
actual
jQuery != JavaScript
T.J. Crowder
jQuery was written in javascript last time I looked :)
mplungjan
@mplungjan: ...and?
T.J. Crowder
Well seeing most JS answers at SO involve jQuery, it is almost like jQuery==JavaScript ;) (but still not ===)
mplungjan
@mplungjan: It is, nevertheless, inappropriate and incorrect to answer a JavaScript / HTML / DOM question with a pure jQuery answer. (It's fine to give a pure JS answer and then say "but this would be easier if you used library X".)
T.J. Crowder
true - I see a lot of answers on the net here and elsewhere that does not even bother to mention jQuery, just gives the jQuery example. Such is life ;)
mplungjan
Ok, ok, Do not get angry. Solution it is not pure javascript, it is obvious and i am sure that @actual realize.But do not get angry. This is not a competition!
angelcervera
+4  A: 

Internet Explorer, Opera, Safari and Chrome all support element.insertAdjacentHTML(). Unfortunately, Firefox doesn't support it but I managed to find a workaround that uses ranges to insert the HTML, I've adapted it below to work for your scenario:

var el = document.getElementById("div-2"),
    html = "<span>Some HTML <b>here</b></span>";

// Internet Explorer, Opera, Google Chrome and Safari
if (el.insertAdjacentHTML)
    el.insertAdjacentHTML ("beforeBegin", html);
else {
    var range = document.createRange();
    var frag = range.createContextualFragment(html);
    el.parentNode.insertBefore(frag, el);
}

Live example: http://jsfiddle.net/AndyE/jARTf/

Andy E