开发者

jQuery works in FF but not in Safari

I have some event handlers that work in FF and not in Safari. Simply put, I have a list of friends, some hard-coded, some pulled in from a database. Clicking on a buddy opens a chat window... this is much like the Facebook chat system.

So in Firefox, everything works normally and as expected. In Safari, clicking on buddies that are hard-coded works fine, but clicking on buddies that are pulled in from the database doesn't pull up the chat window.

<script type="text/javascript" src="js/jQuery.js"></script>
<script type="text/javascript" src="js/chat.js"></script>
<script type="text/javascript" src="js/ChatBar.js"></script>
<script type="text/javascript" src="js/settings.js"></script>
<script type="text/javascript">
    var chat = new Chat();
    var from = <?php echo "'" .$_SESSION['userid'] . "'"; ?>;
    chat.getUsers(<?php echo "'" .$_SESSION['userid'] . "'"; ?>);
</script>

So I load all my buddies with chat.getUsers. That function is:

// get list of friends 
function getBuddyList(userName) {
    userNameID = userName;

    $.ajax({
        type: "GET",
        url: "buddyList.php",
        data: {
            'userName': userName,
            'current': numOfUsers
        },
        dataType: "json",
        cache: false,
        success: function(data) {
            if (numOfUsers != data.numOfUsers) {
                numOfUsers = data.numOfUsers;
                var list = "<li><span>Agents</span></li>";
                for (var i = 0; i < data.friendlist.length; i++) {  
                    list += "<li><a class=\"buddy\" href=\"#\"><img alt=\"\" src=\"images/chat-thumb.gif\">"+ data.friendlist[i] +"</a></li>";
                }
                $('#friend-list ul').append($(list));
            }
            setTimeout('getBuddyList(userNameID)', 1000);
        }
    });
}

buddyList.php just pulls in the Users from the database and returns an array with the user names. So the jQuery for clicking a buddy is:

// click on buddy in #friends-panel
$('#friends-panel a.buddy').click(function() {
    alert("Loaded");    
    // close #friends-panel
    $('.subpanel').hide();
    $('#friends-panel a.chat').removeClass('active');

    // if a chat window is already active, close it and deactivate
    $('#mainpanel li[class="active-buddy-tab"] div').not('#chat-box').removeAttr('id');
    $('#mainpanel li[class="active-buddy-tab"]').removeClass('active-buddy-tab').addClass('buddy-tab');

    // create active buddy chat window
    $('#mainpanel').append('<li class="active-buddy-tab"><a class="buddy-tab" href="#"></a><div id="chat-window"><h3><p id="to"></p></h3></div></li>');

    // create name and close/minimize buttons
    $('.active-buddy-tab div h3 p#to').text($(this).text());
    $('.active-buddy-tab div h3').append('<span class="close"> X </span><span class="minimize"> &ndash; </span>');
    $('.active-buddy-tab').append('<span class="close"> X </span>');

    // create chat area
    $('.activ开发者_如何学Pythone-buddy-tab div').append('<div id="chat-box"></div><form id="chat-message"><textarea id="message" maxlength="100"></textarea></form>');

    // put curser in chat window
    $('.active-buddy-tab #message').focus();

    // create a chat relationship
    return false;
});

... and the basic structure of the HTML is:

<div id="footpanel">
  <ul id="mainpanel">
    <li id="friends-panel">
      <a href="#" class="chat">Friends (<strong>18</strong>) </a>
      <div id="friend-list" class="subpanel">
        <h3><span> &ndash; </span>Friends Online</h3>
        <ul>
          <li><span>Family Members</span></li>
          <!-- Hard coded buddies -->
          <li><a href="#" class="buddy"><img src="images/chat-thumb.gif" alt="" /> Your Friend 1</a></li>
          <li><a href="#" class="buddy"><img src="images/chat-thumb.gif" alt="" /> Your Friend </a></li>
          <!-- buddies will be added in dynamically here -->
        </ul>
      </div>
    </li>
  </ul>
</div>

I'm not too sure where to begin solving this issue. I thought it might be a rendering bug or something with the DOM but I've been staring at this code all day and I'm stuck. Any ideas on why it works in FF and not in Safari? btw... I'm testing on Snow Leopard.

Thanks, Hristo

EDIT: I tried creating the jQuery event with .live() and .delegate() and the same thing happens... FF breaks and Safari remains broken. So the functionality is now the same, which is good, but the click event doesn't work. Any other ideas?


Try this:

$('#friends-panel').delegate( 'a.buddy', 'click', function() {
    alert("Loaded");    
    // ...your code
});

...instead of $('#friends-panel a.buddy').click(function() {...

http://api.jquery.com/delegate/

When you call .click(function...), you are actually calling .bind('click', function...).

If it is set up to run after the DOM loads, it assigns the click handler to existing elements.

Elements added dynamically after the DOM is loaded don't benefit from this.

Using .delegate() places the click handler on the #friends-panel, and listens for clicks that take place in side of it. When one occurs, it checks to see if it was agains the a.buddy, and if so, fires the handler.

Another option would be to simply bind the click() in your success callback before (or after) you append to #friends-panel.


To bind the click handler in your success callback, first move the function into a variable:

var myfunc = function() {
    alert("Loaded");    
    // close #friends-panel
    $('.subpanel').hide();
    $('#friends-panel a.chat').removeClass('active');

    // ...and so on
}

...then in place of your current click, do this instead:

$('#friends-panel a.buddy').click( myfunc );

...then in your success callback, do this:

success: function(data) {
            if (numOfUsers != data.numOfUsers) {
                numOfUsers = data.numOfUsers;
                var list = "<li><span>Agents</span></li>";
                for (var i = 0; i < data.friendlist.length; i++) {  
                    list += "<li><a class=\"buddy\" href=\"#\"><img alt=\"\" src=\"images/chat-thumb.gif\">"+ data.friendlist[i] +"</a></li>";
                }

                   // new version
                $(list).click( myfunc ).appendTo('#friend-list ul'); 

                // old version
// off-topic, no need to create jQuery object-----v
                // $('#friend-list ul').append($(list)); 

            }
            setTimeout('getBuddyList(userNameID)', 1000);
        }

EDIT: To assign a function that requires parameter to a click handler, one way is to place the function call inside the callback function.

So instead of this:

$('#friends-panel a.buddy').click( buddyClick );

you'll do this:

// Set up a handler that calls your function------v
$('#friends-panel a.buddy').click( function() { buddyClick(parameters) } );

The other method, is to have your buddyClick return a function that uses the parameters passed in, like:

// Calling buddyClick actually returns a function
//   that can use the parameters you passed in
var buddyClick = function(parameters) {
    return function() {
       alert("Loaded");
       // do something with the parameters  
       // ...and so on
    };
};

// Calling buddyClick returns the function
$('#friends-panel a.buddy').click( buddyClick('some_parameter') );

This way, you can call buddyClick, and it will return the function that accepts parameters to be used for the hander.

A little more confusing perhaps, but a valid approach. Take your pick. :o)


the way I usually do this is:

$('#friends-panel a.buddy').live('click',function() { ... });

instead of:

$('#friends-panel a.buddy').click(function() { ... });

.live allows you to bind event handlers to elements that are AJAX loaded (after DOM ready).


EDIT:

example of using console.log() to debug your issue:

// get list of friends 
function getBuddyList(userName) {
    userNameID = userName;
    console.log('userNameID: '+ userNameID); //make sure a userNameID is being passed.

    $.ajax({
        type: "GET",
        url: "buddyList.php",
        data: {
            'userName': userName,
            'current': numOfUsers
        },
        dataType: "json",
        cache: false,
        success: function(data) {
            console.log(data); //dump the returned data into the console.log
            if (numOfUsers != data.numOfUsers) {
                numOfUsers = data.numOfUsers;
                var list = "<li><span>Agents</span></li>";
                for (var i = 0; i < data.friendlist.length; i++) {  
                    list += "<li><a class=\"buddy\" href=\"#\"><img alt=\"\" src=\"images/chat-thumb.gif\">"+ data.friendlist[i] +"</a></li>";
                    console.log(list); //dump each iteration to the console but also show each addition on each iteration.
                }
                $('#friend-list ul').append($(list));
            }
            setTimeout('getBuddyList(userNameID)', 1000);
        }
    });
}

And // click on buddy in #friends-panel $('#friends-panel a.buddy').click(function() { alert("Loaded");
// close #friends-panel $('.subpanel').hide(); $('#friends-panel a.chat').removeClass('active');

// if a chat window is already active, close it and deactivate
$('#mainpanel li[class="active-buddy-tab"] div').not('#chat-box').removeAttr('id');
$('#mainpanel li[class="active-buddy-tab"]').removeClass('active-buddy-tab').addClass('buddy-tab');

// create active buddy chat window
$('#mainpanel').append('<li class="active-buddy-tab"><a class="buddy-tab" href="#"></a><div id="chat-window"><h3><p id="to"></p></h3></div></li>');

// create name and close/minimize buttons
$('.active-buddy-tab div h3 p#to').text($(this).text());
$('.active-buddy-tab div h3').append('<span class="close"> X </span><span class="minimize"> &ndash; </span>');
$('.active-buddy-tab').append('<span class="close"> X </span>');

// create chat area
$('.active-buddy-tab div').append('<div id="chat-box"></div><form id="chat-message"><textarea id="message" maxlength="100"></textarea></form>');

// put curser in chat window
$('.active-buddy-tab #message').focus();

// create a chat relationship
return false;

});

This might give you some ideas as to where it's breaking and why. You should also add console.log() throughout your click event function.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜