Before you do anything, you need to find out if the browser is ready for you

Whenever you want to write some code with ChocolateChip, you need to check to see if the browser has finished parsing the document so that you can get nodes. ChocolateChip makes this possible with the $.ready() method. Here is an example of how to wrap your code in the $.ready function or $(function() {}):

$.ready(function() {
    // Your code goes here.
});

Whatever code you put inside the ChocolateChip ready function will not execute until the document is ready for it. It’s just like jQuery’s $(document).ready(function() {}), or any other framework’s DOMready method. Except that you don’t have to pass in the document as an argument. $.ready() straightaway checks to see when the document is ready. What else would you be waiting for?

So, $.ready() takes one argument, a function to execute when the document is ready. To get your script to execute, you can pass in a predefined function that you’ve defined elsewhere:

var doSomething = function() {
    console.log("This is doing something. Cool, huh?");
};
$.ready(function() {
    doSomething();
});

This works fine. However, in most cases you’ll want to write code blocks inside an anonymous function that is defined directly within the parentheses of the $.ready() function. This isolates your code inside the $.ready() function to avoid namespace collisions with any other code you might have elsewhere:

$(function() {
    var logSomething = function(msg) {
        console.log(msg);
    };
    logSomething("I hope this is working properly.");
});

You can also access the window and document objects with $, and if you pass no selector to $, it will by default return the document object. Please note that although you can access the window and document objects, they do not have the same interface as DOM nodes and therefore most of those methods will not work on the window and document objects.

var windowHeight = $(window).outerHeight; // returns the height of the window frame
var docSource = $(document).title // returns the title of the document
var docSource = $().title // same as above.

All ghosts of selector engines be gone!

Selector engines are now so out of fashion. Why does anyone seriously think they need one when we have querySelector and querySelectorAll? These both take as their argument a valid CSS3 selector. You can’t get any simpler than that. It’s built into the mobile browser too. It’s a complete no-brainer, right?

ChocolateChip uses querySelector and querySelectorAll to return matching nodes in your document. To get a single node is really easy. Just invoke the $() method.

$(function() {
    var elem = $("#menu > li:last-of-type > a");
    elem.css("border-bottom: solid 2px blue");
});

No rocket science here. Just describe what element you want using CSS3 selectors and, bang! You’ve got it and can do stuff. Here I’m using ChocolateChip’s css() method to add inline CSS on the anchor tag in the last list item in a container with an id of “menu.” Bare in mind the the $() method uses querySelector. This means it always returns a single node. If there are multiple matches, $() will return the first match. However, with the power of CSS3 selectors you can craft a selector to pick out the node you want with surgical precision without having to loop through a collection.

OK, now let’s get a little complicated here. If I use $$() to search a document for multiple matches, I get back what’s called an HTML collection. The $$() method turns that collection into an array so that we can do something practical with it:

$(function() {
    $$("#list > li").each(function(item) {
        item.css("background-color: red");
    });
});

So, to clarify what’s going on, when ChocolateChip finds a number of matches for a query, it takes that HTML collection and turns it into an array. Since it returns an array, you can use the forEach method. As a matter of fact you can use any of the array methods you want. In most cases, though, you’ll want to use the forEach method. This takes as its argument a function to execute on each index of the array. This function can take an argument of an object using any name you want to indicate the value of “this” during execution of the function. During the execution of the function, “this” will refer to that particular index of the array. In the above example of code, I get an array of list items. To operate on each list item I use the term “item” as the argument of the method being executed by forEach. You can use whatever term makes sense for the individual members of the array. The nice thing about this is that it makes your code more readable, and that makes your code easier to maintain and easier for other people to use as well.

Danger! Will Robinson, danger!
I could have rolled the two selector methods together. Actually, at one point I did. But that led to several problems. It was crazy trying to decide when to return a single node and when to return a collection. And how to know if the user intended to get a single node or a collection. Rather than writing a mess of code to deal with all the edge cases, I decided that for simplicity and sanity I would keep the two method separate. jQuery handles this problem eloquently by wrapping everything in the jQuery object, where everything is hidden from the user. I did not want to go this route. I wanted everything to stay accessible JavaScript and no obfuscation.

Personally, I want to have a way to get a single node and deal with it as such, not as an object. I want to be able to get a node that I can use normal JavaScript on. I do not want a node wrapped in an object that forces me to use the framework’s methods instead of natural JavaScript methods. I thought long and hard about this and decided that it was better not to use object wrappers.

Besides, there was another reason I didn’t want to hide the looping from you. I wanted to give you the opportunity to choose how you operate on the array returned by $$(). Instead of using forEach(), you might want to use reverse(), sort(), indexOf(), lastIndexOf(), some(), every(), map() or filter(). Depending on your needs, these are all possible array methods that you could use on the array returned by $$(). If you’re a developer of any standing, you’re probably already familiar with these array methods from other programming languages. If you’re not familiar with them, you can read more about them here.

One more thing, don’t forget that if you want, you can use the DOM’s built-in querySelectors. Here’s an example:

// The querySelector method will return a single node:
var elem = document.querySelector("#menuList > li:first-of-type");
elem.style.backgroundColor = "red";

// The querySelectorAll method will return a nodeList, even if only one node is found:
var items = document.querySelectorAll("#menuList > li");
for (var i = 0, i < items.length; i++) {
    items[i].style.cssText = "font: bold 14px/20px Helvetica, Sans-serif;"
}

To see examples of what ChocolateChip can do, visit http://www.css3wizardry.com. That site has numerous posts about how to built out various mobile Web controls that work like native controls on the iPhone, iPad, iPod and Android platforms.

Find and FindAll

As of version 1.1.7 ChocolateChip offers element.find() and element.findAll() as ways to get nodes starting from a particular node. If you already have a node and one to get one or more of its descendants, you can use these methods. Element.find() is works like $() in that it returns a single node, and element.findAll() works like $$() in that it will return a collection.

Here’s an example:

var menu = $("#menu");
var firstMenuItem = menu.find("li");
menu.findAll("li").each(item) {
    item.css("background-color: yellow; border: solid 2px red;");
});
Advertisements