jQuery is like CSS in that it takes the JS out of the markup and let’s you modify it in another place. It also uses the same selectors as CSS.
Unobtrusive (as in, not getting in the way of the user) JS is all about putting the user first, and making sure the site works regardless of their connection, browser or device. This is the key to user experience.
You can then call methods on them to modify their behavior. In this case we want to hide it, but where would we look to learn how to do that? You can check out the documentation site. Use the search box in the top right to look for stuff. Here we want to use .hide(). Notice how it gives code examples at the bottom.
To get it to show, we’ll use the .show() method. However, if we just add that it won’t give us what we want, the “It’s a trap” will show instantly. So, we pass in the string “slow” as a parameter, like we saw in the documentation.
Now, instead of having to write jQuery all the time, you can instead use a $.
jQuery has method chaining, which allows you to reduce redundancy in your code. You can add methods after each other to affect the same selected elements. This works because many jQuery methods return the element they were selecting. So, hide() returns the .warning elements.
The Document Object Model is how the browser interprets the html files. Aka the DOM tree.
Let’s say we wanted all the children elements of the head element. Simply write document.head.children
You can access this array of elements just like any array, by passing in the index of the element you want. If we want the first p element in the body, we’d write document.body.children. Remember, you can pull up what you’ve previously written by using the up key.
However, this it a brittle way to program, we don’t know if the order of the elements in the html document will change in the future.
Moving from on element to another is called traversal, or, traversing the DOM.
The method getElementByClassName is a much better option. Here we’ll select the element with the .warning class: document.getElementsByClassName(“warning”). Note that in the string a period wasn’t used, because we’re already saying we want a class name with the method.
jQuery makes this way easier, and also will make it work with all browsers.
There are different kinds of methods based on what you’re looking to do.
Now, we’ll go over the different categories listed on the left hand side in the documentation.
The attributes category lets you change and modify the attributes of elements, like if you need to change the href attribute for a link. You can also use this to add/remove classes, or see if an element has a class.
The CSS category lets you change and read the style properties. You’ll find that the add/remove class methods are here as well, sometimes they will be in multiple categories.
The dimensions category lets you check an elements heights, widths, etc, with or without the padding and margins. This is manipulation.
The effects category is manipulation over time, like an animation, showing, hiding, fading in/out, etc.
The events category is basically for when a user interacts with a thing, like the keyboard in a form, scrolling, resizing a window, etc, then doing something when that occurs. Has sub categories for each of these. Can be triggered by user or the computer.
The offset category is similar to dimensions, is used to figure out the offset of an element, like from the top or the left of a parent element, how far it’s been scrolled right of left. Handy for triggering an event for the browser to scroll to the top or bottom of a page.
The traversing category includes all the methods to move around the document and manipulate it. Like getting the children of an element, or elements with a certain class.
The selectors category talks about the CSS selectors that can be used for jQuery. There are even special jQuery selectors can only be used with it and not CSS.
Ways to include jQuery in a project
You can download it from jQuery.com. But, what most people do is host it on a CDN, a Content Delivery Network, which serve jQuery all over the world. The nice thing is if the user has already been on a page that has this, it’s been cached in their browser so they don’t have to download it again. Put the CDN link above your link to your .js file.
However, when we try to execute the function in our .js file, it doesn’t work.
In the documentation, under Events > Document loading, we find the ready() method, used for executing a function when the DOM is fully loaded. Note the other two hear are marked as depreciated and should be ignored. Looks like there’s three ways to do this.
We can select the document itself and run it with this method, we’ll ignore the second method, or simply run the function when the page is ready.
It’s worth noting, that “handler” is explained above, and basically just means the function you want to run.
We’ll try the first method. Note that we don’t use parentheses to call the function in this case, as we want jQuery to do that once the page is loaded.
Now, remember that we can also declare functions using a variable. So instead of this,
we do this, and it still will work.
Now, a lot of times people will use functions without a name, aka an anonymous function. We can actually pass the function itself into the ready method. The example below works as well.
If you remember, the third way that you can do this is by simply passing the handler into the jQuery method, which is $().
Now, in our original example last lesson we didn’t do that, because we included our jQuery at the bottom of the mark up.
By doing this, the code will still work, but now we don’t need to wait for that .ready event to be triggered by the DOM. Because we’re including the JS at the bottom of the page, we can assume that the DOM has already loaded. We can now cut out those parts of the code.
This way of including the JS at the bottom of the page is a best practice, because it speeds up the user’s experience. It’s a bit faster, and lets your content and images load before your JS files do.
Spoiler revealer project
Preparation is where is sleuth out what the problem is (the first two lines below). In the plan stage, we’ll write some pseudocode, which is high level, informal code that describes what we’re looking to do.
We’ll start by selecting the span containing the spoiler. Note how we were able to use a descendent selector, just like in CSS.
Next, we need to add a button. To do that we’ll use append(), listed under Manipulation, which adds content to the end of the specified element. The parameters is accepts include html, so we’ll make it take a button. NOTE: They already had styling in place for the button.
Now, we want to hide the button and show the spoiler on a mouse click. Under Event > Mouse Events we find the .click() method. To remove the button, we’ll use the .remove() method under the manipulation > DOM removal section.
Now, will the remove method we were able to use “this”, rather than having to write the selector for button elements. The nice part about this is that it refers to specific button that’s being clicked, and will affect just that button, rather than all buttons on the page. If we were to instead use the button selector, all buttons on the page would be removed whenever we clicked any button.
REMEMBER, the selector you put in the parentheses after the $ is what is going to be affected by the method after. So $(“.spoiler span”).show(); will show any span element within one with the spoiler class.
Now, to perfect our project. Let’s put in another spoiler. Issue – when we click one of the buttons, both spoilers get revealed.
In our current code, we’re selecting all spans within a spoiler class element, which is not good, we only want to affect the span for the button we clicked. We want to select the previous element to the button, which we can do with the prev() method, under the traversing the DOM section. It selects the immediately preceding sibling element.
Now, jQuery methods return things, which I guess means the things that will be selected. So with $(“.spoiler span”).hide();, it’s returning what was selected in those first parentheses. However, with something like the $(this).prev().show(); used above, .prev() is actually returning the sibling of button (which were using this to refer to), rather than button itself. That sibling is then affected by the .show() method.
Creating a Simple Lightbox
Issue is that when you click on one of the images it takes you to a dead end, which is a poor UX. Solution: make a lightbox with jQuery. Here’s that with the psuedocode for our plan:
First, we need to capture the click. The best way to do this, with keeping future scenarios in mind, would be to create an id for the unordered list. That way, if there are non image links added to the site later they won’t be affected. To do so, we then simply write $(“#imageGallery a”).click();
To add to that, we want to select the info in the href attribute for those links. We can use this to make sure we’re getting it from the link that’s just been clicked, along with the attr() method, which is unsurprisingly listed under the attribute section. We can simply pass in a string for the name of the attribute we want. We can then store that in a variable, which we’ll name href, then use a console.log with that variable to display it in the console. We should now see what was listed as the value for its href attribute.
The issue though is that if we click a link it still takes us to another page with just the image, we need to stop that. The event.preventDefault() method will do just that. If it is called, the default action of the event will not be triggered. So if it’s a link, it won’t take you to a page with that URL.
Good progress. Though 1.1 is to show the overlay, we actually need to add the overlay to the document first. You do NOT want to add this to the HTML, but rather via the jQuery. This is because you don’t want to add any markup that’s unnecessary. If someone didn’t have JS turned on in their browser and you added the overlay in the html, they would then see that with everything else and it would be weird.
We’ll move this step to the top, remember, pseudocode order can be rearranged.
Now, we want to use and do things (update the image/caption, hide and show it) to the overlay, so it’s best if we store it into a variable.
But, this won’t do us much good, as it’s just storing that as a string, and we need it to be a jQuery representation of an object. jQuery lets you create a representation of a DOM element that isn’t part of the document yet, yet still use it in your code. This is called a disembodied element. Select the string and put $() around it. Also, it’s good to add a $ to the variable name, so you know it’s a jQuery representation of an object, and not a string or something. This is a common practice.
This adds the div to the page, which we can then style.
Since we want to hide it by default, rather than doing the .hide() method with jQuery, we’ll just do display: none; in the CSS. We’ll also add opacity, so it looks like all lightboxes for when we do eventually display it.
Finally, because we made the div a jQuery object instead of just a string, we can use the show method on it directly, rather than having to do $(“#overlay”).
Now we need the overlay to show the image that was clicked. We’l start by creating another jquery object that is an img tag. Then, even though the $overlay object hasn’t been appended to the body yet, we can still mess around with it and append the $image object to it. Now when it does get appended to the body, it will include and <img> tag.
Now, we need the image in the overlay to update and show the correct image. We can use the attr() method again, this time to modify the src attribute for it.
Now href as a variable name could get confusing later, so we’ll rename that variable to imageLocation. WE’ll also remove that console.log, since we don’t really need it anymore.
Aside – I original made the overlay background: black; with opacity: .7;, but this actually made the image transparent as well. But, by doing rgba(0,0,0,.7);, it only made the overlay transparent and not the image.
We’ll now do some quick styling for the image, giving it a margin top of 10%, and giving its parent overlay a text-align:center so it is centered.
Now, we want the overlay to go away when clicked again. We’ll start with the jQuery $overlay object and the click method, with an anonymous function. Within that, we can use $(this) or even the $overlay object with the hide() method.
Time to add the caption. We’ll start by adding another disembodied element at the top, then appending that to our overlay, like we did for the $image earlier.
So if you recall, the click event handler is tied to the link, but the links child img element has the alt attribute we need for the caption.
We’ll look under the traversing the DOM section of the documentation for this, and see that the children() method is what we need here. We’ll start by using $(this), which selects the link we’ve clicked on, followed by children(“img”), which selects that link’s child img elements, follow by attr(“alt”), which gets that img’s alt attribute’s value. Finally, we’ll set all that equal to the variable captionText so we can use it later.
Now we need to manipulate the $caption object to add the content of the captionText variable in there, so we’ll look under Manipulation this time, and find the text() method. NOTE: a lot of jQuery methods are setters ad getters. Usually, if you don’t pass in a parameter it will get you info from the selected element, and if you do, it will set info for that element.
So, we simply do $caption.text(captionText);
Slight issue, p text was black so you couldn’t see it unless you highlighted it, so we restyled it white.
And on to the next one. Feels good to be back on track.