Section 2: Advanced Selection, Events, Listeners, and Inputs

Overview: Today we will cover more advanced selection, events, event listeners, as well as inputs. All of these things often relate to each other, so lets get started!

How can I select...?

Basic DOM selection in both Javascript and jQuery is pretty strightforward as we saw in the last section. However, we may find ourselves with much harder items to select, and in rare cases, we cannot change the existing HTML code to give an element a unique ID to select it by.

Let's take a look at a difficult selections...

The plugin generated grid

We have all worked with plugin generated grids at some point. If you are stuck with the wrong plugin, it can be very difficult to do any DOM manipulations and selections with a grid.

So let's pretend we cannot touch the HTML code for this mini bingo grid, and we need to select and blackout the "free" space in the middle, using only Javascript or jQuery.
B I N G O
A1 A2 A3 A4 A5
B1 B2 Free! B4 B5
C1 C2 C3 C4 C5

jQuery

See the Pen eebWXW by Mike Parda (@mikeparda) on CodePen.

Javascript

See the Pen EbdLzm by Mike Parda (@mikeparda) on CodePen.

Is selecting this specifically a good idea?

Absolutely not! If you find yourself needing to select things using children, parents, indexes, etc, then you should probably take a look at why. That being said, there is times when you have no choice, but techniques like this should really be avoided because if the HTML changes, the code will break!

For our Bingo example we could also get creative and calculate the center (by counting the rows, and columns, then find what the index of the middle
td
would be, and go from there), but this still would leave us with issues when trying to select and black out other squares.

jQuery to Javascript DOM Traversal Methods

jQuery's strong point (and also a pitfall as we saw above) is its ability to traverse the DOM with its various functions. Here is some examples of the more common DOM traversal and selection methods and their Javascript equivalent:

jQuery

  • .find()
  • $('[data-id="someId"]')
  • $('div').not('.dontSelect');
  • $('#parent').children();
  • $('#child').parent();
  • $('#element').next();

Javascript

  • document.querySelectorAll()
  • document.querySelectorAll('[data-id="someId"]');
  • document.querySelectorAll('div:not(.dontSelect)');
  • document.getElementById('parent').children;
  • document.getElementById('child').parentNode;
  • document.getElementById('element').nextElementSibling;

Can you replace jQuery selection with JS
querySelectorAll
?

You actually almost can, although it's not quite as flexible as jQuery and you will not be able to directly call jQuery functions on those elements (remember jQuery provides a wrapper over each element to interact with its API).
querySelectorAll
returns an array of matching results, which is something to keep in mind when dealing with it. Simply add a function called
$
to the
window
and you can make a bad version of jQuery in a few lines of code, which actually is not too bad for simple selections:

See the Pen bYOrGr by Mike Parda (@mikeparda) on CodePen.


Events and Event Listeners

Events and event listeners are really one of the core functions of Javascript, and one of the primary reasons we use it. The first step in anything to do with events, is to attach an event listener. There is 2 ways to do this in jQuery, and 2 ways in Javascript, we all probably know these, but here they are anwyay:

Exploring the Event Object

Events are, like most things in Javascript, objects. When an event is triggered by some kind of action (click, touch, mouseover, etc), if the element that the event occured on has an event listener, the listener will execute what is referred to as the event handler. This is really just the function that you define when attaching your event listener. There is a ton of properties to the Event object, we will only go over the most popular ones.

I should also note that there is different Event objects, depending on what triggered the event (keyboard, mouse, etc) depends on what type of event our listener will recieve (KeyboardEvent, MouseEvent, etc). These events are most the same, with a few properties added or removed. For a full reference on the types of Events, please see the MDN Web Docs
  • keyCode
    is an integer which represents the key pressed (EX: 13 === 'Enter' key) NOTE: This property only comes with KeyboardEvents
  • target
    This property tells us the element that the event was targeting (EX: handling a click event for a button, the button itself will be the target)
  • type
    This property is the actual event type (NOT the event object type, but the type of event, such as
    keydown
    or
    click
    ).
  • defaultPrevented
    This lets us know if the default browser behavior for this type of event has been stopped (more on this below).
  • cancelBubble
    This property lets us know if the event is going to bubble up or not to any parents (more on this below)

More on
event.preventDefault()
and
event.stopPropagation()

The 2 properties in the Event object,
defaultPrevented
and
cancelBubble
can be changed with these functions to stop events from acting in how the browser would normally let them happen.

event.preventDefault()

This will do pretty much what it sounds like, it will prevent the default behavior of the browser from happening, and it is generally used to help stop form submissions. If you have a
<form>
with a
<button type="submit">
, since the type of the button is "submit", the browser will attempt to submit the form. NOTE: if you have a button inside of a form, unless it is specifically type="button", the browser will attempt to submit the form.

See the Pen rYoGNV by Mike Parda (@mikeparda) on CodePen.

event.stopPropagation()

This is a bit more obscure and not used nearly as much.
stopPropagation
will stop the event from bubbling up. Wait... what? An example would be this scenerio: you have 2 elements, both with click events, but one is nested inside the other. If you click on the inner element, the event will bubble up to the parent element, and trigger its event handler as well. Let's take a look at an example:

See the Pen wPRPLd by Mike Parda (@mikeparda) on CodePen.

Removing Events

There may be times when you want to remove an event listener from an element, for example maybe you only want a user to be able to click something once, fire and event, and then thats it, next time they click the element, you want nothing to happen. Removing events is just as easy as adding them.

jQuery

With jQuery, you can actually remove ALL the events on an element, or you can specify the event listener to remove by passing in the event handler function for the listener to just remove 1 at a time.

See the Pen pdqpaq by Mike Parda (@mikeparda) on CodePen.

Javascript

Javascript requires you to specify the event listener to remove by passing in the event handler function name. Unlike jQuery you cannot leave that empty and just remove all events of a certain type.

See the Pen LOMeab by Mike Parda (@mikeparda) on CodePen.

Dynamic Elements and Events

A very common use of Javascript/jQuery is to use it to perform AJAX calls to get data, then build HTML elements based on that data. When we are dynamically loading and creating elements, we must properly attach events to those elements. You cannot attach events to elements that are not in the DOM yet, so if your code that attaches the event listener fires before the element is in the DOM, then element never gets the event listener. To avoid this issue, we have a few options:

jQuery

jQuery makes it nice and easy to account for dynamic elements and attaching events listeners to them. jQuery will allow us to attach events to the
document
and pass in the selector of the element we want the event listener to be put on. Since the document is the DOM, it is always there, so we are gaurenteed to have our event attached somewhere. So if we just pass in the selector of the element we want to add the event listener to, jQuery will create the event listener on the document, but will only fire the event if the event was triggerd by the selector.

The other choice we have is to add the events to the elements as we insert them into the DOM. Let's take a look at both choices:

See the Pen VrqQeM by Mike Parda (@mikeparda) on CodePen.

Javascript

Javascript is not as forgiving as jQuery, and there is pretty much one way to add event listeners to elements. The only wait to attach events to elements in Javascript (that will actually fire), is to wait for them to be present in the DOM, or when they are put into the DOM, add the event listener then.

If you try to attach an event to an element not in the DOM yet, nothing will happen. You will not get any kind of error message or warning, and you may be left wondering why your event is not firing.

See the Pen yPGKPz by Mike Parda (@mikeparda) on CodePen.


Waiting for the DOM to be ready

How to we make sure we do not execute any of our Javascript until the imitial DOM is loaded? Your answer might be that you use
document.ready
and that answer is not wrong. That is one way to make sure you do not run any JS before the document is loaded. But is it necessary?

The answer to that depends on the organization of your application somewhat. It is recommended and advised that you not include your Javascript in a page until right before the closing body tag. Why? Since the browser loads the HTML from bottom to top, putting your JS at the bottom of the body, ensures that all the HTML has been loaded before we start loading any JS.

Once agian, do NOT load your Javascript or jQuery in the
<head>
tag, that is an old standard that is not valid anymore. Including your scripts in the
<head>
only ensures that you will need to use some sort of
document ready
, since your scripts will load well before any of your HTML. That being said, you may find yourself working on an application that includes the scripts in the
<head>
and there is nothing you can do to change it. Not a problem, let's look at a few ways to defer executing your JS until the HTML document is ready.



Regardless of which method you use, you do need to try and keep only 1 document ready type function per page. This is more of code standards and best practices than anything, as you can have 100 document ready function in your code and it will work, however this will become a nightmare to update later, so keep 1 document ready function per page, and anything that must execute as soon as the DOM is loaded should live there and only there.

Input

The last thing we will cover in this section is input fields. This is a pretty standard thing that we all most likely know how to do, as it is the bread and butter of utilizing Javascript and jQuery in any application that does any kind of CRUD, as such we will not dig too deep into these.

Getting Values

There is quite a few types of inputs, and getting their values is not always the same. Let's take a look at how to get the value of each of the input types in both jQuery and Javascript.

Get Input Values jQuery

See the Pen QOzVKm by Mike Parda (@mikeparda) on CodePen.

Get Input Values Javascript

See the Pen WXLgVL by Mike Parda (@mikeparda) on CodePen.

Set Input Values jQuery

See the Pen POXyzB by Mike Parda (@mikeparda) on CodePen.

Set Input Values Javascript

See the Pen wPRYRV by Mike Parda (@mikeparda) on CodePen.

Wrapping Up

Alright so that concludes this section on a bit more advanced selection, events, event listeners, and inputs. Next week will start taking a deep dive into function, objects, and start adding events to our inputs. I will also go over some AJAX by submitting forms, data, and/or files.