Some really cool tips on using Chrome's developer tools are shown on this video:
Monday, February 28, 2011
HW6 Graded and my Solution
I have just emailed the grades for HW 6. People seem to be having trouble with creating closures. Below is my solution to the this homework. Notice how the makeDisperse
function creates other functions (closures), each of which with possibly different 'neighbors' depending on the arguments passed to makeDisperse
.
//Returns a list of the 4 elements that are North, South, East and West of the // button with id= 'b' + row + col function getNeighbors (row, col) { var result = []; var nrow = (row == 0) ? SIZE - 1 : row - 1; var ncol = col; result.push(document.getElementById('b'+ nrow + ncol)); nrow = row ncol = (col + 1) % SIZE; result.push(document.getElementById('b' + nrow + ncol)); nrow = (row + 1) % SIZE; ncol = col; result.push(document.getElementById('b' + nrow + ncol)); nrow = row; ncol = (col == 0) ? SIZE - 1 : col -1; result.push(document.getElementById('b' + nrow + ncol)); return result; } //Creates and returns an event handler which is a closure that holds // 'neighbors', a list of the 4 elements that are North, S, E, West of the // button at row,col. The function it returns distributes the value of this // over the 4 neighbors. function makeDisperse(row, col){ var neighbors = getNeighbors(row,col); function disperse () { var myNumber = Number(this.value); while (myNumber > 0){ for (var i =0; i < neighbors.length; i++){ var nelement = neighbors[i]; nelement.value = Number(nelement.value) + 1; myNumber--; if (myNumber <= 0 ) { break;} } } this.value = 0; updateScore(); }; return disperse; } //This method on <body onload="setup()". It sets an event-handler for every button. function setup(){ for (var row =0; row < SIZE; row++){ for (var col=0; col < SIZE; col++){ var button = document.getElementById('b' + row + col); button.onclick = makeDisperse(row,col); } } } //Updates the value of the score button to be the count of all the zeros in all the buttons. function updateScore(){ var total = 0; for (var row =0; row < SIZE; row++){ for (var col=0; col < SIZE; col++){ var button = document.getElementById('b' + row + col); if ('0' == button.value) { total++; } } } var scoreButton = document.getElementById('score'); score.value = total; }
People do a lot of JavaScript programming without understanding closures. Still, they are a really useful and powerful feature of the language: used for creating private variables, custom functions (as above), and namespaces, among other uses. I think you will be a much better developer if you understand and use them as needed.
HW7: A JavaScript Math Quiz App
For this homework you will build a stand-alone math quiz/drill program. If you have ever visited the Khan Academy you will see that, in addition to all the cool videos, Kahn also has a webapp for practicing math. For this homework you will build JavaScript application that asks the user simple math questions, and provides him with feedback on his progress. Note that this will be a stand-alone application, independent of the survey webapp we have been developing (for now?). You will be using jQuery for this and jQueryUI if you want.
There are a few things that we know, from educational and video game research, about how to build these types of apps.
- Students should be given immediate feedback. So, you should immediately tell the user if his answer is right or wrong, and give him the correct answer.
- Achievements (badges, medals, etc.) keep them hooked. So, we are going to have a lot of them.
- You can never have too much eye candy.
- When loading the page the user is asked whether we wants to practice addition, subtraction, or multiplication.
- In this game the user is asked one question at a time. They all consist of a problem using the digits 0 to 9. For example: 4 + 2 = __. The user answers the question by typing in the number and hitting enter.
- Rather than generating numbers from a flat random probability, which generates too many 0,1, and 5s, pick them randomly from this list:
[0,1,2,2,2,2,2,3,3,3,3,3,4,4,4,4,4,5,5,6,6,6,6,6,7,7,7,7,7,8,8,8,8,8,9,9,9,9,9]
. - Do not ask subtraction questions for which the answer is a negative number.
- If the answer is wrong, the program tells the user he was wrong and tells him the right answer. If we was right the program tells him. In both cases the user is immediately presented with the next question.
- The app show the latest 2 questions and their answer. You should show both the answer the user gave and the correct answer, if different. Correct answers should look different than wrong answers (different color, strikethru, etc.). Below these (or above) we see the current question. When a new question appears it should smoothly scroll the oldest question off. The is no scroll bar, this is an automatic scrolling.
- There is a clock that countdowns the 10 seconds the user has to answer the question. If the user does not answer within the 10 seconds then the answer is considered wrong, the right answer is shown and a new question appears.
- There is a bar that keeps track of the number of consecutive correct answers.
- There are achievements that appear, and fade away slowly, for different events:
- when the user gets 10, 20, 30,....consecutive correct answers.
- when the user correctly answers 10 questions in less than 20 seconds total, 20 in less than 40 seconds, and so on. Basically, he is averaging less than 2 secs per answer (that might be too hard, feel free to change the exact time to what you think is a good number).
- when the user has had a total of 10 correct (not necessarily consecutive) answers, 20, 30, and so on
- Each one of the 3 type of achievements above should appear with a different animation. Try to be creative. Use jQueryUI if you want, or even a jQuery sound plugin, if you want (not required). Remember, you cannot have too much eye candy when giving out achievements.
This homework is due on Monday, March 14 @11am, you can turn it in here.
Required Reading
Friday, February 25, 2011
How Not to do onclick
Check out the following code, which is live in this page.
<!DOCTYPE html> <html> <body> <input type="button" value="0" id="a" onclick="increase()"/>
<input type="button" value="10" id="b"/> <script> function increase(){ this.value = Number(this.value) + 1; } document.getElementById('b').onclick = increase; </script> </body> </html>
In my chrome and firefox, clicking on the first button does nothing, while clicking on the second one increases the number by 1. If we open up firebug and print out the onclick properties for the two elements, we can see why the first one does not work.
> document.getElementById('a').onclick function onclick(event) { increase() } > document.getElementById('b').onclick function increase(){ this.value = Number(this.value) + 1; }
The first one has a function called onclick
wrapped around the call to increase
. So, in the first case, increase
gets called as a global function which means that this
will be bound to the global object. In the second case increase
is called as a method of the input
element.
Why this distinction? I don't know. What do you need to know? 1) Use the second form for this homework and 2) always use a good javascript library for setting up and handling events; like jQuery, which you will start using next week.
John Resig on jQuery
Below is John Resig, jQuery author, on jQuery. The first part of the video is about JavaScript. You can skip to the 0:30 mark, or so, where he starts to talk about jQuery.
Theory and History of the DOM
Crockford is back, this time discussing the Document Object Model. We will be talking about this, and jQuery, next week.
Wednesday, February 23, 2011
JavaScript: The Good Parts: The Video
Basically, you should think of Crockford as the one teaching CSCE 242 and me as the TA.
JavaScript Closures: Used for Privacy
I mentioned in class how you could use closures to create private variables, just like Java has. The code below shows how this is done. Notice that the only way to get at joe's name is using the given functions. If you wanted to make the name a constant then you could just get rid of setName
and no one would be able to change joe's name. Pretty cool!
//This is how you make an object with private variables. function Employee(){}; function newEmployee(theName) { var name = theName; Employee.prototype.getName = function(){return name;} Employee.prototype.setName = function(n){name = n;} return new Employee(); } //The only way to change joe's name is by calling joe.setName. joe = newEmployee('Joe'); joe.getName(); //get his name joe.setName('bob'); //he is now bob
You don't need the name
variable, we could have just used theName
instead. But, maybe this makes it clearer? I find it a bit more intuitive this way.
Challenge Round: First Group
This Friday we start the challenge rounds. The following students will report to my office at the given times.
- 11:30, Abbot
- 11:40, Boykin
- 11:50, Carroway
- 12:00, Clarke
Monday, February 21, 2011
HW5 Grades Out
I emailed grades earlier. Those of you who did not get it to work, please do so. Let me know if you need help. At worst, I can finish the coding for you (which will be better than you starting over with someone else's code). You will need this code in a couple of weeks when we start putting our JavaScript skills to work on prettying up the webapp.
Lecture Examples
I added some comments to the class example (see the script.js and jspage.html files). I'll be talking more about JavaScript and closures on Wednesday. Next week we will cover DOM manipulation and jQuery.
The example files show a simple way to handle events. However, the recommended way is to use a JavaScript library. Different browsers implement event-handling in different ways (they are converging, but there are a lot of old browsers in use) and there are many good javascript libraries that deal with all this ugliness so we don't have to. We will be using jQuery.
We will be building again on our surveys webapp in future weeks: adding some drag-and-drop editing and AJAX functionality, and graphics, gotta have graphics! Stay tuned.
HW6: JavaScript Practice
This homework is a short stand-alone JavaScript+HTML program that will give you some practice with the JavaScript basics. You will write one HTML page and one JavaScript file that together implement a simple game (well, game-like thing). Specifically:
- You will write an HTML with 100 buttons in a 10 by 10 table. Every button has the number 1 in it.
- When the user clicks a button the number in that button gets distributed among its North, East, South, and West neighbors, with wraparound. For example, if the button has the number 2 button to the North will have its number increased by one, as well as the number to the East. The button that had the 2 will now have 0.
- There is a score button which always contains the number of zeroes in the game board.
- You will use closures for implementing the
onclick
methods. I know that this homework can be done without using closures, but I want you to practice using closures. Specifically, you will write one function that generates a function for each button. - You cannot use any JavaScript libraries. We will be using jQuery in the next homework, but not for this one.
You can turn it in here. The deadline is Monday, February 28 @11am. Also, make you you post it on your appspot.com site. You can just put in in a /test
directory and add that directory as a static_dir in your app.yaml. Make sure you put the url to your published code in the source code you turn in.
Required Reading
- The videos from the previous post.
- The JavaScript Guide.
Here is a quick demo of what it should look like: