A first jQuery script

When you read the first few pages of this chapter, you must have noticed that very little was said about Drupal. jQuery is a standalone library with no dependency on Drupal, which means it can be used on its own.

In fact, that's the way we are going to dip our toes into the topic. Don't worry though. We will be coming back to Drupal just a little later in the chapter.

We are going to start out with a static HTML document and take a look jQuery in this simplified context. In the next section, we will apply this knowledge in the Drupal environment.

Getting jQuery

For our examples here, you will need the jQuery library. At this point, you have two options. You can either download a copy from http://jQuery.com or you can make a copy of the jQuery library that comes with Drupal. It's located in misc/jquery.js.

The copy that comes with Drupal is packed. Extraneous whitespace (such as newlines) has been removed, and long variable names have been replaced with short computer-generated names. That makes it difficult to read the jQuery library code, should you so desire.

For that reason, I suggest going to jQuery.com and downloading the Uncompressed version (it's right there on the front page).

[rlTX For more about packing code with Packer, see http://dean.edwards. I name/packer/ I

Once you have the jquery.js file (or jquery.i.2.x.js), just make sure it is in the same directory as the HTML we will create in the next part.

Again, since Drupal already includes jQuery, there is no need to worry about putting this file where Drupal can see it. In fact, you should not put this in a Drupal directory.

Now, let's work up some simple HTML for a few examples.

Starting with a basic HTML document

Here is a very basic HTML document that will serve as a starting point. Notice that we are including the jQuery library in the <script></script> tag in the document's head.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/19 99/xhtml"

xml:lang="en" lang="en"> <head>

<meta http-equiv=»Content-Type»

content=»text/html; charset=utf-8»/> <title>sample</title>

<script src="jquery.js" type="text/javascript"></script>

<p class="odd">Paragraph 1</p> <p class="even">Paragraph 2</p> <p class="odd">Paragraph 3</p> <p class="even">Paragraph 4</p>

This document is just a standard XHTML document. We are concerned mainly with the highlighted sections. The first highlighted section loads jQuery with the file jquery.js. If you grab a copy from jQuery.com, it may have a name such as jquery.1.2.x.js. You can either rename that or change the src attribute to point to your version.

The second highlighted section exhibits the elements that we will be using in this section. Nothing should look unfamiliar here. It's just a header and four paragraphs.

Notice that the <h1></h1> has an id, id='title'. Also, the paragraph elements have class attributes. The even paragraphs have the even class, and the odd paragraphs have the odd class.

We are going to make use of these id and class attributes. Now we're ready for some jQuery.

Querying with jQuery (and the Firebug console)

We could demonstrate jQuery by adding a script to the previous HTML code. But that would require us to write a complete script first. For a gentler method of introducing jQuery, we will start out with the Firebug console introduced in Chapter 1, instead.

Firebug is a Firefox add-on that provides a debugging and inspection environment for web development—particularly for HTML, CSS, and JavaScript. One of the tools it provides is a JavaScript console, which can be used to interactively run JavaScript. That's exactly what we are going to do.

While we will use Firebug here, the Safari browser also includes similar developer tools that can be enabled by opening Safari's preferences window and then checking the Show Develop menu in menu bar check box. The examples that follow can also be duplicated on Safari's Web Inspector console.

To start off, let's use jQuery to find the <hi></hi> element in our document. Locating parts of an HTML document was, after all, the original purpose of using jQuery.

In the previous screenshot, we are entering the command jQuery('hi'). When we run this command, it should search the document and return a jQuery object that wraps a list of all <hi></hi> elements found in the document.

So if we hit ENTER to run the command, we will get something that looks like this:

ooo

file:// - sample

cz>

Title

Paragraph 1 Paragraph 2 Paragraph 3 Paragraph 4

Jfy? Inspect Clear Profile Q

9 ©

Con sole ^

HTML CSS Script DOM Net

Options

>» jQueryC'hl1};

Object length = I

»> 9

In this case, when we executed jQuery('hi'), it returned an object with a length property set to 1. We know that there is only one <hi></hi> element in our document, so this length is what we would expect. In fact, if we re-ran the command as jQuery('p'), we would get the output: Object length=4. The length is four because there are four <p></p> tags in our document.

What is the output on the console?

When you run a command on the console, Firebug always prints a representation of the returned value to the screen. In this way, you can get an idea of what is coming back from any executed function. If you come from a Ruby or Python background, this behavior is similar to the interactive shells of these languages.

But what is the object? It's a jQuery object. To show this, we could enter the following command into the console:

jQuery('h1') instanceof jQuery

The instanceof operator will compare the object type on the left hand with the type on the right hand. It will return true if both objects are of the same type. More specifically, if the object on the left side has the type of the object on the right side, the result will be true. Since prototypes are chainable, they may not have exactly all the same prototypes).

It should come as no surprise that the returned value is true. In fact, even if we were to search for an element that does not exist in our document, jQuery() will still return a jQuery object (though the length of this object will be 0).

How do you run a function called jQuery() without the new keyword, and get a jQuery object? The short answer is that jQuery() acts like a factory method. This function simply creates a new jQuery object and then returns that object. For this reason, there is no need to use new jQuery(). Instead, just jQuery() will suffice.

This method of creating a new jQuery object resembles the Factory pattern. The Factory is a common design pattern in object-oriented programming, where one object (the factory) takes responsibility for creating new instances of another object. Of course in jQuery's case, the jQuery object is responsible for creating new jQuery objects. The flexibility of JavaScript's prototyping system allows this sort of thing to be done.

What else can we query with jQuery? We can get elements by their id attribute:

To find an element by ID, we prefix the ID with a "#" (pound sign). We can also get elements by class:

Just as an ID is prefixed with #, a class is prefixed with a "." (dot).

Now we've seen four jQuery query strings: h1, p, #title, and .even. Do these look familiar? If you have worked with CSS stylesheets before, they should. jQuery's query language is none other than the CSS selector language.

To style all the even paragraphs in CSS, you might write a CSS statement like this:

That same selector, p.even, can be used in jQuery to find all even paragraphs like this: jQuery('p.even'). Since jQuery supports all CSS selectors through CSS version 3, you can even build more complex queries. For example, we could grab only the first even paragraph with this:

This looks for all paragraphs with the even class, and then returns only the first of those. Incidentally, since CSS 3 defines a pseudo-class for selecting the even and odd children, we could drop the odd and even classes altogether and use queries such as jQuery('p:nth-child(even):first') or even jQuery('p:even:first') (We've just used the ":" (colon) symbol to indicate that we are using a built-in CSS pseudo-class instead of the even class we defined ourselves.)

Throughout this book we will be using these CSS selectors to create queries. But if you are eager to gain a detailed insight into selectors, you might want to take a look at the W3C's current CSS 3 draft standard at http://www.w3.org/TR/ css3-selectors/.

We've seen our last jQuery() function call.

From now on, we will be using an alias for that function. Instead of calling jQuery('h1'), we will be making calls such as $('h1').

Surprising as it may seem, the $ (dollar) sign is a legal character for function or variable names in JavaScript. That means iNeed$, $tar, and my$amount are all legal tokens in JavaScript. And as it turns out, so is $.

Making use of this, the jQuery developers aliased the jQuery() function to $(). That saves you five whole characters of typing. And it looks cool.

Generally speaking, you (as the software developer) can use either or both of these names to call jQuery. But the Drupal JavaScript convention suggests using the $() version. And so we shall.

Doing more with jQuery

We now have a glimpse of how we can find parts of a document with jQuery. But a querying engine alone doesn't get us too far. We need the ability to manipulate the information we've retrieved. Of course, jQuery provides such tools.

To start, let's get the text content of our <hi></hi> element. This is done with the text() function:

The first line retrieves a jQuery object containing our <hi></hi> element and stores this in the title variable. The second line calls the jQuery object's text() function. This will return all of the text inside of that element. Any HTML tags will be removed. (If you want the HTML content, use html() instead of text().) Running this pair of statements would cause Firebug to output "Title" to the console.

Likewise, if we wanted to change the title of our document, we could call:

Immediately, the bolded text in the document would be changed as if we had written <hi>New Title</hi> instead of <hi>Title</hi>. What would Firebug output to the console when we set text? A string representing the jQuery object (for example Object length=1). This means that even a setter function returns an object. As we will see in a moment, this is an important aspect of the jQuery library.

Our two-line text-getting scriptlet is functional, but we can shorten it down to one line by making use of a convention called function chaining or method chaining. When we call a function that returns an object, we often store that object in a variable — as we did with the title variable. That way, we can use the object later by referring to title.

Sometimes we don't need to store the object, we just need to call one of its functions. Rather than storing the object in a variable, we can just use the dot operator (.) to chain the function to the function that returned the object.

Sounds confusing? An example will clear it up. We can rewrite our previous scriptlet like this:

$('h1').text('A New Title'); The text() function operates on whatever jQuery object the $() function returns.

This is one of the important reasons why $() returns a jQuery object even if it doesn't find any matches to the query. Otherwise, scripts would be plagued with errors when a chain returned, say, a null instead of an object.

Just as with the earlier code, the previous line will find the <hi></hi> element and change its content.

jQuery makes greater use of the chaining concept by using a design pattern called the Fluent Interface. In a fluent interface, any member function that would normally return void (that is, nothing) returns its parent object instead.

[r^lTK A member function is a function that belongs to an object. In most I

object-oriented languages, all functions are members of an object. I

The jQuery object provides this type of fluent interface. So when we call $('hi'). text('A New Title'), the title is changed; but we also get the jQuery object returned again.

How is this useful? Well, we can combine several tasks into the same line. Let's say we not only want to change the text of the title, but also want to underline the title. This additional step would involve changing the <hi></hi> element's CSS. We can chain another function to our code to accomplish this:

$('hi').text('New Title').css('text-decoration', 'underline');

The result should look something like this:

The result should look something like this:

There are two things to notice here.

First, the title and text decoration have indeed changed.

Second, as you can see in the console output, the css() function still returned our jQuery object. That means we could continue our chain if we so desired.

Not every function returns a jQuery object

Before we get too addicted to the fluent interface, we should take another look at an earlier example as an illustration (or perhaps a reminder ) that not all jQuery functions return jQuery objects.

In our first example of the text() function, we saw that running $('h1').text() returned the string Title.

In this case, we have a string object, not a jQuery object. Sure, we could continue chaining, but we could only call functions of the string object. For instance, the following would work just fine:

The text() function returns a string, and substring() is a member function of a string object. However, we could not do this:

This would generate an error looking something like this: TypeError: $("h1").text(). css is not a function. That happens because a string object does not have a css() function.

At this point, the important things to understand about jQuery are:

• How queries can be composed from CSS selectors

• How $() and jQuery() return jQuery objects (that often wrap lists of elements from the document)

• That jQuery function calls are often chained together to produce longer lines that do more

We will pick up more about jQuery as we proceed.

Feeling comfortable with the basic concepts of jQuery? Now it's time to get back to Drupal. We will be making use of jQuery to build Drupal-centric JavaScript.

0 0

Post a comment