I've implemented a page with a list of options (job categories) that when clicked should display data (job descriptions). I am using BBQ to handle the back stack.
Everything works dandy, except for setting the initial selection when the user first navigates to the page. My code is getting called to addClass('selected')
to the right element but it is like that element is not actually available when the code runs.
Note that I added a debug call $('#category' + C).append('bite me');
to prove to myself this was NOT a problem with the stylesheet/CSS.
Here's my code:
<script>
function historyCallback(e) {
var C = $.bbq.getState("category");
if (C != undefined && 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>
The first time through historyCallback
, called directly from $(document).ready
, C
is undefined and thus the else
statement executes $.bbq.pushState({ category: 3 },2);
which sets the #has to category=3
which is my default category.
This causes historyCallback
to be called again, this time with C == 3
. The three lines at the end of the if
clause have no effect:
$('a.jobcat').removeClass('selected');
$('#category' + C).addClass('selected');
$('#category' + C).append('bite me');
Note these lines DO work as expected when I click on a category.
It seems like the #category
anchors created in loadCategories()
are not yet available to jQuery/DOM/whatever when this code runs.
Do I need some sort of delay ore something? What am I missing?
Thanks a ton.
Looks to me like the problem is timing - you can't guarantee that the elements have been created, since they depend on whether the JSON has loaded and the related function has executed. Your code will almost certainly call historyCallback() before addCategory() ever executes. I'm not familiar with BBQ, though.