From 0aa48d0503c69c9ebc1d2bb209bfbec10e8bed64 Mon Sep 17 00:00:00 2001 From: Bryan Berry Date: Wed, 17 Feb 2010 09:39:34 +0000 Subject: initial commit. Lesson English_Animal_Identification is current template --- (limited to 'docs/symbols/src/js_karma.js.html') diff --git a/docs/symbols/src/js_karma.js.html b/docs/symbols/src/js_karma.js.html new file mode 100755 index 0000000..44a432b --- /dev/null +++ b/docs/symbols/src/js_karma.js.html @@ -0,0 +1,1766 @@ +
  1 /* Documentation Note:
+  2  *   Public methods and properties are commented with /** some text *\/
+  3  *   and private methods and properties are commented with //
+  4  *   
+  5  *   Please leave it that way to keep this documentation sane
+  6  */
+  7 
+  8 
+  9 /*
+ 10 *	Karma Framework
+ 11 *	http://karmaeducation.org
+ 12 *	
+ 13 *	Copyright (c)  2009
+ 14 *	Bryan W Berry		bryan@olenepal.org
+ 15 * 	Felipe López Toledo	zer.subzero@gmail.com
+ 16 *      
+ 17 *	Under MIT License:
+ 18 *	Permission is hereby granted, free of charge, to any person
+ 19 *	obtaining a copy of this software and associated documentation
+ 20 *	files (the "Software"), to deal in the Software without
+ 21 *	restriction, including without limitation the rights to use,
+ 22 *	copy, modify, merge, publish, distribute, sublicense, and/or sell
+ 23 *	copies of the Software, and to permit persons to whom the
+ 24 *	Software is furnished to do so, subject to the following
+ 25 *	conditions:
+ 26 *	
+ 27 *	The above copyright notice and this permission notice shall be
+ 28 *	included in all copies or substantial portions of the Software.	
+ 29 * 
+ 30 *	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ 31 *	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ 32 *	OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ 33 *	NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ 34 *	HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ 35 *	WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ 36 *	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ 37 *	OTHER DEALINGS IN THE SOFTWARE.
+ 38 */
+ 39 
+ 40 /**
+ 41 * @fileOverview Contains karma library
+ 42 * @author Bryan Berry <bryan@olenepal.org> 
+ 43 * @author Felipe Lopez Toledo <zer.subzero@gmail.com>
+ 44 */
+ 45 
+ 46 
+ 47 //common.js modules use exports object
+ 48 if(!this.exports) {
+ 49     exports = {};
+ 50 }
+ 51 
+ 52 
+ 53 
+ 54 /** Karma is the namespace for the Karma library and Karma() is the constructor 
+ 55  * function for the Karma library object Karma. 
+ 56  * Karma() checks if the current document type is set to HTML 5, throws
+ 57  * an error if not. Otherwise, initializes the karma object and returns
+ 58  * a reference to that object.
+ 59  * @namespace Global namespace for Karma library
+ 60  * @constructor
+ 61  * @param {Object} [options={}] options for intializing Karma library
+ 62  * @param {String} [options.locale=''] sets current locale Not Yet Implemented
+ 63  * @param {Array} [options.image=[]] array of images to be converted into a collection
+ 64  * @param {Array} [options.audio=[]] array of audio to be converted into a collection
+ 65  * @param {Array} [options.video=[]] NYI array of videos to be converted into a collection
+ 66  * @param {Array} [options.svg=[]] array of SVG elements to be 
+ 67  * converted into a collection. Each SVG element must already exist in the html document
+ 68  * @param {Array} [options.canvas=[]] array of canvas elements 
+ 69  * to be converted into a collection. Each canvas element must already exist in the 
+ 70  * html document and width and height of each element must be set as attributes
+ 71  * @throws {Error} if the document type declaration is not set to HTML 5, e.g. 
+ 72  * <!DOCTYPE html>
+ 73  * @throws {Error} If any of the initialization parameters are invalid values
+ 74  * @returns {Object} Karma -- reference to the initialized Karma library
+ 75  * @example
+ 76  * 
+ 77  * var k = Karma({ 
+ 78  *                 image: [ 
+ 79  *                    {name: "ninja", file: "ninja.png"}, 
+ 80  *                    {name: "cowboy", file: "cowboy.png"}
+ 81  *                         ],
+ 82  *                 audio: [
+ 83  *                    {name: "woosh", file: "woosh.ogg"},
+ 84  *                    {name: "yeehaw", file: "yeehaw.ogg"}
+ 85  *                         ],
+ 86  *                 video: [  //Not Yet Implemented
+ 87  *                    {name: "attack", file: "attack.ogv"},
+ 88  *                    {name: "ride", file: "ride.ogv"}
+ 89  *                         ]
+ 90  *                 canvas: [
+ 91  *                    {name: "ninja", domId: "ninjaCanvas"},
+ 92  *                    {name: "cowboy", domId: "cowboyCanvas"}
+ 93  *                         ],
+ 94  *                 svg: [ 
+ 95  *                    {name: "ninja", domId: "ninjaSvg"},
+ 96  *                    {name: "cowboy", domId: "cowboySvg"}
+ 97  *                         ],
+ 98  *                 });
+ 99  * Next, call the ready function with a callback to your program code
+100  * 
+101  * k.ready(function () { ... your application code . . . }                       
+102  * 
+103  * after that you can access each asset like so
+104  * k.image.ninja;
+105  * k.svg.cowboy;
+106  * k.audio.yeehaw.play();
+107  * k.canvas.ninja.drawImage(k.image.ninja, 0, 0);
+108  * 
+109  */	
+110 var Karma = exports.Karma  = function (options) {
+111     Karma._isHtml5(document.doctype.nodeName);
+112 
+113     if ( Karma._initialized === true ) {
+114 	return Karma;
+115     } else {
+116 	return Karma._init(options);
+117     }
+118 };
+119 
+120 
+121 //helper functions
+122 
+123 /**This emulates the Object.create method in ecmascript 5 spec
+124  * This isn't a full implementation as it doesn't support an all of Object.create's features
+125  * This has the same functionality as Crockford's beget method
+126  * and this primary building block for prototypal inheritance in
+127  * this library
+128  * @param {Object} parent that the new object's prototype should point to
+129  * @returns {Object} a new object whose prototype is parent
+130  * @example
+131  * 
+132  * var ninja = { weapon : "sword" };
+133  * var ninja1 = Karma.create(ninja);
+134  * ninja1.weapon === "sword"
+135  */
+136 Karma.create = function (parent){
+137     function F () {};
+138     F.prototype = parent;
+139     return new F();
+140 };
+141 
+142 /** Returns a shallow copy of the passed in object
+143  * @param {Object} target to be copied
+144  * @returns {Object} a shallow copy of target
+145  */
+146 Karma.clone = function (target){
+147     var copy = {};
+148     for ( var i in target ) {
+149 	if(target.hasOwnProperty(i)){
+150 	    copy[i] = target[i];
+151 	}
+152     }
+153     return copy;
+154 };
+155 
+156 /** Extends properties of the target object with those of 
+157  * the source object
+158  * @param {Object} target object to be extended 
+159  * @param {Object} source whose properties will extend target
+160  * @returns {Object} target extended by source
+161  */
+162 Karma.objectPlus = function (target, source){
+163     for ( var i in source){
+164 	if (source.hasOwnProperty(i)){
+165 	    target[i] = source[i];
+166 	}
+167     }
+168     return target;
+169 };
+170 
+171 Karma.extend = Karma.objectPlus;
+172 
+173 /** Creates a new object that is a prototype of the first argument
+174  * then extends it with the properties of the second argument
+175  * @param {Object} parent1 will be prototype of returned object
+176  * @param {Object} parent2 will extend properties of returned object
+177  * @returns {Object} object that whose prototype is parent1 and has 
+178  * been extended with properties of parent2
+179  */ 
+180 Karma.copyObjectPlus = function (parent1, parent2){
+181     function F () {};
+182     F.prototype = parent1;
+183     var G = new F();
+184     return Karma.objectPlus(G, parent2);
+185 };
+186 
+187 
+188 //Throws big ugly error if doctype isn't html5
+189 Karma._isHtml5 = function (doctype){
+190     var regex = new RegExp('^html$', 'i');
+191     if(!regex.test(doctype)){
+192 	var errorMsg =  "ERROR: The doctype must be set to <!DOCTYPE html> " +
+193 	    "in order to use Karma. Karma require you use html5";
+194 	var errorElem = document.createElement('div');
+195 	errorElem.setAttribute('id', 'errorDoctype');
+196 	errorElem.innerText = errorMsg;
+197 	document.body.appendChild(errorElem);
+198 	   throw new Error(errorMsg);
+199 	}
+200 };
+201 
+202 /**
+203  * Shuffles an array of items randomly
+204  * @param {Array} oldList of choices to be shuffled
+205  * @returns {Array} newlist of choices randomly reordered 
+206  */
+207 Karma.shuffle = function (oldList) {
+208     var newList = oldList.slice(0);
+209     for (var i = newList.length - 1; i > 0; i -= 1) {
+210         var j = Karma.rand(0, i);
+211         var t = newList[i];
+212         newList[i] = newList[j];
+213         newList[j] = t;
+214     }
+215     return newList;
+216 };
+217 
+218 
+219 /**
+220  * Converts a number to numerals in the specified locale. Currently only
+221  * supports Nepali
+222  * @param {Number} Number to be converted
+223  * @param {locale} locale that number should be converted to
+224  * @returns {String} Unicode string for localized numeral 
+225  */
+226 Karma.convertNumToLocale = function(num, locale){
+227     locale = locale || Karma.locale;
+228     //48 is the base for western numerals
+229     var convertDigit = function(digit){
+230 	
+231 	var numBase = 48;
+232 	var prefix = "u00";
+233 	
+234 	if (locale === "ne"){
+235 	    prefix = "u0";
+236 	    numBase = 2406;
+237 	}
+238 	
+239 	return '\\' + prefix + 
+240 	    (numBase + parseInt(digit)).toString(16);
+241     };
+242     
+243     var charArray = num.toString().split("").map(convertDigit);
+244     return eval('"' + charArray.join('') + '"');
+245 };
+246 
+247 /**
+248  * @name Karma._n
+249  * @function
+250  * @public
+251  * Alias for Karma.convertNumToLocale. Converts a number to numerals to 
+252  * Karma.locale or to specified locale. Currently only supports Nepali
+253  * @param {Number} Number to be converted
+254  * @param {locale} locale that number should be converted to
+255  * @returns {String} Unicode string for localized numeral 
+256  */
+257 Karma._n = Karma.convertNumToLocale;
+258 
+259 /* Scales the dimensions of document.body to the innerHeight and innerWidth
+260  * of the viewport, i.e. browser window, with a minor offset to the height to 
+261  * make sure the scrollbars do not appear
+262  */
+263 Karma.scaleToViewport = function(){
+264     var width = window.innerWidth;
+265     var height = window.innerHeight;
+266     
+267     //hack to ensure scrollbars don't appear
+268     if (height === 900){
+269 	height = "" + 900 + "px";
+270     } else {
+271 	height = "" + (height - 13) + "px";
+272     }
+273     
+274     document.body.style.width = "" + width + "px";
+275     document.body.style.height = height;
+276 };
+277 
+278 Karma.scaleWindow = function(){
+279     var width = "1200px";
+280     var height = "900px";
+281     var viewportHeight = "760px";
+282     var $body = $('body');
+283     var $kMain = $('#kMain');
+284 
+285     if (window.innerWidth < 1150){
+286 	width = "950px";
+287 	height = "600px";
+288 	viewportHeight = "460px";
+289 	$body.css('border', '2px solid black');
+290 
+291 	//  460/760 * 16 = 9.6
+292 	$kMain.css('font-size', '9.6px');
+293     } 
+294 
+295     $body.css({border: '2px solid black', width: width, height: height});
+296     $kMain.css({width: width, height: viewportHeight});
+297 
+298 
+299 };
+300 
+301     // Below are geometry and math helper methods
+302     
+303 /**
+304  * Converts a value from degrees to radians.
+305  * @param {Number} angle The angle in degrees
+306  * @returns {Number} The angle in radians 
+307  */
+308 Karma.radians = function( angle ){
+309 	return ( angle / 180 ) * Math.PI;
+310 };
+311 
+312 /**
+313  *  Gets the square of the Euclidian (ordinary) distance between 2 points.
+314  * @param {Object} Point No. 0
+315  * @param {Number} Point0.x
+316  * @param {Number} Point0.y
+317  * @param {Object} Point No. 1
+318  * @param {Number} Point1.x
+319  * @param {Number} Point1.y
+320  * @returns {Number} The square of the Euclidian distance 
+321  * @example
+322  * 
+323  * p0 = {x:0, y:1};
+324  * p1 = {x:50, y:70};
+325  * var d = distance2(p0, p1);
+326  * 
+327  */
+328 Karma.distance2 = function ( p0, p1 ) {
+329     return   (p1.x - p0.x) * (p1.x - p0.x) + (p1.y - p1.y) * (p1.y - p1.y); 
+330 };
+331 
+332 /**
+333  * Gets the Euclidian (ordinary) distance between 2 points.<br>
+334  * <b>Warning:</b> It's slower than distance2 function
+335  * @param {Object} Point No. 0
+336  * @param {Number} Point0.x
+337  * @param {Number} Point0.y
+338  * @param {Object} Point No. 1
+339  * @param {Number} Point1.x
+340  * @param {Number} Point1.y
+341  * @returns {Number} The Euclidian distance 
+342  * @example
+343  * 
+344  * p0 = {x:0, y:1};
+345  * p1 = {x:50, y:70};
+346  * var d = distance2(p0, p1);
+347  * 
+348  */
+349 Karma.distance = function ( p0, p1 ) {
+350 	return   Math.sqrt( this.distance2( p0, p1 ) ); 
+351 };
+352 
+353 /** Returns a random number within the range provided
+354  * @param {Number} lower limit of the range, lowest number that can be returned
+355  * @param {Number} upper limit of the range, highest number that can be returned
+356  * @returns {Number} number that is >= lower and <= upper
+357  * @example
+358  * 
+359  * var num = rand(0, 10);
+360  * 
+361  * //num could be 0, 1, 2, 3 ... or 10
+362  * 
+363  */
+364 Karma.rand = function ( lower, upper ){
+365   return Math.floor(Math.random() * (upper - lower + 1) + lower);  
+366 };
+367 
+368 
+369 Karma.extend(Karma, {      
+370     /** This is the global locale as passed to Karma(),
+371      * such as "en", "es_SP"
+372      * @fieldOf Karma
+373      * @property {string} locale This is the global locale as passed to Karma()
+374      * @default 'en'
+375      */
+376     locale : 'en',
+377     /** Collection of images with special helper
+378      * methods added to each reference
+379      * @fieldOf Karma
+380      * @type object
+381      * @default empty object
+382      */
+383     image : {},
+384     /** Collection of audio files with special helper
+385      * methods added to each reference
+386      * @fieldOf Karma
+387      * @type object
+388      * @default empty object
+389      */
+390     audio : {},
+391     /** Collection of html 5 canvases with special helper
+392      * methods added to each reference
+393      * @fieldOf Karma
+394      * @type object
+395      * @default empty object
+396      */
+397     canvas : {},
+398     /** Collection of svgs with special helper
+399      * methods added to each reference
+400      * @fieldOf Karma
+401      * @type object
+402      * @default empty object
+403      */
+404     svg : {},
+405     /** Collection of videos with special helper
+406      * methods added to each reference
+407      * @fieldOf Karma
+408      * @type object
+409      * @default empty object
+410      */
+411     video : {},
+412     _localized : false,
+413     _assetPath : "assets/",
+414     _localePath : "",
+415     _initialized : false,
+416     _statusDiv: undefined,
+417     _loaderDiv : undefined,
+418     _counters : { total : 0, errors : 0, loaded : 0},
+419 
+420     //This constructs the Karma object per values provided by the user
+421     _init: function(options) {
+422 	this._initialized = true;
+423 	
+424 	//set up message that show count of assets loaded
+425 	//and has an ordered list to append error messages to
+426 	var _statusDiv = this._statusDiv = document.createElement('div');
+427 	this._loaderDiv = this._loaderDiv = document.createElement('div');	
+428 	var errorList = document.createElement('ol');
+429 
+430 	_statusDiv.setAttribute('id', 'karma-status');
+431 	_statusDiv.setAttribute('style', 'position:absolute;');
+432 	_statusDiv.innerHTML = 'Karma is loading ...';
+433 	this._loaderDiv.setAttribute('id', 'karma-loader');
+434 	this._loaderDiv.setAttribute('class', 'status');
+435 	errorList.setAttribute('id', 'errorList');
+436 
+437 	_statusDiv.appendChild(this._loaderDiv);
+438 	this._statusDiv.appendChild(errorList);
+439 	document.body.appendChild(_statusDiv);
+440 
+441 	//regular expression that matches the name of aprivate property
+442 	// the karma object
+443 	var regexPrivate = new RegExp('^_.*');
+444 	
+445 	for ( var option in options ) {
+446 	    if (options.hasOwnProperty(option)){
+447 		if (option === "image" || option === "audio" || option === 
+448 		    "svg" || option === "video" || option === "canvas"){ 
+449 		    
+450 		    if(!(options[option] instanceof Array)){
+451 			throw new Error("" + option + " must be an array");
+452 		    } else if (options[option].length === 0){
+453 			continue;
+454 		    }
+455 		} else if (regexPrivate.test(option)){
+456 		    //don't overwrite a private property of karma object
+457 		    continue;
+458 		}
+459 		
+460 		switch (option){
+461 		case "locale":
+462 
+463 		    if (this._isValidLocale(options[option])){
+464 			this.locale = this._normalizeLocale(options[option]);
+465 			this._localized = true;
+466 			this._localePath = Karma._computeLocalePath(this.locale);
+467 		    } else {
+468 			throw new Error("locale provided to karma._init() is invalid");
+469 		    }
+470 		    
+471 		    break;
+472 		case "image":
+473 		    options[option]._type = 'image';
+474 		    Karma._makeCollection(options[option], 'image');
+475 		    break;
+476 		case "audio":
+477 		    options[option]._type = 'audio';
+478 		    Karma._makeCollection(options[option], 'audio');
+479 		    break;
+480 		case "video":
+481 		    options[option]._type = 'video';
+482 		    Karma._makeCollection(options[option], 'video');
+483 		    break;
+484 		case "svg":
+485 		    options[option]._type = 'svg';
+486 		    Karma._makeCollection(options[option], 'svg');
+487 		    break;
+488 		case "canvas":
+489 		    options[option]._type = 'canvas';
+490 		    Karma._makeCollection(options[option], 'canvas');
+491 		    break;
+492 		}
+493 	    }
+494 	}
+495 
+496 
+497 
+498 	return this;
+499     },
+500     
+501     /** Waits until all assets loaded(ready), then calls callback cb
+502      * @memberOf Karma
+503      * @param {Function} [cb] callback function
+504      * @returns this
+505      * @throws {Error} if Karma is not initialized with the 
+506      * Karma({ options }) function
+507      * @example
+508      * 
+509      * var k = Karma({ . . . your assets here . . . });
+510      * k.ready(function(){ .. your code here . . .});
+511      * 
+512      * your code will not be called until all assets have been loaded
+513      * into collections
+514      * 
+515      */
+516     ready : function( cb ) {
+517 	var that = this;
+518 	if (Karma._initialized !== true){
+519 	    throw new Error("Karma not initialized");
+520 	}
+521 
+522 	if (this._counters.loaded !== this._counters.total){
+523 	    setTimeout(function(){ that.ready(cb);}, 5);
+524 	} else if (cb) {
+525 	    //hide the "Karma is loading..." message
+526 	    this._statusDiv.setAttribute('style', 'display:none;');
+527 
+528 	     cb();
+529 	} else if (!cb) {
+530 	    //hide the "Karma is loading..." message
+531 	    this._statusDiv.setAttribute('style', 'display:none;');
+532 	    
+533 	    //if no options passed, show it works message
+534 	    this._showStarterMessage();
+535 	}
+536 	
+537 	
+538 	   
+539 
+540 	return this;
+541     },
+542 
+543     //Display Apache-like "It works" message if no options
+544     _showStarterMessage : function (){
+545 	var starterMsg = document.createElement('div');
+546 	starterMsg.setAttribute('id', 'starterMsg');
+547 	starterMsg.innerHTML = "<h1>It Works</h1>";
+548 	document.body.appendChild(starterMsg);
+549     },
+550 
+551     //Updates visible counter of how many assets are loaded
+552     _updateStatus : function (errorMsg) {
+553 	var loaded = this._counters.loaded;
+554 	var total = this._counters.total;
+555 	var errors = this._counters.errors;
+556 	this._loaderDiv.innerHTML = "Loaded " + loaded + " / " + total + 
+557 	    "" + (errors > 0 ? " Errors [ " + errors +" ]" : '');
+558 	if (errorMsg) {
+559 	    var liError = document.createElement('li');
+560 	    liError.innerHTML = errorMsg;
+561 	    var errorList = document.getElementById('errorList');
+562 	    errorList.appendChild(liError);  
+563 	}
+564     },	    
+565 
+566     //matches 2 letter country code then optionally
+567     //a dash or underscore followed by a country or language identifier
+568     //i currently only allow a language identifier 2-3 chars long
+569     _isValidLocale : function (locale) {
+570 	var localeRegex = new RegExp('^[a-zA-Z][a-zA-Z]([-_][a-zA-z]{2,3})?$');
+571 	return localeRegex.test(locale);
+572     },
+573 
+574     _normalizeLocale : function(locale) {
+575 	var lang = "";
+576 	var country = "";
+577 	var divider = "";
+578 
+579 	lang = locale.slice(0, 2).toLowerCase();
+580 	divider = "_";
+581 	country = locale.slice(3, 6).toUpperCase();
+582 	
+583 	return locale.length > 2 ? "" + lang + divider + country : lang;
+584     },
+585     
+586 
+587     
+588 });
+589 
+590 //Helper functions for creating assets
+591 Karma._isLocalized = function (boolLocalized) {
+592     if (typeof boolLocalized === "boolean" ) {
+593 	if(boolLocalized === true && 
+594 	   Karma.locale === undefined){
+595 	    throw new Error("You cannot localize a media asset" +
+596 			    " if the global locale for Karma isn't set");
+597 	} else {
+598 	    return boolLocalized;
+599 	}
+600     } else if (typeof boolLocalized === undefined){
+601 	return false;
+602     } else{ 
+603 	throw new Error("This is not a valid value for the localized option");
+604     }
+605 };
+606 
+607 Karma._computeLocalePath = function(locale) {
+608     return Karma._assetPath + locale + "/";
+609 };
+610 
+611 
+612 
+613 
+614 Karma._makeCollection = function (configs, type){
+615     var makeAsset = function (config){
+616 	var asset = undefined;
+617 	var target = undefined;
+618 	switch(type){
+619 	    case "image":
+620 		target = Karma.kImage;
+621 		break;
+622 	    case "audio":
+623 		target = Karma.kAudio;
+624 		break;
+625 	    case "video":
+626 		target = Karma.kVideo;
+627 		break;
+628 	    case "svg":
+629 		target = Karma.kSvg;
+630 		break;
+631 	    case "canvas":
+632 		target = Karma.kCanvas;
+633 		break;
+634 	}
+635 
+636 	asset = Karma.create(target)._init(config);
+637 	Karma[type][config.name] = asset;
+638     };
+639 		       
+640     configs.forEach(function(config){ makeAsset(config);});
+641 };
+642 
+643 
+644 
+645 
+646 
+647 //Prototype objects for assets
+648 
+649 
+650 /** Prototype object for images
+651  *  @class This object is the prototype for images submitted to Karma in the
+652  *  Karma() method
+653  *  @ throws {Error} if the image asset is set to be localized but 
+654  *  the global locale is not set on the Karma object
+655  *  @ throws {Error} if the name and file properties are not supplied
+656  *  @example
+657  *  kImage is the prototype object for images. This 'media' asset is loaded 
+658  *  in a distinctly different way from the canvas or svg assets.    
+659  *
+660  */
+661 Karma.kImage = 
+662     {
+663     /** file location of image
+664      * @type String
+665      * @default ""
+666      */
+667     file : "",
+668     /** media object
+669      * @type Image
+670      * @default undefined 
+671      */	
+672     media : undefined,
+673     //actual path to the file
+674     _path : "",
+675     //if using localized version of this image
+676     _localized : false,
+677     _type : "image", 
+678     //initializes kImage instance with values provided by user
+679     _init : function (image) {
+680 	image._localized = image._localized || false;
+681 	Karma._counters.total++;
+682 
+683 	if (image.name === undefined || image.file === undefined){
+684 	    throw new Error("properties name and file have to be defined");
+685 	} else {
+686 	    this.name = image.name;
+687 	    this.file = image.file;
+688 	}
+689 
+690 	this.media = new Image(); 
+691 	
+692 	if(Karma._isLocalized(image._localized)){
+693 	    this._localized = image._localized;
+694 	    this._path = Karma._localePath + "image/";
+695 	} else {
+696 	    this._path = Karma._assetPath + "image/";
+697 	}
+698 
+699 	//IMPORTANT: This one magic line loads the file
+700 	this.media.src = this.src = this._path + this.file;
+701 	
+702 	//add event handlers
+703 	this._addEventHandlers();
+704 
+705 	
+706 	return this;
+707     },
+708     //Adds event handlers to update the counters when 
+709     //the image is successfully or unsuccessfully loaded
+710     _addEventHandlers : function () {
+711 	var that = this;
+712 
+713 	that.media.addEventListener(
+714 	    "load", 
+715 	    function (e) { 
+716 		Karma._counters.loaded++;
+717 		Karma._updateStatus();
+718 		that.status = "loaded";}, false);
+719 	
+720 	that.media.addEventListener(
+721 	    "error", 
+722 	    function (e) { 
+723 		Karma._counters.errors++;
+724 		that.status = "error";
+725 		var errorMsg = "Error: " + that._type.toUpperCase() +
+726 		    " " + that.name + " cannot be loaded."; 
+727 		Karma._updateStatus(errorMsg);
+728 	    }, 
+729 	    false);
+730 	that.media.addEventListener(
+731 	    "abort", 
+732 	    function (e) { 
+733 		Karma._counters.total++;
+734 		that.status = "aborted";
+735 		var errorMsg = "ABORT: " + that._type.toUpperCase() +
+736 		    " " + that.name + " loading was aborted."; 
+737 		Karma._updateStatus(errorMsg);
+738 
+739 	    }, false);
+740     }
+741     
+742 };
+743 
+744 /** Prototype object for audio files 
+745  *  @class This object is the prototype for audio files submitted to Karma in the
+746  * Karma() method
+747  *  @ throws {Error} if the individual audio asset is set to be localized but 
+748  *  the globale locale is not set on the Karma object
+749  *  @ throws {Error} if the name and file properties are not supplied
+750  *  @example
+751  *  kAudio is the prototype object for audio
+752  *  The audio assets are loaded in a distinctly different way
+753  *  from the canvas or svg assets. They also have distinctly different
+754  *  helper methods 
+755  *  
+756  *  You initialize the kAudio assets by passing an array of objects
+757  */
+758 Karma.kAudio = {
+759     /** file location of asset
+760      * @type String
+761      * @default ""
+762      */
+763     file : "",
+764     /**  Media object. You can access the src, autobuffer, autoplay, loop, and 
+765      * controls attributes 
+766      * via the media property of kAudio. Read more about the properties of the <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html#media-element-attributes">HTML 5 media element</a>
+767      * @type Audio
+768      * @default undefined
+769      */	
+770     media : undefined,
+771     //actual path to the file
+772     _path : "",
+773     //if using localized version of this asset
+774     _localized : false,
+775     _type : "audio", 
+776     //initializes kAudio instance with values provided by user
+777     _init : function (audio) {
+778 	audio._localized = audio._localized || false;
+779 	Karma._counters.total++;
+780 
+781 	if (audio.name === undefined || audio.file === undefined){
+782 	    throw new Error("properties name and file have to be defined");
+783 	} else {
+784 	    this.name = audio.name;
+785 	    this.file = audio.file;
+786 	}
+787 
+788 	this.media = new Audio(); 
+789 	
+790 	if(Karma._isLocalized(audio._localized)){
+791 	    this._localized = audio._localized;
+792 	    this._path = Karma._localePath  + "audio/";
+793 	} else {
+794 	    this._path = Karma._assetPath + "audio/";
+795 	}
+796 
+797 
+798 	//IMPORTANT: This one magic line loads the file
+799 	this.media.src = this.src = this._path + this.file;
+800 	
+801 	//add event handlers
+802 	this._addEventHandlers();
+803 
+804 	this.media.autobuffer = true;
+805 	this.media.load();
+806 
+807 	
+808 	return this;
+809     },
+810     //Adds event handlers to update the counters when 
+811     //the asset is successfully or unsuccessfully loaded
+812     _addEventHandlers : function () {
+813 	var that = this;
+814 	//'canplaythrough' event is a Browser Hack recommended by chromium devs
+815 	//http://code.google.com/p/chromium/issues/detail?id=20251&q=loading%20audio&colspec=ID%20Stars%20Pri%20Area%20Type%20Status%20Summary%20Modified%20Owner%20Mstone%20OS#c4
+816 
+817 	that.media.addEventListener(
+818 	    "canplaythrough", 
+819 	    function (e) { 
+820 		Karma._counters.loaded++;
+821 		Karma._updateStatus();
+822 		that.status = "loaded";}, false);
+823 	
+824 	that.media.addEventListener(
+825 	    "error", 
+826 	    function (e) { 
+827 		Karma._counters.errors++;
+828 		that.status = "error";
+829 		var errorMsg = "Error: " + that._type.toUpperCase() +
+830 		    " " + that.name + " cannot be loaded."; 
+831 		Karma._updateStatus(errorMsg);
+832 	    }, 
+833 	    false);
+834 	that.media.addEventListener(
+835 	    "abort", 
+836 	    function (e) { 
+837 		Karma._counters.total++;
+838 		that.status = "aborted";
+839 		var errorMsg = "ABORT: " + that._type.toUpperCase() +
+840 		    " " + that.name + " loading was aborted."; 
+841 		Karma._updateStatus(errorMsg);
+842 
+843 	    }, false);
+844 
+845     },
+846     /** Plays the audio file  */
+847     play : function () {
+848 	    this.media.play();  
+849     }
+850     
+851 };
+852 
+853 /** NYI:Prototype object for Video files 
+854  *  @class Not Yet Implemented:This object is the prototype for video files submitted 
+855  * to Karma in the Karma() method
+856  *  @ throws {Error} if the individual video asset is set to be localized but 
+857  *  the globale locale is not set on the Karma object
+858  *  @ throws {Error} if the name and file properties are not supplied
+859  */
+860 Karma.kVideo = {
+861     /** file location of asset
+862      * @type String
+863      * @default ""
+864      */
+865     file : "",
+866     /** media object
+867      * @type Video
+868      * @default undefined 
+869      */	
+870     media : undefined,
+871     //actual path to the file
+872     _path : "",
+873     //if using localized version of this asset
+874     _localized : false,
+875     _type : "video", 
+876     //initializes kVideo instance with values provided by user
+877     _init : function (video) {
+878 	//Not Yet Implemented
+879 	Karma._counters.errors++;
+880 	throw new Error("Video is not Yet Implemented");
+881 
+882 	video._localized = video._localized || false;
+883 	Karma._counters.total++;
+884 
+885 	if (video.name === undefined || video.file === undefined){
+886 	    throw new Error("properties name and file have to be defined");
+887 	} else {
+888 	    this.name = video.name;
+889 	    this.file = video.file;
+890 	}
+891 
+892 	this.media = new Video(); 
+893 	
+894 	if(Karma._isLocalized(video._localized)){
+895 	    this._localized = video._localized;
+896 	    this._path = Karma._localePath  + "video/";
+897 	} else {
+898 	    this._path = Karma._assetPath + "video/";
+899 	}
+900 
+901 
+902 	//IMPORTANT: This one magic line loads the file
+903 	this.media.src = this.src = this._path + this.file;
+904 	
+905 	//add event handlers
+906 	this._addEventHandlers();
+907 
+908 	return this;
+909     },
+910     //Adds event handlers to update the counters when 
+911     //the asset is successfully or unsuccessfully loaded
+912     _addEventHandlers : function () {
+913 	var that = this;
+914 	//'canplaythrough' event is a Browser Hack recommended by chromium devs
+915 	//http://code.google.com/p/chromium/issues/detail?id=20251&q=loading%20audio&colspec=ID%20Stars%20Pri%20Area%20Type%20Status%20Summary%20Modified%20Owner%20Mstone%20OS#c4
+916 
+917 	that.media.addEventListener(
+918 	    "canplaythrough", 
+919 	    function (e) { 
+920 		Karma._counters.loaded++;
+921 		Karma._updateStatus();
+922 		that.status = "loaded";}, false);
+923 	
+924 	that.media.addEventListener(
+925 	    "error", 
+926 	    function (e) { 
+927 		Karma._counters.errors++;
+928 		that.status = "error";
+929 		var errorMsg = "Error: " + that._type.toUpperCase() +
+930 		    " " + that.name + " cannot be loaded."; 
+931 		Karma._updateStatus(errorMsg);
+932 	    }, 
+933 	    false);
+934 	that.media.addEventListener(
+935 	    "abort", 
+936 	    function (e) { 
+937 		Karma._counters.total++;
+938 		that.status = "aborted";
+939 		var errorMsg = "ABORT: " + that._type.toUpperCase() +
+940 		    " " + that.name + " loading was aborted."; 
+941 		Karma._updateStatus(errorMsg);
+942 
+943 	    }, false);
+944 
+945     }
+946     
+947 };
+948 
+949 
+950 
+951 /** Prototype object for each canvas element submitted to Karma in the
+952  * Karma() method
+953  * @throws {Error} if the name and domId for the canvas element are not specified
+954  * @thows {Error} if the supplied domId does not match an element in the DOM
+955  * @class This object is the prototype for each canvas element submitted to Karma in the
+956  * Karma() method
+957  */
+958 Karma.kCanvas = {
+959     /** Name of the canvas, used internally by karma.js
+960      * @type String
+961      * @default ''
+962      */
+963     name : '',
+964     /** Width of canvas element
+965      * @type Number
+966      * @default 0
+967      */
+968     width: 0,
+969     /** Height of canvas element
+970      * @type Number
+971      * @default 0
+972      */
+973     height: 0,
+974     /**  Whether canvas is visible
+975      * @type boolean
+976      * @default true
+977      */
+978     visible: true,
+979     /** Element ID for canvas element in html document. This value is read-only
+980      * @type String
+981      * @default undefined
+982      */
+983     domId: undefined,
+984     /** Reference to the DOM element
+985      * @type DOMElement
+986      * @default undefined
+987      * @example
+988      * //You can access all properties and methods of the underlying DOM element
+989      * //using the 'node' property
+990      * Karma.canvas.someCanvas.node.dispatchEvent( ... some event ...);
+991      * var stuff = Karma.canvas.someCanvas.node.innerHTML;
+992      * 
+993      */
+994     node: undefined,
+995     /** The 2 Dimensional Rendering context property for this canvas
+996      * @type 2DRenderingContext
+997      * @default undefined
+998      * @example
+999      * //Almost all of the context attributes and methods are wrapped in helper functions
+1000      * //but you can also access them directly using the ctx property
+1001      * Karma.canvas.someCanvas.ctx.drawImage(someImage, x, y);
+1002      * Karma.canvas.someCanvas.ctx.fillStyle = "#ffffff";
+1003      */
+1004     ctx: undefined,
+1005 
+1006     //initializes object with values provides by user
+1007     _init: function (config) {
+1008 	for (var option in config){
+1009 	    if (config.hasOwnProperty(option)){
+1010 		switch (option){
+1011 		case "name":
+1012 		    this.name = config[option];
+1013 		    break;
+1014 		case "domId":
+1015 		    this.domId = config[option];
+1016 		    break;
+1017 		case "width":
+1018 		    if(!this.height){
+1019 			throw new Error("If you specify a width you must also" +
+1020 					"specify a height");
+1021 		    }
+1022 		    this.width = config[option];
+1023 		    break;
+1024 		case "height":
+1025 		    if(!this.width){
+1026 			throw new Error("If you specify a height you must also" +
+1027 					"specify a width");
+1028 		    }
+1029 		    this.height = parseInt(config.option, 10);
+1030 		    break;
+1031 		case "fps":
+1032 		    this.fps = parseInt(config.option, 10);
+1033 		    break;
+1034 		}
+1035 	    }
+1036 	}
+1037 	
+1038 	if(this.domId && document.getElementById(this.domId)){
+1039 	       	this.node = document.getElementById(this.domId);
+1040 		this.ctx = this.node.getContext('2d');
+1041 	} else {
+1042 	    throw new Error('you must specify a valid domId that' +
+1043 			    'is in your html page');
+1044 	}
+1045 
+1046 	if(!config.height && !config.width){
+1047 	    this.width = parseInt(this.node.getAttribute('width'), 10);
+1048 	    this.height = parseInt(this.node.getAttribute('height'), 10);
+1049 	}
+1050 
+1051 	return this;
+1052     },
+1053     /** Clear area of canvas element specified by parameters, if no
+1054      * parameters supplied, clears entire canvas
+1055      * @param {Number} [x=0] x coordinate, defaults to zero if left blank
+1056      * @param {Number} [y=0] y coordinate, defaults to zero if left blank  
+1057      * @param {Number} [width=0] width of area to be cleared, defaults 
+1058      * entire width of canvas
+1059      * @param {Number} [height=0] height of area to be cleared, defaults 
+1060      * entire height of canvas
+1061      * @returns this
+1062      * @example
+1063      * 
+1064      * k.canvas.ninja.clear();
+1065      * // clears the entire ninja canvas
+1066      * 
+1067      * k.canvas.ninja.clear(0, 10, 20, 30);
+1068      * //clears a specific portion of the ninja canvas
+1069      * 
+1070      */
+1071     clear : function ( x, y, width, height ) {
+1072 	var that = this;
+1073 	that.ctx.clearRect(
+1074 	    x || 0,
+1075 	    y || 0, 
+1076 	    width  || that.width, 
+1077 	    height || that.height
+1078 	);
+1079 	return that;
+1080     },
+1081   
+1082      /** The globalAlpha attribute gives an alpha value that is applied to shapes 
+1083      * and images before they are composited onto the canvas
+1084      * @param {Number} number in the range from 0.0 to 1.0
+1085      * @returns this
+1086      */
+1087     globalAlpha : function (attribute){
+1088 	var name = 'globalAlpha';
+1089 	this.ctx[name] = attribute;
+1090 	return this;
+1091     },
+1092  
+1093    /** Sets the globalCompositeOperation attribute, which sets how shapes and images 
+1094      * are drawn onto the existing bitmap, once they have had globalAlpha and the 
+1095      * current transformation matrix applied.
+1096      * For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1097      * @param {String} globalCompositeOperation source-atop, 
+1098      * source-in, source-out, 
+1099      * source-over, destination-atop, destination-in, destination-out, destination-over,
+1100      * lighter
+1101      * @returns this
+1102      */
+1103     globalCompositeOperation: function (attribute){
+1104 	var name = ' globalCompositeOperation';
+1105 	this.ctx[name] = attribute;
+1106 	return this;
+1107     },
+1108 
+1109     /** Sets the lineWidth attribute which gives the width of lines, in coordinate space 
+1110      * units.
+1111      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1112      * @param {Number} lineWidth
+1113      * @returns this
+1114      */
+1115     lineWidth: function (attribute){
+1116 	var name = 'lineWidth';
+1117 	this.ctx[name] = attribute;
+1118 	return this;
+1119     },
+1120     /** The lineCap attribute defines the type of endings that UAs will place on 
+1121      * the end of lines.  
+1122      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1123      * @param {String} type butt, round, square 
+1124      * @returns this
+1125      */
+1126     lineCap: function (attribute){
+1127 	var name = 'lineCap';
+1128 	this.ctx[name] = attribute;
+1129 	return this;
+1130     },
+1131     /** The lineJoin attribute defines the type of corners that UAs will place 
+1132      * where two lines meet. The three valid values are bevel, round, and miter. 
+1133      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1134      * @param {String} type
+1135      * @returns this
+1136      */
+1137     lineJoin: function (attribute){
+1138 	var name = 'lineJoin';
+1139 	this.ctx[name] = attribute;
+1140 	return this;
+1141     },
+1142    
+1143     /** Sets the miter limit 
+1144      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1145      * @param {Number} number
+1146      * @returns this
+1147      */
+1148     miterLimit: function (attribute){
+1149 	var name = 'miterLimit';
+1150 	this.ctx[name] = attribute;
+1151 	return this;
+1152     },
+1153     /** Sets the font property and takes the same syntax as setting the font property 
+1154      *  in CSS
+1155      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1156      * @param {String} 
+1157      * @returns this
+1158      */
+1159     font: function (attribute){
+1160 	var name = 'font';
+1161 	this.ctx[name] = attribute;
+1162 	return this;
+1163     },
+1164 
+1165     /** Changes the text alignment. The possible values are start, end, left, right, 
+1166      * and center. The default is start. Other values are ignored.
+1167      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1168      * @param {string} alignment 
+1169      * @returns this
+1170      */
+1171     textAlign: function (attribute){
+1172 	var name = 'textAlign';
+1173 	this.ctx[name] = attribute;
+1174 	return this;
+1175     },
+1176 
+1177     /** Changes the baseline alignment. If the value is one of top, hanging, middle, 
+1178      * alphabetic, ideographic, or bottom, then the value must be changed to the new value.
+1179      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1180      * @param {String} alignment
+1181      * @returns this
+1182      */
+1183     textBaseline: function (attribute){
+1184 	var name = 'textBaseline';
+1185 	this.ctx[name] = attribute;
+1186 	return this;
+1187     },
+1188     
+1189     /** Save the current state of the context
+1190      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1191      * @param 
+1192      * @returns this
+1193      */
+1194     save : function ( ){
+1195 	var name =  'save'; 
+1196 	this.ctx[name].apply(this.ctx, arguments);
+1197 	return this;
+1198     },
+1199     /** Restore the saved context
+1200      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1201      * @param 
+1202      * @returns this
+1203      */
+1204     restore : function ( ){
+1205 	var name =  'restore'; 
+1206 	this.ctx[name].apply(this.ctx, arguments);
+1207 	return this;
+1208     },
+1209      /** Perform a scale transformation
+1210      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1211      * @param 
+1212      * @returns this
+1213      */
+1214     scale : function ( ){
+1215 	var name =  'scale'; 
+1216 	this.ctx[name].apply(this.ctx, arguments);
+1217 	return this;
+1218     },
+1219    /** Perform a rotation transformation
+1220      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1221      * @param 
+1222      * @returns this
+1223      */
+1224     rotate : function ( ){
+1225 	var name =  'rotate'; 
+1226 	this.ctx[name].apply(this.ctx, arguments);
+1227 	return this;
+1228     },
+1229      /** Performa a translation transformation
+1230      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1231      * @param 
+1232      * @returns this
+1233      */
+1234     translate : function ( ){
+1235 	var name =  'translate'; 
+1236 	this.ctx[name].apply(this.ctx, arguments);
+1237 	return this;
+1238     },
+1239     
+1240     /** Transform the identity matrix
+1241      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1242      * @param 
+1243      * @returns this
+1244      */
+1245     transform : function ( ){
+1246 	var name =  'transform'; 
+1247 	this.ctx[name].apply(this.ctx, arguments);
+1248 	return this;
+1249     },
+1250     /** Set the transform
+1251      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1252      * @param 
+1253      * @returns this
+1254      */
+1255     setTransform : function ( ){
+1256 	var name =  'setTransform'; 
+1257 	this.ctx[name].apply(this.ctx, arguments);
+1258 	return this;
+1259     },
+1260     /** Clear a rectangular area 
+1261      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1262      * @param 
+1263      * @returns this
+1264      */
+1265     clearRect : function ( ){
+1266 	var name =  'clearRect'; 
+1267 	this.ctx[name].apply(this.ctx, arguments);
+1268 	return this;
+1269     },
+1270     /** Fill a rectangular area 
+1271      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1272      * @param 
+1273      * @returns this
+1274      */
+1275     fillRect : function ( ){
+1276 	var name =  'fillRect'; 
+1277 	this.ctx[name].apply(this.ctx, arguments);
+1278 	return this;
+1279     },
+1280       
+1281     /** Draw the outline of the rectangle
+1282      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1283      * @param 
+1284      * @returns this
+1285      */
+1286     strokeRect : function ( ){
+1287 	var name =  'strokeRect'; 
+1288 	this.ctx[name].apply(this.ctx, arguments);
+1289 	return this;
+1290     },
+1291     /** Begin a path 
+1292      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1293      * @param 
+1294      * @returns this
+1295      */
+1296     beginPath : function ( ){
+1297 	var name =  'beginPath'; 
+1298 	this.ctx[name].apply(this.ctx, arguments);
+1299 	return this;
+1300     },
+1301     /** End a path 
+1302      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1303      * @param 
+1304      * @returns this
+1305      */
+1306     closePath : function ( ){
+1307 	var name =  'closePath'; 
+1308 	this.ctx[name].apply(this.ctx, arguments);
+1309 	return this;
+1310     },
+1311     /** Move to specified coordinates 
+1312      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1313      * @param 
+1314      * @returns this
+1315      */
+1316     moveTo : function ( ){
+1317 	var name =  'moveTo'; 
+1318 	this.ctx[name].apply(this.ctx, arguments);
+1319 	return this;
+1320     },
+1321 
+1322 
+1323     /** Draw a line to the given coordinates 
+1324      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1325      * @param 
+1326      * @returns this
+1327      */
+1328     lineTo : function ( ){
+1329 	var name =  'lineTo'; 
+1330 	this.ctx[name].apply(this.ctx, arguments);
+1331 	return this;
+1332     },
+1333 
+1334     /** Draw a quadratic curve to given coordinates 
+1335      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1336      * @param 
+1337      * @returns this
+1338      */
+1339     quadraticCurveTo : function ( ){
+1340 	var name =  'quadraticCurveTo'; 
+1341 	this.ctx[name].apply(this.ctx, arguments);
+1342 	return this;
+1343     },
+1344     /** Draw a bezier curve to given coordinates 
+1345      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1346      * @param 
+1347      * @returns this
+1348      */
+1349     bezierCurveTo : function ( ){
+1350 	var name =  'bezierCurveTo'; 
+1351 	this.ctx[name].apply(this.ctx, arguments);
+1352 	return this;
+1353     },
+1354     /** Draw an arc to the given points
+1355      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1356      * @param 
+1357      * @returns this
+1358      */
+1359     arcTo : function ( ){
+1360 	var name =  'arcTo'; 
+1361 	this.ctx[name].apply(this.ctx, arguments);
+1362 	return this;
+1363     },
+1364     /** Create an arc 
+1365      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1366      * @param 
+1367      * @returns this
+1368      */
+1369     arc : function ( ){
+1370 	var name =  'arc'; 
+1371 	this.ctx[name].apply(this.ctx, arguments);
+1372 	return this;
+1373     },
+1374 
+1375     /** Create a rectangle 
+1376      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1377      * @param 
+1378      * @returns this
+1379      */
+1380     rect : function ( ){
+1381 	var name =  'rect'; 
+1382 	this.ctx[name].apply(this.ctx, arguments);
+1383 	return this;
+1384     },
+1385     /** fill in the current subpaths with the current fillstyle
+1386      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1387      * @param 
+1388      * @returns this
+1389      */
+1390     fill : function ( ){
+1391 	var name =  'fill'; 
+1392 	this.ctx[name].apply(this.ctx, arguments);
+1393 	return this;
+1394     },
+1395     /** Stroke the subpaths
+1396      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1397      * @param 
+1398      * @returns this
+1399      */
+1400     stroke : function ( ){
+1401 	var name =  'stroke'; 
+1402 	this.ctx[name].apply(this.ctx, arguments);
+1403 	return this;
+1404     },
+1405     
+1406     /** description 
+1407      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1408      * @param 
+1409      * @returns this
+1410      */
+1411     clip : function ( ){
+1412 	var name =  'clip'; 
+1413 	this.ctx[name].apply(this.ctx, arguments);
+1414 	return this;
+1415     },
+1416     /** description 
+1417      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1418      * @param 
+1419      * @returns this
+1420      */
+1421     fillText : function ( ){
+1422 	var name =  'fillText'; 
+1423 	this.ctx[name].apply(this.ctx, arguments);
+1424 	return this;
+1425     },
+1426     /** description 
+1427      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1428      * @param 
+1429      * @returns this
+1430      */
+1431     strokeText : function ( ){
+1432 	var name =  'strokeText'; 
+1433 	this.ctx[name].apply(this.ctx, arguments);
+1434 	return this;
+1435     },
+1436     /** description 
+1437      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1438      * @param 
+1439      * @returns this
+1440      */
+1441     measureText : function ( ){
+1442 	var name =  'measureText'; 
+1443 	this.ctx[name].apply(this.ctx, arguments);
+1444 	return this;
+1445     },
+1446     /** description 
+1447      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1448      * @param 
+1449      * @returns this
+1450      */
+1451     isPointInPath : function ( ){
+1452 	var name =  'isPointInPath'; 
+1453 	this.ctx[name].apply(this.ctx, arguments);
+1454 	return this;
+1455     },
+1456     
+1457     /** Sets the stroke style 
+1458      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1459      * @param 
+1460      * @returns this
+1461      */
+1462     strokeStyle: function (attribute){
+1463 	var name = 'strokeStyle';
+1464 	this.ctx[name] = attribute;
+1465 	return this;
+1466     },
+1467 
+1468     /** Sets the fill style
+1469      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1470      * @param 
+1471      * @returns this
+1472      */
+1473     fillStyle: function (attribute){
+1474 	var name = 'fillStyle';
+1475 	this.ctx[name] = attribute;
+1476 	return this;
+1477     },
+1478      /** description 
+1479      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1480      * @param 
+1481      * @returns this
+1482      */
+1483     createLinearGradient : function ( ){
+1484 	var name =  'createLinearGradient'; 
+1485 	this.ctx[name].apply(this.ctx, arguments);
+1486 	return this;
+1487     },
+1488     /** description 
+1489      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1490      * @param 
+1491      * @returns this
+1492      */
+1493     createRadialGradient : function ( ){
+1494 	var name =  'createRadialGradient'; 
+1495 	this.ctx[name].apply(this.ctx, arguments);
+1496 	return this;
+1497     },
+1498     /** description 
+1499      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1500      * @param 
+1501      * @returns this
+1502      */
+1503     createPattern : function ( ){
+1504 	var name =  'createPattern'; 
+1505 	this.ctx[name].apply(this.ctx, arguments);
+1506 	return this;
+1507     },
+1508      /** description 
+1509      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1510      * @param 
+1511      * @returns this
+1512      */
+1513     shadowOffsetX: function (attribute){
+1514 	var name = 'shadowOffsetX';
+1515 	this.ctx[name] = attribute;
+1516 	return this;
+1517     },
+1518     /** description 
+1519      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1520      * @param 
+1521      * @returns this
+1522      */
+1523     shadowOffsetY: function (attribute){
+1524 	var name = 'shadowOffsetY';
+1525 	this.ctx[name] = attribute;
+1526 	return this;
+1527     },
+1528     /** description 
+1529      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1530      * @param 
+1531      * @returns this
+1532      */
+1533     shadowBlur: function (attribute){
+1534 	var name = 'shadowBlur';
+1535 	this.ctx[name] = attribute;
+1536 	return this;
+1537     },
+1538     /** description 
+1539      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1540      * @param 
+1541      * @returns this
+1542      */
+1543     shadowColor: function (attribute){
+1544 	var name = 'shadowColor';
+1545 	this.ctx[name] = attribute;
+1546 	return this;
+1547     },
+1548    /** description 
+1549      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1550      * @param 
+1551      * @returns this
+1552      */
+1553     drawImage : function ( ){
+1554 	var name =  'drawImage'; 
+1555 	this.ctx[name].apply(this.ctx, arguments);
+1556 	return this;
+1557     },
+1558     /** description 
+1559      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1560      * @param 
+1561      * @returns this
+1562      */
+1563     getImageData : function ( ){
+1564 	var name =  'getImageData'; 
+1565 	this.ctx[name].apply(this.ctx, arguments);
+1566 	return this;
+1567     },
+1568     /** description 
+1569      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1570      * @param 
+1571      * @returns this
+1572      */
+1573     putImageData : function ( ){
+1574 	var name =  'putImageData'; 
+1575 	this.ctx[name].apply(this.ctx, arguments);
+1576 	return this;
+1577     },
+1578     /** description 
+1579      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1580      * @param 
+1581      * @returns this
+1582      */
+1583     createImageData : function ( ){
+1584 	var name =  'createImageData'; 
+1585 	this.ctx[name].apply(this.ctx, arguments);
+1586 	return this;
+1587     },
+1588     /** description 
+1589      *  For full details see <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalcompositeoperation">W3C docs</a>
+1590      * @param 
+1591      * @returns this
+1592      */
+1593     drawWindow : function ( ){
+1594 	var name =  'drawWindow'; 
+1595 	this.ctx[name].apply(this.ctx, arguments);
+1596 	return this;
+1597     },
+1598     
+1599 
+1600  
+1601    
+1602 };
+1603 
+1604 
+1605 /** Prototype object for each svg element submitted to Karma in the
+1606  * Karma() method
+1607  * @throws {Error} if the name and domId for the svg element are not specified
+1608  * @thows {Error} if the supplied domId does not match an element in the DOM
+1609  * @class This object is the prototype for each svg element submitted to Karma in the
+1610  * Karma() method
+1611  */
+1612 Karma.kSvg = {
+1613     /** name of instance, used internally 
+1614      * @typeof string
+1615      * @default ""
+1616      */
+1617     name : "",
+1618     /** width of element 
+1619      * @type number
+1620      * @default 0
+1621      */
+1622     width: 0,
+1623     /** height of element 
+1624      * @type number
+1625      * @default 0
+1626      */
+1627     height: 0,
+1628     /** Status of element, either "loaded" or "error"
+1629      * @type string
+1630      * @default ""
+1631      */
+1632     status: "",
+1633     /**  Whether canvas is visible. This value is read-only
+1634      * @type boolean
+1635      * @default true
+1636      */
+1637     visible: true,
+1638     /** Element ID for canvas element in html document. 
+1639      * @type String
+1640      * @default undefined
+1641      */
+1642     domId: undefined,
+1643     /** Reference to the DOM element.
+1644      * @type DOMElement
+1645      * @default undefined
+1646      * @example 
+1647      * //You can access all properties and methods of the underlying DOM element
+1648      * //using the 'node' property
+1649      * Karma.svg.someSvg.node.dispatchEvent;
+1650      * Karma.svg.someSvg.node.addEvenListener(...);
+1651      */
+1652     node: undefined,
+1653     /** Reference to the SVGDocument. You can use the this.doc to manipulate 
+1654      * the SVG document 
+1655      * @type SVGDocument
+1656      * @default undefined
+1657      * @example
+1658      * var myElem = Karma.svg.someSvg.doc.getElementById('foobar');
+1659      * Karma.svg.someSvg.doc.createElement(...);
+1660      * Karma.svg.someSvg.doc.removeChild(someNode);
+1661      *     
+1662      */
+1663     doc: undefined,
+1664     /** Reference to the root element of the SVG Document 
+1665      * @type DocumentElement
+1666      * @default undefined
+1667      * @example
+1668      * // The root element is equivalent to "document" in a regular html document
+1669      * // The root attribute is used frequently with the jQuery SVG plugin for CSS selectors
+1670      * $('#someId', Karma.svg.someSvg.root).css(.. manipulate css attributes ...);
+1671      */
+1672     root: undefined,
+1673     _localized : undefined,
+1674     _init: function (config) {
+1675 	Karma._counters.total++;
+1676 
+1677 	for (var option in config){
+1678 	    if (config.hasOwnProperty(option)){
+1679 		switch (option){
+1680 		case "name":
+1681 		    this.name = config[option];
+1682 		    break;
+1683 		case "domId":
+1684 		    this.domId = config[option];
+1685 		    break;
+1686 		case "width":
+1687 		    if(!this.height){
+1688 			throw new Error("If you specify a width you must also" +
+1689 					"specify a height");
+1690 		    }
+1691 		    this.width = parseInt(config[option], 10);
+1692 		    break;
+1693 		case "height":
+1694 		    if(!this.width){
+1695 			throw new Error("If you specify a height you must also" +
+1696 					"specify a width");
+1697 		    }
+1698 		    this.height = config[option];
+1699 		    break;
+1700 		}
+1701 	    }
+1702 	}
+1703 	
+1704 	if(this.domId && document.getElementById(this.domId)){
+1705 	       	this.node = document.getElementById(this.domId);
+1706 	} else {
+1707 	    throw new Error('you must specify a valid domId that' +
+1708 			    'is in your html page');
+1709 	}
+1710 
+1711 	if(!config.height && !config.width){
+1712 	    this.width = parseInt(this.node.getAttribute('width'), 10);
+1713 	    this.height = parseInt(this.node.getAttribute('height'), 10);
+1714 	}
+1715 	
+1716 	var that = this;
+1717 	that._addEventHandlers();
+1718 		   
+1719 	return this;
+1720 	
+1721 	
+1722     },
+1723     _addEventHandlers : function () {
+1724 	var that = this;	
+1725 	that.doc = that.node.getSVGDocument();	
+1726 	that.node.addEventListener(
+1727 		"load", 
+1728 	    function (e) { 
+1729 		that.doc = that.node.getSVGDocument();    
+1730 		that.root = that.doc.documentElement;
+1731 		Karma._counters.loaded++;
+1732 		Karma._updateStatus();
+1733 		that.status = "loaded";
+1734 	    }, false);
+1735 
+1736 	that.node.addEventListener(
+1737 	    "error", 
+1738 	    function (e) { 
+1739 		Karma._counters.loaded--;
+1740 		Karma._counters.errors++;
+1741 		that.status = "error";
+1742 		var errorMsg = "Error: " + that._type.toUpperCase() +
+1743 		    " " + that.name + " cannot be loaded."; 
+1744 		Karma._updateStatus(errorMsg);
+1745 	    }, 
+1746 	    false);
+1747 	that.node.addEventListener(
+1748 	    "abort", 
+1749 	    function (e) { 
+1750 		that.status = "aborted";
+1751 		var errorMsg = "ABORT: " + that._type.toUpperCase() +
+1752 		    " " + that.name + " loading was aborted."; 
+1753 		Karma._updateStatus(errorMsg);
+1754 
+1755 	    }, false);
+1756 
+1757     }
+1758 };
+1759 
\ No newline at end of file -- cgit v0.9.1