/* -------------------------------------------------------------------------- */
/** 
 *    @fileoverview
 *       Smooth Scroll w/auto setup
 *
 *    @version rev010.2006-02-07
 *    @requires common.js
 */
/* -------------------------------------------------------------------------- */


var BA_SMOOTHSCROLL;



/* -------------------- Settings for BASmoothScrollAutoSetup -------------------- */

var BA_SMOOTHSCROLL_AUTOSETUP_ENABLED         = true;
var BA_SMOOTHSCROLL_AUTOSETUP_USE_POSTPROCESS = false;
var BA_SMOOTHSCROLL_AUTOSETUP_OFFSET_X        = 0;
var BA_SMOOTHSCROLL_AUTOSETUP_OFFSET_Y        = -31;
var BA_SMOOTHSCROLL_AUTOSETUP_FOCUSED_CLASS   = 'focused';



/* -------------------- Constructor : BASmoothScroll -------------------- */

function BASmoothScroll() {
	this.offsetX =  0;
	this.offsetY =  0;
	this.unit    =  5;
	this.wait    = 10;
	this.usePostProcess = false;
}

BASmoothScroll.prototype = {
	setTargetNode : function(node) {
		this.stopScroll();
		this.targetNode = node;
		this.timer      = null;
	},
	
	setFromNode : function(node) {
		this.fromNode = node;
	},
	
	startScroll : function() {
		BAGetGeometry();
		if (!this.timer) {
			var maxX   = (BA.geom.pageW > BA.geom.windowW) ? BA.geom.pageW - BA.geom.windowW : 0;
			var maxY   = (BA.geom.pageH > BA.geom.windowH) ? BA.geom.pageH - BA.geom.windowH : 0;
			var absOst = this.targetNode.getAbsoluteOffsetBA();
			var posX   = absOst.X + this.offsetX;
			var posY   = absOst.Y + this.offsetY;
			this.cuX   = BA.geom.scrollX;
			this.cuY   = BA.geom.scrollY;
			this.toX   = (posX < 0) ? 0 : (posX > maxX) ? maxX : posX;
			this.toY   = (posY < 0) ? 0 : (posY > maxY) ? maxY : posY;
			this.timer = new BASetInterval(arguments.callee, this.wait, this);
		}

		this.cuX += (this.toX - BA.geom.scrollX) / this.unit; if (this.cuX < 0) this.cuX = 0;
		this.cuY += (this.toY - BA.geom.scrollY) / this.unit; if (this.cuY < 0) this.cuY = 0;
		var newX = Math.floor(this.cuX);
		var newY = Math.floor(this.cuY);
		window.scrollTo(newX, newY);
		if (newX == this.toX && newY == this.toY) this.stopScroll();
	},
	
	stopScroll : function() {
		if (this.timer) {
			this.timer.clearTimer();
			this.timer = null;
			this.postProcess();
		}
	},
	
	postProcess : function() {
		if (this.usePostProcess && this.offsetX == 0 && this.offsetY == 0 &&
		    this.fromNode && (BA.ua.isGecko || BA.ua.isWinIE)) {
			var href = this.fromNode.getAttributeBA('href');
			if (href) location.href = href;
		}
		
		var targetNode = e.currentTarget.__BASmoothScrollAutoSetup_targetNode__;
		if (targetNode && targetNode.tagName.toLowerCase() == 'a') {
			targetNode.focus();
		}
	}
}



/* -------------------- Constructor : BASmoothScrollField Inherit BASmoothScroll -------------------- */

function BASmoothScrollField(node) {
	this.node    = node;
	this.offsetX = 0;
	this.offsetY = 0;
	this.unit    = 10;
	this.wait    = 10;
}

BASmoothScrollField.prototype = {
	setTargetNode : function(node) {
		this.stopScroll();
		this.targetNode = node;
		this.timer      = null;
	},
	
	startScroll : function() {
		if (!this.timer) {
			var maxX   = this.node.scrollWidth  - this.node.offsetWidth;  if (maxX < 0) maxX = 0;
			var maxY   = this.node.scrollHeight - this.node.offsetHeight; if (maxY < 0) maxY = 0;
			var fldOst = this.node.getAbsoluteOffsetBA();
			var tgtOst = this.targetNode.getAbsoluteOffsetBA();
			var posX   = (tgtOst.X - fldOst.Y) + this.offsetX;
			var posY   = (tgtOst.Y - fldOst.Y) + this.offsetY;
			this.toX   = (posX < 0) ? 0 : (posX > maxX) ? maxX : posX;
			this.toY   = (posY < 0) ? 0 : (posY > maxY) ? maxY : posY;
			this.timer = new BASetInterval(arguments.callee, this.wait, this);
		}
		var dX = Math.round((this.toX - this.node.scrollLeft) / this.unit);
		var dY = Math.round((this.toY - this.node.scrollTop ) / this.unit);
		if (dX == 0 && this.toX < this.node.scrollLeft) dX = -1;
		if (dX == 0 && this.toX > this.node.scrollLeft) dX =  1;
		if (dY == 0 && this.toY < this.node.scrollTop ) dY = -1;
		if (dY == 0 && this.toY > this.node.scrollTop ) dY =  1;
		this.node.scrollLeft += dX;
		this.node.scrollTop  += dY;
		if (this.node.scrollLeft == this.toX && this.node.scrollTop == this.toY) {
			this.stopScroll();
		}
	},
	
	stopScroll : function() {
		if (this.timer) {
			this.timer.clearTimer();
			this.timer = null;
		}
	}
}



/* -------------------- Function : BASmoothScrollAutoSetup -------------------- */

function BASmoothScrollAutoSetup() {
	var html    = document.getElementsByTagNameBA('html')[0];
	var body    = document.getElementsByTagNameBA('body')[0];
	var div     = document.createElementBA('div');
	var anchors = document.getElementsByTagNameBA('a');

	if (!document.getElementById('top'   )) html.setAttributeBA('id', 'top'   );
	if (!document.getElementById('bottom'))  div.setAttributeBA('id', 'bottom');
	div.style.margin  = 0;
	div.style.padding = 0;
	div.style.clear   = 'both';
	body.appendChildBA(div);

	BA_SMOOTHSCROLL = new BASmoothScroll;
	BA_SMOOTHSCROLL.offsetX        = BA_SMOOTHSCROLL_AUTOSETUP_OFFSET_X;
	BA_SMOOTHSCROLL.offsetY        = BA_SMOOTHSCROLL_AUTOSETUP_OFFSET_Y;
	BA_SMOOTHSCROLL.usePostProcess = BA_SMOOTHSCROLL_AUTOSETUP_USE_POSTPROCESS;
	

	document.addEventListenerBA('click'     , function(e) { BA_SMOOTHSCROLL.stopScroll() });
	document.addEventListenerBA('mousewheel', function(e) { BA_SMOOTHSCROLL.stopScroll() });

	for (var i = 0, n = anchors.length; i < n; i++) {
		var ident = _getInternalLinkFragmentIdentifier(anchors[i]);
		if (ident) {
			var target = document.getElementById(ident) || document.getElementsByName(ident)[0];
			if (target) {
				anchors[i].__BASmoothScrollAutoSetup_targetNode__ = target;
				anchors[i].addEventListenerBA('click', function(e) {
					e.preventDefault();
					e.stopPropagation();
					e.currentTarget.blur();
					BA_SMOOTHSCROLL.setTargetNode(e.currentTarget.__BASmoothScrollAutoSetup_targetNode__);
					BA_SMOOTHSCROLL.setFromNode(e.currentTarget);
					BA_SMOOTHSCROLL.startScroll();
				});
			}
		}
	}

	function _getInternalLinkFragmentIdentifier(node) {
		var ret      = '';
		var linkHref = node.getAttributeBA('href');
		if (linkHref && linkHref.match(/#/)) {
			linkHref = linkHref.split('#');
			if (!linkHref[0] || linkHref[0] == location.href.split('#')[0]) {
				ret = linkHref[1];
			}
		}
		return ret;
	}
}





/* -------------------- Main : register start-up -------------------- */

if (typeof BA == 'object' && BA.ua.DOMok && BA_SMOOTHSCROLL_AUTOSETUP_ENABLED) {
	BAAddOnload(BASmoothScrollAutoSetup);
}
