Karl
Karl

Reputation: 97

Using JQuery .insertBefore() Method isn't Executing in the Order Given

I have a problem where the matching end tag is migrating up to it's pair, instead of wrapping content as in the order I have listed the statements. I am missing how/why this would happen. The JS Function:

$('.add-contributor-button').click(function(){
 $("<input type=\"text\" name=\"contributor\">").insertBefore('.add-contributor-button');
 $("<select>").insertBefore('.add-contributor-button');
  $("<option value=\"\" name=\"author\">Author</option>").insertBefore('.add-contributor-button');
  $("<option value=\"\" name=\"editor\">Editor</option>").insertBefore('.add-contributor-button');
  $("<option value=\"\" name=\"illustrator\">Illustrator</option>").insertBefore('.add-contributor-button');
  $("<option value=\"\" name=\"translator\">Translator</option>").insertBefore('.add-contributor-button');
  $("<option value=\"\" name=\"other\">Other</option>").insertBefore('.add-contributor-button');
$("</select>").insertBefore('.add-contributor-button');
});

The HTML before(and what is the target for duplication.):

<input type="text" name="contributor">
<select>
 <option value="" name="author">Author</option>
 <option value="" name="editor">Editor</option>
 <option value="" name="illustrator">Illustrator</option>
 <option value="" name="translator">Translator</option>
 <option value="" name="other">Other</option>
</select>
<div class="add-contributor-button">+ Add Contributor</div>

The Resulting HTML once the div is clicked(I am getting this from Firefox 50.1.0 inspector tool):

<input type="text" name="contributor">
<select>
 <option value="" name="author">Author</option>
 <option value="" name="illustrator">Illustrator</option>
 <option value="" name="translator">Translator</option>
 <option value="" name="other">Other</option>
</select>
<input type="text" name="contributor">
<select></select>
 <option value="" name="author">Author</option>
 <option value="" name="illustrator">Illustrator</option>
 <option value="" name="translator">Translator</option>
 <option value="" name="other">Other</option>
<div class="add-contributor-button">+ Add Contributor</div>

Upvotes: 0

Views: 343

Answers (2)

Tyler Roper
Tyler Roper

Reputation: 21672

I believe the issue here is a misunderstanding of how insertBefore() works in jQuery.

insertBefore() is not used to build lines of HTML. If you specify an HTML element like $("<select>").insertBefore(), it will create a new <select> element and add it to your page, closing tags and all.

That being said, we can keep that code. We do want a new <select> element, after all. But rather than inserting all our options, we want to append them, which adds them as children to the targeted element.

Like so:

$('.add-contributor-button').click(function() {
    $("<input type=\"text\" name=\"contributor\">").insertBefore('.add-contributor-button');
    $("<select>").insertBefore('.add-contributor-button')
        .append("<option value=\"\" name=\"author\">Author</option>")
        .append("<option value=\"\" name=\"editor\">Editor</option>")
        .append("<option value=\"\" name=\"illustrator\">Illustrator</option>")
        .append("<option value=\"\" name=\"translator\">Translator</option>")
        .append("<option value=\"\" name=\"other\">Other</option>");
});

I should really note, there are some more efficient ways of doing this. I was in the process of typing one, but zer00ne has posted a good example of how you can take the original inputs, and use the button to simply duplicate them instead of creating new ones from scratch each time.

Upvotes: 3

zer00ne
zer00ne

Reputation: 43880

Save yourself some headache and wrap <input> and <select> in a container (I used a <fieldset>) and then .clone() it.

SNIPPET

$('.add-contributor-button').click(function() {
  var clone = $('.original').clone(true, true);
  clone.removeClass('original').addClass('clone').insertBefore('.add-contributor-button');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<fieldset class='original set'>
  <input type="text" name="contributor">
  <select>
    <option value="" name="author">Author</option>
    <option value="" name="editor">Editor</option>
    <option value="" name="illustrator">Illustrator</option>
    <option value="" name="translator">Translator</option>
    <option value="" name="other">Other</option>
  </select>
</fieldset>

<div class="add-contributor-button">+ Add Contributor</div>

Upvotes: 2

Related Questions