Question

I currently have two parts: an interactive chat, and a couple functions that can dynamically add tabs and remove them again. As you might expect I now want to merge them so that you can have a chat within each tab. The way I'm now trying that is by merging all functions in one script, and upon adding a new tab, simply appending the textarea and conversation-div (to hold messages) that I need to run the chat. The problem is that when I hit the send button it doesn't seem to call the function sendMessage().

So I add the html dynamically is like this:

function addTab() {
    $('#pageTab').append(
        $('<li><a href="#usertab' + this.id + '">' + this.id +
            '<button class="close" type="button">×</button></a></li>'));
    $('#pageTabContent').append($('<div class="tab-pane" id="usertab' + this.id 
        +'"><form id="send_message_form"><textarea id="messageText" rows="1" cols="25"></textarea></br>'
        + '<input type="button" id="sendButton" value="Send Message"></form>'
        + '<div class="conversation"></div></div>'));
    $('#page' + this.id).tab('show');
}

and instead of the sendMessage I simplified the click action like this:

$("#sendButton").click(function(){
    alert("BEHOLD, I AM ALIVE!!");
});

But unfortunately no alert pops up. Does anybody know how I can get this to work? All tips are welcome!

(a paste of the full code that I have is right here)

[EDIT] Thanks for the help! I now indeed can show the alert button. The strange thing is that when I subsequently call another function from within this one to POST a message to the server, it does nothing.

So I now call sendMessage from within the on("click" like below. Although it now does show the "BEHOLD, I AM ALIVE!!" and also the "BEHOLD, We're in the sendMessage.", Firebug shows that it doesn't do the POST, even though I use this very same message in another page (without the tabs) where it does work. Any ideas what's wrong with this then?

function sendMessage(message, user_id) {
    alert("BEHOLD, We're in the sendMessage.");
    $.ajax({
        type: "POST",
        contentType: "application/json",
        accepts: "application/json; charset=utf-8",
        url: "/api/support/" + "1",
        data: JSON.stringify({
            'action': 'ADD_MESSAGE',
            'user_id': user_id,
            'message': message
        }),
        dataType: "json",
        success: function(data) {
            alert("BEHOLD, I have posted!!");
            updateConversation();
        }
    });
}

$(".container").on("click", "#sendButton", function() {
    alert("BEHOLD, I AM ALIVE!!");
    var text = $("#messageText").val(); // Get the text
    sendMessage(text, 1);
});
Was it helpful?

Solution

This is a delegation issue. The button doesn't exist at the time that you try to assign the event handler to it. There are two ways you can handle this. You can either move the click event handler assignment to the addTab() function, after the code has been appended, or you can change it to this...

$("#pageTab").on("click", "#sendButton", function(){
    alert("BEHOLD, I AM ALIVE!!");
});

I'd recommend looking at the documentation for .on()...

http://api.jquery.com/on/

Edit:

As for your data posting issue, try changing the code to this...

$.ajax({
    type: "POST",
    contentType: "application/json",
    accepts: "application/json; charset=utf-8",
    url: "/api/support/1",
    data: {
        action: 'ADD_MESSAGE',
        user_id: user_id,
        message: message
    },
    dataType: "json",
    success: function(data) {
        alert("BEHOLD, I have posted!!");
        updateConversation();
    }
});

The only significant difference is that it's allowing jQuery to send the data as JSON, rather than you converting it first. Let us know how you get on with that.

OTHER TIPS

The useful terms here are event delegation and bubbling. You can't attach an event listener to an element that doesn't exist yet, but you can attach a listener to a parent element so that when you add the new element to the DOM the event bubbles up.

In this case you can probably get away with using #pageTab rather than document.

$('#pageTab').on('click', '#sendButton', function(){
  alert("BEHOLD, I AM ALIVE!!");
});

#sendButton is created dynamically, so you need to use even delegation. Attach the click event the to the '#pageTab' and then delgate it to #sendButton. Basically the element doesn't exist when you bind the click event to it

$('#pageTab').on('click', '#sendButton', function(){
    alert("BEHOLD, I AM ALIVE!!");
});

You must add the event response to a parent, for example:

$("#pageTab").click( "#sendButton", function(){ ... } )};

When you create the event response it doesn't matter if there is not any button. In your example if there is not any buttom the function is not associated with the event.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top