
jQuery.print = function(message, insertionType) {
  if (typeof(message) == 'object') {
    var string = '{<br />',
        values = [],
        counter = 0;
    jQuery.each(message, function(key, value) {
      if (value && value.nodeName) {
        var domnode = '&lt;' + value.nodeName.toLowerCase();
        domnode += value.className ? ' class="' + value.className + '"' : '';
        domnode += value.id ? ' id="' + value.id + '"' : '';
        domnode += '&gt;';
        value = domnode;
      }
      values[counter++] = key + ': ' + value;
    });
    string += values.join(',<br />');
    string += '<br />}';
    message = string;
  }

  var $output = jQuery('#print-output');
  
  if ($output.length === 0) {
    $output = jQuery('<div id="print-output" />').appendTo('body');
  }
  
  var $newMessage = jQuery('<div class="print-output-line" />');
  $newMessage.html(message);
  insertionType = insertionType || 'append';
  $output[insertionType]($newMessage);
};

var MSG_NORMAL = 1;
var MSG_WARNING = 2;

var KEY_LINEFEED = 10;
var KEY_ENTER = 13;
var KEY_ESCAPE = 27;
var jjConstants = {
	BOARD_FLASH:	"webClient",	// 게시판형 플래쉬
	BOARD_WIDTH:	480,			// 게시판형 너비
	BOARD_HEIGHT:	360,			// 게시판형 높이
	WIDGET_FLASH:	"AdShowClient",	// 위젯형 플래쉬
	WIDGET_WIDTH:	170,			// 위젯형 너비
	WIDGET_HEIGHT:	155,			// 위젯형 높이
	STUDIO_WIDTH:	894,			// 스튜디오창 너비
	STUDIO_HEIGHT:	574,			// 스튜디오창 높이
	
	nothing: null
};


var jjTools = {
		
	// E-mail
	emailPattern: /^[a-zA-Z0-9._-]+@[a-zA-Z0-9-]+(\.[a-zA-Z.]{2,4})*(\.[a-zA-Z.]{2,5})$/,

	// 4자의  영문, 숫자 조합
	authCodePattren: /[a-zA-Z]{1,}[0-9]{1,}$/,
	
	// 6자 이상의 영문, 숫자 조합
	passwdPattren: /[a-zA-Z0-9]{6,12}$/,
	
	// 2자 이상의 영문,숫자,한글 조합
	wordPattern: /^[^-+=\{}\\[\]:;"'<>,.?\/`~!@#$%^&*()\s][^-+=\\{}\[\]:;"'<>,.?\/`~!@#$%^&*()\s]+$/,
	
	numPattern: /^[0-9]+$/,
	
	isValidNum: function(num) {
		return this.numPattern.test(num);
	},
	
	isValidEmail: function(email) {
		return this.emailPattern.test(email);
	},
	
	isValidPassword: function(passwd) {
		var chk1 = /[a-zA-Z0-9]{6,12}$/;  //a-z와 0-9이외의 문자가 있는지 확인
		var chk2 = /[a-zA-Z]{1,}/;  //적어도 한개의 a-z 확인
		var chk3 = /[0-9]{1,}/;  //적어도 한개의 0-9 확인
	    return chk1.test(passwd) && chk2.test(passwd) && chk3.test(passwd);
	},
	
	isValidAuthCode: function(authCode) {
		return this.authCodePattren.test(authCode);
	},
	
	isValidWord: function(word) {
		return this.wordPattern.test(word);
	},

	// 좌표값 계산
	cumulativeOffset: function(element) {
	    var valueT = 0, valueL = 0;
	    do {
	      valueT += element.offsetTop  || 0;
	      valueL += element.offsetLeft || 0;
	      element = element.offsetParent;
	    } while (element);
	    return {x: valueL, y: valueT};
	},
	
	// radio, checkbox 체크된 값 리턴
	getCheckboxValue: function(checkbox, defaultValue) {
		if( checkbox.length ) {
			for (i = 0 ; i < checkbox.length ; i++) {
				if (checkbox[i].checked == true)	{
					return checkbox[i].value;
				}
			}
		}
		else {
			if( checkbox.checked ) {
				return checkbox.value;
			}
		}

		return defaultValue;
	},
	
	varsion: '0.1',

	messageBox: function(title, msg, callback) {
		new jjTools.MessageBoxModal({
			title: title, 
			msg: msg,
			callback: callback
		}).dialog('open');
	},

	messageBoxConfirm: function(title, msg, callback) {
		new jjTools.MessageBoxModal({
			title: title, 
			msg: msg,
			confirm: true,
			callback: callback
		}).dialog('open');
	},
	
	responseMessageBox: function(data, title, confirm, successCallback, errorCallback) {
		var xml = new jjTools.XML(data);
		var msg = xml.getMessage();
	
		if (xml.success()) {
			new jjTools.MessageBoxModal({
				title: title, 
				msg: msg,
				confirm: confirm,
				callback: successCallback
			}).dialog('open');
		}
		else {
			new jjTools.MessageBoxModal({
				title: title, 
				msg: msg,
				callback: errorCallback
			}).dialog('open');
		}
	},
	
	responseMessageBoxConfirm: function(data, title, successCallback, errorCallback) {
		jjTools.responseMessageBox(data, title, true, successCallback, errorCallback);
	},

	checkEmail: function(v) {
	     var isEmail = /[-!#$%&'*+\/^_~{}|0-9a-zA-Z]+(\.[-!#$%&'*+\/^_~{}|0-9a-zA-Z]+)*@[-!#$%&'*+\/^_~{}|0-9a-zA-Z]+(\.[-!#$%&'*+\/^_~{}|0-9a-zA-Z]+)+/;
	     return isEmail.test(v);
	},

	checkPasswd: function(v) {
		var isPasswd = /[0-9a-zA-Z]+/;
		return isPasswd.test(v);
	},

	checkEnter: function(func) {
		if (event.keyCode == 10 || event.keyCode == 13)
		{
			func();
			return false;
		}
	},

	getFieldValue: function(field, index) {
		if (field) {
			if (field.length) {
				return field[index].value;
			}
			return field.value;
		}
		return null;
	},
	
	goTop: function() {
		if (document.documentElement && document.documentElement.scrollTop) {
			top.document.documentElement.scrollTop = 0;
		}
		else if (document.body) {
			top.document.body.scrollTop = 0;
		}
	},
	
	strlen: function(str) {			// 한글 문자열 길이 계산
		return (str.length+(escape(str)+"%u").match(/%u/g).length-1);
	},
	substr: function(str, size) {	// 한글 문자열 자르기
		var len = this.strlen(str);
		var s = escape(str);
		var x = "";
		var n = 0;
		for (var i = 0; i < s.length; ) {
			if (s.charAt(i) == '%' && s.charAt(i+1) == 'u') {
				if (n + 2 > size) {
					//Ua.debug(n);
					break;
				}
				
				x += unescape(s.substr(i, 6));
				i += 6;
				n += 2;
			}
			else if (s.charAt(i) == '%') {
				x += unescape(s.substr(i, 3));
				i += 3;
				n++;
			}
			else {
				x += s.charAt(i);
				i++;
				n++;
			}
			
			if (n >= size)
				break;
		}
		
		return x;
	},
	
	// Layer를 브라우저의 가운데에 열어 준다. (스크롤 반영)
	openLayerToCenter: function(obj) {
		
		jQuery('.jjangPopupLayer').hide();
		
		if (typeof(obj) == 'string') {
			obj = jQuery(obj);
		}
		var width = document.documentElement.clientWidth || document.body.clientWidth;
		var height = document.documentElement.clientHeight || document.body.clientHeight;
		
		obj.show();
		
		var x = parseInt((width - obj.width()) / 2);
		var y = parseInt((height - obj.height()) / 2);
		obj.css('left', x + (document.documentElement.scrollLeft || document.body.scrollLeft));
		obj.css('top', y + (document.documentElement.scrollTop || document.body.scrollTop));
	},
	
	closeLayer: function(id) {
		jQuery(id).hide();
	},
	
	popup: function(url, popupName, attrs) {
		var defaultAttrs = {
			toolbar: "no",
			location: "no",
			directories: "no",
			status: "no",
			menubar: "no",
			scrollbars: "no",
			resizable: "no",
			copyhistory: "no"
		};
		if( attrs ) {
			jQuery.each( attrs, function(key, value){
				defaultAttrs[key] = value;
			});
		}
		else {
			alert("팝업속성이 지정되지 않았습니다.");return;
		}
		
		var attrArr = new Array();
		jQuery.each( defaultAttrs, function(key, value){
			attrArr.push(key+ "=" +value);
		});
		
		var w = defaultAttrs.width;
		if( !w ) {alert("너비가 지정되지 않았습니다.");return;}
		var h = defaultAttrs.height;
		if( !h ) {alert("높이가 지정되지 않았습니다.");return;}
		
		attrArr.push("top=" + parseInt((screen.availHeight / 2 ) - h/2));
		attrArr.push("left=" + parseInt((screen.availWidth / 2 ) - w/2));
		
		return window.open(url, popupName, attrArr.join(","));
	},
	
	toHex: function(color){
	    //valid HEX code is entered
	    if(color.match(/[0-9a-fA-F]{3}$/) || color.match(/[0-9a-fA-F]{6}$/)){
	      color = (color.charAt(0) == "#") ? color : ("#" + color);
	    }
	    //rgb color value is entered (by selecting a swatch)
	    else if(color.match(/^rgb\(([0-9]|[1-9][0-9]|[1][0-9]{2}|[2][0-4][0-9]|[2][5][0-5]),[ ]{0,1}([0-9]|[1-9][0-9]|[1][0-9]{2}|[2][0-4][0-9]|[2][5][0-5]),[ ]{0,1}([0-9]|[1-9][0-9]|[1][0-9]{2}|[2][0-4][0-9]|[2][5][0-5])\)$/)){
	      var c = ([parseInt(RegExp.$1),parseInt(RegExp.$2),parseInt(RegExp.$3)]);
	      
	      var pad = function(str){
	            if(str.length < 2){
	              for(var i = 0,len = 2 - str.length ; i<len ; i++){
	                str = '0'+str;
	              }
	            }
	            return str;
	      }

	      if(c.length == 3){
	        var r = pad(c[0].toString(16)),g = pad(c[1].toString(16)),b= pad(c[2].toString(16));
	        color = '#' + r + g + b;
	      }
	    }
	    else color = false;
	    
	    return color
	},
	

	// 숫자에 콤마 넣기
	addCommas: function(nStr)
	{
		nStr += '';
		x = nStr.split('.');
		x1 = x[0];
		x2 = x.length > 1 ? '.' + x[1] : '';
		var rgx = /(\d+)(\d{3})/;
		while (rgx.test(x1)) {
			x1 = x1.replace(rgx, '$1' + ',' + '$2');
		}
		return x1 + x2;
	},

	// 숫자에 콤마 빼기
	removeCommas: function(str)
	{
		return str.replace(/,/g, "");
	},
	
	doNothing: function() {}
};

jjTools.XML = function(data) {
	this.data = data;
};

// 
jjTools.XML.prototype.getText = function(path, rootElement) {
	var txt = '';
	var node = this.getNode(path, rootElement);
	
	if (this.data.evaluate) {
		txt = node.textContent;
	}
	else {
		txt = node.text;
	}

	return txt;
};

jjTools.XML.prototype.getAttribute = function(node, name) {
	if (typeof node == "string") {
		node = this.getNode(node);
	}
	
	if (this.data.evaluate == undefined) {
		nodeValue = node.getAttribute(name);
	}
	else {
		nodeValue = node.getAttributeNode(name).nodeValue;
	}

	return nodeValue;
};

jjTools.XML.prototype.getNode = function(path, rootElement) {
	rootElement = rootElement || this.data;
	var node = null;
	
	if (this.data.evaluate) {
		var nodeList = this.data.evaluate(path, rootElement, null, XPathResult.ANY_TYPE, null);
		node = nodeList.iterateNext();
	}
	else {
		node = rootElement.selectSingleNode(path);
	}
	
	return node;
};
// 
jjTools.XML.prototype.getNodeList = function(path, rootElement) {
	rootElement = rootElement || this.data;

	if (this.data.evaluate == undefined) {
		return rootElement.selectNodes(path);
	}
	else {
		return this.data.evaluate(path, rootElement, null, XPathResult.ANY_TYPE, null);
	}
};
jjTools.XML.prototype.getNodeArray = function(path, rootElement) {
	rootElement = rootElement || this.data;
	
	var returnElements = [];
	if (this.data.evaluate == undefined) {
		var nodeList = rootElement.selectNodes(path);
		for (var i = 0; i < nodeList.length; i++) {
			returnElements.push(nodeList[i]);
		}
	}
	else {
		var xpathResult = this.data.evaluate(path, rootElement, null, XPathResult.ANY_TYPE, null);
		var node;
		while (node = xpathResult.iterateNext()) {
			returnElements.push(node);			
		}
	}

	return returnElements;
};


jjTools.Cookies = function() {
	this.cookies = {};
};

var jjCookie = {
	deleteCookie: function(name, domain) {
		setCookie(name, "");
	},
	setCookie: function(name, value, domain, expiredays, path) {
		var todayDate = new Date();
		todayDate.setDate(todayDate.getDate() + expiredays);
		domain = domain || "jjanglive.com";
		document.cookie = name + "=" + escape(value) + "; path=/; expires=" + todayDate.toGMTString() + ";"
		                  + (domain ? "domain="+domain : "" ) + ";";
	},
	getCookie: function(name) {
		var nameOfCookie = name + "=";
		var x = 0;
		while (x <= document.cookie.length) {
			var y = (x+nameOfCookie.length);
			if (document.cookie.substring( x, y ) == nameOfCookie) {
		        if ((endOfCookie=document.cookie.indexOf( ";", y )) == -1)
		            endOfCookie = document.cookie.length;
		        return unescape(document.cookie.substring(y, endOfCookie));
			}
			x = document.cookie.indexOf(" ", x) + 1;
			if (x == 0)
				break;
		}
		return "";
	},
	fixedEncodeURIComponent: function(str) {   
		return encodeURIComponent(str).replace(/!/g, '%21').replace(/'/g, '%27').replace(/\(/g, '%28').replace(/\)/g, '%29').replace(/\*/g, '%2A');   
	}  
};


/**
 * WindowManger 
 */
jjTools.WindowManager = function(config) {
	this.modalLayerId = 'jj_modal_layer';
	this.layer = null;
	this.title = null;
	this.frame = null;
	this.btnClose = null;
	this.modalLayer = null;
	this.modal = false;
	this.btnCloseText = 'x';

	if (config) {
		for (c in config) {
			if (c == 'src') {
				this.frame.src = config[c];
			}
			else {
				this[c] = config[c];
			}
		}
	}
}

jjTools.WindowManager.prototype.show = function() {
	jQuery(this.layer).show();
}
jjTools.WindowManager.prototype.hide = function() {
	jQuery(this.layer).hide();
}
/**
 * Modal dialog box를 만든다.
 * 박스의 내용은 url로 부터 로드하여 채워 넣는다.
 */
jjTools.WindowManager.prototype.showModal = function(id, url, params, callback, className, closeCallback) {
	this.layer = document.getElementById(id);
	if (this.layer == null) {
		this.layer = document.createElement("DIV");
		this.layer.id = id;
		this.layer.className = className || 'jj_dialog';
		document.body.appendChild(this.layer);
	}
	
	var self = this;
	jQuery('#'+id).load(url, params, function() {
		jQuery('.jj_dialog_close').click(function() {
			self.hideModal();
			if (closeCallback) {
				closeCallback();
			}
		});

		document.documentElement.style.overflow = 'hidden';

		if (self.modal) {
			self.createModalLayer();
		}
		var width = document.documentElement.clientWidth || document.body.clientWidth;
		var height = document.documentElement.clientHeight || document.body.clientHeight;
		self.show();
		
		var x = parseInt((width - self.layer.offsetWidth) / 2);
		var y = parseInt((height - self.layer.offsetHeight) / 2);

		jQuery(self.layer)
			.attr('left', x + (document.documentElement.scrollLeft || document.body.scrollLeft) + 'px')
			.attr('top', y + (document.documentElement.scrollTop || document.body.scrollTop) + 'px');

		if (callback) {
			callback.call(self);
		}
	});
}
jjTools.WindowManager.prototype.hideModal = function() {
	if (this.modal) {
		this.closeModalLayer();
	}
	this.hide();
	document.documentElement.style.overflow = 'auto';
}

jjTools.WindowManager.prototype.createWindow = function(config) {
	config = config || {
		id: 'jj_window' + new Date().getTime(),
		title: 'JJ-Window', 
		width: 400, 
		height: 300 
	};

	this.layer = document.getElementById(config.id);
	if (this.layer == null) {
		this.layer = document.createElement("DIV");
		this.layer.id = config.id; 
		this.layer.style.height = (config.height + 20 + 2) + 'px';
		this.layer.style.width = (config.width + 2) + 'px';
		this.layer.className = 'jj_window_css';

		var oTitleDiv = document.createElement("DIV");
		oTitleDiv.style.width = config.width + 'px'; 
		oTitleDiv.style.height = '20px'; 
		oTitleDiv.style.cursor = 'move';
		oTitleDiv.onmousedown = function() {
			Drag.start(this, event);
		}

		this.title = document.createElement("DIV");
		this.title.id = config.id + '_title';
		this.title.style.float = 'left';
		this.title.style.styleFloat = 'left';
		this.title.style.width = (config.width-40) + 'px'; 
		this.title.style.height = '20px'; 
		this.title.className = 'jj_window_title_css';
		this.title.innerHTML = config.title;

		oTitleDiv.appendChild(this.title);

		this.btnClose = document.createElement("DIV");
		this.btnClose.innerHTML = this.btnCloseText;
		this.btnClose.style.float = 'right';
		this.btnClose.style.styleFloat = 'right';
		this.btnClose.style.width = '10px';
		this.btnClose.style.height = '20px';
		this.btnClose.style.cursor = 'pointer';

		var self = this;
		this.btnClose.onclick = function() {
			jQuery(self.layer).hide();
			if (self.modal) {
				jQuery(self.modalLayer).hide();
			}
			window.document.documentElement.style.overflow = 'auto';
		}
		oTitleDiv.appendChild(this.btnClose);
		this.layer.appendChild(oTitleDiv);

		document.body.appendChild(this.layer);
	}
}
jjTools.WindowManager.prototype.createWindowFrame = function(config) {

	if (this.frame == null) {
		this.frame = document.createElement("IFRAME");
		this.frame.id = config.frameId + '_frame'; 
		this.frame.className = 'jj_window_frame_css';
		this.frame.scrolling = 'no';
		this.frame.frameBorder = '0';
		this.frame.src = config.src || 'about:blank';
		this.frame.style.height = config.height + 'px';
		this.frame.style.width = config.width + 'px';
	}
	return this.frame;
}
	
jjTools.WindowManager.prototype.show = function() {
	if (this.layer) {
		if (this.modal) {
			this.createModalLayer();
		}
		window.document.documentElement.style.overflow = 'hidden';
		var width = document.documentElement.clientWidth || document.body.clientWidth;
		var height = document.documentElement.clientHeight || document.body.clientHeight;
		this.layer.style.display = 'block';
		var x = parseInt((width - this.layer.offsetWidth) / 2);
		var y = parseInt((height - this.layer.offsetHeight) / 2);
		this.layer.style.left = x + (document.documentElement.scrollLeft || document.body.scrollLeft) + 'px';
		this.layer.style.top = y + (document.documentElement.scrollTop || document.body.scrollTop) + 'px';
	}
}
jjTools.WindowManager.prototype.setSrc = function(src) {
	this.frame.src = src;
}
jjTools.WindowManager.prototype.createModalLayer = function() {
	this.modalLayer = document.getElementById(this.modalLayerId);
	if (this.modalLayer == null) {
		this.modalLayer = document.createElement("DIV");
		this.modalLayer.id = this.modalLayerId;
		this.modalLayer.style.position = 'absolute';
		this.modalLayer.style.top = 0;
		this.modalLayer.style.left = 0;
		this.modalLayer.style.width = jQuery(document).width();
		this.modalLayer.style.height = jQuery(document).height();
		this.modalLayer.style.opacity = .75;
		this.modalLayer.style.filter = 'alpha(opacity=75)';
		this.modalLayer.style.backgroundColor = '#ffffff';
		this.modalLayer.style.zIndex = 1;
		
		var self = this;
		this.modalLayer.onclick = function() {
			//jQuery(self.modalLayer).hide();
		}

		document.body.appendChild(this.modalLayer);
	}
	jQuery(this.modalLayer).show();
}
jjTools.WindowManager.prototype.closeModalLayer = function() {
	jQuery(this.modalLayer).hide();
}
jjTools.WindowManager.prototype.createWindowEx = function(config) {
	if (this.frame == null) {
		jQuery('#' + config.dialogId)
			.append(this.createWindowFrame(config))
			.dialog({
				title: config.title,
				autoOpen: false,
				width: config.width + 6,
				height: config.height + 36,
				resizable: false
			});
	}
}


jjTools.TabManager = function(tabs, callback) {
	this.tabs = tabs || new Array();
	this.beforeCallback = callback;
}
jjTools.TabManager.prototype.add = function(btnId, contentId) {
	tabs.push({id : btnId, body: contentId});
}
jjTools.TabManager.prototype.toggleTab = function(btn) {
	if (typeof btn == 'string') {
		btn = document.getElementById(btn);
	}
	if (this.beforeCallback) {
		this.beforeCallback(btn.id);
	}
	for (tabIndex in this.tabs) {
		var tab = this.tabs[tabIndex];
		if (tab.id == btn.id) {
			if (tab.image && tab.imageOver) {
				jQuery('#'+tab.id).addClass(tab.id + '_over');
			}
			jQuery(tab.body).show();
			jQuery('#'+tab.id).addClass('jj_link_selected');
			if (tab.callback) {
				tab.callback(tab);
			}
		}
		else {
			jQuery(tab.body).hide();
			jQuery('#'+tab.id).removeClass('jj_link_selected');

			if (tab.image && tab.imageOver) {
				jQuery('#'+tab.id).removeClass(tab.id + '_over');
			}
		}
	}
}
jjTools.TabManager.prototype.bindClickEvent = function() {
	var self = this;
	for (tabIndex in this.tabs) {
		jQuery('#' + this.tabs[tabIndex].id).click(function() {
			self.toggleTab(this);
		})
		.mouseover(function() {
			jQuery(this).addClass(this.id + '_over');
		})
		.mouseout(function() {
			if (jQuery(this).hasClass('jj_link_selected') == false) {
				jQuery(this).removeClass(this.id + '_over');
			}
		});
	}
}

jjTools.MessageBox = function(config) {

	config = config || { id: 'jj_alert' };
	
	var oMsgBox = jQuery('#' + config.id);
	if (oMsgBox.length == 0) {
		oDiv = document.createElement("DIV");
		oDiv.id = config.id;
		document.body.appendChild(oDiv);
	}
	else {
		jQuery(oMsgBox).dialog("destroy");
		oMsgBox.html('');
	}

	oMsgBox = jQuery('#' + config.id);
	oMsgBox.dialog({
		title: config.title,
		autoOpen: false,
		resizable: true,
		buttons: { "Ok": function() { 
							jQuery(this).dialog("close");
							if (config.callback) {
								config.callback();
							} 
						} 
		}
	});

	return oMsgBox;
}

jjTools.MessageBoxModal = function(conf, msg) {

	var config = { id: 'jj_alert', buttons: true };
	
	if (typeof conf == 'object') {
		for (c in conf) {
			config[c] = conf[c];
		}
	}
	else {
		config.title = conf;
		config.msg = msg;
	}
	
	var oMsgBox = jQuery('#' + config.id);
	if (oMsgBox.length == 0) {
		oDiv = document.createElement("DIV");
		oDiv.id = config.id;
		document.body.appendChild(oDiv);
	}
	else {
		jQuery(oMsgBox).dialog("destroy");
		oMsgBox.html('');
	}

	var buttons = {};
	if (config.buttons) {
		if (config.confirm) {
			buttons = { 
				"아니오" : function() {
							jQuery(this).dialog("close");
							if (config.callback) {
								config.callback('no');
							} 
				},
				"예" : function() {
							jQuery(this).dialog("close");
							if (config.callback) {
								config.callback('yes');
							} 
				}
			};
		}
		else {
			buttons = { 
				"확인": function() { 
							jQuery(this).dialog("close");
							if (config.callback) {
								config.callback();
							} 
						}
			} 
		}
	} 
	
	oMsgBox = jQuery('#' + config.id);
	oMsgBox.html(config.msg);
	oMsgBox.dialog({
		title: config.title,
		autoOpen: false,
		modal: true,
		resizable: false,
		width: config.width,
		height: config.height,
		buttons: buttons
	});

	return oMsgBox;
}

jjTools.form = {
		
	createInput: function(typeName, fieldName, size, value, className, callback) {
		var oInput = document.createElement("INPUT");
		oInput.type = typeName;
		oInput.className = className || '';
		oInput.name = name || '';
		oInput.size = size;
		oInput.value = value || '';
		oInput.onclick = function() {
			if (callback) {
				callback(this);
			}
		}

		return oInput;
	}	
}

var Point = function(x, y) {
	this.x = x || 0;
	this.y = y || 0;
}
Point.prototype = {
	moveTo: function(x, y) {
		this.x += x;
		this.y += y;
	}
}

var Rect = function(t, r, b, l) {
    this.top = t;
    this.right = r;
    this.bottom = b;
    this.left = l;
};

Rect.prototype.inner = function(p) {
    return this.left <= p.x && p.x <= this.right && this.top <= p.y && p.y <= this.bottom;
};

var jjDrag = {
	start: new Point(),
	origin: new Point(),
	delta: new Point(),
	element: null,
	event: null,
	start: function(element, event) {
		(function(){
			this.element = element.parentNode;
			this.event = event || window.event;
			
			this.start.x = this.event.clientX;
			this.start.y = this.event.clientY;
			
			this.origin.x = this.element.offsetLeft || 0;
			this.origin.y = this.element.offsetTop || 0;
			
			this.delta.x = this.start.x - this.origin.x;
			this.delta.y = this.start.y - this.origin.y;
			
			if (document.addEventListener) {	// DOM level 2
				document.addEventListener("mousemove", jjDrag.move, true);
				document.addEventListener("mouseup", jjDrag.done, true);
			}	
			else if (document.attachEvent) {	// IE 5 �̻�
				this.element.setCapture();
				this.element.attachEvent("onmousemove", jjDrag.move);
				this.element.attachEvent("onmouseup", jjDrag.done);
				this.element.attachEvent("onlosecapture", jjDrag.done);
			}
			
			if (this.event.stopPropagation)
				this.event.stopPropagation();	// DOM level 2
			else
				this.event.returnValue = false;	// IE
			
			if (this.event.preventDefault)
				this.event.preventDefault();		// DOM level 2
			else
				this.event.returnValue = false;	// IE
		}).call(jjDrag);
	},
	
	move: function(e) {
		(function() {
			e = e || window.event;
			
			this.element.style.left = (e.clientX - this.delta.x) + "px";
			this.element.style.top = (e.clientY - this.delta.y) + "px";
			
			if (e.stopPropagation)
				e.stopPropagation();	// DOM level 2
			else
				e.cancalBubble = true;	// IE
		}).call(jjDrag);
	},
	done: function(e) {
		(function() {
			e = e || window.event;
			
			if (document.removeEventListener) {	// DOM level 2
				document.removeEventListener("mouseup", this.done, true);
				document.removeEventListener("mousemove", this.move, true);
			}
			else if (document.detachEvent) {	// IE
				this.element.detachEvent("onlosecapture", this.done);
				this.element.detachEvent("onmouseup", this.done);
				this.element.detachEvent("onmousemove", this.move);
				this.element.releaseCapture();
			}
			
			if (e.stopPropagation)
				e.stopPropagation();	// DOM level 2
			else
				e.cancelBubble = true;
		}).call(jjDrag);
	}
};

var jjConsole = {
	isDebug: false,
	initialized: false,
	obj: null,
	heightX: 1,
	toString: Object.prototype.toString,
	
	initialize: function(config) {
		config = config || {
			width: 'auto',
			height: 100,
			left: 1
		};
		
		var oDiv = document.createElement("DIV");
		oDiv.id = "debug";
		oDiv.style.position ='absolute';
		oDiv.style.left = config.left; 
		oDiv.style.bottom = 0;
		oDiv.style.border = '1px solid #cecece';
		oDiv.style.background = 'white';
		oDiv.style.padding = '2px;';

		var coord = jQuery(document.body);
		var component = '<div style="text-align: right; cursor: pointer; font-size: 10px;">[ '
						+ '<span style="font-size: 10px;">▲</span> / '
						+ '<span style="font-size: 10px;">▼</span> / '
						+ '<span style="font-size: 10px;">front</span> / '
						+ '<span style="font-size: 10px;">clear</span> / '
						+ '<span style="font-size: 10px; margin-left: 3px; ">full</span>'
						+ ' ]</div>'
						+ '<textarea style="width: ' + (coord.width()-7) + 'px; height: ' + config.height + 'px;"></textarea>';
		
		jQuery(oDiv).append(component);
		jQuery(oDiv).css('z-index', 99999);
		jQuery('span', oDiv).click(function() {
			switch (jQuery(this).text()) {
			case 'clear':
				jQuery('TEXTAREA', oDiv).val(''); 
				break;
			case '▲':
				jjConsole.heightX++;
				if (jjConsole.heightX > 5) {
					jjConsole.heightX = 0;
				}
				if (jjConsole.heightX == 0) {
					jQuery('TEXTAREA', oDiv).height(0);
				}
				else {
					jQuery('TEXTAREA', oDiv).height(jjConsole.heightX * config.height);
				}
				break;
			case '▼':
				jjConsole.heightX--;
				if (jjConsole.heightX < 0) {
					jjConsole.heightX = 5;
				}
				if (jjConsole.heightX == 0) {
					jQuery('TEXTAREA', oDiv).height(0);
				}
				else {
					jQuery('TEXTAREA', oDiv).height(jjConsole.heightX * config.height);
				}
				break;
			case 'full':
				jQuery('TEXTAREA', oDiv).height(coord.height()-20);
				jQuery(this).text('min');
				break;
			case 'min':
				jQuery('TEXTAREA', oDiv).height(config.height);
				jQuery(this).text('full');
				break;
			case 'front':
				jQuery(oDiv).css('z-index', 99999);
				jQuery(this).text('back');
				break;
			case 'back':
				jQuery(oDiv).css('z-index', 1);
				jQuery(this).text('front');
				break;
			}
		});
		document.body.appendChild(oDiv);
		jjConsole.obj = jQuery('#debug > TEXTAREA');
	},
	debugX: function(msg) {
		jjConsole.insert(msg);
	},
	debug: function(msg, title, depth) {
		if (jjConsole.isDebug == false) {
			return;
		}
		//jjConsole.debugX(this.caller);
		depth = depth || 0;
		
		if (jjConsole.initialized == false) {
			jjConsole.initialized = true;
			jjConsole.initialize();
		}

		var sep = '';
		for (var i = 0; i <= depth; i++) {
			sep += '\t';
		}

		if (typeof msg == 'object') {
			if (jjConsole.isArray(msg)) {
				for (var i = 0; i < msg.length; i++) {
					if (typeof msg[i] == 'object') {
						jjConsole.insert(sep + '}');
						jjConsole.debug(msg[i], title, depth+1);
						jjConsole.insert(sep + '[' + i + ']= {');
					}
					else {
						jjConsole.insert(sep + '[' + i + ']=' + msg[i]);
					}
				}
			}
			else {
				for (var c in msg) {
					if (jjConsole.isArray(msg[c])) {
						jjConsole.insert(sep + '}');
						jjConsole.debug(msg[c], title, depth+1);
						jjConsole.insert(sep + '[' + c + ']= {');
					}
					else if (typeof msg[c] == 'object') {
						jjConsole.insert(sep + '}');
						jjConsole.debug(msg[c], title, depth+1);
						jjConsole.insert(sep + c + '= {');
					}
					else {
						jjConsole.insert(sep + c + '=' + msg[c]);
					}
				}
			}
		}
		else {
			if (msg === '') {
				msg = '[]';
			}
			jjConsole.insert(sep + msg);
		}

		if (title) {
			jjConsole.insert('--[ ' + title + ' ]-------------------' );
		}
	},
	insert: function(msg) {
		jjConsole.obj.val(msg + '\n' + jjConsole.obj.val()); //.scrollTop(1000000);
	},
	isFunction: function( obj ) {
		return jjConsole.toString.call(obj) === "[object Function]";
	},
	isArray: function( obj ) {
		return jjConsole.toString.call(obj) === "[object Array]";
	}
};


var Drag = {
	start: new Point(),
	origin: new Point(),
	delta: new Point(),
	element: null,
	event: null,
	start: function(element, event) {
		(function(){
			this.element = element.parentNode;
			this.event = event || window.event;
			
			this.start.x = this.event.clientX;
			this.start.y = this.event.clientY;
			
			this.origin.x = this.element.offsetLeft || 0;
			this.origin.y = this.element.offsetTop || 0;
			
			this.delta.x = this.start.x - this.origin.x;
			this.delta.y = this.start.y - this.origin.y;
			
			if (document.addEventListener) {	// DOM level 2
				document.addEventListener("mousemove", Drag.move, true);
				document.addEventListener("mouseup", Drag.done, true);
			}	
			else if (document.attachEvent) {	// IE 5 이상
				this.element.setCapture();
				this.element.attachEvent("onmousemove", Drag.move);
				this.element.attachEvent("onmouseup", Drag.done);
				this.element.attachEvent("onlosecapture", Drag.done);
			}
			
			if (this.event.stopPropagation)
				this.event.stopPropagation();	// DOM level 2
			else
				this.event.returnValue = false;	// IE
			
			if (this.event.preventDefault)
				this.event.preventDefault();		// DOM level 2
			else
				this.event.returnValue = false;	// IE
		}).call(Drag);
	},
	
	move: function(e) {
		(function() {
			e = e || window.event;
			
			this.element.style.left = (e.clientX - this.delta.x) + "px";
			this.element.style.top = (e.clientY - this.delta.y) + "px";
			
			if (e.stopPropagation)
				e.stopPropagation();	// DOM level 2
			else
				e.cancalBubble = true;	// IE
		}).call(Drag);
	},
	done: function(e) {
		(function() {
			e = e || window.event;
			
			if (document.removeEventListener) {	// DOM level 2
				document.removeEventListener("mouseup", this.done, true);
				document.removeEventListener("mousemove", this.move, true);
			}
			else if (document.detachEvent) {	// IE
				this.element.detachEvent("onlosecapture", this.done);
				this.element.detachEvent("onmouseup", this.done);
				this.element.detachEvent("onmousemove", this.move);
				this.element.releaseCapture();
			}
			
			if (e.stopPropagation)
				e.stopPropagation();	// DOM level 2
			else
				e.cancelBubble = true;
		}).call(Drag);
	}
};


// Tab 인터페이스
function MM_swapImgRestore() { //v3.0
  var i,x,a=document.MM_sr; for(i=0;a&&i<a.length&&(x=a[i])&&x.oSrc;i++) x.src=x.oSrc;
}

function MM_preloadImages() { //v3.0
  var d=document; if(d.images){ if(!d.MM_p) d.MM_p=new Array();
    var i,j=d.MM_p.length,a=MM_preloadImages.arguments; for(i=0; i<a.length; i++)
    if (a[i].indexOf("#")!=0){ d.MM_p[j]=new Image; d.MM_p[j++].src=a[i];}}
}

function MM_findObj(n, d) { //v4.01
  var p,i,x;  if(!d) d=document; if((p=n.indexOf("?"))>0&&parent.frames.length) {
    d=parent.frames[n.substring(p+1)].document; n=n.substring(0,p);}
  if(!(x=d[n])&&d.all) x=d.all[n]; for (i=0;!x&&i<d.forms.length;i++) x=d.forms[i][n];
  for(i=0;!x&&d.layers&&i<d.layers.length;i++) x=MM_findObj(n,d.layers[i].document);
  if(!x && d.getElementById) x=d.getElementById(n); return x;
}

function MM_swapImage() { //v3.0
  var i,j=0,x,a=MM_swapImage.arguments; document.MM_sr=new Array; for(i=0;i<(a.length-2);i+=3)
   if ((x=MM_findObj(a[i]))!=null){document.MM_sr[j++]=x; if(!x.oSrc) x.oSrc=x.src; x.src=a[i+2];}
}

