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');
});
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(' - ');
});
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:
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:
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
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.