/*
 * jsonPageLoader
 *
 * version: 1.0.3
 * author: yusuke0927
 * url: http://www.sukechan.net/
 */

/* ---------------------------------- */

/* Parameter
 * 
 * url						:	必須。
 * cache					: キャッシュを利用するかどうかを true/false で指定します。指定しなければ true になりキャッシュが利用される可能性があります。
 * callbackString	:	callback パラメータ名を指定します。指定しなければ 'callback' になります。
 * pageString			:	page パラメータ名を指定します。指定しなければ 'page' になります。
 * start					:	開始ページ数を指定します。指定しなければ 1 ページ目から取得します。
 * end						:	必須。終了ページ数、または処理を継続するかどうかの関数を指定します。
										関数の場合、各ページ取得毎に実行され、false を返せば処理が終了します。引数は現在ページの取得結果とページ数です。
 * onStart				:	各ページの JSONP 取得開始時に呼び出される関数を指定します。引数はページ数です。
 * onEnd					: 各ページの JSONP 取得完了時に呼び出される関数を指定します。引数は当該ページの取得結果とページ数です。
 * callback				: 全ページの JSONP 取得完了時に呼び出される関数を指定します。引数はページ番号を添字とした配列と開始、終了ページ数です。
 */

/* Version History
 * 
 * 1.0.3 (2009/05/25)
 *		Array.prototype を拡張している場合に Win IE でエラーになる問題を修正
 * 1.0.2 (2009/05/23)
 *		end 関数の引数にページ数を追加
 * 1.0.1 (2009/05/23)
 *		cache パラメータを追加
 * 1.0 (2009/04/19)
 *		公開
 */
 
/* ---------------------------------- */

function jsonPageLoader(option) {
	this.id = (new Date()).getTime();
	this.url = option.url;
	this.cache = (option.cache === false) ? false : true;
	this.results = [];
	this.page = option.start || 1;
	this.pageString = option.page || 'page';
	this.end = option.end;
	this.onStart = option.onStart;
	this.onEnd = option.onEnd;
	this.callback = option.callback;
	this.callbackString = option.callbackString || 'callback';
	
	if((this.url) && ((typeof(this.end) == 'function') || (typeof(this.end) == 'number'))) {
		this.request(this.page);
	}
}

jsonPageLoader.prototype.request = function() {
	var self = this;
	var url = '';
	var callbackName = 'jsonPageLoader' + self.id + '_' + self.page;
	url = self._setQueryString(self.url, self.pageString, self.page);
	url = self._setQueryString(url, self.callbackString, callbackName);
	
	if(self.onStart) {
		self.onStart(self.page);
	}
	
	var s = document.createElement('script');
	s.type = 'text/javascript';
	s.src = url;
	if(!self.cache) {
		s.src += '&d=' + (new Date()).getTime();
	}
	s.charset = 'UTF-8';
	document.getElementsByTagName('head')[0].appendChild(s);
	
	window[callbackName] = function(result) {
		if(self.onEnd) {
			self.onEnd(result, self.page);
		}
		self.results[self.page] = result;
		
		if((typeof(self.end) == 'function') && (self.end(result, self.page))) {
			self.page++;
			self.request();
		} else if((typeof(self.end) == 'number') && (self.page < self.end)) {
			self.page++;
			self.request();
		} else {
			self.callback(self.results, self.start, self.page);
		}
		
		window[callbackName] = undefined;
		try {
			delete window[callbackName];
		} catch(e) {
			document.getElementsByTagName('head')[0].removeChild(s);
		}
	}
}

jsonPageLoader.prototype._setQueryString = function(url, key, value) {
	var qs = this._parseQueryString(url);
	if(qs) {
		qs[key] = value;
		var idx = url.indexOf('?');
		if(idx > -1) {
			url = url.substring(0, idx);
		}
		return this._createQueryString(url, qs);
	}
}

jsonPageLoader.prototype._parseQueryString = function(url) {
	if((typeof(url) != 'string') || (url.length == 0)) return null;
	var qs = new Array();
	var idx = url.indexOf('?');
	if(idx > -1) {
		var arr = url.substr(idx + 1).split('&');
		for(var i in arr) {
			if(arr.hasOwnProperty(i)) {
				var x = arr[i].split('=');
				qs[x[0]] = x[1];
			}
		}
	}
	return qs;
}

jsonPageLoader.prototype._createQueryString = function(url, arr) {
	var qs = '';
	if(arr) {
		for(var i in arr) {
			if(arr.hasOwnProperty(i)) {
				qs += ((qs.length == 0) ? '?' : '&') + i + '=' + arr[i];
			}
		}
	}
	return url + qs;
}