/**
 * jQueryオブジェクトの拡張
 *
 * @name jquery.init.js
 */
(function($) {
	/**
	 * userAgent判定フラグ
	 *
	 * @date 2011-06-06
	 */
	var ua = navigator.userAgent.toLowerCase();
	$.ua = {
		// IE
		isIE: /msie (\d+)/.test(ua),
		// IE6
		isIE6: /msie (\d+)/.test(ua) && RegExp.$1 == 6,
		// IE9未満
		isLtIE9: /msie (\d+)/.test(ua) && RegExp.$1 < 9,
		// iOS
		isIOS: /i(phone|pod|pad)/.test(ua),
		// iPhone、iPod touch
		isIPhone: /i(phone|pod)/.test(ua),
		// iPad
		isIPad: /ipad/.test(ua),
		// Android
		isAndroid: /android/.test(ua),
		// モバイル版Android
		isAndroidMobile: /android(.+)?mobile/.test(ua)
	};



	/**
	 * ロールオーバー
	 *
	 * @date 2011-05-30
	 *
	 * @example $('.rollover').rollover();
	 * @example $('.rollover').rollover({ over: '-ov' });
	 * @example $('.rollover').rollover({ on: '_on', onOver: '_on_ov' });
	 */
	$.fn.rollover = function(options) {
		var defaults = {
			over: '_ov',
			on: null,
			onOver: null
		};
		var settings = $.extend({}, defaults, options);
		var over = settings.over;
		var on = settings.on;
		var onOver = settings.onOver;
		return this.each(function() {
			var src = this.src;
			var ext = /\.(gif|jpe?g|png)(\?.*)?/.exec(src)[0];
			var isOn = on && new RegExp(on + ext).test(src);
			if (isOn && !onOver) return;
			var search = (isOn && onOver) ? on + ext : ext;
			var replace = (isOn && onOver) ? onOver + ext : over + ext;
			var overSrc = src.replace(search, replace);
			new Image().src = overSrc;
			$(this).mouseout(function() {
				this.src = src;
			}).mouseover(function() {
				this.src = overSrc;
			});
		});
	};



	/**
	 * スムーズスクロール
	 *
	 * @date 2011-05-30
	 *
	 * @example $.scroller();
	 * @example $.scroller({ hashMark: false });
	 * @example $.scroller({ noscroll: '.no-scroll' });
	 * @example $.scroller('#content');
	 * @example $.scroller('#content', { pitch: 20, delay: 5 });
	 */
	$.scroller = function() {
		var self = arguments.callee.prototype;
		if (!arguments[0] || typeof arguments[0] == 'object') {
			self.init.apply(self, arguments);
		} else {
			self.scroll.apply(self, arguments);
		};
	};

	// プロトタイプにメンバを定義
	$.scroller.prototype = {
		// 初期設定
		defaults: {
			hashMark: true,
			noscroll: '.noscroll',
			pitch: 10,
			delay: 10
		},

		// 初期化
		init: function(options) {
			var self = this;
			var settings = this.settings = $.extend({}, this.defaults, options);
			$('a[href^="#"]:not(' + settings.noscroll + ')').each(function() {
				var hash = this.hash || '#';
				$(this).click(function(e) {
					e.preventDefault();
					this.blur();
					self.scroll(hash);
				});
			});
		},

		// スクロールを実行
		scroll: function(id, options) {
			if (this.timer) this.clearScroll();
			var settings = (options) ? $.extend({}, this.defaults, options) : (this.settings) ? this.settings : this.defaults;
			if (!settings.hashMark && id == '#') return;
			var self = this;
			var win = window;
			var $win = $(win);
			var d = document;
			var pitch = settings.pitch;
			var delay = settings.delay;
			var scrollLeft = $win.scrollLeft();
			if (($.ua.isIPhone || $.ua.isAndroidMobile) && win.pageYOffset == 0) win.scrollTo(scrollLeft, (($.ua.isAndroidMobile) ? 1 : 0));
			var scrollEnd = (id == '#') ? 0 : $(id + ', a[name="' + id.substr(1) + '"]').eq(0).offset().top;
			var windowHeight = ($.ua.isAndroidMobile) ? Math.ceil(win.innerWidth / win.outerWidth * win.outerHeight) : win.innerHeight || d.documentElement.clientHeight;
			var scrollableEnd = $(d).height() - windowHeight;
			if (scrollableEnd < 0) scrollableEnd = 0;
			if (scrollEnd > scrollableEnd) scrollEnd = scrollableEnd;
			if (scrollEnd < 0) scrollEnd = 0;
			scrollEnd = Math.floor(scrollEnd);
			if ($.ua.isAndroid && scrollEnd == 0) scrollEnd = 1;
			var dir = (scrollEnd > $win.scrollTop()) ? 1 : -1;
			(function() {
				var callee = arguments.callee;
				var prev = self.prev;
				var current = self.current || $win.scrollTop();
				if (current == scrollEnd || typeof prev == 'number' && (dir > 0 && current < prev || dir < 0 && current > prev)) {
					self.clearScroll();
					return;
				};
				var next = current + (scrollEnd - current) / pitch + dir;
				if (dir > 0 && next > scrollEnd || dir < 0 && next < scrollEnd) next = scrollEnd;
				win.scrollTo(scrollLeft, next);
				self.prev = current;
				self.current = next;
				self.timer = setTimeout(function() {
					callee();
				}, delay);
			})();
		},

		// スクロールを解除
		clearScroll: function() {
			clearTimeout(this.timer);
			this.timer = null;
			this.prev = null;
			this.current = null;
		}
	};



	/**
	 * orientationchangeに関するイベントハンドラ登録用メソッド
	 *
	 * @date 2011-05-30
	 *
	 * @example $(window).orientationchange(function() { alert(window.orientation); });
	 * @example $(window).portrait(function() { alert(window.orientation); });
	 * @example $(window).landscape(function() { alert(window.orientation); });
	 */
	var type = ($.ua.isAndroid) ? 'resize' : 'orientationchange';
	$.fn.extend({
		// オリエンテーションチェンジ
		orientationchange: function(fn) {
			return this.bind(type, fn);
		},
		// ポートレイト
		portrait: function(fn) {
			return this.bind(type, function() {
				if (window.orientation === 0) fn();
			});
		},
		// ランドスケープ
		landscape: function(fn) {
			return this.bind(type, function() {
				if (window.orientation !== 0) fn();
			});
		}
	});



	/**
	 * script要素のsrc属性を利用して指定したファイル名のルートにあたるパスを取得
	 *
	 * @date 2011-06-20
	 *
	 * @example $.getScriptRoot('common/js/base.js');
	 */
	$.getScriptRoot = function(filename) {
		var elms = document.getElementsByTagName('script');
		for (var i = elms.length - 1; i >= 0; i--) {
			var src = elms[i].src;
			if (new RegExp('(.*)?' + filename + '([\?].*)?').test(src)) return RegExp.$1;
		};
		return false;
	};



	/**
	 * script要素のsrc属性からオブジェクトに変換したクエリを取得
	 *
	 * @date 2011-06-20
	 *
	 * @example $.getScriptQuery();
	 * @example $.getScriptQuery('common/js/base.js');
	 */
	$.getScriptQuery = function(filename) {
		var elms = document.getElementsByTagName('script');
		if (!filename) {
			return $.getQuery(elms[elms.length - 1].src);
		} else {
			for (var i = elms.length - 1; i >= 0; i--) {
				var src = elms[i].src;
				if (new RegExp(filename).test(src)) return $.getQuery(src);
			};
			return false;
		};
	};



	/**
	 * 文字列からオブジェクトに変換したクエリを取得
	 *
	 * @date 2011-05-30
	 *
	 * @example $.getQuery();
	 * @example $.getQuery('a=foo&b=bar&c=foobar');
	 */
	$.getQuery = function(str) {
		if (!str) str = location.search;
		str = str.replace(/^.*?\?/, '');
		var query = {};
		var temp = str.split(/&/);
		for (var i = 0, l = temp.length; i < l; i++) {
			var param = temp[i].split(/=/);
			query[param[0]] = decodeURIComponent(param[1]);
		};
		return query;
	};



	/**
	 * デバッグ
	 *
	 * @date 2011-05-12
	 *
	 * @example $.debug.dump(window, 'html');
	 * @example $.debug.alert([screen.height, screen.availHeight]);
	 * @example $.debug.html([screen.height, screen.availHeight]);
	 */
	$.debug = {
		// ダンプ
		dump: function(obj, mode) {
			var temp = [];
			for (var key in obj) temp.push(key + ': ' + obj[key]);
			if (mode == 'alert') {
				this.alert(temp);
			} else {
				this.html(temp);
			};
		},

		// アラートを表示
		alert: function(src) {
			alert(src.join('\n'));
		},

		// HTMLを出力
		html: function(src) {
			if (!$('#debug').get(0)) {
				$('body').eq(0).prepend('<div id="debug" style="padding:15px 15px 15px 15px;" />');
			};
			$('#debug').html(src.join('<br />'));
			location.href = '#debug';
		}
	};
})(jQuery);










