Exploratory Programming with jQuery

jQuery is a widely used framework for inspecting and manipulating the DOM in modern browsers. It’s often one of the fundamental libraries that’s used in major websites, even underlying higher level frameworks like Backbone and AngularJS. But JQuery can also be used as a tool for experimentation, prototyping, and testing ideas and features interactively in the browser in the course of developing features for a website. This post will explore some ways this can be done.

I’ll be using the developer console in the Chrome browser, but all major browsers support developer consoles with a similar command line feature. Open the developer console like this:

  • Ctrl-Shift-I to open Chrome on Windows
  • Option-Command-I for Chrome on Mac OS-X (this also works for Safari and Firefox on Mac)
  • F12 for Internet Explorer on Windows

As a subject for exploration, I’ll use the home page for this WordPress site. Most times, the jQuery API is bound to the “$” symbol, so for example you’d look for an element with id “mydiv” using ‘$(“#mydiv”)’. But WordPress calls jQuery.noConflict() to remove the alias to “$” (allowing other frameworks to bind to “$”). If you try to use jQuery bound to “$” to find the list of all divs in the page, for example, you’d get an error like this in the Chrome browser dev console:

> $('div')
VM81:1 Uncaught TypeError: $ is not a function
    at <anonymous>:1:1

But the jQuery API is also bound to a global “jQuery” variable, so this will be used in all the commands shown in this post. Interacting with jQuery in this way, this is the list of divs that would be returned for this site:

> jQuery('div')
jQuery.fn.init(37) [div.main-container, div.container.clear, div.site-branding, ...more listed...

The “(37)” shown here indicates that there were 37 elements found by jQuery for this “div” selector. jQuery selectors return “array-like” objects; they’re not true Javascript arrays, but they act like them: you can index into them, and also use the “length” attribute to find their length:

> jQuery('div').length
37
> jQuery('div')[2]
<div class=​"site-branding">​...</div>​
> jQuery('div').get(2)
<div class=​"site-branding">​...</div>​

Notice that jQuery offers the ‘.get(i)’ function as a little syntactic sugar for the array indexing notation. Why have that function in addition to being able to index directly into the results of a select using square brackets? The .get() function provides some additional features. Say, for instance, you wanted to get the last element in the returned array. This can be done by indexing to the 36th element (remembering that arrays in Javascript are 0 based). But .get() also offers the option of negative indexing from the end of the array, whereas square brackets don’t offer that option:

> jQuery('div').get(36)
<div class=​"top">​...</div>​
> jQuery('div')[36]
<div class=​"top">​...</div>​
> jQuery('div').get(-1)
<div class=​"top">...</div>​
> jQuery('div')[-1]
undefined

For most applications of jQuery, you wouldn’t index into the array directly and interact with elements of it. jQuery is a “fluent” interface that allows functions to be chained in a series of calls. A typical query starts with a selector function that selects certain elements, and then chains other calls that operate on each of the elements that were found by the selector. To operate on just one element, a selector would be used to select just that element.

Moving on…we’ve found all “<div>” elements in the page. You may have noticed that each entry in the returned array shows whatever CSS style classes and ids are associated with the elements that were found. So for instance, the third div found was ‘div.site-branding’ – a <div> element with a ‘site-branding’ class applied to it. Where is this element on the page? You can find out using jQuery! Let’s add a red border around this element:

> jQuery('div.site-branding').css('outline', '2px solid red')

This will highlight the name and description of the site in the upper left corner of the page. Note that this makes no permanent changes to the page; refresh the page in the browser, and the red outline will go away.

Another thing to note: I used the ‘outline’ property as opposed to the more commonly used ‘border’ property because ‘outline’ doesn’t add the thickness of the border to the “box” of the element. Sometimes using ‘border’ will cause elements to shift around on the page due to the change in size – ‘outline’ preserves the size of elements on the page and is better to use for experimentation like this.

The “.css()” command used above took as arguments the name of the CSS property and the value to give it. This command will also take an object literal (“name: value” pairs separated by commas and enclosed in curly braces) to set multiple properties on an element at the same time. So say that I wanted to set the outline red, give the div a green background, and make it 50% translucent. This command would do:

> jQuery('div.site-branding').css({
    'outline': '2px solid red',
    'background-color': 'green',
    'opacity': 0.50})

The “.text()” command lists all text (including whitespace) contained in the selected element. To see all the text included in the ‘site-branding’ div:

> jQuery('div.site-branding').text()
"
 
								CuriousProg
 
							Notes from a Curious Programmer
															"

Experimenting with Altering Content

Say that you wanted to see what the site would look like without the branded heading being in place. This would do the trick:

> jQuery('div.site-branding').css({'display': 'none'})

You can then verify that the div is no longer visible like this:

> jQuery('div.site-branding').is(':visible')
false

To bring the heading back you could either refresh the browser page or set the css with “display: block” to restore it without refresh. jQuery also provides “.hide()” and “.show()” commands as short cuts; “.toggle()” is also an option, it flips the visibility. Each of these commands accepts an optional argument that animates the visibility change. So to toggle the visibility of the heading gradually over 2 seconds (2000 milliseconds), try this:

jQuery('div.site-branding').toggle(2000)

Setting the “display: none” CSS property removes the element entirely from the DOM; when the element is hidden, other elements that surrounded it move to fill in the space that the hidden element took up. There is also a “visibility” CSS property that hides the element while retaining its space in the flow of the page:

> jQuery('div.site-branding').css('visibility', 'hidden')
...
> jQuery('div.site-branding').css('visibility', 'visible')

In this case, the above commands would hide and then show the branded text of the heading but leave the heading itself at its current size ( using “display: none”, the heading collapses).

Looking at Everything

jQuery selectors can make broader queries about a page. For example, how many elements are defined in the page? Just how “big” is the content in this page?

> jQuery('*').length
198

There are 198 elements on the main page of this site – a fairly small site as far as content structure goes. If you were to try this on some large portals (news sites, etc), you’d find that they have thousands of elements!

How many anchor links are there in the page?

> jQuery('a').length
128

How can there be so many links in the home page when just the four most recent posts are listed? The “Recent Posts”, “Tags”, and “Archives” sections in the sidebar all have clickable links, as well as the top nav bar that has links for different pages on the site. It adds up!

How many images are there in the page?

> jQuery('img').length
4

Makes sense: there are four posts shown on the page, each with a featured image. But there’s a fifth image, the one at the head of the page…why isn’t that included in the count? A little exploration shows that the URL to this image is specified with a “background-image” CSS property on the “header” tag, not in an image tag. There are in fact 5 header tags used in the page, the page header and then one header for each post:

> jQuery('header').length
5

Night Mode for your Browser

Here’s a fun trick: put a web page into “night” mode: make the text color white on black background:

> jQuery('div,article').css({
    'color': 'white',
    'background-color': 'black'})

The WordPress theme used on this site uses the “article” tag liberally in its markup, so in the above command I had to select both “div” and “article” using a comma separated list to get more elements to flip color. This jQuery command won’t affect the colors in images, so these will retain their normal appearance – image color isn’t a CSS style. Websites sometimes use images for blocks of content, so using this jQuery trick won’t reverse color on those.

These commands are starting to get long now, and you may want to enter them multiple times, tinkering with options. Most if not all developer consoles keep the history of previous commands and recognize the up and down arrow keys for stepping through this command history.

Extending the Reach of jQuery with .each()

jQuery offers a lot of power with selectors that return an array of results and many, many functions like .css(), .text(), .show(), .hide(), that operate on those results. But sometimes more complex code is required to interact with elements on a page. One option is to use .each() to iterate over each element that was found, applying some Javascript code to it (again, using features of jQuery to interact with each element). The .each() function provides a way to drill down for details of each element that’s returned by a selector.

For example, this prints all anchor elements with href attributes:

> jQuery('a[href]')

…but the anchors are all shown bunched together in one line of output, making it difficult to read. Using a console.log() call in each(), a one line per anchor list is displayed:

> jQuery('a[href]').each(function(){
    console.log(this)})
<a class=​"skip-link screen-reader-text" href=​"#content">​Skip to content​</a>​
<a href=​"http:​/​/​curiousprog.com">​CuriousProg​</a>​
<a href=​"#" id=​"pull" class=​"toggle-mobile-menu">​Menu​</a>​
<a href=​"http:​/​/​curiousprog.com/​">​Home​</a>​
<a href=​"http:​/​/​curiousprog.com/​about/​">​About​</a>​
<a href=​"http:​/​/​curiousprog.com/​windows/​">​Windows​</a>​
...more links...

The “this” variable inside the .each() callback function represents each element in the list. Wrapping “this” in jQuery() makes the full API of jQuery available to query the element. The following command references the “href” attribute of “jQuery(this)” to print just the URLs in the href attribute for each anchor tag that has one:

> jQuery('a[href]').each(function(){
    console.log(jQuery(this).attr('href'))
})
#content
http://curiousprog.com
#
http://curiousprog.com/
http://curiousprog.com/about/
http://curiousprog.com/windows/
http://curiousprog.com/quotes/
...more links listed...

Find all <script> tags that refer to a separate source file (via the “src” attribute):

> jQuery('script[src]').each(function(){
    console.log(jQuery(this).attr('src'))
})
http://curiousprog.com/wp-includes/js/twemoji.js?ver=4.9.2
http://curiousprog.com/wp-includes/js/wp-emoji.js?ver=4.9.2
http://curiousprog.com/wp-includes/js/jquery/jquery.js?ver=1.12.4
http://curiousprog.com/wp-includes/js/jquery/jquery-migrate.js?ver=1.4.1
...more links listed...

TL; DR

jQuery is a powerful interface for inspecting and changing the content of a web page. In addition to implementing features in a page, it can be used to experiment with the page from the browser’s development console. Some tricks:

// Outline a div in red
jQuery('div.site-branding').css('outline', '2px solid red')
 
// Set multiple styles on a div
jQuery('div.site-branding').css({'outline': '2px solid red',
    'background-color': 'green', 'opacity': 0.50})
 
// Hide a div, removing it from the DOM flow
jQuery('div.site-branding').css({'display': 'none'})
 
// Test the visibility of a div
jQuery('div.site-branding').is(':visible')
 
// Other options to hide/show an element
jQuery('div.site-branding').hide()
jQuery('div.site-branding').show()
jQuery('div.site-branding').toggle()
 
// Show an element with animation
jQuery('div.site-branding').show(2000)
 
// Find the text within a div
jQuery('div.site-branding').text()
 
// Make the color of major blocks of the site white lettering on black background
jQuery('div,article').css({'color': 'white', 'background-color': 'black'})
 
// Apply a function to each element found by a selector
// (listing something with console.log() in this case)
jQuery('a[href]').each(function(){
    console.log(jQuery(this).attr('href'))})

References

jQuery API Documentation

Searching for the name of a jQuery function (like “.toggle()”) will often find the link to the jQuery documentation as one of the first few results.

The book jQuery: Novice to Ninja: New Kicks And Tricks is a fun read and is full of interesting and useful examples about ways to use jQuery in building a website.

Versions

jQuery 1.12.4
Chrome browser version 64.0
WordPress 4.9.2

Add a Comment