0

I currently have an "Add more" button that when clicked, duplicates a div I have. The problem currently is when the button is clicked and the div duplicates, it appears below the "Add more" button. I want the div to duplicate right under the original div when clicked, this also means the duplicate will be above the "Add more" button. How do I go about doing this?

HTML

                    <!-- Instrument Exp. -->
                    <div>
                        <label>What instruments and level do you want to teach?</label>
                        <div class="form-inline justify-content-center" id="ins_1">
                            <!-- Instrument 1 -->
                            <div>
                                <select class="form-control ins">
                                    <option>Instrument</option>
                                    <option>Cello</option>
                                    <option>Clarinet</option>
                                    <option>Drums</option>
                                    <option>Flute</option>
                                    <option>Guitar</option>
                                    <option>Piano</option>
                                    <option>Saxophone</option>
                                    <option>Violin</option>
                                    <option>Vocal</option>
                                    <option>Trumpet</option>
                                </select>
                            </div>

                            <!-- Level 1 -->
                            <div>
                                <select class="form-control lvl">
                                    <option>Level</option>
                                    <option>Beginner</option>
                                    <option>Advanced</option>
                                    <option>Intermediate</option>
                                </select>
                            </div>
                        </div>


                    <!-- Add More -->
                    <div class="text-center" id="add_more">
                        <button type="button" class="no_link" onclick="add_instrument()">Add more +</button>
                    </div>
            </div>

JavaScript

var i = 0;
var original = document.getElementById('ins_1');

function add_instrument() {
    var clone = original.cloneNode(true);
    clone.id = "ins_1" + ++i;
    original.parentNode.appendChild(clone);
}
  • Please don't vandalize your posts. – Welz May 26 '18 at 00:00
  • Please don't make more work for people by vandalizing your posts. By posting on the Stack Exchange (SE) network, you've granted a non-revocable right, under the [CC BY-SA 3.0 license](//creativecommons.org/licenses/by-sa/3.0), for SE to distribute that content (i.e. regardless of your future choices). By SE policy, the non-vandalized version of the post is the one which is distributed. Thus, any vandalism will be reverted. – Makyen May 26 '18 at 00:00

2 Answers2

2

See insertBefore, https://developer.mozilla.org/en-US/docs/Web/API/Node/insertBefore. If you combine it with nextSibling, you can have it add right after it:

var i = 0;
var original = document.getElementById('ins_1');
function add_instrument() {
    var clone = original.cloneNode(true);
    clone.id = "ins_1" + ++i;
    original.parentNode.insertBefore(clone, original.nextSibling);
}

Also see: How to insert an element after another element in JavaScript without using a library?

Edit: As @Tej pointed out in the comments, there are nice functions to insert nodes adjacently: insertAdjacentHTML, and insertAdjacentElement. insertAdjacentElement requires IE8+ or a recent browser.

The code becomes more readable with those functions, in my opinion:

var i = 0;
var original = document.getElementById('ins_1');
function add_instrument() {
    var clone = original.cloneNode(true);
    clone.id = "ins_1" + ++i;
    original.insertAdjacentElement('afterend', clone);
}
Steve
  • 10,435
  • 15
  • 21
  • 1
    I think we can try insertAdjacentHTML as well. https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML – Tej May 25 '18 at 04:30
  • This will always insert after the first element in the list rather than appending to the end of the list – Garrett Johnson May 25 '18 at 04:32
  • @GarrettJohnson, I believe this is the behavior the questioner wanted: "I want the div to duplicate right under the original div when clicked" – Steve May 25 '18 at 04:34
  • @Tej, nice! I didn't know about those methods. It looks like `insertAdjacentElement` might be the one to go with. – Steve May 25 '18 at 04:36
  • Oh, I suppose that could be true. I hadn't read it that way. That will result in the list of items being ordered in 1, 5, 4, 3, 2 if multiple adds happen. – Garrett Johnson May 25 '18 at 04:36
  • 1
    @Steve Sorry I pasted the wrong URL. Here is the right one https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentElement – Tej May 25 '18 at 04:40
1

appendChild inserts the node as the last child of the node. In this case, that's after the 'add more' button because your list and button are children within the same element.

Solution 1

Put your list of new instruments in a different element so appending to the end of the parent has the desired effect.

<div>
    <label>What instruments and level do you want to teach?</label>
    <div class="items">
        <div class="form-inline justify-content-center" id="ins_1">
            ...
        </div>
    </div>

    <!-- Add More -->
    <div class="text-center" id="add_more">
        <button type="button" class="no_link" onclick="add_instrument()">Add more +</button>
    </div>
</div>

Solution 2

Use insert before and insert before the "add more button".

original.parentNode.insertBefore(clone, addMoreButton);

Solution 3 (not recommended)

Append the "add more" button appending the new instrument item to place it back at the end of the list.

Garrett Johnson
  • 2,413
  • 9
  • 17