[JavaScript] ratween CSS3 Transition jQuery plugin

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

[Android] how to include your app into list in dialog which is launched when you put device on cradle or dock

December 10th, 2011

I am very in trouble not to find how to solve the problem.
The problem is that I want to include my app into list in dialog.
The dialog is launched when I put device on cradle or dock.

I have searched for a very long time.
And finally I found it!

The hint page is here. I appreciate the author writing it very much.
Custom CAR DOCK application in Android

I have to use intent. And the setting is following.

AndroidManifest.xml

            <intent-filter >
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
                <category android:name="android.intent.category.DESK_DOCK" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>

This resolve point is I have to use both category.DESK_DOCK and category.DEFAULT together.
If I use only which one of those, it can’t work.

Here is the screenshot.
DeskDockTest app is my application.
The others are default app of devices.

[Javascript] jQuery mielogger Plugin : Make Any Log Visible

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

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

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>

[Android] Async download file from network and save it in external SD card

November 15th, 2011

I created Async download class.

This usage app is..

Push download button. Then it starts downloading file from network.

When downloading is completed, it saves file in external sd card.

Add user permission in AndroidManifest.xml

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.INTERNET"/>

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <Button
        android:id="@+id/loadStartButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Download" />

</LinearLayout>

AsyncFileLoader.java

I used AsyncTask.
And I read input file little by little and write output file with InputStream and OutputStream.


package com.kinkuma.util;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;

import android.os.AsyncTask;
import android.util.Log;

public class AsyncFileLoader extends AsyncTask<Void, Void, Boolean> {
	private final String TAG = "AsyncFileLoader";
	private String _urlStr;
	private URL _url;
	private URLConnection _urlConnection;
	private final int TIMEOUT_READ = 5000;
	private final int TIMEOUT_CONNECT = 30000;
	private InputStream _inputStream;
	private BufferedInputStream _bufferedInputStream;
	private FileOutputStream _fileOutputStream;
	private File _outputFile;
	private byte[] buff = new byte[5 * 1024];
	
	private int _totalByte = 0;
	private int _currentByte = 0;
	
	public AsyncFileLoader(String urlStr, File outputFile){
		this._urlStr = urlStr;
		this._outputFile = outputFile;
	}
	
	@Override
	protected Boolean doInBackground(Void... params) {
		
		if(isCancelled()){
			return false;
		}
		
		try{
			int len;
			while((len = _bufferedInputStream.read(buff)) != -1){
				_fileOutputStream.write(buff, 0, len);
				_currentByte += len;
				//publishProgress();
				if(isCancelled()){
					break;
				}
			}
	
		}catch(IOException e){
			Log.d(TAG, "error on read file:" + e.toString());
			return false;
		}
		return true;
	}
	
	@Override
	protected void onPreExecute(){
		try{
			connect();
		}catch(IOException e){
			Log.d(TAG, "error on preExecute:" + e.toString());
			cancel(true);
		}
	}
	/*
	@Override
	protected void onProgressUpdate(Void... progress){
		
	}
	*/
	@Override
	protected void onPostExecute(Boolean result){
		if(result == true){
			try{
				close();
			}catch(IOException e){
				Log.d(TAG, "error on postExecute:" + e.toString());
			}
		}else{
			Log.d(TAG, "result: load error");
		}
	}
	
	private void connect() throws IOException
	{
		_url = new URL(_urlStr);
		_urlConnection = _url.openConnection();
		_urlConnection.setReadTimeout(TIMEOUT_READ);
		_urlConnection.setConnectTimeout(TIMEOUT_CONNECT);
		_inputStream = _urlConnection.getInputStream();
		_bufferedInputStream = new BufferedInputStream(_inputStream, 1024 * 5);
		_fileOutputStream = new FileOutputStream(_outputFile);
		
		//_totalByte = _bufferedInputStream.available(); //this is not work
		_totalByte = _urlConnection.getContentLength();
		_currentByte = 0;
	}
	
	private void close() throws IOException
	{
		_fileOutputStream.flush();
		_fileOutputStream.close();
		_bufferedInputStream.close();
	}
	
	public int getLoadedBytePercent()
	{
		if(_totalByte <= 0){
			return 0;
		}
		//Log.d(TAG, Integer.toString(_currentByte) + ":" + Integer.toString(_totalByte));
		return (int)Math.floor(100 * _currentByte/_totalByte);
	}
}

main activity

To get the external sd card path, I used Environment.getExternalStorageDirectory().

package com.myprogress;

import java.io.File;

import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button;

import com.kinkuma.util.AsyncFileLoader;

public class DownloadingAndProgressbarActivity extends Activity {
    private final String TAG = "DownloadSample";
	private Button _loadStartButton;
	private ProgressDialog _progressDialog;
	private Handler _progressHandler;
	private final String VIDEO_URL = "http://192.168.1.0/video/sample_movie.mp4";
	private AsyncFileLoader _fileLoader;
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        _loadStartButton = (Button)findViewById(R.id.loadStartButton);
        _loadStartButton.setOnClickListener(new View.OnClickListener() {
		
			@Override
			public void onClick(View v) {
				initFileLoader();
				showDialog(0);
				_progressDialog.setProgress(0);
				_progressHandler.sendEmptyMessage(0);
			}
		});
        
        _progressHandler = new Handler(){
        	public void handleMessage(Message msg){
        		super.handleMessage(msg);
        		if(_fileLoader.isCancelled()){
        			_progressDialog.dismiss();
        			Log.d(TAG, "load canceled");
        		}
        		else if(_fileLoader.getStatus() == AsyncTask.Status.FINISHED){
        			_progressDialog.dismiss();
        		}else{
        			_progressDialog.setProgress(_fileLoader.getLoadedBytePercent());
        			_progressHandler.sendEmptyMessageDelayed(0, 100);
        		}
        	}
        };
    }
    
    @Override
    protected void onPause(){
    	Log.d(TAG, "onPause");
    	super.onPause();
    	cancelLoad();
    }
    
    @Override
    protected void onStop(){
    	Log.d(TAG, "onStop");
    	super.onStop();
    	cancelLoad();
    }
    
    private void cancelLoad()
    {
    	if(_fileLoader != null){
    		_fileLoader.cancel(true);
    	}
    }
    
    private void initFileLoader()
    {
    	File sdCard = Environment.getExternalStorageDirectory();
    	File directory = new File(sdCard.getAbsolutePath() + "/SampleFolder");
    	if(directory.exists() == false){
    		directory.mkdir();
    	}
    	File outputFile = new File(directory, "myvideo.mp4");
    	_fileLoader = new AsyncFileLoader(VIDEO_URL, outputFile);
    	_fileLoader.execute();
    }
    
    @Override
    protected Dialog onCreateDialog(int id){
    	switch(id){
    		case 0:
    			_progressDialog = new ProgressDialog(this);
    			_progressDialog.setIcon(R.drawable.ic_launcher);
    			_progressDialog.setTitle("Downloading files..");
    			_progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
    			_progressDialog.setButton(DialogInterface.BUTTON_POSITIVE, "Hide", new DialogInterface.OnClickListener() {
					
				@Override
				public void onClick(DialogInterface dialog, int which) {
						Log.d(TAG, "hide");
					}
				});
    			_progressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "Cancel", new DialogInterface.OnClickListener() {
					
					@Override
					public void onClick(DialogInterface dialog, int which) {
						Log.d(TAG, "cancel");
						cancelLoad();
					}
				});
    	}
		return _progressDialog;
    }
}