¿Por qué la función onclick no funciona en una clase?

I'm running Drupal 7 with JQuery and Node.js. I want an event to happen in a div onclick event. However, it won't work on a class, although it works if I use the parent div id.

The line that I'm having trouble with is:

    $(document).ready(function() {

  $('.chatNickname').click(function(){ 
alert("hello");
  });

The code snippet works in jsfiddle..not sure what the problem is. The entire code is below:

<script src="http://<?php print $_SERVER['SERVER_ADDR'] ?>:8080/socket.io/socket.io.js"></script>
<script>
  (function($){
    var myNick = 'me';
    var newlyJoined = true;
    var socket = io.connect('http://<?php print $_SERVER['SERVER_ADDR'] ?>:8080');

    socket.on('connect', function () {
      $('#chat').addClass('connected');
    });

    socket.on('announcement', function (msg) {
      $('#lines').append($('<p>').append($('<em>').text(msg)));
    });

    socket.on('nicknames', function (nicknames) {
    $('#nicknames').empty().append($('<span>Online: </span>'));
      for (var i in nicknames) {
    $('#nicknames').append($('<div class="chatNickname" id="' + nicknames[i] + '">').text(nicknames[i]));
      }
    });

    socket.on('user message', message);
    socket.on('reconnect', function () {
      $('#lines').remove();
      message('System', 'Reconnected to the server');
    });

    socket.on('reconnecting', function () {
      message('System', 'Attempting to re-connect to the server');
    });

    socket.on('error', function (e) {
      message('System', e ? e : 'A unknown error occurred');
    });

    socket.on('chat log', function(chatlog) {
      if (newlyJoined) {
    var i = 0;
    for (stamp in chatlog) {
      if (chatlog[stamp].type == 'user message') {
        var ts   = tstamp(stamp);
        var nick = chatlog[stamp].nick
        var msg  = chatlog[stamp].msg
        message(ts, nick, msg);
        i++;
      }
    }
    if (i > 0) {
      $('#lines').append($('<hr>')).append($('<small style="text-align:center; display:block; color: #888;">').text('Chat messages posted within the past half hour appear above this line.')).append($('<hr>'));
      $('#lines').get(0).scrollTop = 10000000;       
    }
    newlyJoined = false;
      }
    });

    function message (msg_time, from, msg) {
      $('#lines').append($('<p>').append($('<small>').text(msg_time)).append($('<b>').text(from), linkify(msg)));
    }

    function linkify(inputText) {
      //URLs starting with http://, https://, or ftp://
      var replacePattern1 = /(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim;
      var replacedText = inputText.replace(replacePattern1, '<a href="$1" target="_blank">$1</a>');

      //URLs starting with www. (without // before it, or it'd re-link the ones done above)
      var replacePattern2 = /(^|[^\/])(www\.[\S]+(\b|$))/gim;
      var replacedText = replacedText.replace(replacePattern2, '$1<a href="http://$2" target="_blank">$2</a>');

      //Change email addresses to mailto:: links
      var replacePattern3 = /(\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,6})/gim;
      var replacedText = replacedText.replace(replacePattern3, '<a href="mailto:$1">$1</a>');

      return replacedText
    }

    function tstamp(stamp) {
      var currentTime = new Date(); 
      if (typeof stamp != 'undefined') {
    currentTime.setTime(stamp);
      }
      var days = new Array('Sun', 'Mon', 'Tue', 'Wed', 'Thr', 'Fri', 'Sat');
      var day = currentTime.getDay();
      var hours = currentTime.getHours();
      var minutes = currentTime.getMinutes();
      if (minutes < 10) {
    minutes = "0" + minutes;
      }
      if (hours > 11) {
    var ap = 'p';
      }
      else {
    var ap = 'a';
      }
      if (hours > 12) {
    hours = hours - 12;
      }
      return "["+ days[day] + " " + hours + ":" + minutes + ap + "m] ";
    }

    $(document).ready(function() {

      $('#nicknames .chatNickname').click(function(){ 
    alert("hello");
      });

      $('input#message').focus(function() {
    if ($(this).val() == 'Type your chat messages here...') {
      $(this).val('');
    }
      });

      $('input#show-timestamps').click(function() {
    if ($(this).is(':checked')) {
      $('#messages p small').show();
    }
    else {
      $('#messages p small').hide();
    }
      })

      socket.emit('nickname', '<?php print $username ?>', function (nick) {
    if (nick != 'me') {
      myNick = nick;
      socket.emit('get log');          
      return $('#chat').addClass('nickname-set');
    }
      });

      $('#send-message').submit(function () {
    message(tstamp(), myNick, $('#message').val());
    socket.emit('user message', $('#message').val());
    clear();
    $('#lines').get(0).scrollTop = 10000000;
    return false;
      });

      function clear () {
    $('#message').val('').focus();
      };

    });
  })(jQuery);
</script>
<div id="chat">
  <div id="messages">
    <div id="nicknames">
    </div>
    <div id="lines">
    </div>
  </div>
  <form id="send-message" autocomplete="off">
    <input id="message" type="text" value="Type your chat messages here..." autocomplete="off" />
    <button>Send</button>
  </form>
</div>
<small><input id="show-timestamps" type="checkbox" checked="checked" /> Show timestamps</small>

preguntado el 04 de julio de 12 a las 03:07

2 Respuestas

You're using sockets and appending the element after the click handler has been attached. That means the element did'nt exist when the original click handler was set. You'll need to delegate the event to a higher element, like so:

$('#nicknames').on('click', '.chatNickname', function(){ 
   alert("hello");
});

Respondido 04 Jul 12, 04:07

Thanks for the help! that was the answer. I guess I don't understand how Javascript handlers work. The elements have to be created BEFORE the handler is called, so the handler binds to the existing elements? Javascript isn't dynamically listening to see if new divs are created? Also, what's the difference between .on('click') and .click? according to aquí, .click is a shortcut function - Trevor Newhook

No, it only attaches handlers to elements that already exists. To attach handlers to future elements delegation is necessary. Using on() the regular way with a click event is just the same as click(), but none of those will delegate the event, for that you'll need live(), delegate(), or preferrably on() like it's written in my answer, where it listens on a non dynamic element for events that bubble, and when the target matches it executes the function etc. - adeneo

As I can see you are appending the element dynamically please try this: sample demo: http://jsfiddle.net/CGxyj/

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

$(document).ready(function() {

  $('.chatNickname').on('click', function(){ 
       alert("hello");
  });

}); // this was not closed wither

Respondido 04 Jul 12, 04:07

This does nothing for dynamic elements as it's not a delegated event handler, is just a regular handler like element.click(function() {..}); - adeneo

Hiya @adeneo mire aquí : jsfiddle.net/CGxyj I do what do you mean but I you have mentioned it hence I wont update my post, anyhoo, not worth a downvote though but thats just my opinion thanks for comment, - Tats_innit

Yes, but in your example the element exists before the handler is attached, try this VIOLÍN and see the difference if the element is appended after the handler, and this VIOLÍN to see it working with delegation, which is how you deal with dynamic elements. It's also exhaustively explained in the documentation for on(), and there's a million questions about it on here aswell. - adeneo

@adeneo yes but why would the .on will reside after append, it is clear in api doc as well, Yes that will be placed after the .append script, D'uh yep second will work in any case, beacuse of $(document).on( Thank-you for the comment though :) - Tats_innit

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.