2

This is probably something really obvious but I'm new to jquery so don't know what the problem is.

I'm making a simple forum (to see if I can) using php/jquery/html etc. When it's first opened it displays a list of the forums (works fine) and empty boxes(divs) for the other content. When you click on a forum from the list it calls showForum(id) and puts up an alert (just so i know it's working) and that loads a list of the threads in the forum into an empty div (works fine). The problem is when I try to load a thread (by clicking on it), nothing happens, not even the alert.

Jquery code:

$(document).ready(function() {
    $('.flink').click(function() {
        var id = $(this).attr('id');
        showForum(id);
        alert("Forum opened");
    });                    

    $('.tlink').click(function() {
        var id = $(this).attr('id');
        showThread(id);
        alert("Thread opened");
    }); 
});

function showForum(id) {
    $('.topic-container').load("showforum.php", {
    'f': +id
    });
    showLinks(id, 1);
}

function showThread(id) {
    $('.entry-container').load("showthread.php", {
    'thread': +id
    });
    showLinks(id, 2);
    alert(id);
}

HTML code:

<html>
    <head>
        <title>
            Title
        </title>
    </head>
    <body>

        <table class="out-table">
            <tr>
                <td rowspan="6" class="side-menu">
                    <table class="side-header">
                        <?php  // Code to get stuff from DB, flinks are created in here. tlinks are created with more php in showforum.php ?>
                    </table>
                </td>
            </tr>
            <tr>
                <td>
                    <div class="topic-container">
                    </div>
                </td>
            </tr>
            <tr>
                <td>
                    <div class="top-links">
                    </div>
                </td>
            </tr>
            <tr>
                <td>
                    <div class="entry-container">
                    </div>
                </td>
            </tr>
        </table>
    </body>
</html>

I've checked the classnames to make sure that they're right. I made clicking on a forum open call showThread (just to make sure the function worked) and it worked fine.

Any help anyone can give will be greatly appreciated.

user2371266
  • 163
  • 8
  • 3
    You need to use `.on()` to delegate handlers to elements that aren't yet in the DOM when you bind the handlers. – Barmar May 10 '13 at 19:41
  • What version of jQuery are you using? If it's 1.7+, @PSL answer should work (on guarantees that any added element will be bound to the event), otherwise, you'll have to hook the thread click events in the load callback function (complete). – rivarolle May 10 '13 at 19:48
  • @rivarolle In jQuery v1.3 - v1.6, the recommended substitute for `.on` is [`.delegate`](http://api.jquery.com/delegate/). – apsillers May 10 '13 at 19:51
  • @apsillers Yes, definitely better. – rivarolle May 10 '13 at 19:54

2 Answers2

2

You need event delegation for the content added with load using on. Your click events are only applied to the elements existing in DOM. SO you need to attach the event to the parent (which already exists) or the document element, so the elements added later on will have the events available by "delegation".

See .on()

Sample Demo

In your case i am guessing .tlink are added later in time during load to the DOM. But you are attaching the events to .tlink before even it exists, so effectively those binds are of void effect.

$(document).on('click','.flink', function() {
        var id = $(this).attr('id');
        showForum(id);
        alert("Forum opened");
    });                    

    $(document).on('click','.tlink', function() {
        var id = $(this).attr('id');
        showThread(id);
        alert("Thread opened");
    }); 

Delegated events have the advantage that they can process events from descendant elements that are added to the document at a later time. By picking an element that is guaranteed to be present at the time the delegated event handler is attached, you can use delegated events to avoid the need to frequently attach and remove event handlers. This element could be the container element of a view in a Model-View-Controller design, for example, or document if the event handler wants to monitor all bubbling events in the document.

PSL
  • 123,204
  • 21
  • 253
  • 243
  • I've tried this code (and the code from danda1man's comment) and neither works, now showForum isn't called when flink is clicked – user2371266 May 10 '13 at 19:49
  • `document` really shouldn't be used here unless absolutely needed. And it seems in this case it isn't as the two element which are being `load`ed can easily be used. – James Montagne May 10 '13 at 19:50
  • @JamesMontagne i agree document shouldn't be used, but i have mentioned it in the answer as i don't know OP's DOM structure. `event to the parent (which already exists) or the document element` – PSL May 10 '13 at 19:51
  • @user2371266 Which version of jquery you are using, also can you show your html structure... – PSL May 10 '13 at 19:51
  • using jquery 1.9.1 and managed to get this code to work by change $(document) to $('body') – user2371266 May 10 '13 at 19:58
  • Ok. Instead of body, use the container element that is guaranteed to be present at any given time... – PSL May 10 '13 at 19:59
  • Only works if i remove the $(document).ready(function() { line :S – user2371266 May 10 '13 at 20:06
  • Can you post your minimal code to replicate the issue in a fiddle. – PSL May 10 '13 at 20:07
  • Check out this Fiddle http://jsfiddle.net/Cm5Dc/ – PSL May 10 '13 at 20:15
0

You need to use the .on handler for your clicks since your content is being dynamically loaded: http://api.jquery.com/on/

For your code try this:

$(document).on("click", ".flink", fLink);
function fLink(e) {
var id = $(this).attr('id');
        showForum(id);
        alert("Forum opened");
}

$(document).on("click", ".llink", lLink);
function lLink(e) {
var id = $(this).attr('id');
        showThread(id);
        alert("Thread opened");
}
Dan
  • 1,101
  • 1
  • 9
  • 30