MdFarzan
MdFarzan

Reputation: 390

Unable to insert element before and after (both) in jQuery

I am using jQuery 3.x. I am trying to append a dynamically created element before and after an element using insertBefore() and insertAfter(). However, only insertBefore() is working, and another one is ignored. When I am commenting one then other is working. why?

p = $("<p></p>").text("This is a dynamicly created element");
p.insertAfter($('nav'));
p.insertBefore($('nav'));
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-size: 20px;
}

header,
nav,
main,
aside,
footer {
  padding: 10px 15px;
  border: 1px solid mediumseagreen;
  text-align: center;
}

header {
  background: dodgerBlue;
}

nav {
  background: mediumSeaGreen;
}

main {
  background: #d3d3d3;
}

main,
aside {
  height: 1200px;
}

main {
  width: 80%;
  float: left;
}

aside {
  width: 20%;
  float: right;
}

div::after {
  content: " ";
  float: none;
  clear: both;
  display: table;
}

main {
  text-align: left;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<header>
  This is header
</header>

<nav>
  This is navbar
</nav>

<main>
  <article>
    <h2>This is heading</h2>
    <p>
      Lorem ipsum dolor sit amet consectetur adipisicing elit. Cum atque fuga, eos neque ipsum enim id inventore necessitatibus laboriosam quo nobis, repellendus maxime veritatis error ut expedita, velit aspernatur asperiores!
    </p>
  </article>
</main>

<aside>
  This is side bar
</aside>
<div></div>
<footer>
  This is <a href="http://">footer</a>
</footer>

Upvotes: 1

Views: 609

Answers (1)

Rory McCrossan
Rory McCrossan

Reputation: 337560

The issue is because the p references only a single element. You insert it in to the DOM in the insertAfter() call, then move the same element to a new location using insertBefore().

To do what you require you can clone() the element before the second insertion. Also note that you don't need to create an entire jQuery object to select nav, you can just pass the selector as a string. Try this:

let p = $("<p />", { 
  text: "This is a dynamicly created element"
});
p.insertAfter('nav');
p.clone().insertBefore('nav');
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-size: 20px;
}

header,
nav,
main,
aside,
footer {
  padding: 10px 15px;
  border: 1px solid mediumseagreen;
  text-align: center;
}

header {
  background: dodgerBlue;
}

nav {
  background: mediumSeaGreen;
}

main {
  background: #d3d3d3;
}

main,
aside {
  height: 1200px;
}

main {
  width: 80%;
  float: left;
}

aside {
  width: 20%;
  float: right;
}

div::after {
  content: " ";
  float: none;
  clear: both;
  display: table;
}

main {
  text-align: left;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<header>This is header</header>
<nav>This is navbar</nav>
<main>
  <article>
    <h2>This is heading</h2>
    <p>
      Lorem ipsum dolor sit amet consectetur adipisicing elit. Cum atque fuga, eos neque ipsum enim id inventore necessitatibus laboriosam quo nobis, repellendus maxime veritatis error ut expedita, velit aspernatur asperiores!
    </p>
  </article>
</main>

<aside>This is side bar</aside>
<div></div>
<footer>This is <a href="http://">footer</a></footer>

One other thing to mention, I would suggest researching flexbox layouts. They're a much more modern and extensible technique than forcing display: table on a div to create a multi-column layout.

Upvotes: 2

Related Questions