function BAEnvironment() {
	var d  = document;
	var di = d.implementation;
	var de = d.documentElement;
	var ua = navigator.userAgent;
	var lp = location.protocol;
	var lh = location.hostname;

	this.url = {}; this.ns = {}; this.prefix = {}; this.ua = {}; this.env = {}; this.css = {}; this.geom = {};

	this.url.commonDir   = BAGetCommonDir('shared');
	this.url.cssDir      = this.url.commonDir + 'css/';
	this.url.scriptDir   = this.url.commonDir + 'js/';

	this.ns.defaultNS    = (de && de.namespaceURI) ? de.namespaceURI : (de && de.tagUrn) ? de.tagUrn : null;
	this.ns.xhtml1       = 'http://www.w3.org/1999/xhtml';
	this.ns.xhtml2       = 'http://www.w3.org/2002/06/xhtml2';
	this.ns.bAattrs      = 'urn:bA.attrs';

	this.prefix.bAattrs  = 'bAattrs:';

	this.ua.productSub   = navigator.productSub;
	this.ua.isGecko      = ua.match(/Gecko\//);
	this.ua.isSafari     = ua.match(/AppleWebKit/);
	this.ua.isOpera      = window.opera;
	this.ua.isOpera6     = (this.ua.isOpera && ua.match(/Opera\.6/));   // Opera 6.x
	this.ua.isIE         = (d.all && !this.ua.isGecko && !this.ua.isSafari && !this.ua.isOpera);
	this.ua.isIE40       = (this.ua.isIE && ua.match(/MSIE 4\.0/));     // IE 4.0x
	this.ua.isIE45       = (this.ua.isIE && ua.match(/MSIE 4\.5/));     // IE 4.5x
	this.ua.isIE50       = (this.ua.isIE && ua.match(/MSIE 5\.0/));     // IE 5.0x
	this.ua.isIE55       = (this.ua.isIE && ua.match(/MSIE 5\.5/));     // IE 5.5x
	this.ua.isNN4        = d.layers;                                    // NN 4.x
	this.ua.isMac        = ua.match(/Mac/);
	this.ua.isWin        = ua.match(/Win/);
	this.ua.isWinIE      = this.ua.isWin && this.ua.isIE;
	this.ua.isMacIE      = this.ua.isMac && this.ua.isIE;
	this.ua.DOMok        = (di) ? di.hasFeature('HTML','1.0') : (this.ua.isIE && de);

	this.env.online      = (lp == 'http:' && !lh.match(/.local\.?$/));
	this.env.referer     = (typeof document.referrer == 'string') ? document.referrer : '';

	this.css.revise      = {
//		'Safari'   : 'revise_safari.css',
//		'IE50.Win' : 'revise_winie50.css'
	};
	this.css.reviseTitle = '';

	this.debugMode       = false;
}



/* -------------------- EventHandler : BAErrorHandler -------------------- */

window.onerror = function() {
	if (BA.debugMode) {
		var msg = 'Error: ' + arguments[0] + '\n' +
		          'File: '  + arguments[1] + '\n' + 
		          'Line: '  + arguments[2];
		alert(msg);
	}
	return true;
}



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

/* --- Array.push() --- */

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

if (!Array.prototype.indexOf) {
	Array.prototype.indexOf = function(value){
		var i = 0;
		while(i < this.length){
			if(this[i] == value) return i;
			i++;
		}
		return -1;
	}
}


/* ----- String.BAGetAfter() ----- */

String.prototype.BAGetAfter = function(word) {
	var offset = this.indexOf(word);
	return (offset == -1) ? '' : this.substring(offset + word.length, this.length);
}



/* ---------- Constructor : BAElement ---------- */

function BAElement() { }

BAElement.prototype = {

	/* ----- Node.addEventListenerBA() ----- */

	addEventListenerBA : function(type, listener, useCapture) {
		function _Event_IE(_node) {
			var e  = window.event;
			var de = document.documentElement;
			var db = document.body;
			this.currentTarget   = _node;
			if (!e) return;
			this.type            = e.type;
			this.target          = e.srcElement;
			this.relatedTarget   = (e.srcElement == e.toElement) ? e.fromElement : e.toElement;
			this.clientX         = e.clientX;
			this.clientY         = e.clientY;
			this.pageX           = (de.scrollLeft ? de.scrollLeft : db.scrollLeft) + e.clientX;
			this.pageY           = (de.scrollTop  ? de.scrollTop  : db.scrollTop ) + e.clientY;
			this.stopPropagation = function() { e.cancelBubble = true  };
			this.preventDefault  = function() { e.returnValue  = false };
		}

		function _Event_Safari(_e) {
			for (var i in _e) this[i] = _e[i];
			try {this.target = (_e.target.nodeType == 3) ? _e.target.parentNode : _e.target } catch (err) { }
			this.preventDefault  = function() { _e.currentTarget['on' + type] = function() { return false } };
			this.stopPropagation = function() { window.event_safari_cancelBubble[_e.type] = true };
		}

		if (this.addEventListener) {
			if (!BA.ua.isSafari) {
				this.addEventListener(type, listener, useCapture);
			} else {
				this.addEventListener(type, function(e) {
					if (typeof window.event_safari_cancelBubble != 'object') {
						window.event_safari_cancelBubble = {};
					} else if (typeof window.event_safari_cancelBubble[e.type] != 'boolean') {
						document.addEventListener(e.type, function(_e) {
							window.event_safari_cancelBubble[_e.type] = false;
						}, false);
					}
					if (!window.event_safari_cancelBubble[e.type]) {
						listener(new _Event_Safari(e));
					}
				}, useCapture);
			}
//		} else if (this.attachEvent) {
//			var _this = this;
//			this.attachEvent('on' + type, function() { listener(new _Event_IE(_this)) });
		} else {
			var _this  = (this.window) ? this.window : this; // measure for WinIE
			var exists = _this['on' + type];
			_this['on' + type] = (exists) ?
				function() { exists(); listener(new _Event_IE(_this)) } :
				function() {           listener(new _Event_IE(_this)) } ;
		}
	},

	/* ----- Node.createElementBA() ----- */

	createElementBA : function(tagName) {
		var node = (BA.ns.defaultNS && document.createElementNS && tagName.match(/:/)) ?
		           	document.createElementNS(BA.ns[tagName.split(':')[0]], tagName.split(':')[1]) :
		           	(BA.ns.defaultNS && document.createElementNS) ?
		           		document.createElementNS(BA.ns.defaultNS, tagName) : 
		           		document.createElement(tagName) ;
		return BARegisterDOMMethodsTo(node);
	},

	/* ----- Node.getElementsByTagNameBA() ----- */

	getElementsByTagNameBA : function(tagName) {
		if (tagName == '*') {
			var nodes = this.getElementsByTagName(tagName);
			if (nodes.length > 0) {
				return nodes;
			} else {
				var ret   = [];
				var nodes = (document.all && this.nodeType != 1) ?
					document.all :
					(function (_node) {
						var _nodes = _node.childNodes;
						var _ret   = [];
						for (var i = 0, n = _nodes.length; i < n; i++) {
							_ret.push(_nodes[i]);
							_ret = _ret.concat(arguments.callee(_nodes[i]));
						}
						return _ret;
					})(this);
				for (var i = 0, n = nodes.length; i < n; i++) {
					if (nodes[i].nodeType == 1 && !nodes[i].nodeName.match(/^[!\?]/)) {
						ret.push(nodes[i]);
					}
				}
				return ret;
			}
		} else if (tagName.match(/:/)) {
			var prfx  = tagName.split(':')[0];
			var name  = tagName.split(':')[1];
			var nodes = (BA.ns.defaultNS && this.getElementsByTagNameNS) ?
			            	this.getElementsByTagNameNS(BA.ns[prfx], name) :
			            	this.getElementsByTagName(tagName) ;
			if (nodes.length == 0) {
				var nodes = (name == '*') ? this.getElementsByTagNameBA(name) : this.getElementsByTagName(name);
				for (var nodes_ = [], i = 0, n = nodes.length; i < n; i++){
					if (BA.ns.defaultNS && nodes[i].namespaceURI == BA.ns[prfx] || nodes[i].tagUrn == BA.ns[prfx]) {
						nodes_.push(nodes[i]);
					}
				}
				if (nodes_.length == 0) {
					var nodes = (name == '*') ? nodes : this.getElementsByTagNameBA('*');
					for (var nodes_ = [], i = 0, n = nodes.length; i < n; i++) {
						var prfx_ = nodes[i].nodeName.split(':')[0];
						var name_ = nodes[i].nodeName.split(':')[1];
						if (name_ && prfx_ == prfx && (name == '*' || name_.toLowerCase() == name.toLowerCase())) {
							nodes_.push(nodes[i]);
						}
					}
				}
				nodes = nodes_;
			}
			return nodes;
		} else {
			var nodes = (BA.ns.defaultNS && this.getElementsByTagNameNS) ?
			            	this.getElementsByTagNameNS(BA.ns.defaultNS, tagName) :
			            	(tagName.match(/^body$/i) && document.body) ?
			            		/* measure for Netscape7.1 */ [document.body] :
			            		this.getElementsByTagName(tagName) ;
			if (typeof document.documentElement.tagUrn == 'string') {
				for (var nodes_ = [], i = 0, n = nodes.length; i < n; i++){
					if (!nodes[i].tagUrn || nodes[i].tagUrn == BA.ns.defaultNS) {
						nodes_.push(nodes[i]);
					}
				}
				nodes = nodes_;
			}
			return nodes;
		}
	},

	/* ----- Node.getElementsByClassNameBA() ----- */

	getElementsByClassNameBA : function(className, tagName) {
		if (!className) return undefined;
		if (!tagName)   tagName = '*';
		var nodes = this.getElementsByTagNameBA(tagName);
		var ret   = [];
		for (var i = 0, n = nodes.length; i < n; i++) {
			if (nodes[i].hasClassNameBA(className)) {
				ret.push(nodes[i]);
			}
		}
		return ret;
	},

	/* ----- Node.appendTextNodeBA() ----- */

	appendTextNodeBA : function(str) {
		if (BA.ua.isMac && BA.ua.isIE50) {
			this.innerHTML += str;
		} else {
			this.appendChild(document.createTextNode(str));
		}
	},

	/* ----- Node.getInnerTextBA() ----- */

	getInnerTextBA : function() {
		var nodes = this.childNodes;
		var ret   = [];
		for (var i = 0, n = nodes.length; i < n; i++) {
			if (nodes[i].hasChildNodes()) {
				ret.push(nodes[i].getInnerTextBA());
			} else if (nodes[i].nodeType == 3) {
				ret.push(nodes[i].nodeValue);
			} else if (nodes[i].alt) {
				ret.push(nodes[i].alt);
			}
		}
		return ret.join('').replace(/\s+/g, ' ');
	},

	/* ----- Node.getAttributeBA() ----- */

	getAttributeBA : function(attr) {
		if (BA.ua.isIE && attr == 'class') {
			attr += 'Name';
		}
		var ret = this.getAttribute(attr);
		if (!ret && this.getAttributeNS && attr.match(/:/)) {
			var prfx = attr.split(':')[0];
			var attr = attr.split(':')[1];
			return this.getAttributeNS(BA.ns[prfx], attr)
		}
		return ret;
	},

	/* ----- Node.setAttributeBA() ----- */

	setAttributeBA : function(attr, value) {
		if (attr.match(/:/)) {
			var prfx = attr.split(':')[0];
			var attr = attr.split(':')[1];
			if (this.setAttributeNS && this.namespaceURI || BA.ua.isSafari) {
				this.setAttributeNS(BA.ns[prfx], attr, value);
			} else {
				this.setAttribute('xmlns:' + prfx, BA.ns[prfx]);
				this.setAttribute(prfx + ':' + attr, value);
			}
		} else {
			if (BA.ua.isIE && attr == 'class') attr += 'Name';
			this.setAttribute(attr, value);
		}
	},

	/* ----- Node.hasClassNameBA() ----- */

	hasClassNameBA : function(className) {
		var flag  = false;
		var cname = this.getAttributeBA('class');
		if (cname) {
			cname = cname.split(' ');
			for (var i = 0; i < cname.length && !flag; i++) flag = (cname[i] == className);
		}
		return flag;
	},

	/* ----- Node.appendClassNameBA() ----- */

	appendClassNameBA : function(className) {
		if (className && !this.hasClassNameBA(className)) {
			var cnames = this.getAttributeBA('class');
			this.setAttributeBA('class', ((cnames) ? cnames + ' ' + className : className));
		}
	},

	/* ----- Node.removeClassNameBA() ----- */

	removeClassNameBA : function(className) {
		if (className && this.hasClassNameBA(className)) {
			var cname = this.getAttributeBA('class');
			var cntmp = [];
			if (cname) {
				cname = cname.split(' ');
				for (var i = 0; i < cname.length; i++) if (cname[i] != className) cntmp.push(cname[i]);
			}
			this.setAttributeBA('class', cntmp.join(' '));
		}
	},

	/* ----- Node.normalizeTextNodeBA() ----- */

	normalizeTextNodeBA : function (deep) {
		(function (curNode) {
			for (var i = 0; i < curNode.childNodes.length; i++) {
				var node = curNode.childNodes[i];
				if (node.nodeType == 3) {
					node.nodeValue = node.nodeValue.replace(/^\s+/, '');
					node.nodeValue = node.nodeValue.replace(/\s+$/, '');
					if (node.nodeValue.match(/^\s*$/))  {
						node.parentNode.removeChild(node);
						i--;
					}
				} else if (deep && node.nodeType == 1 && node.hasChildNodes()) {
					arguments.callee(node);
				}
			}
		})(this);
	},

	/* ----- Node.getAbsoluteOffsetBA() ----- */

	getAbsoluteOffsetBA : function() {
		var offset = { X : this.offsetLeft, Y : this.offsetTop };
		if (this.offsetParent) {
			offset.X += this.offsetParent.getAbsoluteOffsetBA().X;
			offset.Y += this.offsetParent.getAbsoluteOffsetBA().Y;
		}
		return offset;
	},

	/* ----- Node.getCurrentStyleBA() ----- */

	getCurrentStyleBA : function(property, pseudo) {
		return (window.getComputedStyle) ?
			window.getComputedStyle(this, pseudo)[property] : (this.currentStyle) ?
				this.currentStyle[property] : 0;
	},

	/* ----- Node.
