Posts Tagged Tutorial
Jumping Into Javascript – Objects and Loops
Posted by Nick Zarczynski in Javascript, Programming on 2011/03/27
In the last post I used an array to model a rectangle. This worked for a quick test, however the rectangle is probably best modeled as an object. Especially considering that the rectangle is only part of a candlestick bar that also must include a wick, or line. In this part we’ll turn the rect into an object, then move on to creating a bunch of them and moving them all at the same time using a loop.
The first thing we’ll do is convert rect to be an object. Objects in Javascript are different than objects in many other languages. In many languages objects are class based, the object system in Javascript is prototype based. Very quickly what that means is that, in a class based object system, there is the abstract definition of an object (the class definition) and there are instances of objects defined by the class. In a prototype based system there is no distinction between the two.
In many practical ways these two systems are very similar, however there are some differences that may trip you up. I encourage you to read more about the differences and similarities. Unfortunately I can’t go much more in-depth than that here.
var chart = document.getElementById("chart");
var c = chart.getContext("2d");
chart.onclick = moveRect;
function drawRect() {
c.fillRect(rect.x,rect.y,rect.width,rect.height);
}
function moveRect() {
c.clearRect(0, 0, chart.width, chart.height);
rect.x += 20;
drawRect();
}
function Rect(x, y, width, height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
var rect = new Rect(10, 25, 20, 50);
drawRect(rect)
As you can see we simply use a function to construct a Rect object. The this keyword is similar to self in Python and signifies that the variable is an attribute of the object. To create a new object we have to use the new keyword, this can be seen in the line: var rect = new Rect(10, 25, 20, 50);.
Other than these few modifications, nothing else has changed. rect is still used as a global variable and the functions drawRect and moveRect operate directly on rect. The next thing we’ll do is create a global array where we can store a number of Rects. This will require changing almost everything, however most changes will be minor.
var chart = document.getElementById("chart");
var c = chart.getContext("2d");
chart.onclick = moveRects;
function drawRects() {
for (var i in rects) {
var r = rects[i];
c.fillRect(r.x, r.y, r.width, r.height);
}
}
function moveRects() {
for (var i in rects) {
rects[i].x += 20;
}
c.clearRect(0, 0, chart.width, chart.height);
drawRects();
}
function Rect(x, y, width, height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
var rects = [new Rect(10, 25, 20, 50), new Rect(40, 25, 20, 50)];
drawRects();
Make sure that you use the new keyword when you create new objects, even when they are in an array. I spent at least 10 minutes trying to figure out what I was doing wrong in the for loop, just to realize that I did not use the new keyword when I initialized the array!
Also I noticed that, at least some, Javascript implementations are very forgiving regarding errors. Until now I’ve been passing rect as an argument to drawRect in the moveRect function. The drawRect function does not expect any arguments, yet I am allowed to give it one without complaint. I can see this “feature” being problematic down the road, however I can also see that it might be necessary with all the different non-conforming implementations out there. I have since gone back and fixed this in previous posts.
Since we’ve already covered objects and arrays, the only thing new here is the for loop. There are two methods of invoking the for loop in Javascript. The one that I used above is…
for (var i in sequence) {
// body;
// use sequence[i] to access elements
}
One thing to note with this method is that i is not bound to the nth element in sequence, rather i is simply a counter. This method is basically a shorthand for the next method which is more similar to C syntax…
for (var i = 0; i > sequence.length; i++) {
// body;
// use sequence[i] to access elements
}
This is the standard for loop syntax available in many languages. No matter which method you use you must still use sequence[i] to access the elements. The (var i in sequence) syntax does not act like Python’s for i in sequence.
The next post will explore downloading and manipulating stock data. However I have run into a small problem that I haven’t been able to solve in <30 minutes of searching. It seems that the same origin policy will prevent me from downloading historical data from Google Finance. From what I’m reading I need to find a source of historical quotes that offers the data in JSONP (or CORS) which will allow cross domain access. While I can understand the security implications of allowing arbitrary cross-domain access, this part of the app (which was trivial in Python) is a real pain in Javascript.
GOTO Part 4 – Same Origin Policy, JSONP, XMLHttpRequest, and Cheating with jQuery
Links
Jumping Into Javascript – Moving Objects on the Canvas
Posted by Nick Zarczynski in Javascript, Programming on 2011/03/26
In the first part of Jumping Into Javascript, we created a simple html page with a canvas element on it and drew a single square. In this part we will concentrate on moving objects that we have drawn.
The concept of moving an object on the canvas is a bit of a misnomer. We actually won’t move anything at all, instead we must clear the canvas (or part of it) and repaint the object in a new location. Let’s look at the simplest code I could come up with that accomplishes this.
chart.js
var chart = document.getElementById("chart");
var c = chart.getContext("2d");
c.fillRect(10, 25, 20, 50);
c.clearRect(0, 0, chart.width, chart.height);
c.fillRect(30, 25, 20, 50);
This code starts by drawing a rectangle, then c.clearRect(0, 0, chart.width, chart.height) clears the canvas, then it draws another rectangle 20 pixels over to the right. If you run this code, you probably won’t see anything but the final rectangle. This is because it is running very fast. To see it we need to slow things down a bit.
There are a number of ways we could achieve this. We could set an event loop and move the rectangle on each loop, or we could set a timer between draws. However I’m going to use an event handler to call a function that clears the canvas and redraws the rectangle.
chart.js
var chart = document.getElementById("chart");
var c = chart.getContext("2d");
c.fillRect(10, 25, 20, 50);
chart.onclick = moveRect;
function moveRect() {
c.clearRect(0, 0, chart.width, chart.height);
c.fillRect(30, 25, 20, 50);
}
When you click on the canvas you will see the rectangle “move” a bit to the right. This illustrates a few things about Javascript that I haven’t covered. First moveRect is an example of how functions are defined in Javascript. You can also define functions like this…
var moveRect = function() { //body; }
… see here for an explanation of the difference. This little snippet also hints to us that functions are first-class values in Javascript, but I won’t get into that now.
Also this demonstrates one of the ways to set an event handler. This sets the function moveRect to be called whenever the canvas is left clicked. This method of event handling will work with any modern browser.
Another way to accomplish event handling is to use the inline method. This is the oldest way to set handlers in Javascript. If you have to maintain compatibility with very old browsers you will be forced to use this method. Here’s a link to more info on the inline method and an example…
<canvas id="chart" onclick="moveRect();"></canvas>
So far we’ve got our rectangle to “move” once when the canvas is clicked on. However it will not move any further, no matter how many clicks occur. The reason for this is that we are not incrementing the x position of the rectangle, rather the new position is hardcoded into the moveRect function.
Even though we see a rectangle on the screen, in our source code there is really no notion of the rectangle as a separate entity. There are a variety of options to fix this behavior, we could code the rectangle as an object, or use a closure, or even use 4 different variables to hold the position and size of our rectangle. I’ll be covering some of those options later, but for now I want to focus on arrays.
Temporarily I’ll use an array to hold the values of the rectangle and a variable to hold the array. I’ll call it rect for now. Because the fillRect function does not accept an array as a parameter, we’ll need to define a function drawRect that will call fillRect with the correct values. To keep things simple, I’ll use rect as a global variable.
var chart = document.getElementById("chart");
var c = chart.getContext("2d");
chart.onclick = moveRect;
function drawRect() {
c.fillRect(rect[0],rect[1],rect[2],rect[3]);
}
function moveRect() {
c.clearRect(0, 0, chart.width, chart.height);
rect[0] += 20;
drawRect();
}
var rect = [10, 25, 20, 50];
drawRect()
When you run this code you’ll notice that the rectangle keeps moving to the right every time you click the canvas. This is exactly the behavior we were looking for here.
Once again there are a few new concepts here. var rect = [10, 25, 20, 50]; creates an array and assigns it to the variable rect. You do not have to specify the number of elements in the array and it is also resizable. Indexing into an array is similar to most Algol inspired languages using varName[n] to access the nth element of an array stored in varName. += also works as expected and destructively increments the value of the index n by the value of the right hand expression. This code also gives you a quick peek at the scoping rules used in Javascript, however a through overview will have to wait for a later article.
That quick overview concludes this post on moving objects on a canvas and arrays. In the next post I’ll probably cover objects and loops and create more rectangles to move about.
GOTO – Part 3 – Objects and Loops
Links
Jumping Into Javascript
Posted by Nick Zarczynski in Javascript, Programming on 2011/03/26
A few weeks ago I decided to post my first question to stackoverflow…
How does a self-taught programmer know when he’s ready to look for a job?
The responses I got were very encouraging, but one in particular pointed out some shortcomings in my education. To paraphrase, it instructed me to look around at job offerings and compare the skill set employer’s are looking for to my own. This was a bit disheartening to me as I’ve been focusing mainly on theory and AI and found that my skills are not all that marketable in an environment that is dominated by web and database programming.
This endeavor is an attempt to remedy that problem, or at least demonstrate to future employers and myself, that I can pick up these technologies relatively quickly. When I learn a new technology/language/framework I usually prefer to start with a project that can be done simply but can also scale up, rather than simply following along with a tutorial or book.
For this purpose I will be writing a Javascript version of pyTrade, which will not be a port, but a complete rewrite to allow me to understand the language better. It wasn’t too long ago that I wrote pyTrade, so a lot of it is still fresh in my mind, however it’s been long enough that at least some of the details escape me and I will do my best not to look at the source code.
I’ll be writing this in tutorial fashion to help reinforce the concepts that I’ll be learning and to let others follow along if they wish. This will not be a beginner’s introduction to Javascript. I’m assuming that the reader is intimately familiar with at least one Algol inspired language. My background is mainly Python and Scheme with a little C, so you may see Javascript idioms compared against their counterparts in these languages.
Since I don’t want to constantly refer to this project as “this project”, for now it will be codenamed JamochaTrade. Maybe I just didn’t think hard enough, but I couldn’t come up with a short prefix that didn’t make it sound like this was implemented in Java. Not that JamochaTrade satisfies that criteria, but I like it as a codename.
First Step to JamochaTrade
As I said earlier, I’m going to start out with the simplest thing I can and work up from there. The simplest thing I can think of to start with is the html shell page that will allow people to access JamochaTrade. Without further ado here’s the shell…
index.html
<html>
<head>
<title>JamochaTrade - A Javascript stock charting program.</title>
<style>
body {text-align: center;}
canvas {border: 1px solid #000;}
</style>
</head>
<body>
<canvas id="chart"></canvas>
<script src="chart.js"></script>
</body>
</html>
I’ve saved this code in a file named “index.html” and also created a blank file named “chart.js” where the Javascript will eventually reside. This code doesn’t do much and I think it’s relatively self-explanatory so I won’t go over it, except to say the important part of this shell is that we create a canvas and give it the id of chart.
Now that we have a canvas, my first goal is to draw something on it. Since my preferred charting style is the candlestick chart, I’ll start by figuring out how to draw a box on the canvas. To do this we need to do 3 things in our chart.js file, first we need to get the reference to the canvas from the dom, then we need to get the context from the canvas and finally we need to draw a box.
What is a context? The simplest way to think about a context is as an API. A context provides methods of drawing on the canvas, different contexts provide different methods of drawing. That’s the best explanation I have at the moment, I’ll probably explain it more throughly later.
Currently there is only one universally supported context for the canvas, which is the “2d” context. At some point in the future there will also be a “3d” context that will allow 3d graphics to be displayed in the browser. Since that only exists in a few vendor-specific instances right now I’ll ignore that from here on out.
chart.js
var chart = document.getElementById("chart");
var c = chart.getContext("2d");
c.fillRect(10, 25, 20, 50);
The first line above simply gets the chart object from the dom tree. The second line sets the chart’s 2d context to the variable c. I chose c because it is short and we will be using it in many of our drawing calls, also it can be thought of as short for context, canvas and chart which works out pretty well if I do say so myself.
Finally we draw our first object onto the canvas. The fillRect procedure is used to do the actual drawing. There’s two common way’s I’ve come across drawing rectangles in GUI programs, the first is to specify the x and y starting point of one corner of the rectangle and the x and y point of the opposite side (Left/Top/Right/Bottom). The other way, and the way the 2d context in Javascript works, is to specify the x and y starting position and then the length of the rectangle along the x axis and the y axis (X/Y/Width/Height).
The easiest way to test which coordinate system is being used is to give large numbers for the first 2 parameters and small negative numbers for the next 2 parameters, like (100, 100, -10, -10). If the resulting rectangle fills the entire top left corner you are using the (Left/Top/Right/Bottom) coordinate system, if the rectangle is small and off of the edge you are using the (X/Y/Width/Height) coordinate system.
With that lengthy discussion out of the way the first Jumping Into Javascript post has reached its conclusion. The next post will cover moving the rectangle as well as a brief overview of arrays.
GOTO – Part 2 – Moving Objects on the Canvas
Links
WhatWG Canvas Standard/Reference