jQuery Basics
For this workshop, we will learn how to use jQuery, a Javascript library that provides shorthand notations for javascript. It also uses css-style notations for its selectors. We will get to know what this actually means. Here is what we will make today:
Click to view the demo as a full web page.
This tutorial will be more about the tools of making this demo, rather than the steps you need to take to make the demo, because learning the fundamentals of jQuery is more important than achieving the final result of the demo. The code for the demo is available at the bottom of this page as usual.
Using jQuery
jQuery is a library. This means that we need to include the library as a script tag inside of our html. We don't actually need to download the file (although you can, if that is what you want), and we can use jQuery CDN. Using the latest minified version is recommended. When you click on the "minified" link, it will show you a lightbox with a script tag you can paste into your html, that looks something like this:
<script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
You should put this script tag inside of the <head> tag. The reason for this is that this library needs to be included inside of the web page before we can write javascript that uses this library. Once this step is done, we can go ahead and use jQuery!
Select with $
With jQuery, you can refer to html elements using a $ sign, and the selector in the style of css inside of () brackets.
For example, if you want to refer to all <div> elements inside of your html page, simply write:
$('div')
If you want to refer everything with class name 'row', then simply write:
$('.row')
Similarly, if you want to refer to an element of id 'specialDiv':
$('#specialDiv')
As you may now come to realize, you can use css notations inside of the quotation marks of the brackets to refer to html elements inside of your web page. No more document.getElementbyId()!
You can also use filters with your selectors, meaning that you can be more specific with the selection you make. For example, it is possible to select only the even <div> elements of class .row by doing:
$('.row:even')
Looking at the example selector above, notice that the word "even", a jQuery selector filter, is followed by a colon and this is included INSIDE of the quotation marks. Another thing to note is that the zero-indexing applies here as well. The first .row element is of index 0, and the second .row element will be of index 1. So when $('.row:even') is called, it means the elements of even indexes. Thus, if I have html that looks like this:
<div class="row"></div> <div class="row"></div> <div class="row"></div> <div class="row"></div>
then, the first and third <div> will be returned, because they have index of 0 and 2.
There is a list of filters that you can use, and there are filters of 5 categories: basic filters, content filters, visibility filters, child filters and attribute filters. The basic filters filter within the elements referred to with the selector. For example, $('.row:even') returns the even elements within the entire .row class. The child filters make selections within the children of the elements referred to with the selector. So, if you want to select the even children of the .row class, you can write $('.row:nth-child(even)'). If you are confused what "children" means, please refer to the section about Traversing HTML Elements further down this tutorial. If you are curious about all existing jQuery filters, this w3schools page has a comprehensive list of all jQuery selectors.
Using $(document).ready()
This function call is similar to that of vanilla javascript's window.onload(), but the crucial difference is that while window.onload() function runs after all the content INCLUDING its media content (i.e. all images and videos included in the html) has been loaded, while jQuery's $(document).ready() function runs once the html content has been loaded. This means, if your html page contains a lot of media content, window.onload() will run quite significantly later than $(document).ready(). Most of the jQuery code that you will find online are surrounded inside of the $(document).ready() function, because it ensures that the html elements that you want to modify / add events to, exist before the function is being called.
$(document).ready(function(){ //code here will run after all html content has been loaded (excluding loading media content) });
Adding and Removing
It is easier to generate HTML content using jQuery. We don't actually need to create an element, but we can simply write html code inside of the append() function. See the demo below:
$('.pattern').append('<div class="pattern-bar"></div>');
You can also attach remove() function to the element that you want remove. So, if I want to remove the last element of <div> of class .pattern, all we need to do is figure out how to write the selector, and call the remove() function, like so:
$('.pattern:last-child').remove();
Attaching Events
It becomes easier to attach events in jQuery. We can attach events, without having to define it inside of html using attributes and it is simpler than adding event handliers.
This w3schools page has a comprehensive list of all jQuery events. Please DO NOT use events in the list, if it says "removed" or "deprecated" in red text. This means that those events have been taken out of the recent version of jQuery, and you will not be able to use it.
Effects in jQuery
jQuery provides effects that are useful for transitioning elements from being visible to not visible. The most commonly used effects are hide / show, fade and slide.
This w3schools page has a comprehensive list of all jQuery effects.
Collective vs Individual
If you want to apply the same actions / styles to all elements of a certain class, this is really easy using jQuery. We don't need a for-loop! For example, if we want to have background-color of all elements of class 'red' to be red, we can simply do:
$('.red').css('background-color', 'red);
However, this gets a little tricky if you want to attach events (click, dbclick, mouseover...) to all elements of a certain class name. The code below will demonstrate this.
$('.top-bar').click(function(){ $('.bottom-bar').slideToggle("slow"); });
The above code basically makes clicking on any .top-bar element to toggle slide of all .bottom-bar elements AT THE SAME TIME. This may be something you want, but you might also be wondering how to allow individual .top-bar element to toggle slide for individual .bottom-bar element. Here is where each() function becomes useful.
$('.top-bar').each(function(){ $(this).click(function(){ $(this).next().slideToggle("slow"); }) });
The each() function in the above code allows each element of .top-bar class to be accessible inside of the function. You can refer to the individual element as $(this), and therefore create individual click events for each element of the .top-bar class. Inside of the click function, it is being told to slideToggle the element that is referred to as $(this).next() -- and you might be wondering, what does next() do? Now, we will have to talk about "traversing" html elements.
Traversing HTML elements
To talk about traversing, looking at an html grid will make it easier to understand. Let's say we have html code that looks like this:
<div class="row"> <div class="row-item"> <div class="top-bar"></div> <div class="bottom-bar"></div> </div> <div class="row-item"< <div class="top-bar"></div> <div class="bottom-bar"></div> </div> <div class="row-item"> <div class="top-bar"></div> <div class="bottom-bar"></div> </div> <div class="row-item"> <div class="top-bar"></div> <div class="bottom-bar"></div> </div> </div>
Inside of the <div> with class "row", there are four <div> elements of class "row-item". And inside of each <div> "row-item", there is a <div> of class "top-bar" and a <div> of class "bottom-bar". The elements directly inside of the <div> of class "row" are it's children. In this example, $('.row').children() will return 4 <div> elements of class "row-item". This means that for each of the 4 <div> elements of class "row-item", their parent is the <div> of class "row". Each <div> of class "row-item" also has 2 children -- one of class "top-bar" and another of "bottom-bar". The relationship between <div> of "top-bar" and "bottom-bar" is that they are siblings. You can refer to all elements within a same div (or elements that have a common parent), by saying $('top-bar').siblings(). You can also use the .next() function to refer to the slibling that appears after itself, or .prev() to refer to the sibling that appeared before itself. It can be a little complicated to wrap your head around. But this is the way that you can basically traverse along html elements (this is also true for vanilla javascript as well as jQuery).
Using animate()
You can use the animate() jquery function to apply animation to html elements. The syntax of the function is:
$('.class').animate({cssProperty: "value"}, time_in_milliseconds);
Replace '.class' with any selector. Replace cssProperty with any css properties, but this needs to be camelCased (no dash - this is probably the only place you CANNOT refer to something in jQuery in non-css syntax!). The "value" should be the numeric value (and its unit) for the cssProperty. Replace time_in_milliseconds to a number to refer to the actual milliseconds in time that you want the total duration of the animation to be. You can also use "slow", "normal" and "fast" which are predetermined times in jQuery ("slow" = 600, "normal" = 400, "fast" = 200).
However, there are some limitations with this function. One thing to note is that you CANNOT use animate() for css properties of non-numeric values. What this means is that you can animate an element to go from height of 100px to height of 200px using animate() function like this:
$('.row').animate({height: '200px'}, 2000);
However, below code will NOT work:
$('.row').animate({transform: 'rotateZ(90deg)'}, 2000);
Since the value of the transform css property is non-numeric (it is not just a number with a specfied unit), animate() function will not take effect. One other important thing to note is that this will NOT cause any errors.
Another thing to note is that it is not so straight-forward to make your animate() function run an infinite animation loop. You can do this by recursion, but it is easier to use @keyframes if you want an animation to happen infinitely. However, you can chain animate() events so that it does more than one single animation. For example, if you want your element to blink once, you can write:
$('.row').animate({opacity: '0.25'}, 1000).animate({opacity: '1.0'}, 1000);
The above code will make all elements of class .row to first change their opacity to 0.25 during 1000 ms, and to 1.0 during 1000 ms. animate() function leaves the state of elements to its end state (same as saying animation-fill-mode: forwards; in css). Because of the above reasons, it is best to leave animate() to use to create transitions, rather than to create on-going animations.
Using toggleClass()
toggleClass() can be used to add and remove a class to an element. Just like toggleFade() and toggleSlide(), it basically goes back and forth of one state to another -- in the case of toggleClass(), the state of adding a class and removing a class. This is useful when an event is triggered you want certain set of css styles to be applied and removed repeatedly.
$('.top-bar').each(function(){ $(this).click(function(){ $(this).parent().toggleClass('rotate'); }); });
The above code will add and remove the class .rotate to the parent of all elements of class .top-bar. The above code is basically a condensed way of writing the below code:
$('.top-bar').each(function(){ $(this).click(function(){ if($(this).parent().hasClass('rotate')){ $(this).parent().removeClass('rotate'); }else{ $(this).parent().addClass('rotate'); } }); });
Code
Here is the code for what we have made during the workshop: