Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery adding elements to parent

I'm having some trouble figuring out how to add elements to a parent object on a click event.

The result that i'm hoping to achieve is this:

<ul>
        <li><button>B1</button>
            <ul class="newul">
                <li><button>B1.1</button>
                    <ul class="newul">
                        <li><button>1.1.1</button></li>
                        <li><button>1.1.2</button></li>
                    </ul>
                </li>
                <li><button>B1.1</button></li>
            </ul>
        </li>
        <li><button>B2</button></li>
        <li><button>B3</button></li>
</ul>

Let's say I click button B2. I want a new UL added to the parent LI of that button and then be able to add new LI elements to the newly created UL. I hope that makes sense!

So basically, click button, add new UL with class "newul" to the LI you're currently in -> add new LI's to that newly created UL.

The jquery I'm currently using is as follows:

$('button').click(function(){
    //Get parent..
        var parent = $(this).parent();
        //Add a new UL to the parent and save it as newul           
        var newul = parent.add("ul");
                    //Add the class to the new UL
        newul.addClass('newul');               
        //Add a new li to the new UL            
            newli = newul.add('li');
            //Add a button to the new LI
            newli.append('<button></button>');

});

Unfortunately, this is having completely undesired effects and sticks buttons everywhere all over the place. I'd appreciate any help you can offer.

Here's a visible example of what i'm after. The top part is the effect id like to achieve.

Example of desired result

like image 370
Sinmok Avatar asked Jun 28 '12 16:06

Sinmok


2 Answers

Even though @am not i am has the correct code. There is no explanation of why your code fails, and I think that's the answer you are asking for.

There are several problems in your code:

First

//Add a new UL to the parent and save it as newul           
var newul = parent.add("ul");

The 'ul' is a selector and so is going to search the DOM for other <ul> elements, rather than create a new one. Also, parent.add() method is returning the parent object, not the ul's that you selected.

Correct code:

//Add a new UL to the parent and save it as newul           
var newul = $("<ul>").appendTo(parent);

Second:

//Add a new li to the new UL            
newli = newul.add('li');

Same problem again, and since newul is actually still the parent you're getting all types of craziness. Also, you're missing a var, but maybe I just don't get your closure.

Correct code:

//Add a new li to the new UL         
var newli = $("<li>").appendTo(newul);

That's all. If you fix that in your code, it'll work.

However, unless you really need those references to persist, better performance is usually achieved if you pass the whole thing as a string:

$('button').click( function() {

  $(this).parent()
    .append(
      $('<ul class="newul"><li><button></li></ul>')
    );
});

Edit

And if you wanted all the new buttons to have the same functionality, use the on() method and a class for your buttons:

$('body').on('click', 'button.ul-appending', function() {

  $(this).parent()
    .append(
      $('<ul class="newul"><li><button class="ul-appending"></li></ul>')
    );
});

You could change the 'body' selector to something much more specific so this doesn't get queried on every click on your page. Just make sure to add the class ul-appending to all the existing buttons that aren't generated by this handler.

JSFiddle

like image 163
merv Avatar answered Nov 16 '22 03:11

merv


One issue I see here is that the new buttons created will not have the click event bound to them. I fix this by using on and setting the event as a delegate. In doing so I give the outer ul an id of container. I also check to make sure you haven't already added a ul element and append one if it isn't inside the li. Here is a working example.

$('#container').on("click", "button.newbtn", function(){
    var parent = $(this).closest('li');
    var childUl = parent.children('ul');
    if(childUl.length === 0) {
        parent.append("<ul class='newul'></ul>");
        childUl = parent.children('ul');       
    }
    childUl.append($("<li><button class='newbtn'>" + $(this).html() + "." + (childUl.children().length + 1) + "</button></li>"));
});​
like image 1
John Kalberer Avatar answered Nov 16 '22 02:11

John Kalberer