jQuery can’t do it all alone. Although it is a JavaScript library, unfortunately it can’t do everything its parent language can do. In this chapter, we’ll look at some of the features of JavaScript that you’ll need to create really compelling sites, and how jQuery can use them to create custom lists and objects as well as loop through those lists and objects to make your life much easier.
Lucky you, news of your jQuery prowess is spreading far and wide. Check out this email from the Head First Lounge asking for some help to increase the entertainment level for its visitors.
From: Head First Lounge |
Subject: Blackjack Application |
Hi! |
It’s your pals over at the Head First Lounge. We’re hoping you can help us out with a new application we want to give to our visitors. |
We would REALLY like a blackjack application for our site. Can you do that? |
Ideally, the player would click and get dealt two cards, with the option to ask for more cards. |
Here’s the house rules we would want included in the game:
|
If none of those conditions is met, players can ask for another card. |
If one of the rules/conditions is met, then end the game. |
Give the players the option to reset and play again. |
But we don’t want them to have to reload the page. The game should reset itself. |
Can you do that for us? We’d be ever so grateful! |
-- |
Head First Lounge |
Jim: Hey, have you guys read the email from the Head First Lounge folks?
Frank: Yeah, it looks like they want an easy-to-play blackjack game on their site. Should be pretty straightforward, I think.
Jim: Straightforward? But it’s blackjack! We need a deck of cards, a dealer, a counter for the hand, and more. Do you think we can do all that?
Joe: It’s not going to be easy, but I think we can get it done. Like you said, we’ll need something to deal the cards. We can write a function to do that. We’ve already written a random function before, so we can probably use that again.
Jim: Oh yeah... But what about the cards? There are 52 of them in a deck.
Frank: We can just have a big list of them and pick a random one from the list each time.
Jim: But how do we avoid picking the same card twice?
Frank: I think I know how to do that...
Jim: Wow, that’s impressive! And what about remembering which cards we have already? And counting them up as we go?
Frank: OK, now you’ve got me. I’m not too sure how to do that.
Joe: No worries. There are quite a few JavaScript and jQuery features we can use to help us out here.
Jim: Wait, wait, JavaScript? Can’t we use variables or jQuery arrays to remember our cards? I thought we really didn’t have to get into a bunch of JavaScript if we’re using jQuery...
Frank: Variables on their own may not cut it. They can only really store one value at a time, like a number or a string of text, or a particular element on the page. And a jQuery array can hold multiple values, but only of DOM elements returned by a selector...
Joe: That’s right. We need something a little more flexible.
Frank: Like our own structures or variable types.
Joe: Correct again! And we’re going to need JavaScript to create our own structures...
The data structures you’ve used so far are variables and arrays. Variables offer simple storage: they assign one value to one name. Arrays let you store more data more efficiently by letting you create multiple values with one variable name.
Objects offer even smarter storage. You use objects when you need to store multiple variables about a particular thing. Inside of an object, a variable is called a property. An object can also contain functions that let you interact with the object’s properties. When you build such a function inside of an object, it’s called a method.
Use objects when you need to store multiple pieces of data about a particular thing.
Objects are essentially a way to create your own custom variables exactly how you want them. You can create one-time-use objects, or create your own object blueprint that you can use again and again. We’ll look at reusable objects in a little bit, but for now let’s discuss how to create a one-time-use object and some of the terms and diagrams associated with an object.
Objects can be described in a standard way, using a UML (Unified Modeling Language) diagram. UML is a general-purpose, worldwide standard for helping to describe objects in object-oriented programming.
When an object has a variable associated with it, we call that a property of the object. When an object has a function associated with it, we call that a method of the object. You create one-time-use objects using the var
keyword, just like for all the other variables you’ve seen so far.
This structure helps you see how your object is structured before you write any code.
And here’s how you’d write that object in code:
One really nice aspect of objects is that they can have the same structure but hold different values for their properties (or variables). Just like creating reusable functions—like we did in Chapter 3—we can create an object blueprint, or object constructor, so we can use it multiple times. An object constructor can also be used to create instances of the object.
The constructor is just a function, so in order to create a constructor for an object, you use the keyword function
instead of the keyword var
. Then, use the new
keyword to create a new instance of the object.
Objects come in all shapes and sizes. After you instantiate (or create an instance of) an object—whether it is an object you created or one created by someone else—you interact with it using the dot (.) operator. To get a feel for how this works, let’s take a closer look at the myCountry
and myPerson
objects that we just defined.
Yes! That’s a great idea.
Let’s set up the HTML page and then have a look at how we can go about creating a card object.
Create your HMTL and CSS files using the information below. Don’t forget to create a my_scripts.js file, too, in your scripts folder. We’ll be adding plenty of code to that in the coming pages. You can download all the image resources for the entire chapter from http://thinkjquery.com/chapter06/images.zip.
We need a way to store and access cards as they’re dealt. Good thing is, we’ve already seen how to do this...
As you’ve already seen, we can group several items into a single structure called an array. The items in an array are not necessarily related to one another, but accessing their values becomes a lot easier this way. Back in Chapter 4, we saw how a jQuery selector returns items and stores them in an array. Now we’re going to use JavaScript to get even more utility out of arrays.
Variables in an array can be any type, including strings, numbers, objects, even HTML elements! There are several different ways of creating your own arrays:
And, as we mentioned earlier, arrays are objects too, which means they have methods and properties. A common array property is length
. This denotes how many items there are in the array. You can access the length
property with array_name.length
.
Unlike with creating arrays, there is only one way to access the information inside an array. Arrays are zero-indexed—that is, their position (or index) in the list starts at 0. We used the index back in Chapter 3, so you can always go back there for a refresher if this isn’t clicking.
The index of an item in a list refers to where it appears in the list.
Definitely not!
It’s easy to add, change, and delete items in an array. Let’s take a look at how.
We can add as many items to an array as we want. In the example on the previous pages, we prepopulated some items into the my_arr2
and my_arr3
arrays, but we left the my_arr1
array empty. We can add or update items in an array, and to do that, it’s again all about the index. Here are a few different approaches to updating an array:
You’re going to be putting cards into and getting info back out of arrays quite a bit for this blackjack game. Thankfully, JavaScript comes prepared for just this scenario with loops. And the even better news is you’ve already done this before: back in Chapter 3, you used the each
jQuery method to loop through elements based on a jQuery selector. But in this case, we’ve got more options, as JavaScript has several different types of loops, each with a slightly different syntax, and each with its own purpose.
Every loop, regardless of type, has four distinct parts:
Initialization
This takes place one time, at the start of the loop.
Test condition
This checks to see if the loop should stop or keep going for another round of running code, usually by checking the value of a variable.
Action
This is the code that is repeated each time we go through the loop.
Update
This portion updates the variables being used by the test condition to see if we should keep looping or not.
Frank: Well, we have our array of card
objects, but we need to be able to pull out a card at random when we deal, right?
Joe: Yes, and thankfully, we’ve already written that getRandom
function back in Chapter 3. That’ll give us a random number each time to pull a card out of the array.
Jim: But what will we do with it then?
Frank: We’re going to have to remember it. We have to be able to add up the total value of the cards to find out if the players went over 21 or not.
Joe: And for another reason. We can’t give them the same card twice, so we also have to make sure it hasn’t been dealt already.
Jim: Can we use a variable to remember the cards?
Frank: We can use an array variable...
Joe: Good thinking! We don’t even have to store the cards; we can just store their index values. That way we can test if it’s in our used_cards
array.
Jim: Wow, that’s impressive! How can we tell if a value is in an array?
Frank: Using a jQuery utility method called inArray
.
Joe: That sounds handy. But I think we’re going to need several functions to do this for us. We have to get a random number between 0 and 51, and we have to check if we’ve used it already. If we have, we need to try again. If not, we need to get the correct card out of the deck and remember the index of that card. And then we need to show that card to the player.
Jim: Sounds like a lot! How are we going to show the card to the player?
Frank: Well, we already have the images, and they’re arranged by suit and named type, so we can use those attributes of the card
object to put the image on the screen.
Joe: Exactly. We can create a DOM element and append it to the my_hand div
element already on our page.
Frank: This card
object is already paying dividends... Let’s get to it!
Often you’ll need to see if a variable already exists in an array or not, so you don’t end up duplicating data, or to prevent your code from adding the same thing several times to an array. This can be particularly useful if you use arrays to store things like a shopping cart or a wish list.
jQuery provides a whole host of utility methods to help us get particular tasks done more efficiently. These include functions for checking what type of browser the site visitor is using, for returning the current time, for merging arrays, or for removing duplicates from arrays.
The utility method that’s useful for this particluar situation is the inArray
method. It will return where in the array the value you’re looking for is located (its index), if at all. If it cannot find the value in the array, it will return –1
. Like other utility methods, inArray
does not require a selector—it’s called directly by the jQuery function or jQuery shortcut.
Sure, we can create an option to get more cards from the deck using the hit
function we’ve already created.
We just need something to run that function, like a button click or similar. This adds a new wrinkle, too: now we have to remember and count which cards have been dealt out so we can tell if the player goes bust or not.
We definitely don’t want that.
Then there will be no way to see who’s won. Based on the rules set out in the email from the Head First Lounge, we have to decide if you won based on several different criteria. Let’s have a look at those criteria again.
If a player’s cards add up to exactly 21, then she has a blackjack, and the game is over.
If a player’s cards add up to more than 21, then she is bust and must start again. The game is over.
If a player’s cards add up to 21 or less, but she has already been dealt five cards, then the game is over, and she wins.
Otherwise, the player can choose to get another card or stop playing.
Back in Chapter 3, we looked at using conditional logic to run different code based on decisions you want your code to make, given information it already has.
As it turns out, there’s an additional option for making more than a single decision at a time. By combining if
and else
statements into a composite statement called else if
, you can check several conditions all inside one statement. Let’s take a look.
For conditional logic statements (like if/else
or do...while
) to work properly, they have to be able to make the right decision based on what they are checking for. To do this, they use a series of comparison and logical operators to help them make the decision. In JavaScript, there are seven different comparison operators and three logical operators, as well as a shorthand operator for the if/else
statement, called the ternary operator. We’ve seen some of these already, but here’s the full list.
Yeah, we’re not quite done yet.
You already have all the pieces in your HTML code for dealing the initial cards, asking for another card, and ending the game. You just haven’t wired them up yet. And don’t forget, you need to call the method to add up the card totals each time you deal a new card.
Frank: Not so fast. We still have to add in the reset feature they asked for. So, once a game is over, the players can start again without reloading the page.
Joe: We also need to make sure that people aren’t getting cards from previous games. We have to be sure we’re removing everything.
Jim: But how do we do that? We have HTML elements that we added dynamically and new items in arrays. We have to clear it all?
Frank: Yes. We’ll have to use slightly different techniques for each, but yes, we have to clear it all.
Joe: I know just the tricks! For jQuery, have a look at the empty
method. For the arrays, there are a few ways, but not all are cross-browser. Let’s see what the best options are.
Remember back in Chapter 2 when we used the jQuery remove
method to eliminate a particular element and all its child elements from the DOM, never to be seen again? That approach is great if you want to remove the parent element. However, if you want to keep the main element around and you just want to empty out its contents, you can use the jQuery empty
method, which—like remove
—requires a selector, but will leave the calling element in place.
Often we find ourselves writing jQuery to avoid having to write multiple lines of JavaScript. Thankfully, there are a few occasions where doing something in JavaScript is as easy as it is in jQuery, and this is one of those times. While the syntax is a little different, the end result is the same and you don’t have to keep track of where you are in the DOM. To truly empty an array in JavaScript, you simply set its length to 0 (zero):
used_cards.length = 0;
Things can’t get much easier than that, right?
Yes, but the order in which you clear stuff is important.
Since we also have to deal the next hand from a restart, we should clear everything first, then deal the new hand. We also have to make another element clickable to call our code.
Update your my_scripts.js file with a new end
function, which gets called by btnStick
, and some other updates to the computational logic in sumCardTotal
. Also, grab the latest my_style.css file here: http://thinkjquery.com/chapter06/end/styles/my_style.css.
Do this!
You’ve got Chapter 6 under your belt and now you’ve added JavaScript objects, arrays, and loops to your toolbox.
Creating standalone and creating a constructor
Using objects and calling the constructor