/*
$Rev: 16 $
*/
(function(){


/* =============== create CWAVE global object and prepartions =============== */
/**
 * 
 */
var window = this;
// supplements 'undefined'
window.undefined = window.undefined;

$.easing.def = 'easeOutCubic';

window.CWAVE = $.extend(window.CWAVE, new (function() {
	var d  = document;
	var de = d.documentElement;
	var di = d.implementation;
	var ua = navigator.userAgent;
	
	/**
	 * 
	 */
	this.settings        = {};
	this.settings.common = { useBackCompat : false, showGeometry : false };

	/**
	 * 
	 */
	this.ua              = {};
	this.ua.versionText  = $.browser.version;
	this.ua.version      = parseFloat($.browser.version);
	this.ua.isGecko      = !!$.browser.mozilla;
	this.ua.isSafari     = !!$.browser.safari;  // deprecated
	this.ua.isWebkit     = !!$.browser.webkit;
	this.ua.isOpera      = !!$.browser.opera;
	this.ua.isIE         = !!$.browser.msie;
	this.ua.isWin        = /Win/.test(ua);
	this.ua.isMac        = /Mac/.test(ua);
	this.ua.isQuirksMode = (d.compatMode == 'BackCompat' || this.ua.isIE && this.ua.version < 6);
	this.ua.documentMode = (!this.ua.isIE        ) ? 0               :
	                       (d.documentMode       ) ? d.documentMode  :
	                       (!this.ua.isQuirksMode) ? this.ua.version :
	                                                 5               ;
	this.ua.isDOMReady   = (di) ? di.hasFeature('HTML', '1.0') : (this.ua.isIE && de);
	
	this.geom            = {};
	
	this.env             = {};
	this.env.isOnline    = /^https?\:$/.test(location.protocol);
	this.env.isDOMReady  = false;

}));

if (typeof window.console != 'object') {
	window.console = {
		  element           : null
		, firebug           : "0"
		, userObjects       : {}
		, assert            : function(){}
		, clear             : function(){}
		, count             : function(){}
		, debug             : function(){}
		, dir               : function(){}
		, dirxml            : function(){}
		, error             : function(){}
		, getFirebugElement : function(){}
		, group             : function(){}
		, groupCollapsed    : function(){}
		, groupEnd          : function(){}
		, log               : function(){}
		, notifyFirebug     : function(){}
		, profile           : function(){}
		, profileEnd        : function(){}
		, time              : function(){}
		, timeEnd           : function(){}
		, trace             : function(){}
		, warn              : function(){}
	};
}

if (typeof window.Node == 'undefined') {
	window.Node = {
		  ELEMENT_NODE                : 1
		, ATTRIBUTE_NODE              : 2
		, TEXT_NODE                   : 3
		, CDATA_SECTION_NODE          : 4
		, ENTITY_REFERENCE_NODE       : 5
		, ENTITY_NODE                 : 6
		, PROCESSING_INSTRUCTION_NODE : 7
		, COMMENT_NODE                : 8
		, DOCUMENT_NODE               : 9
		, DOCUMENT_TYPE_NODE          : 10
		, DOCUMENT_FRAGMENT_NODE      : 11
		, NOTATION_NODE               : 12
	};
}


/* =============== regester onload func =============== */

(function() {
	// prevent background image flicker.
	if (CWAVE.ua.isIE) try { document.execCommand('BackgroundImageCache', false, true) } catch(err) { }

	$(function() {
		CWAVE.env.isDOMReady = true;
		new CWAVE.Timeout(function() {
			$(document.body).addClass('cwave-enabled');
			if (CWAVE.settings.common.useBackCompat) $(document.body).addClass('dom-enabled');
			if (CWAVE.settings.common.showGeometry ) BAJL.GetGeometry.continuously();
		}, 1);
	});
})();


/* =============== custom / shortage methods for built-in objects =============== */

/* ----- Array.indexOf() ----- */

if (!Array.prototype.indexOf) {
	Array.prototype.indexOf = function(aSearchElement, aFromIndex) {
		if (typeof aFromIndex != 'number') {
			aFromIndex = 0;
		} else if (aFromIndex < 0) {
			aFromIndex = this.length + aFromIndex;
		}
		for (var i = aFromIndex, n = this.length; i < n; i++) {
			if (this[i] === aSearchElement) {
				return i;
			}
		}
		return -1;
	};
}

/* ----- Array.lastIndexOf() ----- */

if (!Array.prototype.lastIndexOf) {
	Array.prototype.lastIndexOf = function(aSearchElement, aFromIndex) {
		if (typeof aFromIndex != 'number') {
			aFromIndex = this.length - 1;
		} else if (aFromIndex < 0) {
			aFromIndex = this.length + aFromIndex;
		}
		for (var i = aFromIndex; i >= 0; i--) {
			if (this[i] === aSearchElement) {
				return i;
			}
		}
		return -1;
	};
}

/* ----- Array.forEach() ----- */

if (!Array.prototype.forEach) {
	Array.prototype.forEach = function(aCallback, aThisObject) {
		for (var i = 0, n = this.length; i < n; i++) {
			aCallback.call(aThisObject, this[i], i, this);
		}
	};
}

/* ----- Array.map() ----- */

if (!Array.prototype.map) {
	Array.prototype.map = function(aCallback, aThisObject) {
		var ret = [];
		for (var i = 0, n = this.length; i < n; i++) {
			ret.push(aCallback.call(aThisObject, this[i], i, this));
		}
		return ret;
	};
}

/* ----- Array.filter() ----- */

if (!Array.prototype.filter) {
	Array.prototype.filter = function(aCallback, aThisObject) {
		var ret = [];
		for (var i = 0, n = this.length; i < n; i++) {
			if (aCallback.call(aThisObject, this[i], i, this)) {
				ret.push(this[i]);
			}
		}
		return ret;
	};
}

/* ----- Array.some() ----- */

if (!Array.prototype.some) {
	Array.prototype.some = function(aCallback, aThisObject){
		for (var i = 0, n = this.length; i < n; i++) {
			if (aCallback.call(aThisObject, this[i], i, this)) return true;
		}
		return false;
	};
}

/* ----- Array.every() ----- */

if (!Array.prototype.every) {
	Array.prototype.every = function(aCallback, aThisObject){
		for (var i = 0, n = this.length; i < n; i++) {
			if(!aCallback.call(aThisObject, this[i], i, this)) return false;
		}
		return true;
	};
}

(function($){
$.fn.animateSuper = $.fn.animate;
$.fn.animate = function(prop, speed, easing, callback) {
	if ( $.browser.msie && prop.hasOwnProperty('opacity') ) {
		var option = speed && typeof speed === "object" ? jQuery.extend({}, speed) : {
			complete: callback || !callback && easing || $.isFunction( speed ) && speed,
			duration: speed,
			easing: callback && easing || easing && !jQuery.isFunction(easing) && easing
		};
		var complete = option.complete;
		option.complete = function () {
			if ( $(this).css('opacity') == 0 || $(this).css('opacity') == 1 ) $(this).get(0).style.removeAttribute('filter');
			if( complete != undefined && $.isFunction(complete) ) complete();
		};
		return $(this).animateSuper(prop, option);
	}
	else {
		return $(this).animateSuper(prop, speed, easing, callback);
	}
};
})(jQuery);


/* --------------- Function : CWAVE.Delegate --------------- */
/**
 * 
 */
CWAVE.Delegate = function(func, aThisObject) {
	if (typeof func != 'function') {
		throw new TypeError('CWAVE.Delegate: first argument must be a function object.');
	}
	
	var aThisObj = aThisObject || window;
	var delegate = function(){
		return func.apply(aThisObj, arguments);
	};
	delegate.func        = func;
	delegate.aThisObject = aThisObj;
	return delegate; 
};


/**
*
*/
CWAVE.setRollOver = setRollOver;
function setRollOver ( imgEl ) {
	imgEl._orgSrc = imgEl.src;
	new Image().src = imgEl._overSrc = imgEl.src.replace(/\.(gif|jpe?g|png)$/, function($0){return('_o' + $0);});
	$(imgEl).hover( 
		function(){
			$(this).attr('src', imgEl._overSrc);
		},
		function(){
			$(this).attr('src', imgEl._orgSrc);
		}
	);
}

/**
 * CWAVE.Observable
 */
CWAVE.Observable = function() {
	this.callbackChains = null;
	this.callbackIgnoreLevel = {};
};
CWAVE.Observable.prototype.doCallback = function (name, /* arg1, arg2, ... */ _arguments) {
	var chain = this.callbackChains;
	if (!chain || !chain[name]) {
		return undefined;
	}

	var ret;
	var args = Array.prototype.slice.call(arguments, 1);

	chain[name]
		.filter(function(delegate) {
			var level = this.callbackIgnoreLevel[name] || 'none';
			switch (level) {
				case 'preserved'  : return  delegate.isDisposable;
				case 'disposable' : return !delegate.isDisposable;
				case 'all'        : return  false;
				case 'none'       : return  true;
				default           : return  true;
			}
		}, this)
		.forEach(function(delegate) {
			ret = delegate.apply(null, args);
		});

	this.removeDisposableCallback(name);
	return ret;
};
CWAVE.Observable.prototype.addCallback = function(name, func, aThisObject, disposable) {
	if ( typeof name != 'string' || name == '' ) {
		throw new TypeError('CWAVE.Observable.addCallback: argument \'name\' must be a string as callback name.');
	} else if ( typeof func != 'function') {
		throw new TypeError('CWAVE.Observable.addCallback: argument \'func\' must be a Function object.');
	}

	if (!this.callbackChains      ) this.callbackChains       = {};
	if (!this.callbackChains[name]) this.callbackChains[name] = [];

	var delegate = CWAVE.Delegate(func, aThisObject);
	delegate.isDisposable = (disposable == 'disposable');
	this.callbackChains[name].push(delegate);

	return this;
};
CWAVE.Observable.prototype.removeCallback = function(name, func, aThisObject) {
	var chain = this.callbackChains;
	if (typeof name != 'string' || name == '') {
		throw new TypeError('CWAVE.Observable.removeCallback: argument \'name\' must be a string as callback name.');
	}
	
	if (chain && chain[name]) {
		if (typeof func != 'function') {
			delete chain[name];
		} else {
			var obj = (typeof aThisObject == 'object' && aThisObject) ? aThisObject : window;
			chain[name] = chain[name].filter(function(delegate) {
				return (delegate.func !== func || delegate.aThisObject !== obj);
			});
		}
	}
	return this;
};
CWAVE.Observable.prototype.removeDisposableCallback = function(name) {
	var chain = this.callbackChains;
	if (chain && chain[name]) {
		chain[name] = chain[name].filter(function(delegate) { return !delegate.isDisposable; });
	}
	return this;
};
CWAVE.Observable.prototype.ignoreCallback = function(name, level) {
	var chain = this.callbackChains;
	if (typeof name != 'string' || name == '') {
		throw new TypeError('CWAVE.Observable.ignoreCallback: argument \'name\' must be a string as callback name.');
	}
	
	if (chain && chain[name]) {
		var levels = ['all', 'preserved', 'disposable', 'none'];
		this.callbackIgnoreLevel[name] = (levels.indexOf(level) != -1) ? level : 'all';
	}
	return this;
};


CWAVE.Timeout = function(func, ms, aThisObject) {
	/** timer ID.
	    @type Number
	    @private */
	this.timer       = 0;
	/** callback function
	    @type Function
	    @private
	    @constant */
	this.func        = $.isFunction(func) ? func : new Function;
	/** milliseconds to timeout
	    @type Function
	    @private
	    @constant */
	this.ms          = Math.max(0, ms) || 0
	/** the object that will be a global object ('this') in the func
	    @type Object
	    @private
	    @constant */
	this.aThisObject = aThisObject || window;
	/** native timer function name; 'setTimeout' or 'setInterval'
	    @type String
	    @private
	    @constant */
	this.timerFunc   = 'setTimeout';

	if (arguments.length) {
		this.init();
	}
}

CWAVE.Timeout.prototype.init = function() {
	var delegate  = CWAVE.Delegate(this.func, this.aThisObject);
	var timerFunc = window[this.timerFunc];
	this.timer    = (CWAVE.ua.isIE) ?
	              	timerFunc(delegate, this.ms, 'JScript') : 
	              	timerFunc(delegate, this.ms           ) ;
}

CWAVE.Timeout.prototype.clear = function() {
	clearTimeout (this.timer);
	clearInterval(this.timer);
}

CWAVE.Timeout.prototype.clearTimer = function() { return this.clear.apply(this, arguments) }



/**
 *
 */
CWAVE.GetGeometry = function(e) {
	var w = window;
	var d = document.documentElement;
	var b = document.body;
	var g = CWAVE.geom;
	var _ = arguments.callee;

	var isWinIEqm = (CWAVE.ua.isIE && CWAVE.ua.isWin && CWAVE.ua.isQuirksMode);
	var isMacIE   = (CWAVE.ua.isIE && CWAVE.ua.isMac);
	var isSafari2 = (CWAVE.ua.isSafari && CWAVE.ua.version < 522); /* Safari 2.0.x or ealier */

	g.windowW   = w.innerWidth  || (isMacIE ? b.scrollWidth  : d.offsetWidth );
	g.windowH   = w.innerHeight || (isMacIE ? b.scrollHeight : d.offsetHeight);
	g.pageW     = (isMacIE) ? d.offsetWidth  : (isWinIEqm) ? b.scrollWidth  : d.scrollWidth ;
	g.pageH     = (isMacIE) ? d.offsetHeight : (isWinIEqm) ? b.scrollHeight : d.scrollHeight;
	g.scrollX   = w.scrollX || d.scrollLeft || b.scrollLeft || 0;
	g.scrollY   = w.scrollY || d.scrollTop  || b.scrollTop  || 0;
	g.windowX   = (!e) ? (g.windowX || 0) : e.clientX - (( isSafari2) ? g.scrollX : 0);
	g.windowY   = (!e) ? (g.windowY || 0) : e.clientY - (( isSafari2) ? g.scrollY : 0);
	g.pageX     = (!e) ? (g.pageX   || 0) : e.clientX + ((!isSafari2) ? g.scrollX : 0);
	g.pageY     = (!e) ? (g.pageX   || 0) : e.clientY + ((!isSafari2) ? g.scrollY : 0);
	//g.zoom      = _.getZoomRatio();
	g.scrollBar = _.getScrollBarWidth();

	return g;
};

CWAVE.GetGeometry.getZoomRatio = function() {
	var d = document.documentElement;
	var b = document.body;
	var _ = arguments.callee;
	_._cache_ = _._cache_ || 1;
	if (CWAVE.ua.isIE && CWAVE.ua.version >= 7.0) {
		if (_._lock_) {
			_._lock_.clear();
			_._lock_ = new CWAVE.Timeout(function() { _._lock_ = null; }, 500);
		} else {
			_._lock_ = new CWAVE.Timeout(function() { _._lock_ = null; }, 500);
			if (CWAVE.ua.isQuirksMode) {
				_._cache_ = d.offsetWidth / b.offsetWidth;
			} else {
				var id  = 'CWAVE_GetGeometry_getZoomRatio_TestNode';
				var css = {
					  'position'   : 'absolute'
					, 'left'       : '0px'
					, 'top'        : '0px'
					, 'width'      : (d.scrollWidth * 10) + 'px'
					, 'height'     : '10px'
					, 'background' : 'red'
				};
				var node = $('#' + id).get(0) || $(document.createElement('ins')).attr('id', id).css(css).appendTo(document.body).get(0);
				$(node).show();
				_._cache_ = d.scrollWidth / node.offsetWidth;
				$(node).hide();
			}
		}
	}
	return _._cache_;
};

CWAVE.GetGeometry.getScrollBarWidth = function() {
	var _ = arguments.callee;
	if (typeof _._cache_ != 'number') {
		var id  = 'CWAVE_GetGeometry_getScrollBarWidth_TestNode';
		var css = {
			  'position'   : 'absolute'
			, 'left'       : '-10000px'
			, 'top'        : '-10000px'
			, 'display'    : 'block'
			, 'visibility' : 'hidden'
			, 'overflow'   : 'scroll'
			, 'width'      : '100px'
			, 'height'     : '100px'
			, 'border'     : 'none'
			, 'margin'     : '0'
			, 'padding'    : '0'
		};
		var node = $('#' + id).get(0) || $(document.createElement('ins')).attr('id', id).css(css).appendTo(document.body).get(0);
		_._cache_ = node.offsetWidth - node.clientWidth;
		$(node).remove();
	}
	return _._cache_;
};


/**
 * CWAVE.Scroller
 */
CWAVE.Scroller = function (node,offsetX,offsetY,duration, easing) {
	this.node     = $(node).get(0);
	this.offsetX  = Number(offsetX) || 0;
	this.offsetY  = Number(offsetY) || 0;
	this.duration = (Number(duration) >= 0) ? Number(duration) : 1000;
	this.easing   = ($.easing[easing]) ? easing : 'swing';
	this.init();
};
CWAVE.Scroller.prototype = new CWAVE.Observable;
CWAVE.Scroller.prototype.init = function () {
	if (!this.node || this.node.nodeType != Node.ELEMENT_NODE) return;
	var $node = ($(this.node).is('html, body')) ? $(document) : $(this.node);
	
	// workaround for when jquery.mousewheel.js is not loaded.
	if (!$node.mousewheel) {
		$node.mousewheel = new Function;
	}

	$node.click(CWAVE.Delegate(function() { this.abort(); }, this));
	$node.mousewheel(CWAVE.Delegate(function() { this.abort(); }, this));
};
CWAVE.Scroller.prototype.scrollTo = function(x, y, duration, offsetY) {
	if (isNaN(x) || isNaN(y)) {
		throw new TypeError('CWAVE.Scroller.scrollTo: all arguments must be numbers.');
	}
	var zoom = 1;
	var maxX = Math.max(0, this.node.scrollWidth  - this.node.clientWidth );
	var maxY = Math.max(0, this.node.scrollHeight - this.node.clientHeight);
	duration = (Number(duration) >= 0) ? Number(duration) : this.duration;

	var params = {
		  scrollLeft : Math.min(maxX, Math.max(0, Math.round((x + this.offsetX) * zoom)))
		, scrollTop  : Math.min(maxY, Math.max(0, Math.round((y + this.offsetY + offsetY) * zoom)))
	};
	var options = {
		  duration : duration
		, easing   : this.easing
		, step     : CWAVE.Delegate(this.step    , this)
		, complete : CWAVE.Delegate(this.complete, this)
	};

	var $node = (CWAVE.ua.isSafari && $(this.node).is('html')) ? $(document.body) : $(this.node);

	if ($node.scrollLeft() != params.scrollLeft || $node.scrollTop() != params.scrollTop) {
		this.abort();
		this.doCallbackByName('onStart');
		this.isBusy = true;
		$node.animate(params, options);
	}
	else {
		this.doCallbackByName('onComplete');
	}

	return this;
};
CWAVE.Scroller.prototype.scrollToNode = function(node, duration, offsetY) {
	node = $(node).get(0);
	if (!node || node.nodeType != Node.ELEMENT_NODE) {
		throw new TypeError('CWAVE.Scroller.scrollToNode: first argument must be an element node.');
	}

	var $base = $(this.node);
	var $node = $(node);
	if ($node.parents().filter(function() { return (this == $base.get(0)); }).get(0)) {
		var basePos = $base.is('html, body') ? { left : 0, top : 0 } : $base.offset();
		var baseSrl = $base.is('html, body') ? { left : 0, top : 0 } : { left : $base.scrollLeft(), top : $base.scrollTop() };
		var nodePos = $node.offset();
		//console.log(nodePos.top  + baseSrl.top  - basePos.top,duration,offsetY)
		this.scrollTo(
			  nodePos.left + baseSrl.left - basePos.left + (CWAVE.ua.isSafari ? 4 : 0)
			, nodePos.top  + baseSrl.top  - basePos.top
			, duration
			, offsetY
		);
	}

	return this;
};
CWAVE.Scroller.prototype.step = function() {
	this.doCallbackByName('onScroll');
};

CWAVE.Scroller.prototype.complete = function() {
	//console.log('complete?')
	//if ( !$(this.node).is(':animated')) {
		this.doCallbackByName('onComplete');
		//console.log('complete')
	//}
};
CWAVE.Scroller.prototype.abort = function() {
	var $node = $(this.node);
	if ($node.is(':animated')) {
		$node.stop();
		this.doCallbackByName('onAbort');
	}
	return this;
};
CWAVE.Scroller.prototype.doCallbackByName = function(name) {
	this.doCallback(name, this.node.scrollLeft, this.node.scrollTop);
};


})(jQuery);


