0

I have got a list full of items that contain img tags with some text inside of them.

I am trying to insert a <br> tag between the end of the img tag and text node before the closing <li> tag.

So each li item should look like:

<li><img><br>Text</li>

I want the code to be strictly JavaScript - no libraries.

My JavaScript begins like this:

var images = [];
// get all the images on the page
images = document.getElementsByTagName("img");
// create br element
var br = document.createElement("br");

for (var i = 0; i < images.length; i++) {
    // loop through all the image tags and 
    // append br element as first sibling as img
}

I have tried the following inside the for loop

  • images[i].parentNode.insertBefore(br, images[i].nextSibling);
  • images[i].appendChild(br);

Here's a snippet of the HTML:

<div>
    <ul>
        <li role="button"><img src="icons/home.png" alt="Home icon" height="24" width="24"/>Home</li>
        <li role="button"><img src="icons/pan-map.png" alt="Pan Map icon" height="24" width="24"/>Pan Map</li>
        <li role="button"><img src="icons/initial-map-view.png" alt="Initial Map View icon" height="24" width="24"/>Initial View</li>
        <li role="button"><img src="icons/zoom-in.png" alt="Zoom In icon" height="24" width="24"/>Zoom In</li>
        <li role="button"><img src="icons/zoom-out.png" alt="Zoom Out icon" height="24" width="24"/>Zoom Out</li>
    </ul>
</div>

Edit: The above script is for use in IE7 which does not support display: inline-block, therefore in this case, CSS cannot be relied upon for a solution

David
  • 139
  • 1
  • 12

4 Answers4

1

You must create a new br for each image:

var br = document.createElement("br");
images[i].parentNode.insertBefore(br, images[i].nextSibling);

var images = document.getElementsByTagName("img");
for (var i = 0; i < images.length; i++) {
  var br = document.createElement("br");
  images[i].parentNode.insertBefore(br, images[i].nextSibling);
}
<div>
  <ul>
    <li role="button"><img src="/favicon.ico" />Home</li>
    <li role="button"><img src="/favicon.ico" />Pan Map</li>
    <li role="button"><img src="/favicon.ico" />Initial View</li>
    <li role="button"><img src="/favicon.ico" />Zoom In</li>
    <li role="button"><img src="/favicon.ico" />Zoom Out</li>
  </ul>
</div>

Or you can clone it:

images[i].parentNode.insertBefore(br.cloneNode(false), images[i].nextSibling);

var images = document.getElementsByTagName("img");
var br = document.createElement("br");
for (var i = 0; i < images.length; i++) {
  images[i].parentNode.insertBefore(br.cloneNode(false), images[i].nextSibling);
}
<div>
  <ul>
    <li role="button"><img src="/favicon.ico" />Home</li>
    <li role="button"><img src="/favicon.ico" />Pan Map</li>
    <li role="button"><img src="/favicon.ico" />Initial View</li>
    <li role="button"><img src="/favicon.ico" />Zoom In</li>
    <li role="button"><img src="/favicon.ico" />Zoom Out</li>
  </ul>
</div>

That said, you can produce a line break by displaying the image as a block:

img { display: block; }

img {
  display: block;
}
<div>
  <ul>
    <li role="button"><img src="/favicon.ico" />Home</li>
    <li role="button"><img src="/favicon.ico" />Pan Map</li>
    <li role="button"><img src="/favicon.ico" />Initial View</li>
    <li role="button"><img src="/favicon.ico" />Zoom In</li>
    <li role="button"><img src="/favicon.ico" />Zoom Out</li>
  </ul>
</div>
Oriol
  • 274,082
  • 63
  • 437
  • 513
1

Using https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML

images = document.getElementsByTagName("img");

for (var i = 0; i < images.length; i++) {
  images[i].insertAdjacentHTML('afterend', '<br/>')
}
<div>
  <ul>
    <li role="button">
      <img src="icons/home.png" alt="Home icon" height="24" width="24" />Home</li>
    <li role="button">
      <img src="icons/pan-map.png" alt="Pan Map icon" height="24" width="24" />Pan Map</li>
    <li role="button">
      <img src="icons/initial-map-view.png" alt="Initial Map View icon" height="24" width="24" />Initial View</li>
    <li role="button">
      <img src="icons/zoom-in.png" alt="Zoom In icon" height="24" width="24" />Zoom In</li>
    <li role="button">
      <img src="icons/zoom-out.png" alt="Zoom Out icon" height="24" width="24" />Zoom Out</li>
  </ul>
</div>
WalksAway
  • 2,769
  • 2
  • 20
  • 42
0

As seen in How to do insert After() in JavaScript without using a library? you can define your insertAfter function as follows:

var images = [];
images = document.getElementsByTagName("img");

for (var i = 0; i < images.length; i++) {
 var br = document.createElement("br");
 insertAfter(br, images[i])
}

function insertAfter(newNode, referenceNode) {
 referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
}
<div>
 <ul>
  <li role="button"><img src="http://placehold.it/300x200" alt="Home icon" height="24" width="24" />Home</li>
  <li role="button"><img src="http://placehold.it/300x200" alt="Pan Map icon" height="24" width="24" />Pan Map</li>
  <li role="button"><img src="http://placehold.it/300x200" alt="Initial Map View icon" height="24" width="24" />Initial View</li>
  <li role="button"><img src="http://placehold.it/300x200" alt="Zoom In icon" height="24" width="24" />Zoom In</li>
  <li role="button"><img src="http://placehold.it/300x200" alt="Zoom Out icon" height="24" width="24" />Zoom Out</li>
 </ul>
</div>
Community
  • 1
  • 1
Paul Ghiran
  • 1,233
  • 1
  • 16
  • 29
-1

So, as frequently happens when formulating a question for submission on StackOverflow, you come to find a solution to your problem.

For anyone else who finds themselves in a similar situation, here is how I solved the problem (plus a little context on why I was trying to solve this particular problem to begin with). The implemented method is not elegant by any means (if you find a smoother solution, please post it here).

Here's how I solved it; place this inside your for loop:

images[i].outerHTML = images[i].outerHTML + "<br>"; 

Stupidly simple, albeit unsophisticated.


** EDIT ***

Inspired by the selected answer given here, I offer an arguably more semantic approach to the problem using, instead of insertAdjacentHTML, the insertAdjacentElement method. Because we are in fact venturing to insert an element primarily, I think this method is perhaps the better choice.

// init the array
var images = [];
// collect all the img elements
images = document.getElementsByTagName("img");
// loop through the collection of img elements
for (var i = 0; i < images.length; i++) {
    // on each iteration, create a new <br> element and insert adjacent to the <img>
    var br = document.createElement("br");
    images[i].insertAdjacentElement('afterend', br)
}

(original post cont.)

The reason I wanted to insert a <br> tag as the first sibling of the <img> tag was to fix a display issue in IE7, which does not implement the usage display: inline-block. As it were, I was inclined to use display: inline for my images. This created a centering problem. The image tags, in order to be affected by it's parent <ul> style declaration of text-align: center; needed to be on it's own line. However, with a text node as the <img>'s immediate sibling, both the img and text end up on the same line.

In order to center the img with the text below it, a <br> tag needs to be inserted to break both elements onto there own line.

IE7 display: Final result

David
  • 139
  • 1
  • 12
  • This will remove the internal data of the existing elements. Never use `outerHTML` nor `innerHTML` to insert nodes. – Oriol Jul 07 '16 at 21:38