The Karma Project: Code Less, Teach More

December 20, 2009

Karma version 0.2 Released

Filed under: News — Tags: , , , — bryanwb @ 4:23 pm

We are proud to release Karma version 0.2 today. You can test out the demos here. You need Firefox 3.5 or Google Chrome/Chromium to run the demo. You can download the Karma-2.xo bundle here. We now have a well-documented API and a four part tutorial.

The Karma Project aims to create high-quality open-source educational software using openweb technologies, with special emphasis on the Sugar desktop educational environment. karma.js is a javascript library for manipulating HTML 5 and SVG in any context.

New Features:

Features that didn’t make it into Release 0.2:

  • Internationalization mechanism for inline text
  • new browsing layout (Chakra)

I am particularly proud of the Karma version of “Conozco a Uruguay”. You can try it out online right away.

If you are interested in Karma, the first step is to join our Google Group and to look through our four-part tutorial series.

  1. Introduction to karma.js
  2. Comparing HTML 5 Canvas and SVG
  3. Digging into Inkscape
  4. JavaScript and SVG

OLE Nepal and SugarLabs deserve special thanks for their continued support of the Karma Project.


December 17, 2009

Tutorial IV: The Adventure Continues – JavaScript and SVG

Filed under: News — Tags: , , , , — bryanwb @ 7:08 pm

This article is the fourth in a series of four

  1. Introduction to karma.js
  2. This article,Comparing HTML 5 Canvas and SVG
  3. Digging into Inkscape
  4. This article, JavaScript and SVG

Section II: Writing the HTML . . . 5!

Step 1: It’s all about the !DOCTYPE

It all starts with the doctype, please make sure document starts with the following doctype declaration

<!DOCTYPE html>

DO NOT USE the following


Karma will throw a big fat ugly error message and be otherwise unkind

Step 2: Put the JavaScript in

    <script type="text/javascript" src="../../js/jquery-1.3.2.min.js"></script>
    <script type="text/javascript" src="../../js/karma.js"></script>
    <script type="text/javascript" src="../../js/jquery.svg.js"></script>
    <script type="text/javascript" src="../../js/jquery.svgdom.js"></script>
    <!-- Put your code in lesson.js, please -->
    <script type="text/javascript" src="js/lesson.js"></script>

Step 3: You should <object>

Please use <object> tag to embed your SVG into the HTML

Step 4: Don’t put style information into the document, put it in lesson.css

Please don’t do the following

<div id="badDiv" style="display:inline;font-size:bigger;"> Karma Rulez! </div>

The “Karma Rulez!” part is excusable but please don’t use the
style attribute. It is not only bad practice but it
will totally screw up the as-yet-unwritten internationalization
library mundo.js

Section III: The Presentation Layer with CSS

Good News, you can use the same CSS file for both your html and SVG
To use an external css file in your SVG, you need to link it in just above the first <svg> tag.

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?xml-stylesheet href="../../css/lesson.css" type="text/css"?>
<svg ......

We want to make sure that the text on the map and the spaceship are invisible. Let’s also make the cursor become a pointer when it moves over a capital icon.

.text { display: none; } { cursor: pointer;}
.spaceship { display: none;}

Much of our program logic will be to reveal elements of the map and the spaceship when the user answers correctly.

CSS is a complicated, tricky beast that I can’t begin to explain here. Let’s move onto something easy, like JavaScript!

Section IV: Writing the game logic with JavaScript

Step 1: Meet jQuery, jQuery meet you

jQuery is a fantastic library for interacting with the HTML Document
Object Model or DOM. What is this &^&$$! DOM? The DOM is the
programming interface for HTML in the browser. Working with it
directly is pretty painful but jQuery abstracts it to something that
is actually quite pleasant to work with. We start with jQuery using the following:

        //Once the HTML on this page has fully loaded,
	// run my code here

$(document).ready doesn’t mean that everything is ready. It only means that all the html and <img> elements have finished downloading. It does not mean than any <audio>, <video>, or <svg> elements have finished downloading. This is important as your program will fail if it tries to manipulate any of these elements before they are ready.

Step 2: Tell Karma about your assets and Karma will put them into collections

	var k = Karma({
			  svg :[    
                              {name:'capitals', domId: 'capitals'},
			      {name:'alien', domId: 'alien'},
			      {name:'spaceship', domId: 'spaceship'},
			      {name: 'help', domId: 'helpScreen'},
			      {name:'playAgain', domId:'playAgain'},
			      {name:'helpIcon', domId:'helpIcon'},
			      {name:'quitIcon', domId:'quitIcon'}
			      {name:'correct', file:'correct.ogg'},
			      {name:'incorrect', file:'incorrect.ogg'}

The Karma() method initializes Karma.karma object with assets we pass
to it. During this initialization, the svg array we pass in is
converted to the “collection” object k.svg. You can access any of the values k.svg
using the name you passed in as the key. The ‘name’ property is arbitrary. I use this instead of the filename or domID because those can often be lengthy.

var mySvg = k.svg.helpIcon  //same as <svg id="helpIcon">
var myHeight = k.svg.helpIcon.height;
var myWidth = k.svg.helpIcon.width;

var name = 'playAgain';
var mySvg2 = k.svg[name];  //you can reference different assets programmatically

//You can even loop through the entire collection, but remember a collection
//is an object and not an array
$.each(k.svg, function(mySvg){ mySvg.css('display', 'none');

Accessing these items using the collections has an optional
performance benefit. Every time you use a css selector such as
document.getElementByid(‘someId’) or $(‘#someId’), you run a search
through the entire DOM.

Karma currently supports five different collection types,,
k.canvas, k.svg, and Please note that the prefix ‘k’ is an
arbitratry shortcut to Karma.karma and not by default part of the
global scope.

Karma will also throw errors if any of these assets can’t be
loaded. You will probably find this very helpfulin debugging your
application. Karma() also attaches helper methods and properties.

You do not have to tell Karma about all the images, svg images, and audio files in your application. You only need to tell Karma about the ones you want to helper methods for and to be fully loaded when you call Karma.ready()

Step 2: Get Ready!

Most likely, you won’t want to start our program until all of our assets are ready. $(document).ready only makes sure that the HTML and images have loaded. For this reason, Karma provides Karma.ready(), which blocks your program from running until all the assets you told it about in Karma( ) have fully loaded.

	var k =	Karma({ /* tell Karma about your assets */});
	k.ready(function (){

        //Once the HTML on this page has fully loaded,
	// run my code here

You have to wrap your code in function () { } otherwise it will
execute immediately, without waiting for Karma to be ready().

Step 3: Attach Event Handlers to the capitals on the map

 $.map($('', capRoot), function(elem){
		$(elem, capRoot).bind('click', function(event) {
                        if (isActive){
                        } else {
// $('', capRoot)  is a CSS selector that matches every city icon on the map
// $.map( )  executes the anonymous function on each matching item
// .bind() is a jQuery method that attaches an Event Listener
// isActive is a global variable, when the game is paused, it is false
// When the game is paused rather than removing the event handler, simply set isActive to false

Step 4: Make the alien talk

This is easy, use jQuery’s text() method to change the text

The CSS selector ‘foreignObject #alienQuestion’ matches an element with the id alienQuestion preceded by a foreignObject tag. For some reason it doesn’t work without including foreignObject in the selector. Perhaps this is a quirk having to do with using the foreignObject tag.

 $('foreignObject #alienQuestion', k.svg.alien.root).text('some Text');

Step 5: When user makes correct choice, display text and reveal part of the spaceship

//complex command that splits out a part name from those not yet displayed
var part = parts.splice(0,1)[0];  

//previously display for these items was set to 'none', 'block' makes them visible again
$('#' + part, spaceshipRoot).css('display', 'block');
$('foreignObject #alienQuestion', k.svg.alien.root).text("Correct! " + question.capitalName               
    +  " is the capital of " + question.deptName);
//display the text of State and capital 
$('.text.' + question.dept, capRoot).css('display', "block");

Step 6: Make the spaceship fly away

	    var flyAway = function(){
		var isLaunching = true;
		var startEngines = function(){
		var shipFire1 = $('#shipFire1', spaceshipRoot);
		var shipFire2 = $('#shipFire2', spaceshipRoot);
		var toggle = true;		    
	   //this animation alternates the display of two images
           //to simulate rocket propulsion
	    var toggleFires = function(){			
				shipFire1.css('display', "none");
				shipFire2.css('display', "block");
				shipFire1.css('display', "block");
				shipFire2.css('display', "none");
			    //toggle fires
			    toggle = !toggle;
			    setTimeout(toggleFires, 400);


		var fly =  function(){
			    "complete": function(){ 
				isLaunching = false;

		var blastOff = function(){
		    setTimeout(fly, 2000);				   


Step 7: Dialog Boxes

This part is actually quite easy

A ‘dialog box’ is nothing more than an absolutely positioned <div>

The following code takes a div element that previously hidden and centers it in front of everything else in the screen using the ‘z-index’ property

$('#helpScreen').css({"position": "absolute",
				"width": "420px", "height": "360px",
				'top': '25px', 'left': '20%',
				'z-index' : 20,  'display':'block', "opacity": 1});

For further exploration, I highly recommend reading through the original source code.
I haven’t explained every part of this exercise in detail so please leave me comments with what you don’t understand or think should be explained in greater detail.

Tutorial III: Digging into Inkscape

Filed under: News — Tags: , , , , — bryanwb @ 5:10 pm

This article is the third in a series of four

  1. Introduction to karma.js
  2. Comparing HTML 5 Canvas and SVG
  3. This article, Digging into Inkscape
  4. JavaScript and SVG

In the previous two tutorials I introduced you to the karma.js library and to working with HTML 5 <canvas> and <svg>. In this tutorial, I will walk you through creating a geography lesson from scratch using Inkscape. Tutorial #4 will cover manipulating our SVG graphics using JavaScript

This lesson will teach how user the location of the different
states of the country Uruguay.

I confess, I did not create this lesson from scratch. The excellent original “Conozco a Uruguay” (I know Uruguay) was created by Gabriel Eirea and his friends at CeibalJam!, a grassroots organization developing educational software for Uruguay’s nationwide OLPC
implementation. The original version of Conozco a Uruguay was written entirely in Python, using the excellent pygame library, a python wrapper around the animation library SDL. Why rewrite it using HTML5 and JavaScript? The reasoning is simple. CeibalJam! spends a lot of its time teaching Uruguayan volunteers how to write educational software using Python. At the same time, there are a large number of web developers in Uruguay who could start developing with Karma with only minimal training. This situtation holds true for Nepal as well. We spend a lot of our time teaching developers how to program in flash when there are lots of local developers who already know HTML and JavaScript.

The Plot

A poor alien has crash-landed on earth. The pieces of his spaceship have scattered across Uruguay. The user must help him locate the correct state where individual pieces are located. Once all the parts are found, the friendly alien can fly home.

Before we go any further please play the game at least once. You can browse all the source code for this example here.

How we are going to do it

We will have three main graphical elements, a political map of Uruguay, a spaceship, and an alien that asks the user questions. We will use SVG images for all three. The main action through out this application will be alternately showing and hiding text that happens to be superimposed on graphical images. SVG particularly shines in
this use case.

Section 1: Digging into Inkscape

In creating the Karma version of Conozco, I cheated. I didn’t create all the graphics from hand. In fact I didn’t draw a single one of them. I converted the original .png images to .svg using inkscape’s Trace Bitmap feature. I added a few images such as the help and exit icons. Those are GNOME icons that I copied.

You may find this section frustrating if you have never used inkscape before. I highly recommend you run throught the Inkscape Basic tutorial. You can find it through the Help menu in inkscape. Help > Tutorials > Inkscape:Basic

Step 1: Convert the map

File > Import
Choose the image in folder tutorial3/mapStates.png

Path > Trace Bitmap

Select Edge Detection and then click OK

Tracing the Bitmap

Tracing out the map

The Trace Bitmap dialog doesn’t close automatically so just click the X in the upper right corner.

Now click on your image and drag it to the right. You have two maps! The one on top is the SVG version. The one below is the old png. Delete the one below it.

maps superimposed

The one below is png and the one on top SVG

You may find that the white rectangle does not line up with your map. You can fix this with File > Document Properties then click the button “Fit Page to Selection.”

fit page to selection

Fit the page to the map

Step 2: Create the Capitals and the States

The great thing about SVG is that you don’t have to remember any x,y coordinates. Just put something on the map, set the element ID, and you can always access it later using a CSS selector statement.

Let’s create the marker for the state capitals

Click the button with the circle icon in the left vertical tool bar, then create a little circle

Next, right click on your circle and choose the option “Fill and Stroke”

At the fill tab, set all values to 255, to fill the circle with white

Set the color for the fill

Then go to the “Stroke paint” tab, make the R, G, and B values 0, 0, 0

Set the color for the Stroke/Outline

Now drag your little capital into place on the map.

Drag onto map

Click the “Text” icon on the left vertical toolbar. We are going to create two <text> fields, one for the state and one for the state capital. Make sure the font size isn’t too big for the area you highlighted

Create the text elements

Step 3: Add element ids and class names to the states and capital cities

Click on the icon you created for the capital, then click on the icon “Edit XML Tree” in the upper menu bar.

Edit the XML Tree manually

Highlight the “id” attribute in the upper right box. Then type in a new id in the bottom blank area. MAKE SURE YOU CLICK SET otherwise your change will not stick.

Set the id to “cap” + yourCapitalName

Set the element id

Now we are going to create a new attribute “class”

Go to the box where there currently is id and type “class” in its place. For the value, type in:

capital city yourCapitalName yourStateName

make sure you click SET!

Type in class names

Repeat the above for your capital icons

Set the id’s for all the capital text areas with “text” + CapitalName
and the id’s for the States with “textDept” + YourStateName. Using
these prefixes and camelCase consistently will save your tuckus later.

For each state text area, add the following class names

text dept yourStateName yourCapitalName

For each capital text area, add the following class names

text capital yourCapitalName

You may notice that I use “dept” frequently. That is because Uruguay calls their states “departamentos.” It was easier for me to continue using their convention rather than using “state.”

I can’t overstate the importance of setting the id and class properties correctly and to do it consistently.

Using these properties I can do operations such as the following

//hide all text on the map
$('.text', k.svg.capitals.root).css('display', 'none');

//show the text only for yourState and yourCapital
$('.text.yourStateName', k.svg.capitals.root).css('display', 'block');

Wow! Them css selectors aRrrre powerful stuff!

Step 4: Put it into the directory assets/svg

If you haven’t created a project folder yet, now is a good time. Here is a good template


Step 5: Convert the alien

File > Import choose alien.png

Path > Trace Bitmap…

Go to the area “Multiple Scans: create groups of paths” and select the option “Colors”

Next Click OK.

Trace the Colors

Delete the image underneath as you did before.

Delete the Image Below

Step 6: Create the Word Bubble

Click the button “Create Rectangles and Squares” and drag out a nice big rectangle

Create the Word Bubble

Give the rectangle nice rounded corners, set the values in the Rx and Ry boxes to 50

Round the corners

If you can’t see the Rx and Ry boxes, click the “Create Rectangles and Square” box again

Click on Text in the left vertical icon bar and type some text in the word bubble area. Make text area as big as the word bubble.

Create the Text Area

Go to File > Document Properties and click “Fit Page to Selection”

Fit the page to your image

Save your SVG as alien.svg and close Inkscape

Step 7: Text Don’T Wrap in SVG! A Beautiful Hack

In previous, tutorial I explained that inkscape does not support word wrapping in <text> elements. Let’s put into practice the hack I discussed last time.

Open up alien.svg in a text editor

Go to the portion of your file with the text in it. If it is
surrounded with <flowPara> tag, it should be fine. Leave it as
it is. If it is in a <text> element, delete the entire <text> element and replace it with the following:


Step 8: Convert the spaceship

There may be a much easier way to do this. If you know of one, please leave a comment.
Import ship.png

Path > Trace Bitmap

Select Multiple Scan, Grays and click OK

Multiple Scans with Grayscale

Drag out your grayscale version of the rocket

In the left vertical bar, click paint bucket

Select the red color from the lower color bar

Pick a color

dump paint into the left wing in the grayscale image, then drag it away

Paint the Wing

Drag out the wing

repeat for the rest of the space ship to reassemble your ship

Delete the original image and the grayscale

Highlight each individual piece of the ship then choose “Edit the XML tree” and set the id

Set the Id on the left wing

There are other SVG images in the Karma version of Conozco a Uruguay but there is nothing more advanced in them than what we have covered so far. Whatever you do, please put all the your SVG elements into the folder assets/svg/

Next up is manipulating SVG using JavaScript.

Karma Tutorial Part II: Comparing HTML 5 Canvas and SVG

Filed under: News — bryanwb @ 4:40 am

This article is the second in a series of four

  1. Introduction to karma.js
  2. This article,Comparing HTML 5 Canvas and SVG
  3. Digging into Inkscape
  4. JavaScript and SVG

In “Introduction to karma.js” I gave an overview of how the library works. In this article, I want to give an overview of the relative merits of HTML 5 <canvas> and SVG in the context of creating your application. In the next article, I will walk you through the creation of a geography lesson using karma.js. You will need google chrome or Firefox > 3.5 and the following libraries:

  • karma.js
  • jquery-1.3.2.js
  • jquery.svg.js
  • jquery.svgdom.js

You can grab them all here

This tutorial will require a basic understanding of css selectors, jQuery, and the SVG editing application inkscape. karma.js works fine without jQuery but this tutorial makes relies on both jQuery and the jQuery plugin jQuery SVG. If you use chromium, make sure you have web-inspector installed. If you are a Firefoxer, you will need Firebug.

Your Weapons, <audio>, <video>, <canvas>, and <svg>

The success of the Karma Project is contingent upon the good browser support for HTML 5 and SVG. We have seen amazing advances in web technology over the course of the last 12 months, so Karma’s prospects look good! Using SVG for web applications is not well-established, in part because SVG is very complicated specification and in part because until recently SVG has gotten very little love from the Browser vendors.

Twilight SVG: The Standard that Came Back from the Dead

SVG’s stagnation changed in a big way when Google put serious development resources behind it. One of those resources is Brad Neuberg, whom they hired in spring 2009 to evangelize for SVG and other web technologies. There is now a lot of momentum behind SVG.

HTML 5 <canvas> has a nice, simple API and it is fast. Fellow uber-nerds should be excited by the nascent WebGL specification and upcoming GPU acceleration. SVG is quite slow compared to canvas but that shouldn’t be an argument against it. Canvas is faster because it doesn’t have to save its own state. For a number of applications like this tutorial, it would take you much longer to write the same program using straight canvas and would be much harder to maintain. Further, the speed benefits may be negligible in the scope of the larger application. to roughly paraphrase Brad Neuberg, when your graphics need to maintain their state, use SVG. When your graphics don’t need to maintain their own state and are doing performance-sensitive operations, use canvas.

I particularly like the workflows that SVG enables. With SVG, you can first create your images in inkscape, then embed them in your document, then manipulate the image with your code. With canvas, you have to manually write the code to draw the image entirely with javascript code and then frequently redraw large portions of it.

Let’s walk through drawing a circle and then moving it horizontally across the screen using <canvas> and then SVG

<canvas> Example

View the Example

1. Create the element in your html, make sure you set the width and height in your markup. Your image will become incredibly distorted if you try to set the dimensions using css. I can’t remember exactly why.

<canvas id="myCanvas" width="800px" height="600px"></canvas>

2. Tell Karma about it

var k = Karma({ 
                            canvas : [ 
                                       { name : "myCircle", domId: "myCircle" }


			var MAX_X = 600;
			var myX = 30;		

	    var timerId = setInterval(function() {
               if (myX < MAX_X){
		   myX = myX + 20;  
	       } else {
                   //stop the animation
               }, 100);

View the Full Example

Please note that the above example uses the Karma API heavily, which is just wraps around the HTML 5 API to save you boatloads of typing.

SVG example

View the Example

1. Draw the circle using inkscape. I precisely choose whatever color I want with having to actually understand hexadecimal color codes.

Drawing a circle in SVG

Creating a circle in Inkscape

2. Give the circle element the id=”svgCircle” by right-clicking on the circle and choosing Object properties

Setting the Element Id in inkscape

Setting the Element Id in inkscape

3. embed in the html using the object tag

 <object id="myCircle" data="assets/svg/circle.svg" type="image/svg+xml" width="800px" height="600px"> </object>

4. Tell Karma about it

var k = Karma({ 
                            svg : [ 
                                       { name : "myCircle", domId: "myCircle" }

5. Move it! Using the translate transformation

$('#svgCircle', k.svg.myCircle.root).animate({svgTransform:'translate(400,0)'}, 5000);

View the Example

What I like about SVG is that it feels very “webby.” That is, I can manipulate the SVG DOM (Document Object Model) much the same way that I can manipulate the HTML DOM. I can also manipulate the presentation using the same css file I use for my HTML.

I must make an important caveat, SVG’s created in inkscape often do not behave in the browser as you expect them to. I suspect this is because heretofore inkscape has been primarily used to create images for non-browser contexts. That said, I believe that the inkscape team are very interested in making inkscape an integral part of the web development toolset.

I had the pleasure of meeting Josh Andler and Jon Cruz from the Inkscape team at last summer’s Google Summer of Code conference. Both were very enthusiastic about better integrating inkscape with the web workflow.


One of the great benefits of using SVG is that you can use the same css file as you do for your HTML document. To use an external css file in your SVG, you need to link it in just above the first <svg> tag.

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?xml-stylesheet href="../../css/lesson.css" type="text/css"?>
<svg ......

When you use the same css file for both your HTML and SVG documents, you need to make sure your element Id’s are unique across all of them. I found it helpful to prefix my svg element Id’s with “svg.” In an application with multiple svg images embedded, I may consider prefixing each SVG element Id with “svg” followed by a short identifier for that particular image, for example “svgAlienQuestion” or “svgShipWing.”

jQuery and SVG

jQuery is a little Javascript library that has taken the webdev world by storm. The jQuery library itself is quite small and almost entirely focuses on DOM manipulation. In this regard it reminds me of the UNIX philosophy “Do one thing and do it well.” jQuery SVG is a plugin that allows you to manipulate SVG documents in much the same way you use jQuery to manipulate the HTML DOM. Pay special attention to the word “document.” Each SVG image embedded in your HTML is a separate document with its own DOM. You need to pass jQuery SVG root element for your target document so that jQuery SVG know which DOM to use.

// In this example you have 3 SVG images embedded in your HTML
// alien, ship, and map. All 3 have been passed to the Karma in the Karma({ svg : [  . . .  block

//To change the text inside the alien SVG
$('#question', k.svg.alien.root).text('Some new Text!');

//To add and event listener to the left wing of the ship
$('#leftWing', k.svg.ship.root).bind('click', function() { ....  

//hide a mountain on the map
$('#mountainEverest','display', 'none');

jQuery SVG makes SVG manipulation very intuitive to those already familiar with jQuery. One drawback to jQuery SVG is that it is not a well-supported tool. Author Keith Wood has done us all a tremendous favor by writing but as yet there isn’t a larger support community around it. I myself patched the .css() method just last weekend to work on Firefox > 3.5 and Chromium. I did not thoroughly test it and I highly doubt that the .css() method will work on Internet Explorer. SVG lovers, if you really want to see SVG adoption take off, I can’t recommend a better place to put your efforts than jQuery SVG.

You can get my patched version of jQuery SVG here and the original at Keith Wood’s site.

The Vampire’s Dilemma
Since SVG is a Vampire Specification, only recently back from the dead, documentation and examples in the HTML context are relatively scarce. Frequently, the most complete documents are the API specifications from the W3C. It is both frustrating and bewildering to work from the W3C specs as you never quite know if X browser has implemented that spec and to what degree of fidelity.

I have also found a lot more browser bugs and inconsistencies using SVG as compared to <canvas>. One glaring bug/feature, depending on how you look at it, is that chromium will not load an SVG document if its display property is set to ‘none’. Firefox will load an SVG with its display set to ‘none’. It took me a number of hours to figure out this inconsistency as it isn’t documented anywhere that I could find. No, I haven’t filed a bug on this yet but I seriously intend to. I swear on my dead pet hamster’s grave.

There is also a well-known glaring gap in the SVG 1.1 API. SVG’s <text> element does not support line wrapping for text. You have break your text manually into <textspan> elements in order to keep it from overflowing bounds of your <text> element. Luckily, there is a clever hack to get around this problem.
Thanks to Mark Finkle for this fix.

         style="font-size:20px">Some Old Text</xhtml:div>

To change out the text in the above block, I simply use a css selector and jQuery’s text() method:

 $('foreignObject #alienQuestion', k.svg.alien.root).text("Some New Text!");

That may look like a lot of boilerplate text but consider the alternative. Using <canvas> you would have have to redraw the entire canvas area in order to change text embedded in your drawing. That is a considerable waste of computational resources.

That’s it for this installment, stay tuned for Part III, where I will walk you through the creation of a geography lesson.

For further reading, I highly recommend the following resources:

December 14, 2009

An Introduction to karma.js – Making HTML 5 Easy

Filed under: News — Tags: , , , , — bryanwb @ 10:04 am

This is the first in a series tutorials about karma.js

  1. This article, an Introduction to karma.js
  2. Comparing HTML 5 Canvas and SVG
  3. Digging into Inkscape
  4. JavaScript and SVG

While the Karma Project is a broad initiative to develop education software using openweb technologies, at its core is a relatively simple JavaScript library. The karma.js library has three primary functions

  1. Preload assets such as images, svgs, canvases, audio, and video and do some basic error checking on them
  2. Put those assets into collections where they can easily be referenced
  3. Attach helper methods to the individual references.

What Karma Doesn’t Yet Do

  1. It doesn’t provide animation functions. The current mix of Karma lessons use a hodge-podge of HTML 5 canvas, Raphael.js, and jQuery SVG to provide animation. Raphael.js is perhaps the most fully-featured and most robust of these three methods. I personally find that jQuery SVG is the least mature but the easiest to use. We may later promote a particular tool as the default for animation.
  2. Doesn’t fully support internationalization. You can use the _() GNU gettext function with karma lessons but there is currently no open-source mechanism for internationalizing the strings embedded in html markup. GNU gettext only supports localization of strings in application code. The main goal for version 0.3 of karma.js will be support for localizing inline text.
  3. It doesn’t support video yet

What Karma isn’t

Karma’s name is not a religious reference but to the first two syllables of Rabi Karmacharya’s last name. The logo for Karma means “om” or “everything” in Sanskrit. It is in not the character for karma. I made the logo “om” after Om Prakash Yadav, the amazing graphic designer/artist/manager at OLE Nepal. I

First Things First

Your first step in using karma.js is to make sure you set your document type to HTML 5. karma.js will throw a big fat error if you try to use your good ‘ol html 4.01 or XML declaration.

<!DOCTYPE html>

That’s it! Who would have thought migrating to HTML 5 would be so painless?

Next, include the karma.js file, which you can get here . Also, you should put in a link to your application code. Let’s say for the sake of this article you put your application code in js/lesson.js though karma.js does not require you to use that convention.

 <script type="text/javascript" src="js/karma.js"></script>
<!-- Your application code in lesson.js -->
 <script type="text/javascript" src="js/lesson.js"></script>

While we are at it, let’s add in a css file called lesson.css. Again, karma doesn’t require you to use that convention. In the future, our team here in Nepal will probably put the lesson specific styles in lesson.css and styles for all the lessons we use in Nepal in nepal.css. Iran, Bolivia, Equatorial Guinea, etc. may want to do the same.

    <link rel="stylesheet" type="text/css" href="css/lesson.css" />

Initializing Karma

karma.js only adds the value “Karma” to the global namespace. All of the Karma library lives within the Karma namespace.

The Karma() function initializes the Karma.karma object and its “collections” of images, audio, svg, videos, and canvases. During this initialization step karma.js creates the collections and does basic error-checking on them. For example, Karma( ) will throw errors for invalid properties passed in to it. In essence, you tell the Karma about the assets you want it to know about and Karma will 1) start loading them and 2) throw errors if there are problems accessing those assets. In the future, the Karma() constructor will support loading different locales and a variety of other options.


 var k = Karma({
	image: [
	    {name: "ball",   file: "ball37px.png"},
	    {name: "balloon", file: "balloon37px.png"},
	    {name: "banana", file: "banana37px.png"},
	    {name: "chilli", file: "chilli.png"},
	    {name: "fish"  , file: "fish64px.png"},
	    {name: "flower", file: "flower37px.png"},
	    {name: "normalChimp", file: "normalChimp_120x125.png"},
	    {name: "happyChimp", file: "happyChimp_120x125.png"},
	    {name: "sadChimp", file: "sadChimp_120x125.png"}],
	audio: [
	    {name: "correct",  file: "correct.ogg"},
	    {name: "incorrect", file: "incorrect.ogg"},
	    {name: "trigger", file: "trigger.ogg"}
         svg :[    
                              {name:'capitals', domId: 'capitals'},
			      {name:'alien', domId: 'alien'},
			      {name:'spaceship', domId: 'spaceship'},
			      {name: 'help', domId: 'helpScreen'},
			      {name:'playAgain', domId:'playAgain'},
			      {name:'helpIcon', domId:'helpIcon'},
			      {name:'quitIcon', domId:'quitIcon'}
         canvas: [
			      {name:"topLt", domId:"topLtCanvas"},
			      {name:"topRt", domId:"topRtCanvas"},
			      {name:"bottomLt", domId:"bottomLtCanvas"},
			      {name:"bottomMd", domId:"bottomMdCanvas"},
			      {name:"bottomRt", domId:"bottomRtCanvas"},
			      {name:"timer", domId:"timerCanvas"},
			      {name:"scorebox", domId:"scoreboxCanvas"},
			      {name:"chimp", domId:"chimpCanvas"}

I include both svg and canvases in this example but in a real application you would likely only use one or the other.

Notice that every asset has the “name” property. You define the name property. It is not tied to any actual characteristic of the asset. Its purpose is to give you a short, easy identifier for the asset. DOM and file ID’s are frequently long, descriptive, and painful to type repeatedly.

You access the asset from each collection like so:

k.image.ball,, k.svg.alien

You can also iterate through the collections using jQuery’s $.each function. You cannot use JavaScript’s map, forEach, and filter methods because each collection is an object, not an array.

$.each(, function(audio) {;});

The Karma() function attaches helper functions specific to each asset type. The helper functions support function chaining. Here are a few examples. For details please see the API documentation. I have not yet done a good job of documenting the helper methods for or k.canvas;
k.svg.capitals.getElementById('capitalMontevideo').setProperty('display', 'none');
k.canvas.scorebox.clear().drawImage(, x, y).strokeStyle('#000000').fillStroke(); 

As you might have guessed, this can save a lot of typing. I intend to rapidly add helper functions as I work more with karma.js

I have added helper functions for almost the entire HTML 5 canvas API but not yet documented it.

How does Karma locate your assets?

Well the location of some of these assets will be specified inside your html but others may not be, particularly audio and video. karma.js requires you to put your assets in the following directory structure:


If your image chilli.png is in pictures/ instead of assets/image/ , Karma will throw an error. However, this is only true for the assets you tell Karma about in the Karma() constructor. You can locate images that are not passed in to Karma anywhere that you want

Get Ready

Before you proceed with your application, you need to wrap your application code with Karma.ready() much like you would with jQuery’s $(document).ready(function () { …});

// lesson.js
Karma.ready( function () {
      // your code here

Karma.ready blocks your program from running until all the assets you passed to the Karma() constructor are fully loaded.

If you are using jQuery, simply wrap your the Karma.ready() within your $(document).ready

// lesson.js
$(document).ready(function () {
    var k = Karma ( { /* your assets */ });
    k.ready( function () {
         // your code here

So that is karma.js in a nutshell. Very soon I hope to have a extended tutorial that walks you through an example lesson. If you are curious about the internals of karma.js please checkout the code, run the tests, and play with the demos.

Blog at