#javascript #jquery #dhtml #jquery-bbq
#javascript #jquery #dhtml #jquery-bbq
Вопрос:
Я реализовал страницу со списком опций (категорий заданий), при нажатии на которые должны отображаться данные (описания заданий). Я использую BBQ для обработки заднего стека.
Все работает отлично, за исключением настройки начального выбора при первом переходе пользователя на страницу. Мой код вызывается addClass('selected')
к нужному элементу, но похоже, что этот элемент фактически недоступен при запуске кода.
Обратите внимание, что я добавил отладочный вызов $('#category' C).append('bite me');
, чтобы доказать себе, что это НЕ было проблемой с таблицей стилей / CSS.
Вот мой код:
<script>
function historyCallback(e) {
var C = $.bbq.getState("category");
if (C != undefined amp;amp; C != 0) {
// We've been navigated back to
$('#Descriptions').empty();
$.getJSON('/Jobs/GetJobDescriptions?' 'JobCategory=' C, function(descs) {
$.each(descs, function(index, description) {
$('#Descriptions').append('<h3><a href="/Jobs/ShowJob?JobID=' description.ID '">' description.JobTitle '</a></h3>');
$('#Descriptions').append('<p>' description.JobSummary '</p>');
$('#Descriptions').append('<p><a href="/Jobs/ShowJob?JobID=' description.ID '">Read more...</a></p>');
});
});
$('a.jobcat').removeClass('selected');
$('#category' C).addClass('selected');
$('#category' C).append('bite me');
}
else { // category not specified so reset the page
$.bbq.pushState({ category: 3 },2);
}
}
function loadCategories() {
$.getJSON('/Jobs/GetCategories', function(data) {
var categories = data;
$.each(categories, function(index, category) {
addCategory(category.ID, category.CategoryName);
});
});
}
function addCategory(CatID, Name) {
$('#Categories').append('<p><a class="jobcat" id="category' CatID '">' Name '</a></p>');
$('#category' CatID).click(function(event) {
$.bbq.pushState({ category: CatID }, 2); // merge_mode=2 means wipe out
});
}
$(document).ready(function () {
$(window).bind("hashchange", historyCallback); // needed for bbq plugin to work
loadCategories();
historyCallback();
});
</script>
Первый раз через historyCallback
, вызываемый непосредственно из $(document).ready
, C
не определен, и, таким образом, выполняется else
оператор $.bbq.pushState({ category: 3 },2);
, который устанавливает #has в category=3
, который является моей категорией по умолчанию.
Это приводит к historyCallback
повторному вызову, на этот раз с помощью C == 3
. Три строки в конце if
предложения не имеют никакого эффекта:
$('a.jobcat').removeClass('selected');
$('#category' C).addClass('selected');
$('#category' C).append('bite me');
Обратите внимание, что эти строки работают должным образом, когда я нажимаю на категорию.
Похоже, что #category
якоря, созданные в loadCategories()
, еще недоступны для jQuery / DOM / чего угодно, когда выполняется этот код.
Нужна ли мне какая-то задержка или что-то еще? Чего мне не хватает?
Огромное спасибо.
Ответ №1:
Это недоступно, потому что функция getJSON выполняется асинхронно. Обратный вызов getJSON происходит после поступления данных json с сервера.
Не используйте задержку. Что может работать лучше:
- Поместите выбор категории в обратные вызовы.
- Запускает пользовательское событие при загрузке ваших категорий, затем привязывает прослушиватель событий, который делает ваш выбор после.
Ответ №2:
Мне кажется, что проблема во времени — вы не можете гарантировать, что элементы были созданы, поскольку они зависят от того, был ли загружен JSON и выполнена соответствующая функция. Ваш код почти наверняка вызовет historyCallback() до того, как addCategory() когда-либо выполнится. Однако я не знаком с BBQ.
Комментарии:
1. Победитель! Я забыл, что
.getJSON
создан асинхронный делегат. Перемещение вызова вhistoryCallback
сразу после$.each {}
инструкции вloadCategories
исправило это. Я люблю тебя, StackExchange!2. Не почти наверняка, но определенно наверняка. Обратный вызов в AJAX никогда не будет выполняться до
historyCallback
вызова.