zyglobe
zyglobe

Reputation: 1240

jQuery bug when trying to insert partial elements before() / after()?

I'm trying to wrap a div around an element (my 'template' div) by using jQuery's before() and after(). When I try to insert a closing after the selected element, it actually gets placed before the target.

Example:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Div Wrap</title>

<script src="http://code.jquery.com/jquery-1.4.4.min.js"></script>

<script>
$('document').ready(function() {
    var beforestr = "<div id=\"wrap\"><div id=\"header\">Top</div><div id=\"page\">";
    var afterstr = "</div><div id=\"footer\">Bottom</div></div>";
    $('#template').before(beforestr);
    $('#template').after(afterstr);
});
</script>

</head>
<body>

<div id="template">
    <h1>Page Title</h1>
    <p>Pellentesque habitant morbi tristique senectus 
    et netus et malesuada fames ac turpis egestas. Mauris 
    placerat eleifend leo. Quisque sit amet est et sapien 
    ullamcorper pharetra. 
    <script>document.write('This script should still work and might contain variables. Please don\'t recommend concatenation.');</script> 
    Donec non enim in turpis pulvinar facilisis.</p>
</div>

</body>
</html>

The result is:

<div id="wrap">
    <div id="header">Top</div>
    <div id="page">
    </div>
</div>
<div id="template">
    <h1>Page Title</h1>
        <p>Pellentesque habitant morbi tristique senectus 
        et netus et malesuada fames ac turpis egestas. Mauris 
        placerat eleifend leo. Quisque sit amet est et sapien 
        ullamcorper pharetra. 
        This script should still work and might contain variables. Please don't recommend concatenation.
        Donec non enim in turpis pulvinar facilisis.</p>
</div>
<div id="footer">Bottom</div>

Why are my closing wrap and page divs getting placed before the target, when I'm trying to place them after() ? Is there an alternative way to accomplish this (keeping in mind I may need to call script functions within the template div)?

As I'm sure you're aware, best practices aren't what I'm going for here.

Upvotes: 0

Views: 643

Answers (3)

SLaks
SLaks

Reputation: 887365

You cannot insert half of an HTML tag. Your code would leave an invalid DOM between the two calls.
The browser will fix up the HTML string for each call, and generate unwanted results.

Instead, call .wrap:

$('#template')
    .find('script').remove().end()
    .wrap('<div id="page"><div id="wrap"></div></div>')
    .parent()
    .before('<div id="header">Top</div>')
    .after('<div id="footer">Bottom</div>')

This will also correctly preserve <script>s in the content.

Demo

Upvotes: 1

msmithgu
msmithgu

Reputation: 340

Don't use partials. Add your header and footer using before() and after(), but use wrap() for your wrapper. Reference http://api.jquery.com/wrap/

Upvotes: 1

Nick Craver
Nick Craver

Reputation: 630379

You can't insert fragments, as they need to be complete DOM elements. Instead you should use .wrap() in some spots here; it should look like this instead:

$(document).ready(function() {
    $('#template').wrap('<div id="wrap">')
                  .wrap('<div id="page">').parent()
                  .before('<div id="header">Top</div>')
                  .after('<div id="footer">Bottom</div>');
});

You can test it out here. What this does is the effect you were after overall:

<div id="wrap">
  <div id="header">Top</div>
  <div id="page">
    <div id="template">
      <h1>Page Title</h1>
      <p id="aeaoofnhgocdbnbeljkmbjdmhbcokfdb-mousedown">Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Donec non enim in turpis pulvinar facilisis.</p>
    </div>
  </div>
  <div id="footer">Bottom</div>
</div>

Upvotes: 5

Related Questions