Archive for the ‘JavaScript’ Category

[JavaScript] 3D on Canvas2D

Tuesday, December 20th, 2011

I am learning 3D basic theory again.


I have been using these books.
They are very kind for beginners like me.

>> Beginning Math and Physics for Game Programmers [Paperback]
>> Foundation ActionScript 3.0 Animation: Making Things Move! [Paperback]

Although I have learned 3D basic theory in AS3 before, I am trying to implement it by JavaScript.

I wrote above demo by this way.
I wrote CoffeeScript first.
Then it is compiled to js file by Cakefile which watches the .coffee files in certain directory.

[JavaScript] watch and compile, then concatenate them in CoffeeScript Cakefile

Saturday, December 17th, 2011

I am learning CoffeeScript.
I saw Cakefile, and learned it.
I found that it behaves like batch file.

Then I wanted it to use as these way.

1. It keeps watching src/*.coffee files
2. When they are changed, it compiles them
3. It concatenates compiled files to lib/main.js

I made below code.
Although I don’t know whether it is correct or not, it works.

Cakefile

{spawn} = require 'child_process'

task 'watch', 'watch src/ and concatenate them to lib/main.js', (callback) -> 
  watch = spawn 'coffee', ['-w', 'src/']
  watch.stderr.on 'data', (data) ->
    process.stderr.write data.toString()
  watch.stdout.on 'data', (data) ->
    console.log 'file changed'
    build = spawn 'coffee', ['-j', 'lib/main.js', '-cl', 'src/']
    build.stderr.on 'data', (data) ->
      process.stderr.write data.toString()
    build.on 'exit', (code) ->
      if code is 0
        console.log 'build complete'

How to use
In terminal type this

cake watch

I refered these pages. Thanks.

>> node.js – coffee script cakefile task not finishing – Stack Overflow
>> [HowTo] Compiling and Setting Up Build Tools – GitHub
>> The Little Book on CoffeeScript – Compiling
>> Cakefile(zsh) – podhmoの日記
>> CakeFileの使い方 -CoffeeScript- – プログラムdeタマゴ

[JavaScript] ratween CSS3 Transition jQuery plugin

Tuesday, December 13th, 2011

I made ratween jQuery plugin .
This plugin makes elements CSS3 transition.

See demo

>>Download it from github.

It’s very convenient plugin when you develop webkit browser in iOS.
Because CSS3 transition is faster than normal css tween.

These pages contains very useful information.
Thank you for writing.

>> Plugins/Authoring – jQuery JavaScript Library
>> Detecting and generating CSS animations in JavaScript ✩ Mozilla Hacks – the Web developer blog
>> CSS transitions – MDN
>> Visualize and manipulate CSS transition functions

[Javascript] jQuery mielogger Plugin : Make Any Log Visible

Friday, December 2nd, 2011

I made a jQuery plugin named mielogger.

This makes any string you set visible on browser.
It was named from mieru (it means ‘you can see’ in Japanese ) and logger.

It is very useful tool, when you develop mobile browser app such as iOS, Android, etc.
Because those devices can’t be shown console.log() function.
But if log is visible in browser, you can see it.

update Dec. 10th 2011

>> demo
>> download mielogger

how to use

First, you must import jQuery and mielogger.js.

	<script src="jquery-1.6.2.min.js"></script>
	<script src="mielogger.js"></script>

Seccond, init mieLogger.

var logger = $().mielogger();

Third, you can write any string on it with log method.

logger.mlog('Hello mielogger');

I used mielogger’s instance on the last code. But you can also use this way.

$().mlog("It's OK");

option settings

You can set options to it when you init it.

There are some parameters.

width : log area width
height : log area height
maxlow : max log line length. mielogger can hold lines over the height of it
align : if it is set, log area’s layout is changed.
‘TL’ top left
‘TR’ top right
‘BL’ bottom left
‘BR’ bottom right

example1: width 300px, height 100px

$().mielogger({width:300,height:100});

example2: width 450px, maxlow 100

$().mielogger({width:450,maxlow:100});

example3: align BL

$().mielogger({align:'BL'});

Let’s log it.

[JavaScript] Asynchronous library in Javascript

Thursday, December 1st, 2011

I wrote asynchronous JavaScript library.

Here is the code.

if(!window.kinkuma){
	window.kinkuma = {}
}
(function(pkg){
	/**
	 * Command - base class
	 */
	pkg.Command = function(){
		this.delegate;
	};
	pkg.Command.prototype = {
		execute:function(){
		},
		onComplete:function(){
			if(this.delegate){
				this.delegate();
			}
		}
	}
	
	/**
	 * FuncCommand - function command
	 * @param func Object - function reference you want to run
	 */
	pkg.FuncCommand = function(func){
		this.targetFunction = func;
	};
	pkg.FuncCommand.prototype = new pkg.Command();
	pkg.FuncCommand.prototype.execute = function(){
		this.targetFunction();
		this.onComplete();
	};
	
	/**
	 * WaitCommand - timer command
	 * @param waitTime Numer - it's not milliseconds but second
	 */
	pkg.WaitCommand = function(waitTime){
		this.waitTime = waitTime;
		this.timerId;
	};
	pkg.WaitCommand.prototype = new pkg.Command();
	pkg.WaitCommand.prototype.execute = function(){
		var self = this;
		this.timerId = setTimeout(function(){self.onComplete();}, this.waitTime * 1000);
	};
	
	/**
	 * ParallelCommand - run all commands together
	 */
	pkg.ParallelCommand = function(){
		this.commands = [];
		this.count;
	};
	pkg.ParallelCommand.prototype = new pkg.Command();
	pkg.ParallelCommand.prototype.execute = function(){
		if(this.commands.length == 0){
			this.commands = [];
			this.onComplete();
		}else{
			this.count = 0;
			var i, len;
			len = this.commands.length;
			var command;
			var self = this;
			for(i = 0; i < len; i++){
				command = this.commands[i];
				command.delegate = function(){self.commandComplete()};
				command.execute();
			}
		}
	};
	pkg.ParallelCommand.prototype.add = function(command){
		this.commands.push(command);
	};
	pkg.ParallelCommand.prototype.commandComplete = function(){
		this.count++;
		if(this.count == this.commands.length){
			this.onComplete();
		}
	};

	/**
	 * SerialCommand - serial run command
	 */
	pkg.SerialCommand = function(){
		this.commands = [];
		this.currentCommand;
	};
	pkg.SerialCommand.prototype = new pkg.Command();
	pkg.SerialCommand.prototype.execute = function(){
		if(this.commands.length == 0){
			this.onComplete();
		}else{
			this.currentCommand = this.commands.shift();
			var self = this;
			this.currentCommand.delegate = function(){self.commandComplete();};
			this.currentCommand.execute();
		}
	};
	pkg.SerialCommand.prototype.add = function(command){
		this.commands.push(command);
	}
	pkg.SerialCommand.prototype.commandComplete = function(){
		this.currentCommand = null;
		this.execute();
	};
})(kinkuma);

Usage

This function named 'trace' is used with these usage. It's not so important.

function trace(message){
	console.log(message);
}

Let's start it.

WaitCommand
It's a timer class.

var mywait = new kinkuma.WaitCommand(1.0);
mywait.execute();

You can add callback function.

var mywait2 = new kinkuma.WaitCommand(2.0);
mywait2.delegate = function(){
	trace('mywait2 finished');
};
mywait2.execute();

FuncCommand
It's function command. You have to input function reference to constructor's argument.

var myfunc = new kinkuma.FuncCommand(function(){
	trace('myfunc done');
});
myfunc.execute();

You can add callback function.

var myfunc2 = new kinkuma.FuncCommand(function(){
	trace('myfunc2 done');
});
myfunc2.delegate = function(){
	trace('myfunc2 complete');
};
myfunc2.execute();

ParallelCommand
These commands will start in the same time.

var k = kinkuma;
var para = new k.ParallelCommand();
para.add(new k.WaitCommand(1.0));
para.add(new k.FuncCommand(function(){trace('para func1');}));
para.delegate = function(){ trace('finish para');};
para.execute(); 

SerialCommand
Serial execute commands.

var k = kinkuma;
var sc = new k.SerialCommand();
sc.add(new k.WaitCommand(0.5));
sc.add(new k.FuncCommand(function(){trace('seri func1');}));
sc.add(new k.WaitCommand(3.0));
sc.delegate = function(){trace('finish serial');};
sc.execute(); 

Parallel and Serial Mix in
It's very interesting time. You can mix with ParallelCommand and SerialCommand.

var k = kinkuma;
var p = new k.ParallelCommand();
p.add(new k.FuncCommand(function(){
	trace('para func1');
}));
p.add(new k.FuncCommand(function(){
	trace('para func2');
}));
var s = new k.SerialCommand();
s.add(new k.WaitCommand(1.0));
s.add(p);
s.delegate = function(){
	trace('mix finish!');
};
s.execute();

I referred to below ActionScript3 codes in Japan, when I created it.
>> Commands (@fladdict)
>> Progression (@nium)

Thank you for reading it.

[JavaScript] Observer pattern like EventDispatcher in AS3

Tuesday, November 29th, 2011

I made Observer pattern classes in JavaScript.
Here is code.

var kinkuma = {}; //package name
(function(pkg){
	pkg.Event = function(){
		this.target;
		this.context;
	};
	pkg.Observer = function(){
		this.listeners = {};
	};
	pkg.Observer.prototype = {
		addObserver:function(type, listener, context){
			var listeners = this.listeners;
			if(!listeners[type]){
				listeners[type] = [];
			}
			listeners[type].push([listener, context]);
		},
		removeObserver:function(type, listener){
			var listeners = this.listeners;
			if(listeners[type]){
				var i;
				var len = listeners[type].length;
				for(i = len - 1; i >= 0; i--){
					var arr = listeners[type][i];
					if(arr[0] == listener){
						listeners[type].splice(i, 1);
					}
				}
			}
		},
		notify:function(type){
			var listeners = this.listeners;
			var e = new pkg.Event();
			e.target = this;
			if(listeners[type]){
				var i;
				var len = listeners[type].length;
				for(i = 0; i < len; i++){
					var arr = listeners[type][i];
					e.context = arr[1];
					arr[0](e);
				}
			}
		}
	}
})(kinkuma);

Usage 1 simple

I made simple class.

var MyData = function(){
	this.change = function(){
		this.notify("CHANGE"); //trigger
	};
};
MyData.prototype = new kinkuma.Observer(); //extends Observer

function hello(){
	alert('hello');
}

var d = new MyData();
d.addObserver("CHANGE", hello); //linkage with hello function
d.change(); //let's try

Usage 2 With MVC pattern like in AS3

>> Would you try to do this page.

If you push button, mycar moves to right.
But if it is over 200px, it stops to move.

I used MVC pattern.

The code is here.

<html>
<head>
<meta charset="UTF-8" />
<script type="text/javascript" src="jquery-1.6.2.min.js"></script>
<script type="text/javascript">

var kinkuma = {}; //package name
(function(pkg){
	pkg.Event = function(){
		this.target;
		this.context;
	};
	pkg.Observer = function(){
		this.listeners = {};
	};
	pkg.Observer.prototype = {
		addObserver:function(type, listener, context){
			var listeners = this.listeners;
			if(!listeners[type]){
				listeners[type] = [];
			}
			listeners[type].push([listener, context]);
		},
		removeObserver:function(type, listener){
			var listeners = this.listeners;
			if(listeners[type]){
				var i;
				var len = listeners[type].length;
				for(i = len - 1; i >= 0; i--){
					var arr = listeners[type][i];
					if(arr[0] == listener){
						listeners[type].splice(i, 1);
					}
				}
			}
		},
		notify:function(type){
			var listeners = this.listeners;
			var e = new pkg.Event();
			e.target = this;
			if(listeners[type]){
				var i;
				var len = listeners[type].length;
				for(i = 0; i < len; i++){
					var arr = listeners[type][i];
					e.context = arr[1];
					arr[0](e);
				}
			}
		}
	}
})(kinkuma);

function trace(str){
	console.log(str);
}

var DataEvent = {
	CHANGE:"change"
}

//Model
var CarData = function(){
	this.posX = 0;
};
CarData.prototype = new kinkuma.Observer();
CarData.prototype.setPosX = function(aPosX){
	this.posX = aPosX;
	this.notify(DataEvent.CHANGE);
};

//View
var CarView = function(data){
	this.cardata = data;
	this.view;
	this.cardata.addObserver(DataEvent.CHANGE, this.onCardataChange, this);
	this.createView();
};
CarView.prototype.createView = function(){
	$('body').append('<div id="carview" style="width:60px;height:30px;background-color:#aaa;position:absolute;top:100px;left:0px;font-size:12px;text-align:center;font-family:sans-serif">mycar</div>');
	this.view = $('#carview');
};
CarView.prototype.onCardataChange = function(e){
	var self = e.context; //CarView instance
	var data = e.target; //observer instance
	self.view.css({left:data.posX + 'px'});
	if(data.posX > 200){
		self.cardata.removeObserver(DataEvent.CHANGE, self.onCardataChange);
	}
};

//Main
var Main = function(){
	this.cardata;
	this.carView;
};
Main.prototype = {
	init:function(){
		var self = this;
		this.cardata = new CarData();
		this.carView = new CarView(this.cardata);
		$('#pushBtn').click(function(){
			self.cardata.setPosX(self.cardata.posX + 20);
		});
	}
}

$(function(){
	var m = new Main();
	m.init();
});

</script>
</head>
<body>

<input id="pushBtn" type="button" value="pushme" />
</body>
</html>