Не могу изменить элементы, добавленные во время $(document).готово во время $(document).готово

#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 с сервера.

Не используйте задержку. Что может работать лучше:

  1. Поместите выбор категории в обратные вызовы.
  2. Запускает пользовательское событие при загрузке ваших категорий, затем привязывает прослушиватель событий, который делает ваш выбор после.

Ответ №2:

Мне кажется, что проблема во времени — вы не можете гарантировать, что элементы были созданы, поскольку они зависят от того, был ли загружен JSON и выполнена соответствующая функция. Ваш код почти наверняка вызовет historyCallback() до того, как addCategory() когда-либо выполнится. Однако я не знаком с BBQ.

Комментарии:

1. Победитель! Я забыл, что .getJSON создан асинхронный делегат. Перемещение вызова в historyCallback сразу после $.each {} инструкции в loadCategories исправило это. Я люблю тебя, StackExchange!

2. Не почти наверняка, но определенно наверняка. Обратный вызов в AJAX никогда не будет выполняться до historyCallback вызова.