У меня есть обработчики событий, которые работают в FF, а не в Safari. Проще говоря, у меня есть список друзей, некоторые жестко запрограммированы, некоторые взяты из базы данных. При нажатии на друга открывается окно чата ... это очень похоже на систему чата Facebook.
Так что в Firefox все работает нормально и как положено. В Safari щелчок по жестко запрограммированным друзьям работает нормально, но щелчок по друзьям, извлеченным из базы данных, не открывает окно чата.
<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>
Поэтому я загружаю всех своих приятелей chat.getUsers
. Эта функция:
// 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 просто извлекает пользователей из базы данных и возвращает массив с именами пользователей. Итак, jQuery для щелчка по приятелю:
// 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"> – </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;
});
... и основная структура HTML:
<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> – </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>
Я не совсем уверен, с чего начать решение этой проблемы. Я подумал, что это может быть ошибка рендеринга или что-то в этом роде с DOM, но я весь день смотрел на этот код и застрял. Есть идеи, почему он работает в FF, а не в Safari? кстати ... тестирую на Snow Leopard.
Спасибо Христо
РЕДАКТИРОВАТЬ: Я попытался создать событие jQuery с помощью .live () и .delegate (), и произошло то же самое ... FF ломается, а Safari остается сломанным. Таким образом, функциональность теперь та же, и это хорошо, но событие щелчка не работает. Есть другие идеи?
2 ответа
Попробуй это:
$('#friends-panel').delegate( 'a.buddy', 'click', function() {
alert("Loaded");
// ...your code
});
... вместо $('#friends-panel a.buddy').click(function() {...
http://api.jquery.com/delegate/
Когда вы звоните .click(function...)
, вы фактически звоните .bind('click', function...)
.
Если он настроен на запуск после загрузки DOM, он назначает обработчик кликов существующим элементам.
Элементы, динамически добавляемые после загрузки DOM, от этого не выигрывают.
Использование .delegate()
помещает обработчик кликов на #friends-panel
и отслеживает щелчки, которые происходят сбоку от него. Когда это происходит, он проверяет, было ли это снова a.buddy
, и если да, запускает обработчик.
Другой вариант - просто привязать click()
в обратном вызове success
до (или после) добавления к #friends-panel
.
Чтобы привязать обработчик кликов к обратному вызову success
, сначала переместите функцию в переменную:
var myfunc = function() {
alert("Loaded");
// close #friends-panel
$('.subpanel').hide();
$('#friends-panel a.chat').removeClass('active');
// ...and so on
}
... тогда вместо текущего click
сделайте следующее:
$('#friends-panel a.buddy').click( myfunc );
... затем в обратном вызове success
сделайте следующее:
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);
}
РЕДАКТИРОВАТЬ: Чтобы назначить функцию, требующую параметра, обработчику кликов, один из способов - поместить вызов функции внутри функции обратного вызова.
Итак, вместо этого:
$('#friends-panel a.buddy').click( buddyClick );
Ты сделаешь это:
// Set up a handler that calls your function------v
$('#friends-panel a.buddy').click( function() { buddyClick(parameters) } );
Другой метод заключается в том, чтобы ваш buddyClick
возвращал функцию, которая использует переданные параметры, например:
// 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') );
Таким образом, вы можете вызвать buddyClick
, и он вернет функцию, которая принимает параметры, которые будут использоваться для обработчика.
Возможно, немного более запутанный, но действительный подход. Выбирайте. : o)
Как я обычно это делаю:
$('#friends-panel a.buddy').live('click',function() { ... });
Вместо того:
$('#friends-panel a.buddy').click(function() { ... });
.live позволяет привязать обработчики событий к элементам, загруженным AJAX (после готовности DOM).
РЕДАКТИРОВАТЬ:
Пример использования console.log () для отладки вашей проблемы:
// 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);
}
});
}
А также // щелкаем по приятелю на # панели друзей $ ('# friends-panel a.buddy'). click (function () { alert ("Загружено");
// закрыть # панель друзей $ ('. подпанель'). hide (); $ ('# панель друзей 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"> – </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;
});
Это может дать вам некоторое представление о том, где он ломается и почему. Вы также должны добавить console.log () во все функции события щелчка.
Похожие вопросы
Новые вопросы
jquery
jQuery — это библиотека JavaScript. Также рассмотрите возможность добавления тега JavaScript. jQuery — это популярная кросс-браузерная библиотека JavaScript, которая упрощает обход объектной модели документа (DOM), обработку событий, анимацию и взаимодействие AJAX, сводя к минимуму расхождения между браузерами. Вопрос с тегом jQuery должен быть связан с jQuery, поэтому jQuery должен использоваться рассматриваемым кодом, и в вопросе должны быть как минимум элементы, связанные с использованием jQuery.
delegate()
не работает. Вы пробовали мое последнее предложение, где привязать обработчик в обратном вызовеsuccess
? Если вы переместите функцию изclick()
в ее собственную переменную, вы можете повторно использовать ее в обоих местах. Я обновлю свой ответ, чтобы лучше понять, что я имею в виду.$(list).click(buddyClick).appendTo('#friend-list ul');
не добавляет список ни в одном браузере.