Javascript Filter Books by Genre - javascript

So, I've got a bunch of books, all attached to one or more genres and I've got a filter box (think Amazon) so users can filter through books in their preferred genre.
<div class="books">
<div class="filter">
<ul>
<li><a class="" data-filter=".classic" href="#">Classic</a></li>
...
</ul>
</div>
<ul class="library">
<li class="book classic">Classic</li>
...
</ul>
</div>
I'm then using a bit of Javascript, so when users select a genre from the filter list, it adds a class of .hidden to all books outside that genre.
if($('.books').length){
var books = $('.books');
books.find('.filter ul a').on('click', function(){
books.find('.filter ul a').removeClass('active');
$(this).addClass('active');
var selector = $(this).attr('data-filter');
books.find('.book').addClass('hidden');
books.find(selector).removeClass('hidden');
return false;
});
}
I've got a working demo of this in action here: http://codepen.io/realph/pen/atImc
Trouble is, I can only search one genre at a time (i.e. Fantasy). I'm not able to select two genres (i.e. Fantasy and Thriller). If anyone could help me to adapt this code to do just that, I'd really appreciate it.
Thanks in advance!
UPDATE:
Added an All filter to the filter list (thanks to #epascarello for his help on this):
jQuery(document).ready(function($) {
if($('.books').length){
var books = $('.books');
books.find('.filter ul a').on('click', function(e){
e.preventDefault();
books.find('.filter ul a.all').removeClass('active');
$(this).toggleClass('active');
books.find('.book').addClass('hidden');
books.find('.filter ul a.active').each(
function(){
var selector = $(this).attr('data-filter');
books.find(selector).removeClass('hidden');
}
);
});
books.find('.filter ul a.all').on('click', function(e){
e.preventDefault();
books.find('.filter ul a').removeClass('active');
books.find('.book').removeClass("hidden");
$(this).toggleClass('active');
});
}
});

This is untested, but something like this should work
var books = $('.books');
books.find('.filter ul a').on('click', function(e){
e.preventDefault(); //Cancel the click action
$(this).toggleClass('active'); //toggle the active class
books.find('.book').addClass('hidden'); //hide all of the books
books.find('.filter ul a.active').each( //find the selected filters and loop through
function(){
var selector = $(this).attr('data-filter'); //get the attribute
books.find(selector).removeClass('hidden'); //unhide the ones that match
}
);
});

Related

Active navigation class based on current URL problem

I have the following HTML menu:
<div class="nav">
<ul>
<li class="first">Home</li>
<li>Something</li>
<li>Else</li>
<li class="last">Random</li>
</ul>
<ul style="float:right;">
<li class="first last">News</li>
</ul>
</div>
</div>
And then I have this code:
jQuery(function($){
var current = location.pathname;
$('.nav ul li a').each(function(){
var $this = $(this);
// if the current path is like this link, make it active
if($this.attr('href').indexOf(current) !== -1){
$this.addClass('active');
}
})
})
The code is working great, but it has a problem. For example, if I see the Home page (www.example.com) then all of the menu links receives the active class. Another problem would be that it works great for www.example.com/something but it doesn't keep it active if I go to www.example.com/something/1 etc. Any idea how to fix this? Thanks in advance!
For home page add extra class 'default' in list like.
<li class="first default">Home</li>
jquery code.
jQuery(function($){
var current = location.pathname;
console.log(current);
//remove the active class from list item.
$('.nav ul li a').removeClass('active');
if(current != '/'){
$('.nav ul li a').each(function(){
var $this = $(this);
// if the current path is like this link, make it active
if(current.indexOf($this.attr('href')) !== -1 && $this.attr('href') != '/'){
$this.addClass('active');
}
})
}else{
console.log('home');
$('.default a').addClass('active');
}
})
Use the below jQuery code to add active class:
$(function() {
var pgurl = window.location.href.substr(window.location.href
.lastIndexOf("/") + 1);
$(".nav ul li a").each(function() {
if ($(this).attr("href") == pgurl || $(this).attr("href") == '')
$(this).addClass("active");
})
});
By using indexOf(), you are checking if the link's target is the same the current location.
What you want is not "the same URL" but "the same pattern", so I would tend to use a regular expression :
let re = new RegExp("^" + $(this).attr("href") + ".*");
if (re.test($current)) {
$(this).addClass("active");
}
Note that this would force you to create a separate solution for your link to the main page, else it would always be active.

Active tickmark on page load in selected dropdown item

I have written a JavaScript to show a tick mark just to the right side of the selected drop-down item (CSS class name active):
$(document).ready(function () {
$('.select-country ul li a').click(function () {
$('.select-country ul li a').removeClass("active");
$(this).addClass("active");
return false;
});
});
Its works well, but I have a problem here.
Problem:
When I refresh the page the drop-down will default to a default selected item. But that selected item is not showing the tick mark.
How do I rewrite the query to show the tick mark for the default selected item in drop-down?
You need to loop over the li so that respective links are responsible for there own events,
$(document).ready(function () {
$('.select-country ul li a.default').addClass("active");
//loop over all li
$('.select-country ul li a').each(function () {
//remove first from any active link
$(this).click(function(){
$('.select-country ul li a').removeClass("active");
//find and add active on "this" link
$(this).addClass("active");
return false;
});
});
});

Get index of li with button click

Using JQuery I'd like to get the index of the current li that I'm on when I click the button in the tabpanel residing in this list of BootStrap tabs.
<ul id="mytabs" class="nav nav-pills nav-wizard pill-font"
role="tablist" data-tabs="tabs">
<li role="presentation" class="active"><a href="#start"
data-toggle="tab">Before We Start</a></li>
<li role="presentation"><a href="#setup" aria-controls="setup"
role="tab">Setup</a></li>
<li role="presentation"><a href="#signup" aria-controls="Signing Up"
role="tab">Signing Up</a></li>
<li role="presentation"><a href="#speed" role="tab">Shipping Speeds</a</li>
<li role="presentation">Fulfillment</li>
<li role="presentation"><a href="#product"
role="tab">Products</a></li>
</ul>
I'm going to be using a counter in the button within each tabpanel so I can go forward and back. This is my JQuery without the counter..
$(document).ready(function(){
$(":button").click(function(e){
e.preventDefault();
$('#mytabs li:eq(2) a').tab('show');
});
});
Right now it just has the index 2 but if I can find the index of the current li I'll be able to add and subtract from it to get the li I want.
I tried with this but that just returns the index of the button, which isn't what I want.
Thanks everyone, a mish mash of everyone's answer turned into this:
$(document).ready(function(){
$(":button").click(function(e){
e.preventDefault();
var index = $(this).parent().index();
var length = $('#mytabs li a').length
alert(length);
index=index+1;
$('#mytabs li:eq('+index+') a').tab('show');
});
});
Try this:
$(document).ready(function(){
$(":button").click(function(e){
e.preventDefault();
var index = $(this).parent().index();
$('#mytabs li:eq(index) a').tab('show');
});
});
You can use .index to get de index of the element what you want in an array or list. It will be return the position or -1 (if it fails finding the element/value).
You can use it like this:
$(document).ready(function(){
$(":button").click(function(e){
e.preventDefault();
var index = $('#mytabs li').index($(this));
if(index > -1){
$('#mytabs li:eq('+ index +') a').tab('show');
}
});
});
If you want to use "this", I can show you how:
$(document).ready(function(){
$(":button").click(function(e){
e.preventDefault();
var element = $(this);
});
});
If you want to add a class to the element you can use element.addClass("yourClass") to get it.
I wish it that help to you.
P.D: I recommend change your jQuery selector from :button to #mytabs li, so you can get the exact element that you has been click, or you can use element.closest("li") to get the parent li.
This should work:
$(function() {
$("li").click(function() {
var li = $(this);
console.log( li.parent().find("li").index(li));
});
});
Returns you the index of the li you clicked.

How do I simplify the function below?

I was able to achieve a content switcher with the block of code below but I'm looking for a way to simplify it. There are up to 10 or more topics to switch between, how do I simplify it so that the code wouldn't be too large, instead of having a block of code per DIV.
jQuery(document) .ready(function () {
$('.topic-intro:not(:nth-of-type(1))') .hide();
$('#mid-nav-in ul li:nth-of-type(1)') .addClass('active');
$('#mid-nav-in ul li a:nth-of-type(1)') .click(function () {
$('.topic-intro:not(:nth-of-type(1))') .hide();
$('.topic-intro:nth-of-type(1)') .show();
$('#mid-nav-in ul li:not(:nth-of-type(1))') .removeClass('active');
$('#mid-nav-in ul li:nth-of-type(1)') .addClass('active');
});
});
jQuery(document) .ready(function () {
$('#mid-nav-in ul li:nth-of-type(2) a') .click(function () {
$('.topic-intro:not(:nth-of-type(2))') .hide();
$('.topic-intro:nth-of-type(2)') .show();
$('#mid-nav-in ul li:nth-of-type(2)') .addClass('active');
$('#mid-nav-in ul li:not(:nth-of-type(2))') .removeClass('active');
});
});
It appears from your code that you are using the links in #mid-nav-in to show the corresponding .topic-intro and then hiding all others. It also appears that the code depends on the .topic-intro elements being in the same order as the links in the #mid-nav-in. If this is the case something like to following would work:
$('#mid-nav-in li a').on('click', function(){
// Remove 'active' Class from all <li/>
$('#mid-nav-in li').removeClass('active');
// Add 'active' Class to <li/> of Clicked Link
$(this).closest('li').addClass('active');
// Hide All .topic-intro elements
$('.topic-intro').hide();
// Show .topic-intro element at the Same index of Clicked Link
$('.topic-intro').eq($(this).closest('li').index()).show();
return false; // prevent default action
});
// Automatically Select the First Link
$('#mid-nav-in li a').eq(0).trigger('click');
Here is a fiddle as an example: http://jsfiddle.net/6hd97/2/
I hope this helps.

Find the clicked li number

I have a standard list.
<ul>
<li>blah 1</li>
<li>blah 2</li>
<li>blah 3</li>
<li>blah 4</li>
</ul>
And my jQuery:
$('ul li a').live('click', function() {
var parent = $(this).parent('li');
});
What I want to find out is the parent li's position in the list of the clicked link e.g. clicking on blah 3 would give me 2, blah 4 would give 3 etc.
$('ul li a').live('click', function() {
console.log($(this).parent('li').index());
});
Will give you what you want, but keep in mind these are 0 based indexes -- ie the first line item is index 0, the last line item is 3.
jQuery index() method documentation
you can get the index of an element with jquery`s index
$('ul li a').live('click', function()
{
var index = $(this).index();
});
No need to jQueryfy this :
$('ul li a').live('click', function() {
var position = 0;
var currentNode = this;
var firstNode = currentNode.parentNode.firstChild;
while(firstNode != currentNode) {
position++;
currentNode = currentNode.previousSibling;
}
alert(position);
});
I know this is an old post, but .live is now deprecated in jQuery 1.7 and removed in jQuery 1.9.
The alternative is to use .delegate:
$('ul li').delegate('a','click', function() {
alert($(this).parent('li').index());
});
The index method should do what you want.
$(function() {
$('ul li a').live('click', function() {
var parent = $(this).parent('li');
alert(parent.prevAll('li').size());
});
});

Categories