2

I have an HTML code:

<html>
<head>
    <style>
        .selected {
            color: red;
        }

        #myContainer div {
            border: 1px solid #333;
        }
    </style>
    <script type="text/javascript" src="jquery.js"></script>

    <script type="text/javascript">
        $(document).ready(function(){
            // array of links
            var listItems = $('#myList li a');

            // array of divs contain content (called containers)
            var containers = $('#myContainer > div');

            // hide all containers
            containers.hide();

            // listen for click event on links
            listItems.click(function(e){
                // prevent link default action
                e.preventDefault();

                // hide all containers
                containers.hide();

                // show the container that has id like value of link's hash
                containers.filter(this.hash).show();

                // remove selected class on all links
                listItems.removeClass('selected');

                // add selected class on this link
                $(this).addClass('selected');
                return false;
            }).filter(':first').click(); // default the first link is active 
        });
    </script>
</head>
<body>
    <ul id="myList">
        <li><a href="#first">This is the 1st link</a></li>
        <li><a href="#second">This is the 2nd link</a></li>
        <li><a href="#third">This is the 3rd link</a></li>
    </ul>

    <div id="myContainer">
        <div id="first">xxx</div>
        <div id="second">yyy</div>
        <div id="third">zzz</div>
    </div>
</body>
</html>

When you click on one of three link above, the content of the corresponding div (one of three direct children of div#myContainer) will be shown.

But let's say that the HTML is returned from an certain AJAX call. So the click event maybe not work. I remember that a selector resulted from an AJAX call must use something like

$(selector).live('click', function(){
    // do stuff here
})

not

$(selector).click()

So, what should I do in this case to keep all behaviors as expected when HTML code resulted from an AJAX call, not static HTML?

Thanks

Leo Lerdorf
  • 1,304
  • 4
  • 15
  • 19
  • You answered you're own question. Live is OK (you could also use .delegate or .on) http://api.jquery.com/category/events/ – elrado Feb 19 '12 at 09:29
  • FYI, [`.on()`](http://api.jquery.com/on/) requires jQuery 1.7 or above – andyb Feb 19 '12 at 09:33
  • @elrado: but look at this .filter(':first').click(); // default the first link is active I tried .filter(':first').live('click'); but it didnt work – Leo Lerdorf Feb 19 '12 at 10:43
  • FYI, .live() is deprecated in 1.7 – Andy Feb 19 '12 at 10:46
  • 1
    @LeoLerdorf: Elijah Manor has writting an interesting post on his blog about the "Differences Between jQuery .bind() vs .live() vs .delegate() vs .on()": http://www.elijahmanor.com/2012/02/differences-between-jquery-bind-vs-live.html – LeftyX Feb 19 '12 at 11:24

2 Answers2

1
$(document).ready(function(){
    var listItems = $('#myList li a'),
        containers = $('#myContainer > div');

    containers.not(':first').hide();
    $('#myList li a:first').addClass('selected');

    $(document).on('click', listItems, function(e) {
        e.preventDefault();
        containers.hide().filter(e.target.hash).show();
        listItems.removeClass('selected').filter(e.target).addClass('selected');
    });
});​

FIDDLE

If your not using jQuery 1.7 or above, download it and start using the newest version!

adeneo
  • 312,895
  • 29
  • 395
  • 388
  • thanks, but your solution just "not hide" the first container, other events such as active the link (at the begining) are not attached as expected. – Leo Lerdorf Feb 19 '12 at 15:24
  • @LeoLerdorf - I did indeed not make the first link active, as I figured it would be easy to do, anyway, edited my answer to include this, and it's way better to just add a class than faking a click on an element just to attach that class. – adeneo Feb 19 '12 at 15:38
  • "...faking a click on an element just to attach that class" ... I tried to give an uncomplicated example. In fact (the real problem in my project) I send an ajax call when an element is clicked. The reason that I fake a click because of DRY principle (Dont Repeat Yourself) – Leo Lerdorf Feb 19 '12 at 15:48
  • Well, I have no idea how you are doing this other than the example you have given, and in the example you are triggering a click event to make an element that you have hidden visible again, and to set a class. IMHO it is better to just not hide the element, and attach the class right of the bat, and the best way would probably be to just add the selected class to the first link in your HTML. If you are doing something else completely there is no certainty that the answer will work, but the above code should work fine with dynamicly inserted content, and does what it's supposed to for me? – adeneo Feb 19 '12 at 16:43
  • I think I actually get it now, I think your problem is the variables listItems and containers. Those are only updated on first load, and any elements added dynamicly after the first load will not be inside this variable, for that you would have to run the search for elements again after your Ajax call, like so: `var listItems = $('#myList li a');` once again after elements are inserted. – adeneo Feb 19 '12 at 16:50
1

@Leo Lerdorf Code below works as expected:

// array of links
var listItems = $('#myList li a');

$('a').live('click',function(e){
    e.preventDefault();
    alert(11);
});


 $('a:last').one('click',function(e){
    $("#myList").append(
        "<a href='#frt'>This is the 4th link</a> "
    );
}); 

instead of $(selector).filter try using just selector (if it is possible, if not we'll think of something else :)).

Whitch jquery version are you using?

You could also try this

$('#myList').delegate("a:first", "click", function () {
    alert('elrado');
});
elrado
  • 4,960
  • 1
  • 17
  • 15