Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFelipe Lopez Toledo <zer.subzero@gmail.com>2009-09-02 21:49:45 (GMT)
committer Felipe Lopez Toledo <zer.subzero@gmail.com>2009-09-02 21:49:45 (GMT)
commitfc2f4f903be9d7e4ebcdf4b2c71bef65c29f473e (patch)
tree4aafe24d446f0fd77a1f1d1b02c661fea4155dd1
parentcdc2f251d67dd171646f2ab92b99d882d674a0b1 (diff)
multiple canvases support started
-rw-r--r--examples/adding_up_to_10/css/lesson_multiple.css14
-rw-r--r--examples/adding_up_to_10/index_multiple.html26
-rw-r--r--examples/adding_up_to_10/js/lesson_multiple.js31
-rw-r--r--js/jquery.karma-0.4.js5
-rw-r--r--js/jquery.karma-0.5.js1013
5 files changed, 1085 insertions, 4 deletions
diff --git a/examples/adding_up_to_10/css/lesson_multiple.css b/examples/adding_up_to_10/css/lesson_multiple.css
new file mode 100644
index 0000000..c10f168
--- /dev/null
+++ b/examples/adding_up_to_10/css/lesson_multiple.css
@@ -0,0 +1,14 @@
+#karma-main {
+ position: relative;
+ /*background-image: url('../assets/generic/images/bg.png');*/
+ width: 1200px;
+ height: 800px;
+}
+canvas {
+ border: 2px solid #cccccc;
+ image-rendering: optimizeSpeed;
+ -moz-border-radius: 8px;
+ -webkit-border-radius: 8px;
+}
+
+
diff --git a/examples/adding_up_to_10/index_multiple.html b/examples/adding_up_to_10/index_multiple.html
new file mode 100644
index 0000000..bad0372
--- /dev/null
+++ b/examples/adding_up_to_10/index_multiple.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html lang="en">
+
+<head>
+ <title>Karma - Adding Up to 10</title>
+ <meta name="keywords" content="karma,javascript,html5,sugar,sugarlabs,gsoc,ole,nepal">
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+
+ <link type="image/ico" rel="icon" href="../../assets/default/images/favicon.ico" />
+
+ <link type="text/css" rel="stylesheet" href="../../css/karma.css" />
+ <link type="text/css" rel="stylesheet" href="css/lesson_multiple.css" />
+
+ <script type="text/javascript" src="../../js/jquery-1.3.2.min.js"></script>
+ <script type="text/javascript" src="../../js/karma.Gettext.js"></script>
+ <script type="text/javascript" src="../../js/jquery.karma-0.5.js"></script>
+ <script type="text/javascript" src="js/lesson_multiple.js"></script>
+
+</head>
+
+<body>
+ <div id="karma-main" > </div>
+</body>
+
+</html>
diff --git a/examples/adding_up_to_10/js/lesson_multiple.js b/examples/adding_up_to_10/js/lesson_multiple.js
new file mode 100644
index 0000000..53972a5
--- /dev/null
+++ b/examples/adding_up_to_10/js/lesson_multiple.js
@@ -0,0 +1,31 @@
+$(document).ready(function(){
+var k = $.karma ({container: "#karma-main"});
+k.layer( {id:"card1", width:250, height:250} ),
+k.layer( {id:"card2", width:250, height:250} ),
+k.layer( {id:"card3", width:250, height:250} )
+
+k.init({
+ images: [
+ {id: "ball", file: "ball.png", localized : false },
+ {id: "ballon", file: "ballon.png", localized : false },
+ {id: "banana", file: "banana.png", localized : false },
+ {id: "chilli", file: "chilli.png", localized : false },
+ {id: "fish" , file: "fish.png", localized : false },
+ {id: "flower", file: "flower.png", localized : false },
+ {id: "plussign", file: "plussign.png", localized : false },
+ {id: "happyMonkey", file: "happyMonkey.jpg", localized : false },
+ {id: "scorebox", file: "scorebox.png", localized : false }
+ ]
+ ,
+ sounds: [
+ {id: "correct", file: "correct.ogg" },
+ {id: "incorrect",file: "incorrect.ogg" }
+ ]
+});
+k.main(function() {
+ var [library, layers ] = [k.library, k.layers];
+ library.images["ball"].draw( layers["card1"].ctx );
+ library.images["ballon"].draw( layers["card2"].ctx );
+ library.images["banana"].draw( layers["card3"].ctx );
+});
+}); \ No newline at end of file
diff --git a/js/jquery.karma-0.4.js b/js/jquery.karma-0.4.js
index 5d52986..1cf919d 100644
--- a/js/jquery.karma-0.4.js
+++ b/js/jquery.karma-0.4.js
@@ -330,8 +330,6 @@ var Karma = function( options ) {
}
//try to load the localized lang file (po or json or ...)
this.language.fileLoaded = loadAlternatives( );
- //
-
//initializes the container
if ( typeof this.container === "string" ) {
this.container = $( this.container );
@@ -959,10 +957,9 @@ Karma function. It's a shotcut for calling 'new Karma(..)'
**/
$.karma = function (options) {
var k =new Karma( options );
- //var x= new KGraphic( {localized: true })
//var x = new KMedia( "file1", "image", {localized: true} );
//var x = new KImage({file: "ball.png", localized: false, z: 0});
- //alert (x.localized)
+
return k;
}
})(jQuery); \ No newline at end of file
diff --git a/js/jquery.karma-0.5.js b/js/jquery.karma-0.5.js
new file mode 100644
index 0000000..d4115bd
--- /dev/null
+++ b/js/jquery.karma-0.5.js
@@ -0,0 +1,1013 @@
+/*
+* Karma Framework
+* http://wiki.sugarlabs.org/go/Karma
+*
+* Copyright (c) 2009
+* Felipe López Toledo zer.subzero@gmail.com
+* Bryan W Berry bryan@olenepal.org
+*
+* Under MIT License:
+* Permission is hereby granted, free of charge, to any person
+* obtaining a copy of this software and associated documentation
+* files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use,
+* copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following
+* conditions:
+*
+* The above copyright notice and this permission notice shall be
+* included in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+(function ($) {
+//helpers
+/**
+Checks if the argument (arg) is seted and if its type is 'type'.<br>
+1. if arg is seted: it returns toReturn if specified, otherwise it returns
+ 'true'
+2. if arg is not seted: it returns 'false'
+@param arg The param to check
+@param {Object} [type] The expeted type of 'arg'
+@param [toReturn] object or value to return in case 1
+@returns true | false | toReturn
+@example
+var msg = "hi";
+valid(msg); //returns true
+valid(msg, "String" ); //returns true
+valid(msg, "Number"); //returns false
+valid(msg, "String",false ); //returns false
+valid(msg123); //returns false
+**/
+var valid = function ( arg, type, toReturn ) {
+ if ( type ) {
+ if ( typeof arg === type ) {
+ if ( toReturn )
+ return toReturn;
+ return true;
+ }
+ return false
+ }
+ if ( typeof arg !== "undefined" ) return true;
+ return false;
+}
+/**
+Karma
+@class Represents a Karma (master) object.
+@param {String | Object } options Constructor arguments
+@param {String | Object } [options.container] Target DIV-class that will contain
+ any canvas element created using Karma functions
+@param {String} [options.language]
+ <ul>
+ <li>if it's seted:
+ Karma will assume that the according language file exists and Karma will try
+ to load it.<li>
+ <li>if it's not seted:
+ Karma will localise the content according to the Browser language
+ </li>
+ </ul>
+@param {Array} [options.language.alternatives]
+ Alternatives for localizing the content. The first has the priority.
+@param {Object} [options.i18n] Object that contains data for i18n.
+@param {Object | String} [options.i18n.root=self]
+ Parent element where the i18n shortcut function will be attached.
+@param {String} [options.i18n.shortcut=_] Shortcut for calling i18n.
+@param {Number} [options.fps=24]
+ Frames per second at which Karma will perform any refresh action.
+@version 0.3 alpha
+**/
+var Karma = function( options ) {
+ var that = this;
+ this.version = "0.3 alpha";
+ //
+ //relative path to the po, images, sounds, etc. from the html
+ //defined here: http://wiki.sugarlabs.org/go/Karma/Bundle_layout
+ //localized is recalculated inside localizeContent ( $ = language.lang )
+ this.paths = {
+ po: "po/",
+ images: {
+ localized: "assets/$/images/",
+ generic: "assets/generic/images/"
+ },
+ sounds: {
+ localized: "assets/$/sounds/",
+ generic: "assets/generic/sounds/"
+ },
+ videos: {
+ localized: "assets/$/videos/",
+ generic: "assets/generic/videos/"
+ }
+ };
+ this.supportedLangFileTypes = [
+ { ext: "po", type: 'application/x-po' },
+ { ext: "json", type: 'application/json'}
+ ];
+ //
+ //PRIVATE STUFF start
+ /**
+ Gets the language acording to the browser language
+ @returns {Object} <br>
+ lang: countryCode and langCode (if specified)
+ langCode*: language code represented as xx, example: en.<br>
+ countryCode*: country code represented as YY, example: US.<br>
+ *optional
+ **/
+ var getLanguage = function () {
+ //console.log += navigator.language +"\n";
+ var lang = navigator.language || navigator.browserLanguage; //mozilla/ie
+ lang = lang.replace(/_/, '-').toLowerCase();
+ if (lang.length > 3 ) {
+ var country = lang.substring(3, 5);
+ lang = lang.substring(0, 2);
+ if ( country.match(/[^a-zA-Z]/) === null ) {
+ country = country.toUpperCase();
+ return {
+ "lang": lang + "-" + country,
+ "langCode": lang,
+ "countryCode": country
+ };
+ }
+ }
+ return { "lang": lang };
+ }
+ /**
+ Creates a new Gettext object and returns a shortcut function to localise
+ defined strings.<br>We use karma.Gettext.js it's a modification of
+ <a href=http://jsgettext.berlios.de/doc/html/Gettext.html>
+ Gettext.js</a> from beril OS.
+ @requires karma.Gettext.js
+ @param {Object} options The arguments of the Gettext constructor
+ @returns {Function} A generic function to call Gettext functions
+ The generic function will call a Gettext function according to the number of arguments passed
+ <table>
+ <tr>
+ <th>No. params</th>
+ <th>Parameters</th>
+ <th>Gettext function called</th>
+ </tr>
+ <tr>
+ <td>1</td>
+ <td>msgid</td>
+ <td>gettext</td>
+ <tr>
+ <td>2</td>
+ <td>context, msgid</td>
+ <td>pgettext</td>
+ </tr>
+ <tr>
+ <td>3</td>
+ <td>number, singular, plural</td>
+ <td>ngettext</td>
+ </tr>
+ <tr>
+ <td>4</td>
+ <td>number, context, singular, plural</td>
+ <td>npgettext</td>
+ </tr>
+ </table>
+ **/
+ var i18nWrapper = function ( options ) {
+ var gt = new Gettext( options );
+ if ( typeof ( gt ) === 'undefined' )
+ throw new Error("Unable to initialize Gettext object");
+ return (function (str1, str2, str3, str4 ) {
+ var n, context, singular, plural;
+ if (typeof(str4) != 'undefined') {
+ // number, context, singular, plural
+ return gt.npgettext(str2, str3, str4, str1);
+ } else if (typeof(str3) != 'undefined') {
+ // number, singular, plural
+ return gt.ngettext(str2, str3, str1);
+ } else if (typeof(str2) != 'undefined') {
+ // context, msgid
+ return gt.pgettext(str1, str2);
+ } else if (typeof(str1) != 'undefined') {
+ // msgid
+ return gt.gettext(str1);
+ } else {
+ // nothing passed in; return blank string.
+ // XXX: we could error here, but that may cause more harm than good.
+ return '';
+ }
+ });
+ };
+ /**
+ Localises the inline html content and it creates the localised paths for
+ "images", "sounds" and "videos".
+ <b>Note:</b>Inline html localisation under development<br>
+ @param {String} lang The language that will be used to localise the content
+ @see <a href="http://wiki.sugarlabs.org/go/Karma/Bundle_layout">
+ Karma Bundle_layout</a>
+ **/
+ var localiseContent = function ( lang ) {
+
+ var toFix = ["images", "sounds", "videos"];
+ for (var i = 0; i < toFix.length; i++) {
+ that.paths[ toFix[ i ] ].localized = that.paths[
+ toFix[ i ] ].localized.replace('\$', lang );
+ }
+ //dirty hack to support {lang}_AudioFile
+ var prefix = lang.substring(0, 2)+"_";
+ that.paths[ "sounds" ].localized+=prefix;
+ that.paths[ "sounds" ].generic+=prefix;
+ }
+ /**
+ It will attempt to load a language file, the posible languages are defined
+ on language.alternatives.
+ <p>The language file type could be: .po (Pootle) or .json (JSON). The
+ precedence between file types is defined according to which is defined first
+ in supportedLangFileTypes. By default Pootle files has precedence over JSON,
+ files.</p>
+ @see Karma
+ @returns {String} The name of the language file loaded. Example: en-US.po
+ **/
+ var loadAlternatives = function ( ) {
+ var loaded = undefined;
+ var tryNext = true;
+ //try to load the po or json language file if it exists.
+ //the lang order is acording to options.language.alternatives
+ //the type (po or json or ...) is defined in supportedLangFileTypes
+ $.each( that.language.alternatives, function ( c, lang ) {
+ for (var i=0; i < that.supportedLangFileTypes.length
+ && tryNext === true; i++) {
+ $.ajax({
+ url: that.paths.po + lang + "." +
+ that.supportedLangFileTypes[i].ext,
+ cache: true,
+ dataType: "text",
+ async: false, //important: touch it at your own risk
+ success: function( data, textStatus ){
+
+ loaded = lang + "." +
+ that.supportedLangFileTypes[i].ext;
+ //i18n
+ //we pass the data so we avoid re-loading the file
+ //creates the shorcout
+ that.i18n.root[ that.i18n.shortcut ] = i18nWrapper(
+ {
+ domain : lang,
+ file : {
+ type: that.supportedLangFileTypes[i].type,
+ uri: this.url, data: data
+ }
+ }
+ );
+ localiseContent( lang );
+ tryNext = false;
+ },
+ error: function ( XHR, textStatus, errorThrown ) {
+ //the file doesn't exist or it wasn't possible to load it
+ tryNext = true;
+ }
+ });
+ return tryNext;
+ }
+ });
+ return loaded;
+ }
+ //PRIVATE STUFF end
+ // default options
+ var defaultOptions ={
+ container: "#karma-ma1in",
+ language: {
+ lang: undefined,
+ alternatives: ['en-US', 'en'],
+ countryCode: undefined,
+ langCode: undefined,
+ },
+ i18n: {
+ root: self, // self is global
+ shortcut: "_"
+ }
+ };
+ //
+
+ this.library = { "images": [], "sounds": [], "videos":[], "shapes":[] }
+
+ //initializes the defaultOptions argument
+ //1 argument: string. assume it's the container
+ if ( typeof options === "string" ) {
+ options = { container: options };
+ options.language = getLanguage() ;
+ } else if (typeof options === "object" ){
+ if ( typeof options.lang === "string" ) {
+ //if language is string, assume it's the language.lang
+ options.language = { lang: options.lang };
+ }
+ }
+ $.extend( true, defaultOptions, options );
+ //
+ //copy defaultOptions to this, we use this.xyz instead this.defaultOptions.xyz
+ for (var i in defaultOptions ) {
+ this[ i ] = defaultOptions[i];
+ }
+
+ //initializes i18n
+ //add the localized language to the language.alternatives
+ if ( typeof this.language.countryCode !== "undefined" ) {
+ this.language.alternatives.unshift(
+ this.language.langCode,
+ this.language.countryCode
+ );
+ }
+ if ( typeof this.language.lang !== "undefined" ) {
+ this.language.alternatives.unshift( this.language.lang );
+ }
+ //try to load the localized lang file (po or json or ...)
+ this.language.fileLoaded = loadAlternatives( );
+ //initializes the container
+ if ( typeof this.container === "string" ) {
+ this.container = $( this.container )[ 0 ];
+ if ( !valid(this.container) ) delete this.container;
+ }
+ gk = {
+ "paths": this.paths
+ }
+ this.layers={};
+ this.clayers=0;
+}
+/**
+Creates a new canvas element.
+@param {object} options
+@see KLayer
+**/
+Karma.prototype.layer = function ( options ) {
+ if ( !valid(options, "object") ){
+ var options = { id: "klayer-"+(clayers++) };
+ }
+ options.mainContainer = this.container;
+ options.paths = this.paths;
+ this.layers[ options.id ] = new KLayer( options );
+ return this.layer[ options.id ];
+}
+
+
+//Karma packages
+/**
+@namespace Geometry functions.
+**/
+Karma.prototype.geometry = {
+ /**
+ Converts a value from degrees to radians.
+ @param {Number} angle The angle in degrees
+ @returns {Number} The The angle in radians
+ **/
+ radians : function( angle ){
+ return ( angle / 180 ) * Math.PI;
+ },
+ /**
+ Get the square of the Euclidian (ordinary) distance between 2 points.<br>
+ <b>Warning:</b> It's slower than distance2 function.
+ @param {Number} Point Point No. 0
+ @param {Number} Point Point No. 1
+ @returns {Number} The square of the Euclidian distance
+ **/
+ distance2 : function ( p0, p1 ) {
+ return (p1.x - p0.x) * (p1.x - p0.x) + (p1.y - p1.y) * (p1.y - p1.y);
+ },
+ /**
+ Get the Euclidian (ordinary) distance between 2 points.<br>
+ <b>Warning:</b> It's slower than distance2 function
+ @param {Number} Point Point No. 0
+ @param {Number} Point Point No. 1
+ @returns {Number} The Euclidian distance
+ **/
+ distance : function ( p0, p1 ) {
+ return Math.sqrt( Karma.prototype.geometry.distance2( p0, p1 ) );
+ }
+}
+/**
+@namespace Graphics functions.
+**/
+Karma.prototype.graphics = {
+ /**
+ Creates a new rectangle. It's a shortcut for calling 'new KRectangle(..)'.
+ **/
+ rectangle: function ( args ) { return new KRectangle( args ); },
+ /**
+ Creates a new circle. It's a shortcut for calling 'new KCircle(..)'.
+ **/
+ circle: function ( args ) { return new KCircle( args ); }
+}
+/**
+@namespace Math functions.
+**/
+Karma.prototype.math = {
+ /**
+ Generates a random bumber between lower bound and upper bound inclusive.
+ @param {Number} lower The lower bound
+ @param {Number} upper The upper bound
+ @returns {Number} The generated number
+ **/
+ rand : function ( lower, upper ){
+ return Math.round ( Math.random() * (upper - lower) + lower );
+ }
+}
+//
+//everything inside karma.graphics is exported to karma.prototype
+$.extend( Karma.prototype, Karma.prototype.graphics);
+//
+/**
+Attaches an Object of Arrays for preloading. There are 3 valid categories (arrays):
+'images' for images, 'sounds' for sounds and 'videos' for video files.<br>
+Any object within any category must have an 'id' and 'file' attributes.
+Additional attributes will be used as arguments to the constructor of the
+corresponding object.<br>
+Any media file successfully loaded will be availabe through the 'library'.
+The init finishes when all the valid files have finished loading or have
+failed on the process.<br>
+Please note that the preloadinf will NOT start unless you call 'main' function.
+@param {Object} [toLoad] The Object that has the arrays for preloading.
+@param {Array} [toLoad.images] The images
+@param {Array} [toLoad.sounds] The sounds
+@param {Array} [toLoad.videos] The videos
+@returns {Object} this
+@see Karma#main
+@example
+var k = $.karma ({container: "#karma-main"/});
+k.size(1200, 800);
+k.init({
+ images: [
+ {id: "ball", file: "ball.png", localized : false },
+ ],
+ sounds: [
+ {id: "correct", file: "correct.ogg" },
+ ]
+});//1 image and 1 sound attached to load
+**/
+Karma.prototype.init = function( toLoad ) {
+ this.pendingToLoad = toLoad;
+ return this; //chaining :)
+}
+
+/**
+Main function. Any Karma function call should be inside the callback function.
+The callback function will be executed when the preloading finishes.
+@param {Function} cb The callback funtion
+@see Karma#init
+**/
+Karma.prototype.main = function ( cb ) {
+ if ( valid( this.pendingToLoad ) ) {
+ var that = this;
+ var categories = ["images", "sounds", "videos" ];
+ var counters = { "loaded":0, "error": 0 };
+ var totalItems = 0;
+ //get the total items
+ for ( var i=0; i < categories.length; i++ ) {
+ if ( valid ( this.pendingToLoad[ categories[ i ] ] ) ) {
+ totalItems += this.pendingToLoad[ categories[ i ] ].length;
+ }
+ }
+ /**
+ callback to check if all the items were loaded or got an error when
+ loading
+ **/
+ var checkAllLoaded = function ( ev ) {
+ if ( ev.type === "load") counters.loaded += 1;
+ else counters.error += 1;
+ if ( counters.loaded + counters.error === totalItems ) {
+ if ( cb ) cb();
+ }
+ }
+
+ for ( var i=0; i < categories.length; i++ ) {
+ var category = categories[ i ];
+ if ( valid ( this.pendingToLoad[ category ] ) ) {
+ //load all the category elements
+ var type = category.substr( 0, category.length-1 )
+ $.each (this.pendingToLoad[ category ], function( key, config ){
+ var id = config.id;
+ delete config.id;
+ //register the elements into the library
+ that.library[ category ][ id ] = Karma.prototype[ type ](
+ config
+ );
+ that.library[ category ][ id ].media.addEventListener(
+ "load",checkAllLoaded,false
+ );
+ that.library[ category ][ id ].media.addEventListener(
+ "error",checkAllLoaded,false
+ );
+ });
+ }
+ }
+ }else {
+ if ( cb ) cb();
+ }
+}
+/**A shortcut for calling 'KImage( )'
+@see KImage
+**/
+Karma.prototype.image = function ( args ) { return new KImage( args ) };
+/**A shortcut for calling 'KSound( )'
+@see KSound
+
+**/
+Karma.prototype.sound = function ( args ) { return new KSound( args ) };
+/**A shortcut for calling 'KVideo( )'
+@see KVideo
+
+**/
+Karma.prototype.video = function ( args ) { alert("Not implemented yet"); };
+/**A shortcut for calling 'KGroup( )'
+@see KGroup
+**/
+Karma.prototype.group = function ( args ) { return new KGroup( args ) };
+/**A shortcut for calling 'KButton( )'
+@see KButton
+**/
+Karma.prototype.button = function ( args ) { return new KButton( args ) };
+
+/**
+Mouse
+**/
+var mouse = {};
+/**
+Gets the 'x' and 'y' mouse coordinates relatives to the canvas
+@returns {Object} An Object with 'x' and 'y' attributes
+**/
+mouse.getRelativeCanvasPosition = function ( ev ) {
+ if ( !ev ) return;
+ var xy ={x:0, y:0};
+ xy.x = ev.layerX;
+ xy.y = ev.layerY;
+ return xy;
+}
+
+//Events stuff
+var master ={}
+master.buttons =[];
+var handleEvents = function( ev ) {
+ var xy = mouse.getRelativeCanvasPosition( ev );
+ for (var i in master.buttons) {
+ if (master.buttons[i].isPointInPath( xy.x, xy.y) ){
+ master.buttons[i].onClick( ev );
+ }
+ }
+ /*switch(ev.type){
+ case "click": break;
+ }*/
+ /*var s="";
+ for (var i in ev) {
+ s+=i+"="+ev[i]+"\n";
+ }
+ alert(s);*/
+}
+
+/**
+Master Class creator. Supports multiple inheritance.
+It creates a new Object, the new Object will contain the methods that has each
+argument passed (Function or Object). When creating an instance of the new
+Object it will use the 'init' function as the initializer.<br>
+If there is more than one method with the same name, it'll be overwritten by the
+last one.<br>
+warning it's NOT optimal.
+@returns {Object} A new class
+**/
+var Class = function ( ) {
+ var log="";
+ var parents = [];
+ for ( var i = 0; i < arguments.length; i++ ) {
+ if ( arguments[i].prototype && arguments[i].init ) {
+ parents.push( arguments[i].init );
+ }
+ }
+ var o = function ( ) {
+ //we inject all the init functions
+ /*for ( var i = 0; i < this.__parents.length; i++ ) {
+ this.__parents[ i ].apply ( this, arguments );
+ }*/
+ //call the real class init
+ if ( this.init )
+ this.init.apply( this, arguments );
+ };
+
+ o.prototype ={};
+ var a;
+ for ( var i =0; i < arguments.length; i++) {
+ a = arguments[i];
+ log += "**" + typeof a+"\n";
+ //if ( a === "function") {
+ if (a.prototype) {
+ for ( var j in a.prototype ) {
+ //log += j+" = "+a.prototype[j]+"\n";
+ o[ j ] = o.prototype[ j ] = a.prototype [ j ];
+ }
+ }
+ else {
+ //if ( typeof a === "object") {
+ for (var j in a) {
+ //log += j+" = "+a[j]+"\n";
+ o[ j ] = o.prototype[ j ] = a [ j ];
+ }
+ }
+
+ }
+ o.prototype.__parents = parents;
+ //alert( log );
+ return o; //(function ( ) { return new o( arguments );});
+};
+
+/**
+creates a new layer
+@param {object} options
+@param {string} [options.id]
+@param {string | object} [options.container]
+@param {number} [width=100]
+@param {number} [height=100]
+@param {number} [fps=24]
+@param {boolean} [visible=true]
+**/
+var KLayer = Class(
+ {
+ init: function( options ){
+ //fix the container
+ if ( valid( options.container, "string" ) ) {
+ var name=options.container;
+ options.container = $( options.container )[ 0 ];
+ if ( !valid (options.container) ){
+ // the container must be created inside the mainContainer
+ if ( !valid( options.mainContainer ) ){
+ throw ("You need to create the Karma master container");
+ }
+ var div = document.createElement("div");
+ div.id = name;
+ options.container=options.mainContainer.appendChild( div );
+ }
+ }else {
+ if ( !valid( options.mainContainer ) ){
+ throw ("You need to create the Karma master container");
+ }
+ options.container = options.mainContainer;
+ }
+ var defaultOptions = {
+ //mainContainer: '',//must be overwritten by Karma.container
+ id: '',//must be overwritten by the Karma.layer OR user
+ container: '', //must be overwritten by Karma.container OR user
+ paths: '', //must be overwritten by Karma.paths
+ width: 100,
+ height: 100,
+ fps: 24,
+ visible: true
+ }
+ $.extend( this, defaultOptions, options);
+
+ this.canvas = document.createElement("canvas");
+ this.canvas.width = this.width;
+ this.canvas.height = this.height;
+ this.canvas.id = this.id;
+ if ( this.canvas.getContext ) {
+ this.ctx = this.canvas.getContext("2d");
+ this.container.appendChild( this.canvas );
+ }else {
+ throw new Error ("Your browser doesn't support canvas, \
+ try the newest Firefox, Safari or Google Chrome");
+ }
+ //events
+ this.canvas.addEventListener("contextmenu", function(ev){
+ //
+ },false
+ );
+ this.canvas.addEventListener("click",
+ handleEvents,
+ false
+ );
+ },
+ /**
+ Clears a rectangular area within the canvas
+ @param {Number} [x=0] Start position of x
+ @param {Number} [y=0] Start position of y
+ @param {Number} [width=canvas width] Square width
+ @param {Number} [height=canvas height] Square height
+ **/
+ clear : function ( x, y, width, height ) {
+ this.ctx.clearRect(
+ x || 0,
+ y || 0,
+ width || this.canvas.width,
+ height || this.canvas.width
+ );
+ },
+ draw: function ( ) {
+
+ }
+ }
+);
+
+/**
+Karma basic Object
+@class The basic Karma object
+@param {Object} [options] Options
+@param {String} [options.localized = true] The object will be localized
+**/
+var KObject = Class(
+ {
+ init: function ( options ) {
+ if ( valid(options.localized, "boolean" ) ) {
+ this.localized = options.localized;
+ }else {
+ this.localized = true;
+ }
+ }
+ }
+);
+/**
+Graphics basic Object
+@class General methods for any Graphic object
+@param {Object} [options] Options
+@param {Number} [options.x = 0] The 'x' position of the object
+@param {Number} [options.y = 0] The 'y' position of the object
+@param {Number} [options.z = 0] The 'z' index of the object
+@param {Number} [options.width = 0] The 'width' of the object
+@param {Number} [options.height = 0] The 'height' of the object
+@param {Boolean} [options.visible = true] Defines if the object will be visible
+ when drawing
+@augments KObject
+**/
+var KGraphic = Class(
+ KObject,
+ {
+ init: function ( options ) {
+ if ( valid( options.localized ) )
+ KObject.init.call(this, options.localized );
+ var defaultOptions = {
+ x : 0,
+ y : 0,
+ z : 0,
+ width: 0,
+ height: 0,
+ visible : true
+ }
+ $.extend( this, defaultOptions, options);
+ },
+ /**
+ @memberOf KGraphic
+ Determines if the 'x' and 'y' coodinates are inside the object.
+ @returns {Boolean} 'true' if the coordinates are inside or on the border
+ of the object, otherwise 'false'
+ **/
+ isPointInPath : function( x, y ) {
+ return (this.x <= x && (this.x + this.width) >= x &&
+ this.y <= y && (this.y+this.width)>=y);
+ },
+ addEventListener : function (type, cb, bubble) {
+ //FIXME
+ }
+ }
+);
+/**
+Supports multiple objects
+@class
+**/
+var KGroup = Class(
+ KGraphic,
+ {
+ init: function ( options ) {
+ this.childNodes = [];
+ this.sorted = true;
+ },
+ /**
+ @memberOf KGroup
+ Adds each argument passed to the funtion to chilNodes.
+ @param {Array:KGraphic} arguments The elements to add to childNodes
+ @see KGroup#draw
+ **/
+ appendChild : function ( ) {
+ if ( arguments.length > 0 ) {
+ for ( var i = 0; i< arguments.length; i++) {
+ this.childNodes.push ( arguments[ i ] );
+ }
+ this.sorted = false;
+
+ }
+ },
+ removeChild: function () {
+ //FIXME
+ },
+ /**
+ @memberOf KGroup
+ Draws all the elements in childNodes. The elements are drawed according
+ to its 'z' (z-index) value.
+ @see KGroup#appendChild
+ **/
+ draw : function() {
+ if ( this.visible && this.childNodes.length > 0 ) {
+ if ( !this.sorted ) {
+ this.childNodes.sort ( function ( g1, g2 ) {
+ return g1.z - g2.z;
+ });
+ this.sorted = true;
+ }
+ for (var i in this.childNodes) {
+ this.childNodes[ i ].draw();
+ }
+ }
+ },
+ isPointInPath : function() {
+ //TODO
+ }
+
+ }
+);
+
+var KMedia = Class(
+
+ KObject,
+ {
+ init: function (file, type, options ) {
+ if ( !file || !type ) {
+ throw new Error ("file and type needed");
+ }
+ if ( valid ( options ) )
+ KObject.init.call (this, options);
+
+ this.file = file;
+ this.type = type;
+
+ this.status = undefined;
+ this.path = undefined;
+ this.media = undefined;
+ switch ( this.type ) {
+ case "image": this.media = new Image(); break;
+ case "sound": this.media = new Audio(); break;
+ default: throw new Error ("Media type not supported");
+ }
+ this.path = gk.paths[ this.type + "s" ][
+ this.localized ? "localized": "generic"
+ ];
+ this.media.src = this.src = this.path + this.file;
+
+ var that = this;
+ this.media.addEventListener("load",
+ function (e) { that.status = "loaded";}, false);
+ this.media.addEventListener("error",
+ function (e) { that.status = "error";}, false);
+ this.media.addEventListener("abort",
+ function (e) { that.status = "aborted";}, false);
+ }
+ }
+);
+
+var KImage = Class(
+ KGraphic,
+ KMedia,
+ {
+
+ init: function ( options ) {
+ if ( valid ( options, "string" ) ) {
+ options = { file:options };
+ }
+ if ( valid( options ) ) {
+ KGraphic.init.call(this, options);
+ KMedia.init.call(this, options.file, "image", options );
+ }
+ var defaultOptions = {
+ //w : undefined,
+ //h : undefined,
+ }
+ $.extend( this, defaultOptions, options);
+ },
+ draw : function( ctx, x, y ) {
+ if ( this.visible && this.isReady() ) {
+ this.x = x || this.x;
+ this.y = y || this.y;
+ ctx.drawImage( this.media, this.x , this.y );
+ }
+ },
+ isReady : function () {
+ if ( !this.media.complete ) return false;
+ if ( !this.media.naturalWidth || this.media.naturalWidth === 0)
+ return false;
+ return true;
+ }
+ }
+);
+/**@class_ */
+var KSound = Class(
+ /**@lends_ KMedia*/
+ KMedia,
+ {
+ init: function( options ) {
+ if ( valid ( options, "string" ) ) {
+ options = { file: options };
+ }
+ if ( valid( options ) ) {
+ KMedia.init.call(this, options.file, "sound", options );
+ //next line is important!
+ this.media.load();
+ }
+ },
+ isReady: function () {
+ return this.readyState === 4;
+ },
+ play: function (){
+ this.media.play();
+ }
+ }
+);
+/**@class_ */
+var KShape = Class(
+ /**@lends_ KGraphic*/
+ KGraphic,
+ {
+ init : function ( options ) {
+ if ( valid( options ) ) {
+ KGraphic.init.call(this, options );
+ }
+ var defaultOptions = {
+ fill: true,
+ stroke: true,
+ fillStyle: '#000',
+ strokeStyle: '#000',
+ openPath : false
+ }
+ $.extend( this, defaultOptions, options);
+ },
+ draw : function ( ctx ) {
+ if ( this.visible ) {
+ ctx.fillStyle = this.fillStyle
+ ctx.strokeStyle= this.strokeStyle
+ if ( this.fill )
+ ctx.fill();
+ if ( this.stroke )
+ ctx.stroke();
+ if ( !this.openPath )
+ ctx.closePath();
+ ctx.restore();
+ }
+ }
+ }
+);
+/**@class_ */
+var KRectangle = Class(
+ KShape,
+ {
+
+ init : function ( options ) {
+ //ADD multiple constructors support
+ //x,y,w,h
+ //w,y,w,h,options
+ if ( valid( options ) ) {
+ KShape.init.call(this, options );
+ }
+ },
+ draw : function ( ctx ) {
+ if ( this.visible ) {
+ ctx.save();
+ ctx.beginPath();
+ ctx.rect( this.x, this.y, this.width, this.height);
+ KShape.draw.call( this, ctx );
+ }
+ },
+ clear : function ( ) {
+ if ( this.visible ) {
+
+ }
+ }
+ }
+
+);
+
+/**@class_ */
+var KButton = Class(
+ /**@lends_ KGraphic*/
+ KGraphic,
+ {
+
+ init : function ( options ) {
+ //ADD multiple constructors support
+ //x,y,w,h
+ //w,y,w,h,options
+ if ( valid( options ) ) {
+ KGraphic.init.call(this, options );
+ }
+ this.id = options.id;
+ master.buttons.push(this);
+ },
+ draw : function ( ) {},
+ onClick : function() { } //callback
+ }
+);
+//
+/**
+Karma function. It's a shotcut for calling 'new Karma(..)'
+@param [options] Options passed to the Karma constructor
+@returns {Object} a new Karma object
+**/
+$.karma = function (options) {
+ var k =new Karma( options );
+ //var x = new KMedia( "file1", "image", {localized: true} );
+ //var x = new KImage({file: "ball.png", localized: false, z: 0});
+
+ return k;
+}
+})(jQuery); \ No newline at end of file