DOM/jQuery Continued

Objectives

  • Implement advanced jQuery events.
  • Use event delegation to manage dynamic content.
  • Use implicit iteration to update elements of a jQuery. selection and chaining to place methods on selectors.
  • Add a templating language to our projects for better and more abstracted content manipulation.

Review

  • Register and trigger event handles for jQuery click event.
  • Manipulate the DOM by using jQuery selectors and functions.

Events Continued

Mouse Events

  • click
  • dblclick
  • mouseenter
  • mouseleave

Keyboard Events

  • keypress
  • keydown
  • keyup

Form Events

  • submit
  • change
  • focus
  • blur

Window/Document Events

  • load
  • resize
  • scroll
  • unload

Practice

  • Draw out a wireframe of a site
  • Keep in mind user interactions & include 3
  • Psudocode something to do for each user action

Event Delegation and Best Practices

  var $thingListItems = $('#fav-list li');

  $thingListItems.on('mouseenter', function(e) {
    $(this).removeClass('inactive');
    $(this).siblings().addClass('inactive');
  });

  $thingListItems.on('mouseleave', function(e) {
    $(this).siblings().removeClass('inactive');
  });

Register an event

That works great for existing elements, if we add new elements to the DOM, the events will not fire up for the newly added elements.

It is important to understand that the direct events are only attached to elements at the time that the 'on' method is called.

 

If list items did not exist when the above events were called, they do not get included in the calls above.

To get around this, we create a delegated event, which requires us to add the element our event handler executes for, to the right side. Take the above code and modify to:

 

  var $thingList = $('#fav-list');

  $thingList.on('mouseenter', 'li', function(e) {
    $(this).removeClass('inactive');
    $(this).siblings().addClass('inactive');
  });

  $thingList.on('mouseleave', 'li', function(e) {
    $(this).siblings().removeClass('inactive');
  });

Our code is getting a little inefficient and duplicative. Our list items have two event handles attached to them.

 

Grouping our events by element not only helps us group our code, but it is also a faster operation.

var $thingList = $('#fav-list');

  $thingList.on('mouseenter mouseleave', 'li', function(event) {
       if (event.type == 'mouseenter') {
         $(this).removeClass('inactive');
         $(this).siblings().addClass('inactive');
      } else if (event.type == 'mouseleave') {
          $(this).siblings().removeClass('inactive');
      }
  });

Let's add a dash in front of every one of our list items (in addition to the bullets). jQuery gives us a convenience method to iterate through a list of elements.

  var $thingList = $('#fav-list');

  $thingList.find('li').each(function() {
    $(this).prepend(' - ');
  });

Appending: Independent Practice

Open the starter code and refactor it as follows:

use event delegation so that you only have to set one event listener for all the items once when the code first runs - and you don't have to add any others whenever someone adds an item.

 

Bonus:

  • When the user mouses over each item, the item should turn grey. Don't use CSS hovering for this
  • Add another link, after each item, that allows you to delete the item

Separation of Concerns and Templating

Through event handlers and DOM manipulation we are able to making our applications more dynamic, interactive, responsive, and just plain fun.

 

However, even with a small to do list app, our code is starting to grow significantly. If we keep stacking features, our code will soon become much more difficult to manage. We are currently having to interact with our data as DOM elements.

 

As our applications start forming relationships, it will become very messy to get values, serialize them, and pass them around.

 

Separating our data from our view logic becomes very important. We can still use jQuery to interact with the DOM and listen for user events, however our business rules (data) should be kept separate from the view. This is where templating becomes very useful.

 

Templating lets us reference a snippet of code, and populate it with data we store in actual JavaScript objects, before adding it to the DOM.

 

There are many JavaScript templating libraries such as:

 Handlebars, Mustache, and Underscore templates.

Templating: Codealong

CDN

Handlebars has a 4 step process to implementing templates in our applications:

  • Create the template(s)

  • Reference and compile template

  • Pass the object to compile to Handlebars

  • Add the new compiled element to DOM

 <script id="hello-world-template" 
         type="text/x-handlebars-template">
    <h1>{{helloTitle}}</h1>
    <p>{{helloContent}}</p>
  </script>

We create our element surrounded in script tags with a reference id and a type of handlebars template.

 

We surround the content that's to be replaced by double curly brackets.

var source = $('#hello-world-template').html();
  var template = Handlebars.compile(source);

We can then use jQuery to reference the newly created template and pass that reference to Handlebars.

 

We can then pass our data object to the newly created template

var source = $('#hello-world-template').html();
  var template = Handlebars.compile(source);

  var helloStatement = { 
      helloTitle: "Hello world", 
      helloContent: "GA JS class is just awesome"
  };

  var compiledTemplate = template(helloStatement);
  $('body').append(compiledTemplate);

  // or $('body').append(template(helloStatement));

And add it to the DOM via jQuery

To Do List: Independent Practice

 

  • Use Handlebars to add any new DOM content.

  • Store all of your data in a todos object.

  • Organize your code so your app logic is DRY.

  • Bonus: create a method you can reference in your app to compile your data to Handlebars templates, instead of relying on doing this every time you need to add a DOM object.

Build on top of the to-do list app to store your initial to-do data in a JavaScript object and interact with the object whenever the user interacts with the DOM.

Conclusion

  • Why would we want to use templating?
  • What is event delegation? Why would we use it?

Further Resources

Aug 15: DOM/jQuery Continued

By Jessica Bell

Aug 15: DOM/jQuery Continued

  • 158