Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Clone in Desktop Download ZIP
Branch: master
Fetching contributors…

Cannot retrieve contributors at this time

465 lines (387 sloc) 11.5 KB
var MOBILE = Modernizr.touch;
var SMALL = Modernizr.mq('only all and (max-width: 480px)');
var $body;
var $content;
var $books_grid;
var $all_tags;
var $tags = {};
var $clear_tags;
var $current_tag;
var $modal;
var $modal_content;
var $books_list;
var $back_to_top;
var $mobile_filters_btn;
var $filter;
var $toggle_text;
var $show_text_button;
var $show_books_button;
var $review;
var next;
var previous;
var selected_tags = [];
var first_hash = true;
/*
* Scroll to a given element.
*/
var scroll_to = function($el) {
var top = $el.offset().top;
$body.scrollTop(top);
};
/*
* Jump back to the top of the page.
*/
var back_to_top = function() {
$body.scrollTo($content, { duration:450 }, 'y');
return false;
};
/*
* Enable or reapply isotope to the grid.
*/
var isotope_grid = function(filter) {
$books_grid.isotope({
filter: filter,
transformsEnabled: !MOBILE,
getSortData: {
'id': function($el) {
return parseInt($el.data('sort'), 10);
}
},
sortBy: 'id'
});
};
/*
* Show/hide books in the grid.
*/
var filter_books = function() {
$all_tags.parent().removeClass('selected unavailable');
$all_tags.removeClass('selected unavailable');
if (selected_tags.length > 0) {
var filter = '';
var label = [];
// Update selected tags
for (var i in selected_tags) {
var slug = selected_tags[i];
$tag = $tags[slug];
$tag.addClass('selected');
$tag.parent().addClass('selected');
filter += '.tag-' + slug;
label.push(COPY.tags[slug]);
}
label = label.join(', ');
// Replicate isotope filtering so that we can update
// available tags without waiting for isotope to do its thing
var remaining_books = _.filter(BOOKS, function(book) {
for (var i in selected_tags) {
var slug = selected_tags[i];
if (_.indexOf(book.tags, slug) == -1) {
return false;
}
}
return true;
});
// Hide empty tags
for (var tag_slug in COPY.tags) {
var has_results = false;
for (var z = 0; z < remaining_books.length; z++) {
var book = remaining_books[z];
if (_.indexOf(book.tags, tag_slug) >= 0) {
has_results = true;
break;
}
}
if (!has_results) {
$tag = $tags[tag_slug];
$tag.parent().addClass('unavailable');
$tag.addClass('unavailable');
}
}
$clear_tags.removeClass('hide');
$current_tag.find('#showing-span').text('Showing books tagged ');
$current_tag.find('#tag-span').text(label);
filter_books_list(filter);
_.defer(isotope_grid, filter);
} else {
$clear_tags.addClass('hide');
$current_tag.find('#showing-span').text('Showing all books');
$current_tag.find('#tag-span').text('');
filter_books_list(null);
_.defer(isotope_grid, '*');
}
// NB: Force scroll event so that unveils will happen auto-magically.
// We wait a moment first so the grid has animated in.
_.delay(function() {
$(window).trigger('scroll');
}, 1000);
};
/*
* Filter the text book list.
*/
var filter_books_list = function(filter) {
if (filter) {
$books_list.find('li').removeClass('visible');
filter = '';
for (var i in selected_tags) {
var slug = selected_tags[i];
filter += '.tag-' + slug;
}
$books_list.find(filter).addClass('visible');
} else {
$books_list.find('li').addClass('visible');
}
};
/*
* Filter the list to a certain tag.
*/
var on_tag_clicked = function() {
var slug = $(this).data('tag-slug');
var already_selected = selected_tags.indexOf(slug);
if (already_selected >= 0) {
selected_tags.splice(already_selected, 1);
} else {
selected_tags.push(slug);
}
if (selected_tags.length > 0) {
hasher.setHash('tag', selected_tags.join(','));
} else {
hasher.setHash('_');
}
return false;
};
/*
* Handles transitions related to scrolling.
*/
var on_page_scroll = function() {
var y_scroll_pos = window.pageYOffset;
var scroll_pos_test = 1000;
if(y_scroll_pos > scroll_pos_test && $('#myModal:visible').length === 0) {
$back_to_top.fadeIn(1000);
} else {
$back_to_top.fadeOut(1000);
}
};
/*
* Handles tag clicks on modal.
*/
var on_modal_tag_clicked = function() {
back_to_top();
return true;
};
/*
* Clear the current tag
*/
var on_clear_tags_clicked = function() {
hasher.setHash('_');
return false;
};
/*
* New tag hash url.
*/
var on_tag_hash = function(tags) {
selected_tags = tags.split(',');
filter_books();
};
/*
* New book hash url and previous/next buttons.
*/
var on_book_hash = function(slug) {
// Get rid of the old modal.
// They smell so musty.
$modal_content.empty();
// Find this book from the list.
book = _.find(BOOKS, function(book){
return book['slug'] == slug;
});
// Set up a variable to represent this book in the grid.
// It's null because we have TWO DIFFERENT GRIDS AAAAAAA.
var grid_item;
// This next/prev list is sorted two different ways.
// The first way it can be sorted is for the grid view.
// This time, we're checking for if the $books_grid is visible.
if ($books_grid.is(':visible')) {
// The grid item is an id of the book slug.
grid_item = $('#' + book.slug);
// Next and previous are based on hidden/not hidden isotope elements.
next = grid_item.nextAll(':not(.isotope-hidden)').first();
previous = grid_item.prevAll(':not(.isotope-hidden)').first();
// And the buttons fetch the ID of the next element.
if (next.length === 0) {
next = null;
} else {
next = next.attr('id');
}
if (previous.length === 0) {
previous = null;
} else {
previous = previous.attr('id');
}
} else {
// The grid item in the second case is the anchor with the slug as it's class.
grid_item = $('li.' + book.slug);
// Next and previous are based whether these items are visible.
next = grid_item.nextAll(':visible').first();
previous = grid_item.prevAll(':visible').first();
// And the buttons fetch the data-slug attribute of the next element.
if (next.length === 0) {
next = null;
} else {
next = next.attr('data-slug');
}
if (previous.length === 0) {
previous = null;
} else {
previous = previous.attr('data-slug');
}
}
// Now, go about our normal business of building the modal.
$modal_content.append(JST.book_modal({
book: book,
next: next,
previous: previous,
SMALL_MOBILE: (SMALL && MOBILE)
}));
$modal.scrollTop(0); // #174.
// Modals should be modaled whenever modalable.
$modal.modal();
// And hide the "back to the top" button.
$back_to_top.hide();
};
/*
* Respond to url changes.
*/
var on_hash_changed = function(new_hash, old_hash) {
var bits = new_hash.split('/');
var hash_type = bits[0];
var hash_slug = bits[1];
if (hash_type == 'tag') {
$modal.modal('hide');
on_tag_hash(hash_slug);
} else if (hash_type == 'book') {
on_book_hash(hash_slug);
$modal.show().css('overflow-y','hidden').scrollTop(0).css('overflow-y','scroll');
// On first load, we need to load in the books. #142
if (first_hash) {
filter_books();
}
} else {
$modal.modal('hide');
selected_tags = [];
filter_books();
}
// Track _ the same as root
if (new_hash == '_') {
new_hash = '';
}
_gaq.push(['_trackPageview', location.pathname + '#' + new_hash]);
first_hash = false;
return false;
};
/*
* Clear the hash when closing a book modal.
*/
var on_book_modal_closed = function() {
if (selected_tags.length > 0) {
hasher.setHash('tag', selected_tags.join(','));
} else {
/*
* CEG: Don't set to empty string or it will turn into '#' which
* will cause a scroll to top of page that we don't want when
* closing the modal.
*/
hasher.setHash('_');
}
return true;
};
// Never relayout the grid more than twice a second
var relayout = _.throttle(function() {
$books_grid.isotope('reLayout');
}, 500);
/*
* Begin unveiling visible books in the grid.
*/
var unveil_grid = function() {
$books_grid.find('img').unveil(800, function() {
$(this).load(function() {
relayout();
});
});
};
/*
* Show and hide the filters on small screens
*/
var toggle_filter_modal = function() {
$filter.toggleClass('hidden-xs').scrollTop(0);
};
/*
* Toggle the text books list.
*/
var toggle_books_list = function() {
$books_grid.toggle();
$books_list.toggle();
// $show_text_button.toggle();
// $show_books_button.toggle();
$toggle_text.toggleClass('grid-active list-active');
if ($books_grid.is(':visible')) {
isotope_grid();
}
};
$(function() {
// Set up the global variables.
$body = $('body');
$content = $('#content');
$books_grid = $('#books-grid');
$all_tags = $('.tags .tag');
$clear_tags = $('.clear-tags');
$current_tag = $('.current-tag');
$modal = $('#myModal');
$modal_content = $('#myModal .modal-content');
$books_list = $('#books-list');
$back_to_top = $('#back-to-top');
$mobile_filters_btn = $('#mobile-filters');
$filter = $('.filter.tags');
$show_text_button = $('.show-text');
$show_books_button = $('.show-books');
$toggle_text = $('.toggle-text');
$review = $('.review');
// Event handlers.
$body.on('click', '.filter .tag', on_tag_clicked);
$content.on('click', '.back-to-top', back_to_top);
$content.on('click', 'button.clear-tags', on_clear_tags_clicked);
$modal.on('hidden.bs.modal', on_book_modal_closed);
$modal.on('click', '.tag', on_modal_tag_clicked);
$back_to_top.on('click', back_to_top);
$mobile_filters_btn.on('click', toggle_filter_modal);
$filter.find('.close-modal').on('click', toggle_filter_modal);
$toggle_text.on('click', toggle_books_list);
$(window).on('scroll', on_page_scroll);
$modal.keyup(function (e) {
if ($('#myModal:visible').length > 0){
if (e.which === 37 && previous !== null) {
hasher.setHash('book', previous);
} else if (e.which === 39 && next !== null) {
hasher.setHash('book', next);
}
}
});
// Set up the page.
$back_to_top.hide();
$current_tag.find('#showing-span').text('Showing all books');
$current_tag.show();
_.each($all_tags, function(tag) {
var $tag = $(tag);
$tags[$tag.data('tag-slug')] = $tag;
});
// Disable isotope transitions
if (MOBILE) {
$books_grid.addClass('no-transition');
$review.remove();
} else {
$body.append('<style>.book.card { width: 250px; }</style>');
}
// Set up the hasher bits to grab the URL hash.
hasher.changed.add(on_hash_changed);
hasher.initialized.add(on_hash_changed);
hasher.init();
// Set up the grid.
_.delay(unveil_grid, 1000);
});
Jump to Line
Something went wrong with that request. Please try again.