/*********************************************************
*  Start common_path.js
*********************************************************/
/*********************************************************
*로케이션 관리 시작
*********************************************************/
//////  LOCATION CHECK   ////////
var depth1 = "";
var depth2 = "";
var depth3 = "";
var depth4 = "";
var emailPattern = /^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/;

// admin에서 Seller 쪽 common_path.js를 읽으며 Global_DepthPathImage 변수를 찾지 못하는 문제 수정.
var depthImagePath = "";
var tempDepthPathImage  = window["Global_DepthPathImage"];
if (tempDepthPathImage) {
	depthImagePath = tempDepthPathImage;
}
var imgpath = depthImagePath + "/en_US/images/common/path/";
var urlpath = depthImagePath;

function setDepthVar( firVar, secVar, thrVar,fourVar ) {
	depth1 = firVar;
	depth2 = secVar;
	depth3 = thrVar;
	depth4 = fourVar;
}

function locationCheck( depth1, depth2, depth3, depth4 ){

	var returnPram = ""
	var oneDepthName = new Array();
	var twoDepthName = new Array();
	var threeDepthName = new Array();
	var fourDepthName = new Array();

	var home = "<a href='http://seller.samsungapps.com/main/sellerMain.as'>HOME</a>";

	oneDepthName[0] = "<a href='"+urlpath+"/login/signIn.as?view=signUp'>Join Now</a>";
	oneDepthName[1] = "<a href='"+urlpath+"/member/getSellerDetail.as'>My Profile</a>";
	oneDepthName[2] = "<a href='"+urlpath+"/qa/getIssueList.as'>Buyer Support</a>";
	oneDepthName[3] = "<a href='"+urlpath+"/product/realcontent/list.as'>Applications</a>";
	oneDepthName[4] = "<a href='"+urlpath+"/accounting/accountingList.as'>Accounting</a>";
	oneDepthName[5] = "<a href='"+urlpath+"/statistics/statisticsDownloads.as'>Statistics</a>";
	oneDepthName[6] = "<a href='"+urlpath+"/faq/getFaqList.as'>Support</a>";
	oneDepthName[7] = "<a href='"+urlpath+"/help/siteMap.as'>Site Map</a>";
	oneDepthName[8] = "<a href='"+urlpath+"/help/privacy.as'>Privacy Policy</a>";	
	oneDepthName[9] = "<a href='"+urlpath+"'>Terms and Conditions</a>";
	oneDepthName[10] = "<a href='"+urlpath+"'>Contact Us</a>";
	oneDepthName[11] = "<a href='"+urlpath+"/contestcs/getContestMain.as'>Application Contest</a>";

	returnPram = home+"<img src='"+imgpath+"arr_history.gif' border='0' align='absmiddle'>"+oneDepthName[depth1];


	if(depth1 == 0) {
		twoDepthName[0] = "";
		twoDepthName[1] = "<span class='now'>Join Now</span>";
		twoDepthName[2] = "<span class='now'>Find E-Mail / Password</span> ";

		if(depth2 == 1)
			returnPram = home+"<img src='"+imgpath+"arr_history.gif' border='0' align='absmiddle'>"+twoDepthName[depth2];
		else
			returnPram = home+"<img src='"+imgpath+"arr_history.gif' border='0' align='absmiddle'>"+oneDepthName[depth1]+"<img src='"+imgpath+"arr_history.gif' border='0' align='absmiddle'>"+twoDepthName[depth2];

	} else if(depth1 == 1) {
		twoDepthName[0] = "";
		twoDepthName[1] = "<span class='now'>Profile</span>";
		twoDepthName[2] = "<span class='now'>Manage Seller's Page</span>";
		twoDepthName[3] = "<span class='now'>Manage Brand Shop</span>";

		returnPram = home+"<img src='"+imgpath+"arr_history.gif' border='0' align='absmiddle'>"+oneDepthName[depth1]+"<img src='"+imgpath+"arr_history.gif' border='0' align='absmiddle'>"+twoDepthName[depth2];
		
		if(depth2 =="1"){

			if(depth3 =="0"){

				returnPram = home+"<img src='"+imgpath+"arr_history.gif' border='0' align='absmiddle'>"+oneDepthName[depth1]+"<img src='"+imgpath+"arr_history.gif' border='0' align='absmiddle'>"+twoDepthName[depth2];

			}else if(depth3 =="2"){

				twoDepthName[1] = "Profile";
				threeDepthName[2]="<span class='now'>Edit Profile</span>";

				returnPram = home+"<img src='"+imgpath+"arr_history.gif' border='0' align='absmiddle'>"+oneDepthName[depth1]+"<img src='"+imgpath+"arr_history.gif' border='0' align='absmiddle'>"+twoDepthName[depth2]+"<img src='"+imgpath+"arr_history.gif' border='0' align='absmiddle'>"+threeDepthName[depth3];
			
			}else{

				twoDepthName[1] = "Profile";
				returnPram = home+"<img src='"+imgpath+"arr_history.gif' border='0' align='absmiddle'>"+oneDepthName[depth1]+"<img src='"+imgpath+"arr_history.gif' border='0' align='absmiddle'>"+twoDepthName[depth2]
			
			}

		}else{

		returnPram = home+"<img src='"+imgpath+"arr_history.gif' border='0' align='absmiddle'>"+oneDepthName[depth1]+"<img src='"+imgpath+"arr_history.gif' border='0' align='absmiddle'>"+twoDepthName[depth2];

		}
		
	} else if(depth1 == 2) {
		twoDepthName[0] = "";
		twoDepthName[1] = "<span class='now'>Manage Fan Board</span> ";
		twoDepthName[2] = "<span class='now'>Buyer Question</span>";

		returnPram = home+"<img src='"+imgpath+"arr_history.gif' border='0' align='absmiddle'>"+oneDepthName[depth1]+"<img src='"+imgpath+"arr_history.gif' border='0' align='absmiddle'>"+twoDepthName[depth2];

	} else if(depth1 == 3) {
	    
	    var PATH_SEPARATOR = "<img src='"+imgpath+"arr_history.gif' border='0' align='absmiddle'>";
	    
	    /* HOME > Applications > Sales Status */
		if ( depth2 == 1 && depth3 == 1 ) {
		    returnPram =
		          home + PATH_SEPARATOR
		        + oneDepthName[depth1] + PATH_SEPARATOR
		        + "<a href='" + urlpath + "/product/realcontent/list.as'>Sales Status</a>" + PATH_SEPARATOR
		        + "<span class='now'>Application Details</span>";
		}
		/* HOME > Applications > Registration Status > Add New Application */
        else if (depth2 == 3 && depth3 == 1 ) {
            returnPram =
                home + PATH_SEPARATOR
              + oneDepthName[depth1] + PATH_SEPARATOR
              + "<a href='" + urlpath + "/product/initcontent/list.as'>Registration Status</a>" + PATH_SEPARATOR
              + "<span class='now'>Add New Application</span>";
        }
        /* HOME > Applications > Registration Status > Application Details */
        else if (depth2 == 3 && depth3 == 2 ) {
            returnPram =
                home + PATH_SEPARATOR
              + oneDepthName[depth1] + PATH_SEPARATOR
              + "<a href='" + urlpath + "/product/initcontent/list.as'>Registration Status</a>" + PATH_SEPARATOR
              + "<span class='now'>Application Details</span>";
        }
		/* HOME > Applications > Bulk Upload Status */
        else if (depth2 == 4 && depth3 == 1 ) {
            returnPram =
                home + PATH_SEPARATOR
              + oneDepthName[depth1] + PATH_SEPARATOR
              + "<a href='" + urlpath + "/product/content/listBatchUpload.as'>Bulk Upload Status</a>" + PATH_SEPARATOR
              + "<span class='now'>Bulk Upload</span>";
        }
		/* HOME > Applications > Discounts Status */
        else if (depth2 == 8 && depth3 == 0 ) {
            returnPram =
                home + PATH_SEPARATOR
              + oneDepthName[depth1] + PATH_SEPARATOR
              + "<span class='now'>Discounts Status</span>";
        }
		/* HOME > Applications > Discounts Status */
        else if (depth2 == 8 && depth3 == 1 ) {
            returnPram =
                home + PATH_SEPARATOR
              + oneDepthName[depth1] + PATH_SEPARATOR
              + "<a href='" + urlpath + "/product/discount/discountList.as'>Discounts Status</a>" + PATH_SEPARATOR
              + "<span class='now'>Add New Discounts</span>";
        }
		/* HOME > Applications > Discounts Status */
        else if (depth2 == 8 && depth3 == 2 ) {
            returnPram =
                home + PATH_SEPARATOR
              + oneDepthName[depth1] + PATH_SEPARATOR
              + "<a href='" + urlpath + "/product/discount/discountList.as'>Discounts Status</a>" + PATH_SEPARATOR
              + "<span class='now'>Discounts Status Detail</span>";
        }
		else {
		    twoDepthName[0] = "";
		    twoDepthName[1] = "<span class='now'>Sales Status</span>";
		    twoDepthName[2] = "<span class='now'>Approval Status</span> ";
		    twoDepthName[3] = "<span class='now'>Registration Status</span>";
		    twoDepthName[4] = "<span class='now'>Bulk Upload Status</span>";
		    twoDepthName[5] = "<span class='now'>UID Management</span>";
			twoDepthName[6] = "<span class='now'>Item Management</span>";
			twoDepthName[7] = "<span class='now'>Widget ID Management</span>";
		    		    
		    returnPram = home+"<img src='"+imgpath+"arr_history.gif' border='0' align='absmiddle'>"+oneDepthName[depth1]+"<img src='"+imgpath+"arr_history.gif' border='0' align='absmiddle'>"+twoDepthName[depth2];
		}
	} else if(depth1 == 4) {
		twoDepthName[0] = "";
		twoDepthName[1] = "<span class='now'>Sales Summary</span> ";
		twoDepthName[2] = "<span class='now'>Financial Report</span> ";
		twoDepthName[3] = "<span class='now'>Item Sales Summary</span> ";
		twoDepthName[4] = "<span class='now'>Item Financial Report</span> ";

		returnPram = home+"<img src='"+imgpath+"arr_history.gif' border='0' align='absmiddle'>"+oneDepthName[depth1]+"<img src='"+imgpath+"arr_history.gif' border='0' align='absmiddle'>"+twoDepthName[depth2];

	} else if(depth1 == 5) {
		twoDepthName[0] = "";
		twoDepthName[1] = "<span class='now'>Downloads</span> ";
		twoDepthName[2] = "<span class='now'>Sales</span> ";
		twoDepthName[3] = "<span class='now'>Registered Applications</span> ";
		twoDepthName[4] = "<span class='now'>Item Sales</span> ";
		twoDepthName[5] = "<span class='now'>Registered Items</span> ";

		returnPram = home+"<img src='"+imgpath+"arr_history.gif' border='0' align='absmiddle'>"+oneDepthName[depth1]+"<img src='"+imgpath+"arr_history.gif' border='0' align='absmiddle'>"+twoDepthName[depth2];

	} else if(depth1 == 6) {
		twoDepthName[0] = "";
		twoDepthName[1] = "<span class='now'>FAQ</span> ";
		twoDepthName[2] = "<span class='now'>Notices</span>";
		twoDepthName[3] = "<span class='now'>My Q&A</span>";

		returnPram = home+"<img src='"+imgpath+"arr_history.gif' border='0' align='absmiddle'>"+oneDepthName[depth1]+"<img src='"+imgpath+"arr_history.gif' border='0' align='absmiddle'>"+twoDepthName[depth2];
		
	} else if(depth1 == 7) {
		twoDepthName[0] = "";
		twoDepthName[1] = "<span class='now'>Site Map</span> ";
		twoDepthName[2] = "<span class='now'>Privacy Policy</span> ";
		twoDepthName[3] = "<span class='now'>Terms and Conditions</span> ";
		twoDepthName[4] = "<span class='now'>Contact Us</span> ";

		returnPram = home+"<img src='"+imgpath+"arr_history.gif' border='0' align='absmiddle'>"+twoDepthName[depth2];

	} else if(depth1 == 11) {
		twoDepthName[0] = "";
		twoDepthName[1] = "<span class='now'>FAQ</span> ";
		twoDepthName[2] = "<span class='now'>Notices</span>";
		twoDepthName[3] = "<span class='now'>My Q&A</span>";
		twoDepthName[4] = "<span class='now'>Submission</span> ";
		twoDepthName[5] = "<span class='now'>Approval Status</span>";
		twoDepthName[6] = "<span class='now'>Registration Status</span>";
		returnPram = home+"<img src='"+imgpath+"arr_history.gif' border='0' align='absmiddle'>"+oneDepthName[depth1]+"<img src='"+imgpath+"arr_history.gif' border='0' align='absmiddle'>"+twoDepthName[depth2];
		
	}





	return returnPram ;

}

///////  VIEW ///////
function currentPage(){

	var zoneFront ="";
	var zoneBack ="";
	zoneFront="";
	zoneBack="";

 	document.write(zoneFront + locationCheck(depth1, depth2, depth3, depth4) + zoneBack);
}

/*********************************************************
*  로케이션 관리 끝
*********************************************************/
/*********************************************************
*  End common_path.js
*********************************************************/

/*********************************************************
*  Start common.js
*********************************************************/

/*********************************************************************************************************
	check email format :: return true[OK] / false[NOT]
**********************************************************************************************************/

	function chkEmailFormat( str ) {

		//return (/^[_0-9a-zA-Z-]+(\.[_0-9a-zA-Z-]+)*@[0-9a-zA-Z-]+(\.)+([0-9a-zA-Z-]+)(\.0-9a-zA-Z-)*$/.test(str) ) ;
		return (/^[_0-9a-zA-Z-]+(\.[_0-9a-zA-Z-]+)*@[0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*$/.test(str) ) ;
	}


/*********************************************************************************************************
	배경 캐시 끄기
**********************************************************************************************************/
try {
	document.execCommand('BackgroundImageCache', false, true);
} catch(me) {}



/*********************************************************************************************************
	onload function
**********************************************************************************************************/
function addLoadEvent(func) {
	var oldonload = window.onload;
	if (typeof window.onload != 'function') {
		window.onload = func;
	} else {
		window.onload = function() {
			oldonload();
			func();
		}
	}
}

/*********************************************************************************************************
	플래시 삽입 스크립트
**********************************************************************************************************/
var EmbedStr = "";
	function GetFlash3(objid,url,x,y) {

	AC_FL_RunContent(
		'codebase', 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0',
		'width', x,
		'height', y,
		'src', url,
		'quality', 'high',
		'pluginspage', 'http://www.macromedia.com/go/getflashplayer',
		'align', 'middle',
		'play', 'true',
		'loop', 'true',
		'scale', 'showall',
		'wmode', 'transparent',
		'devicefont', 'false',
		'id', objid,
		'bgcolor', '#ffffff',
		'name', 'HubMain',
		'menu', 'true',
		'allowFullScreen', 'false',
		'allowScriptAccess','sameDomain',
		'movie', url,
		'salign', ''
		); //end AC code
		//document.write(EmbedStr);
		//return;

	}



/*********************************************************************************************************
	png이미지 처리 스크립트
**********************************************************************************************************/
function setPng24(object) {
    object.width=object.height=1;
	object.className=object.className.replace(/\bpng24\b/i,'');
    object.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+ object.src +"',sizingMethod='image');"
    var isUrl2Depth = object.getAttribute("isUrl2Depth");
    if ( isUrl2Depth == "true" ) {
    	object.src='../../en_US/images/blank.gif';
    }
    else {
    	object.src='../en_US/images/blank.gif';
    }
    return '';
}

/*********************************************************************************************************
	popup - open / close
**********************************************************************************************************/
var tempY=0;
function open_popup(id,w,h){
	var gId = document.getElementById(id);
	var realX = (document.body.clientWidth-w)/2;
	var realY = (document.documentElement.clientHeight-h)/2;
	var glayerPopup = gId.className;

	if( gId.style.display == "none" || gId.style.display == "" ){
		gId.style.display = "block";
	} else {
		gId.style.display = "none";
	}

	gId.style.width = (w-10)+"px";
	gId.style.position = "absolute";
	gId.style.left = realX + "px";

	var sUserAgent = navigator.userAgent;
	var isKHTML = sUserAgent.indexOf("KHTML") > -1 || sUserAgent.indexOf("Konqueror") > -1  || sUserAgent.indexOf("AppleWebKit") > -1;
	if(isKHTML == true){
		if(tempY != document.body.scrollTop){
			realY = document.body.scrollTop+realY;
		}
	} else {
		if(tempY != document.documentElement.scrollTop){
			realY = document.documentElement.scrollTop+realY;
		}
	}
	gId.style.top = realY + "px";
}
function close_popup(id){
	var gId = document.getElementById(id);
	if( gId.style.display == "none" || gId.style.display == "" ){
		gId.style.display = "block";
	} else {
		gId.style.display = "none";
	}
}

/*********************************************************************************************************
	popup - open-new / close
**********************************************************************************************************/
var win_height = document.documentElement.clientHeight/2;
var win_width = document.documentElement.clientWidth/2;

function Common_GetWindowWidth()
{
	var width =
		document.documentElement && document.documentElement.clientWidth ||
		document.body && document.body.clientWidth ||
		document.body && document.body.parentNode && document.body.parentNode.clientWidth ||
		0;
		
	return width;
}

function Common_GetWindowHeight()
{
	var height =
		document.documentElement && document.documentElement.clientHeight ||
		document.body && document.body.clientHeight ||
		document.body && document.body.parentNode && document.body.parentNode.clientHeight ||
		0;
		
	return height;
}

/*********************************************************************************************************
popup - open-new / close
**********************************************************************************************************/
function open_popup_new(id,w,h){
	
	var gId = document.getElementById(id);
	var realY = (document.documentElement.clientHeight-h)/2;
	var glayerPopup = gId.className;

	if( gId.style.display == "none" || gId.style.display == "" ){
		gId.style.display = "block";
	} else {
		gId.style.display = "none";
	}

	if ( w ) gId.style.width = (w-10)+"px";
	
	var left = document.documentElement.scrollLeft ;
	var top = document.documentElement.scrollTop ;
	
	gId.style.left = Math.max((left + (Common_GetWindowWidth() - gId.offsetWidth) / 2), 0) + 'px';
	gId.style.top = Math.max((top + (Common_GetWindowHeight() - gId.offsetHeight) / 2), 0) + 'px';
}
function close_popup_new(id){
	var gId = document.getElementById(id);
	if( gId.style.display == "none" || gId.style.display == "" ){
		gId.style.display = "block";
	} else {
		gId.style.display = "none";
	}
}

/*********************************************************************************************************
popup - open-new-2 
**********************************************************************************************************/
function open_popup_new_2(id,w,h){
	var gId = document.getElementById(id);
	var realY = (document.documentElement.clientHeight-h)/2;
	var glayerPopup = gId.className;
	
	if( gId.style.display == "none" || gId.style.display == "" ){
		gId.style.display = "block";
	} else {
		gId.style.display = "none";
	}
	
	gId.style.width = (w-10)+"px";
}

/*********************************************************************************************************
	Roll over
**********************************************************************************************************/
function menuOver2(obj) { obj.src = obj.src.replace("_off.gif", "_on.gif");}
function menuOut2(obj) { obj.src = obj.src.replace("_on.gif", "_off.gif");}



/*********************************************************************************************************
	application images change
**********************************************************************************************************/
function preparePlaceholder() {
	if (!document.createElement) return false;
	if (!document.createTextNode) return false;
	if (!document.getElementById) return false;
	if (!document.getElementById("imagegallery")) return false;

	var placeholder = document.createElement("img");
	placeholder.setAttribute("id","placeholder");
	//placeholder.setAttribute("src","../en_US/images/application/noimages_screen_shot_large.gif");
	placeholder.className = "imgPreview";

	var prevArea = document.createElement("p");
	prevArea.setAttribute("id","imgPreviewArea");

	prevArea.appendChild(placeholder);

	var gallery = document.getElementById("imagegallery");

	gallery.parentNode.insertBefore(placeholder,gallery);
	gallery.parentNode.insertBefore(prevArea,placeholder);

	//document.getElementById("imgPreviewArea").className = "imgPreview";
}

function prepareGallery() {
	if(!document.getElementsByTagName) return false;
	if(!document.getElementById) return false;
	if(!document.getElementById("imagegallery")) return false;

	var gallery = document.getElementById("imagegallery");
	var links = gallery.getElementsByTagName("a");
	for(var i=0; i<links.length; i++){
		links[i].onclick = function(){
			return showPic(this);
		}
		links[i].onkeypress = links[i].onclick;
	}
	
	// first product images links
	var source = links[0].getAttribute("href");
	var placeholder = document.getElementById("placeholder");
	placeholder.setAttribute("src",source);
}

function showPic(whichpic) {
	if (!document.getElementById("placeholder")) return true;

	var source = whichpic.getAttribute("href");
	var placeholder = document.getElementById("placeholder");
	placeholder.setAttribute("src",source);

	return false;
}


addLoadEvent(preparePlaceholder);
addLoadEvent(prepareGallery);


/*********************************************************************************************************
	Expand FAQ list - show, hidden Func.
**********************************************************************************************************/
function AnswerExpViewFunc(selfid,targetid,btnid){
	if (!document.getElementById("faqExpandList")) return false;

	var faqlist = document.getElementById("faqExpandList");
	if(selfid){
		var gSelf = document.getElementById(selfid);
		var gTarget = document.getElementById(targetid);
		var gBtn = document.getElementById(btnid);
		if(gTarget.style.display == "block"){
			gTarget.style.display = "none";
			gSelf.className = "queDL";
			gTarget.className = "answerDL";
			gBtn.src = "../en_US/images/common/btn/plus_view.gif";
		} else {
			gTarget.style.display = "block";
			gSelf.className = "queDLOn";
			gTarget.className = "answerDLOn";
			gBtn.src = "../en_US/images/common/btn/minus_view.gif";
		}
	} else {
//		var gSelf = document.getElementById('que01');
//		var gTarget = document.getElementById('answer01');
//		var gBtn = document.getElementById('btn01');
//			gTarget.style.display = "block";
//			gSelf.className = "queDLOn";
//			gTarget.className = "answerDLOn";
//			gBtn.src = "../en_US/images/common/btn/minus_view.gif";
	}
}
addLoadEvent(AnswerExpViewFunc);

/*********************************************************************************************************
	FAQ list - show, hidden Func.
**********************************************************************************************************/

function AnswerViewFunc(selfid,targetid,btnid){
	if (!document.getElementById("faqExpandList")) return false;

	var faqlist = document.getElementById("faqExpandList");
	if(selfid){
		var gSelf = document.getElementById(selfid);
		var gTarget = document.getElementById(targetid);
		var gBtn = document.getElementById(btnid);
		if(gTarget.style.display == "block"){
			gTarget.style.display = "none";
			gSelf.className = "queDL";
			gTarget.className = "answerDL";
			gBtn.src = "../en_US/images/common/btn/plus_view.gif";
		} else {
			gTarget.style.display = "block";
			gSelf.className = "queDLOn";
			gTarget.className = "answerDLOn";
			gBtn.src = "../en_US/images/common/btn/minus_view.gif";
		}
	} else {
//		var gSelf = document.getElementById('que01');
//		var gTarget = document.getElementById('answer01');
//		var gBtn = document.getElementById('btn01');
	}
}
addLoadEvent(AnswerViewFunc);


/*********************************************************************************************************
	statistics - Graph.
**********************************************************************************************************/
	function graphOnOff(showElement){
		var gshow = document.getElementById(showElement);
		if(gshow.style.display == "none"){
			gshow.style.display = "block";
		} else {
			gshow.style.display = "none";
		}
	}

/*********************************************************************************************************
    브라우져 구분 함수
**********************************************************************************************************/
function commonBrowserDetect()
{
    if(navigator.appName == "Microsoft Internet Explorer")
        return "IE";
    else if(navigator.appName == "Netscape" && navigator.vendor.substring(0,5) == "Apple")
        return "Safari";
    else if(navigator.vendor == "")
        return "Firefox";
}

/*********************************************************************************************************
    Word breaking 함수
**********************************************************************************************************/
function commonWordBreak(contents) {
    var wordBreakTag;

    if (commonBrowserDetect() == "Safari")      
        wordBreakTag = "&#8203;";
    else
        wordBreakTag = "<wbr/>";

    return contents.split('').join(wordBreakTag);
}   

function commonDisplayLongContents(contents)
{
    return commonWordBreak(contents);
}



//<![CDATA[

document.getElementsByClassName = function(clsName)
{
    var retVal = new Array();
    var elements = document.getElementsByTagName("*");
    for(var i = 0;i < elements.length;i++)
    {
        if(elements[i].className.indexOf(" ") >= 0)
        {
            var classes = elements[i].className.split(" ");
            for(var j = 0;j < classes.length;j++)
            {
                if(classes[j] == clsName)
                    retVal.push(elements[i]);
            }
        }
        else if(elements[i].className == clsName)
            retVal.push(elements[i]);
    }
    return retVal;
}

function wordBreak(elements)
{
    for(var i=0;i<elements.length;i++)
    {
        var el = elements[i];
        
    	el.innerHTML = el.innerHTML.split('').join('<wbr />');
    	
    	// exclude "<br />" tag
        if ( el && el.getAttribute("noWordBreakForBr") == "true" ) {
        	var pattern = /(<|&lt;)<wbr( \/)?>B<wbr( \/)?>R<wbr( \/)?>(\/<wbr( \/)?>)?(<|&gt;)/gi;
        	el.innerHTML = el.innerHTML.replace(pattern, "<br />");
        }
    }
}

function wbr()
{
    wordBreak(document.getElementsByClassName('wbrClass'));
}

addLoadEvent(wbr);
//]]>

/*********************************************************************************************************
	select - Statistics.
**********************************************************************************************************/

function change_menu1(frm){
    switch(frm){
    case "0":
        document.getElementById('layer1').style.display = 'block';
        document.getElementById('layer2').style.display = 'none';
		document.getElementById('layer3').style.display = 'none';
        break;
    case "1":
        document.getElementById('layer2').style.display = 'block';
        document.getElementById('layer1').style.display = 'none';
		document.getElementById('layer3').style.display = 'none';
        break;
	case "2":
        document.getElementById('layer3').style.display = 'block';
        document.getElementById('layer2').style.display = 'none';
		document.getElementById('layer1').style.display = 'none';
        break;
    }
}

function change_menu2(frm){
    switch(frm){
    case "0":
        document.getElementById('Stalayer1').style.display = 'block';
        document.getElementById('Stalayer2').style.display = 'none';
		document.getElementById('Stalayer3').style.display = 'none';
		document.getElementById('Stalayer4').style.display = 'none';
		document.getElementById('Stalayer5').style.display = 'none';
        break;
    case "1":
        document.getElementById('Stalayer2').style.display = 'block';
        document.getElementById('Stalayer1').style.display = 'none';
		document.getElementById('Stalayer3').style.display = 'none';
		document.getElementById('Stalayer4').style.display = 'none';
		document.getElementById('Stalayer5').style.display = 'none';
        break;
	case "2":
        document.getElementById('Stalayer3').style.display = 'block';
        document.getElementById('Stalayer1').style.display = 'none';
		document.getElementById('Stalayer2').style.display = 'none';
		document.getElementById('Stalayer4').style.display = 'none';
		document.getElementById('Stalayer5').style.display = 'none';
        break;
	case "3":
        document.getElementById('Stalayer4').style.display = 'block';
        document.getElementById('Stalayer5').style.display = 'block';
		document.getElementById('Stalayer1').style.display = 'none';
		document.getElementById('Stalayer2').style.display = 'none';
		document.getElementById('Stalayer3').style.display = 'none';
        break;
    }
}

/**
 *  주민등록번호의 유효성을 체크한다.
 */
function isValidJuminNo(juminno) {
  if(juminno=="" || juminno==null) {
	  showOspWarningPopup("Confirm required fields", "주민등록번호를 적어주세요.");
    return false;
  }
 
  var jumin1 = juminno.substr(0,6);
  var jumin2 = juminno.substr(6,7);
  var yy     = jumin1.substr(0,2);        // 년도
  var mm     = jumin1.substr(2,2);        // 월
  var dd     = jumin1.substr(4,2);        // 일
  var genda  = jumin2.substr(0,1);        // 성별
  var msg, ss, cc;

  // 숫자가 아닌 것을 입력한 경우
  if (!isNumeric(jumin1)) {
	  showOspWarningPopup("Confirm required fields", "주민등록번호 앞자리를 숫자로 입력하세요.");
    return false;
  }
 
  // 길이가 6이 아닌 경우
  if (jumin1.length != 6) {
	  showOspWarningPopup("Confirm required fields","주민등록번호 앞자리를 다시 입력하세요.");
    return false;
  }
 
  // 첫번째 자료에서 연월일(YYMMDD) 형식 중 기본 구성 검사
  if (yy < "00"
      || yy > "99"
      || mm < "01"
      || mm > "12"
      || dd < "01"
      || dd > "31") {
	  showOspWarningPopup("Confirm required fields", "주민등록번호 앞자리를 다시 입력하세요.");
    return false;
  }
 
  // 숫자가 아닌 것을 입력한 경우
  if (!isNumeric(jumin2)) {
	  showOspWarningPopup("Confirm required fields", "주민등록번호 뒷자리를 숫자로 입력하세요.");
    return false;
  }

  // 길이가 7이 아닌 경우
  if (jumin2.length != 7) {
	  showOspWarningPopup("Confirm required fields", "주민등록번호 뒷자리를 다시 입력하세요.");
    return false;
  }
 
  // 성별부분이 1 ~ 4 가 아닌 경우
  if (genda < "1" || genda > "4") {
	  showOspWarningPopup("Confirm required fields", "주민등록번호 뒷자리를 다시 입력하세요.");
    return false;
  }
 
  // 연도 계산 - 1 또는 2: 1900년대, 3 또는 4: 2000년대
  cc = (genda == "1" || genda == "2") ? "19" : "20";
  // 첫번째 자료에서 연월일(YYMMDD) 형식 중 날짜 형식 검사
  if (isValidDate(cc+yy+mm+dd) == false) {
	  showOspWarningPopup("Confirm required fields", "주민등록번호 앞자리를 다시 입력하세요.");
    return false;
  }
 
  // Check Digit 검사
  if (!isSSN(jumin1, jumin2)) {
	  showOspWarningPopup("Confirm required fields", "입력한 주민등록번호를 검토한 후, 다시 입력하세요.");
    return false;
  }
  return true;
}

function isNumeric(s) {
	  for (i=0; i<s.length; i++) {
	    c = s.substr(i, 1);
	    if (c < "0" || c > "9") return false;
	  }
	  return true;
}

function isValidDate(iDate) {
	  if( iDate.length != 8 ) {
	    return false;
	  }
	  
	  var year = parseInt(iDate.substring(0, 4), 10);
	  var mm = parseInt(iDate.substring(4, 6), 10);
	  var dd = parseInt(iDate.substring(6),10);
	  
	  oDate = new Date(year,mm-1,dd);
	  if( oDate.getFullYear()     != year
	      || oDate.getMonth()     != mm -1
	      || oDate.getDate()      != dd){
	    
	    return false;
	  }
	   
	  return true;
	}


function isSSN(s1, s2) {
  n = 2;
  sum = 0;
  for (i=0; i<s1.length; i++)
    sum += parseInt(s1.substr(i, 1)) * n++;
  for (i=0; i<s2.length-1; i++) {
    sum += parseInt(s2.substr(i, 1)) * n++;
    if (n == 10) n = 2;
  }
 
  c = 11 - sum % 11;
  if (c == 11) c = 1;
  if (c == 10) c = 0;
  if (c != parseInt(s2.substr(6, 1))) return false;
  else return true;
}
/**
 *  사업자 등록 번호의 유효성을 체크한다.
 */
function checkBizID(bizID)  //사업자등록번호 체크 
{ 
    // bizID는 숫자만 10자리로 해서 문자열로 넘긴다. 
    var checkID = new Array(1, 3, 7, 1, 3, 7, 1, 3, 5, 1); 
    var tmpBizID, i, chkSum=0, c2, remander; 
     bizID = bizID.replace(/-/gi,''); 

     for (i=0; i<=7; i++) chkSum += checkID[i] * bizID.charAt(i); 
     c2 = "0" + (checkID[8] * bizID.charAt(8)); 
     c2 = c2.substring(c2.length - 2, c2.length); 
     chkSum += Math.floor(c2.charAt(0)) + Math.floor(c2.charAt(1)); 
     remander = (10 - (chkSum % 10)) % 10 ; 

    if (Math.floor(bizID.charAt(9)) == remander) return true ; // OK! 
      return false; 
}

/**
 * form 안에 <input type="text" ..> 태그가  하나만 있을 때는, 
 * enter를 입력하면 입력값에 대한 validation등을 하지도 않은체 submit 되어 버리는 문제 해결용 함수.
 * 
 * <form 태그 안에  onSubmit="return onEnterSubmit(submitSearchForm)" 와 같이 사용하면 된다.
 * 괄호 안의 submitSearchForm는 sumit되기 전에 validation등의 체크를 하고 submit 해주는 함수이다.
 * 즉, 사용자가 Enter를 입력했을 때, 바로 submit되지 않고, onEnterSubmit이 호출되며,
 * onEnterSubmit 안에서 validation 등을 수행하고 submit하는 submitSearchForm()를 호출해주는 것이다.
 */
function onEnterSubmit(callbackSumitFunc) {
    callbackSumitFunc();        
    return false;
/*        
    var keyCode = ( window.event ) ? window.event.keyCode : e.which;
	if (keyCode == 13) {
        alert(0)
        if( window.event ) {
            window.event.returnValue = false;
        } else {
            e.preventDefault();
            e.stopPropagation();
        }
	}
*/ 
}

function clearmember(A){
	if(A.value==A.defaultValue){A.value="";A.className="input"}
}

function checkmember(A){
	if(A.value==""){A.value=A.defaultValue;A.className="input"}
}
/*********************************************************
*  End common.js
*********************************************************/
/*********************************************************
*  Start userDefineCommon.js
*********************************************************/
function addLoadEventUserDefine(func) {
	  var oldonload = window.onload;
	  if (typeof window.onload != 'function') {
		window.onload = func;
	  } else {
		window.onload = function() {
		  oldonload();
		  func();
		}
	  }
	}

	function bgPopupOverUserDefine() {
		var div2= document.createElement("div");
		div2.innerHTML="<div id='bg_popup' style='display:none;'><div></div><!--[if lte IE 6.5]><iframe src='/en_US/images/common/space.gif'></iframe><![endif]--></div></div>";
		document.body.appendChild(div2);
	}

	addLoadEventUserDefine(bgPopupOverUserDefine);


	function openPopupWaringUserDefine(id,w,h,varPopupLayerTitle,varPopupLayerWaringContent){
		
		document.getElementById("idPopupLayerTitle").innerHTML = varPopupLayerTitle;
		document.getElementById("idPopupLayerWaringContent").innerHTML = varPopupLayerWaringContent;
		openPopupUserDefine(id,w,h);
	}

	function openPopupUserDefine(id,w,h){
		
		
	    if ( document.getElementById('bg_popup') ) {
	        document.getElementById('bg_popup').style.display = "block";
	    }	
	    

		var gId = document.getElementById(id);
		
		var realX = (document.body.clientWidth-w)/2;
		var realY = (document.documentElement.clientHeight-h)/2;	
		
		gId.style.width = (w-10)+"px";
		gId.style.height = (h-10)+"px";
		gId.style.position = "absolute";
		gId.style.left = realX + "px";

		var sUserAgent = navigator.userAgent;
		var isKHTML = sUserAgent.indexOf("KHTML") > -1 || sUserAgent.indexOf("Konqueror") > -1  || sUserAgent.indexOf("AppleWebKit") > -1;
		if(isKHTML == true){
			if(tempY != document.body.scrollTop){
				realY = document.body.scrollTop+realY;
			}
		} else {
			if(tempY != document.documentElement.scrollTop){
				realY = document.documentElement.scrollTop+realY;
			}
		}
		gId.style.top = realY + "px";	
		
		gId.style.zIndex = 200;	
	     
	    
		if( gId.style.display == "none" || gId.style.display == "" ){
			gId.style.display = "block";
		} else {
			gId.style.display = "none";
		}    	
		
	    MP_OnWindowResize_UserDefine(id);	
	}


	function closePopupUserDefine(id){
	    if ( document.getElementById('bg_popup') ) {
	        document.getElementById('bg_popup').style.display = "none";
	    }	
		
		var gId = document.getElementById(id);
		if( gId.style.display == "none" || gId.style.display == "" ){
			gId.style.display = "block";
		} else {
			gId.style.display = "none";
		}
	}


	//resize 시 팝업의 중심을 잡아 주는 함수
	function MP_OnWindowResize_UserDefine(varOspPopupLayerID)
	{
		var ospPopupLayerObject = document.getElementById(varOspPopupLayerID);

		var left = window.XMLHttpRequest == null ? document.documentElement.scrollLeft : 0;
		var top = window.XMLHttpRequest == null ? document.documentElement.scrollTop : 0;
		var div = document.getElementById(varOspPopupLayerID);

		var layerWidth = ospPopupLayerObject.childNodes[0].clientWidth;
		var layerHeight = ospPopupLayerObject.childNodes[0].clientHeight;
		
		// ospPopupObject를 쓸 수 없어서 ospPopupWidth를 불가피하게 사용하였음!!
		div.style.left = Math.max((left + (MP_GetWindowWidth_UserDefine() - layerWidth) / 2), 0) + 'px';
		div.style.top = Math.max((top + (MP_GetWindowHeight_UserDefine() - layerHeight ) / 2), 0) + 'px';
	}

	function MP_GetWindowWidth_UserDefine()
	{
		var width =
			document.documentElement && document.documentElement.clientWidth ||
			document.body && document.body.clientWidth ||
			document.body && document.body.parentNode && document.body.parentNode.clientWidth ||
			0;
			
		return width;
	}

	function MP_GetWindowHeight_UserDefine()
	{
	    var height =
			document.documentElement && document.documentElement.clientHeight ||
			document.body && document.body.clientHeight ||
	  		document.body && document.body.parentNode && document.body.parentNode.clientHeight ||
	  		0;
	  		
	  	return height;
	}



	var checkBoxUtil = {

	    /*
	    * 대상이 되는 체크박스를 전체선택
	    */
	    selectAll : function (objForm, strTargetCheckBoxName) {
	        try{
	            var obj = objForm[strTargetCheckBoxName];
	            if(obj == null){
	                return;
	            }
	            
	            if (obj.length > 0)  {
	                for (var i = 0; i < obj.length; i++) {
	                        obj[i].checked = true;
	                }
	            }
	            else {
	                obj.checked = true;
	            }
	        }
	        catch(x) {
	        }
	    },
	    
	    /*
	    * 대상이 되는 체크박스를 전체해제
	    */
	    selectNone : function (objForm, strTargetCheckBoxName)   {
	        try{
	            var obj = objForm[strTargetCheckBoxName];
	            
	            if(obj == null){
	                return;
	            }
	            
	            if (obj.length > 0) {
	                for (i = 0; i < obj.length; i++) {
	                    obj[i].checked = false;
	                }
	            }
	            else {
	                obj.checked = false;
	            }
	        }
	        catch(x) {
	        }
	    },
	    
	    /*
	    * 전체선택/해제 를 동시에 사용하는 체크박스일 경우에 전체선택/전체해제 를 할 경우 사용됨.[상단에 하나 , 하단에 하나 있는 경우에 대해서
	    */
	    changeCheckedByTwo : function(obj, objFormName, strTargetCheckBoxName){
	    
	        var objForm = eval("document." + objFormName);
	    
	        if(obj == null || typeof(obj) == "undefined"){
	            return;
	        }
	        
	        if(obj.checked == true){
	            checkBoxUtil.selectAll(objForm, strTargetCheckBoxName);
	        }else{
	            checkBoxUtil.selectNone(objForm, strTargetCheckBoxName);
	        }
	        
	        var chkObj = objForm[obj.name];
	        
	        if(obj.checked == true){
		        chkObj[0].checked = true;
		        chkObj[1].checked = true;
	        }else{
	            chkObj[0].checked = false;
	            chkObj[1].checked = false;        
	        }
	    },
	    
	    /*
	     * 전체선택/해제 를 동시에 사용하는 체크박스일 경우에 전체선택/전체해제 를 할 경우 사용됨.
	     */
	     changeChecked : function(obj, objFormName, strTargetCheckBoxName){
	     
	         var objForm = eval("document." + objFormName);
	     
	         if(obj == null || typeof(obj) == "undefined"){
	             return;
	         }
	         
	         if(obj.checked == true){
	             checkBoxUtil.selectAll(objForm, strTargetCheckBoxName);
	         }else{
	             checkBoxUtil.selectNone(objForm, strTargetCheckBoxName);
	         }
	         
	         var chkObj = objForm[obj.name];
	         
	         if(obj.checked == true){
	 	        chkObj.checked = true;
	         }else{
	             chkObj.checked = false;        
	         }
	     },    
	    
	    /*
	    * 체크된 체크박스가 존재하는지 여부를 리턴한다.
	    *
	    * 리턴값 : true => 선택된 체크박스가 있음.
	    *        false => 선태된 체크박스가 없음.
	    */
	    isExistCheckedBox : function (objForm, strTargetCheckBoxName)   {
	        try{
	            var obj = objForm[strTargetCheckBoxName];
	            
	            if(obj == null || typeof(obj) == "undefined"){
	                return false;
	            }
	            
	            if (obj.length > 0) {
	                for (i = 0; i < obj.length; i++) {
	                    if(obj[i].checked == true) return true;
	                }
	                
	                return false;
	            }
	            else {
	                return obj.checked;
	            }
	        }
	        catch(x) {
	            return false;
	        }
	    }
	}	


	var userDefineUtil = {
			
		/*
		 * Byte Number Of String
		 */
		getBytes : function(str){
		  	var tcount = 0;

		  	var tmpStr = new String(str);
		  	var temp = tmpStr.length;

		  	var onechar;
		  	for ( k=0; k<temp; k++ )
		  	{
		    	onechar = tmpStr.charAt(k);
		    	if (escape(onechar).length > 4)
		    	{
		      		tcount += 2;
		    	}
		    	else
		    	{
		      		tcount += 1;
		    	}
		  	}

		  	return tcount;
		}
	}


	var radioUtils = {
	    
	    /**
	     * Radio Button의 선택된 값을 가져온다
	     */
	    checkedVal : function (obj) {
	        
	        if(obj.length == undefined) {
	            
	            if(obj.checked == true)
	                return obj.value;
	            else
	                return null;
	        }
	        
	        for(var i = 0; i < obj.length; i++) {
	            if(obj[i].checked == true)
	                return obj[i].value;
	        }
	        return null;
	    },
	    
	    /**
	     * Radio Button의 선택된 값을 가져온다
	     */
	    checkedObj : function (obj) {
	        
	        if(obj.length == undefined) {
	            
	            if(obj.checked == true)
	                return obj;
	            else
	                return null;
	        }
	        
	        for(var i = 0; i < obj.length; i++) {
	            if(obj[i].checked == true)
	                return obj[i];
	        }
	        return null;
	    },
	    
	    disabledRadio : function (obj, isDisabled) {
	        
	        if(obj.length == undefined) {
	            
	            obj.disabled = isDisabled;
	        }
	        
	        for(var i = 0; i < obj.length; i++) {
	            obj[i].disabled = isDisabled;
	        }
	    }
	    
	}



	var StringUtils = {
		    
		    /****************************************************************
		     * 주어진 길이보다 길이가 작은 문자열을 앞에 0을 붙여 패딩한다 <BR>
		     * param str 문자열
		     # param len 길이
		     * return 뒤에 '0'으로 패딩된 문자열을 리턴한다. 단, 주어진 길이보다 크거나 같으면 원본문자열을 그대로 리턴한다
		     ****************************************************************/
		    
		    paddingTailZero : function (str, len) {
		        var strLen = str.length;
		        var cab = 0;
		        var tmp = "";
		        if (strLen >= len)
		            return str;
		        else
		            cab = len - strLen;
		        
		        for (var ii = 0; ii < cab; ii++) {
		            tmp = tmp + "0";
		        }
		        
		        return str + tmp;
		    },
		    
		    paddingBeforeZero : function (str, len) {
		        var strLen = str.length;
		        var cab = 0;
		        var tmp = "";
		        if (strLen >= len)
		            return str;
		        else
		            cab = len - strLen;
		        
		        for (var ii = 0; ii < cab; ii++) {
		            tmp = tmp + "0";
		        }
		        
		        //return str + tmp;
		        
		        return tmp + str;
		    },
		    
		    
		    // 한/영 포함해서 Byte 단위로 자를때 한글이 깨지지 않는 범위에서 최소로 잘려진 글자를 리턴한다.
		    // return : 자른 문자열
		    getLimitChar : function ( value, limitBtye) {
		        var strValue = "";
		        
		        for( var i=0; i<value.length; i++ ) {
		            if( this.getByteLength(strValue) + this.getByteLength(value.charAt(i)) > limitBtye ) {
		                break;
		            } else {
		                strValue += value.charAt(i);
		            }
		        }
		        
		        return strValue;
		    },
		    
		    getByteLength : function (src) {
		        var byteLength = 0;
		        for (var inx = 0; inx < src.length; inx++) {
		            var oneChar = escape(src.charAt(inx));
		            if ( oneChar.length == 1 ) {
		                byteLength ++;
		            } else if (oneChar.indexOf("%u") != -1) {
		                byteLength += 2;
		            } else if (oneChar.indexOf("%") != -1) {
		                byteLength += oneChar.length/3;
		            }
		        }
		        return byteLength;
		        
		    },
		    
		    getByteLengthComment : function (src) {
		        var byteLength = 0;
		        for (var inx = 0; inx < src.length; inx++) {
		            var oneChar = escape(src.charAt(inx));
		            if ( oneChar.length == 1 ) {
		                byteLength ++;
		            } else if (oneChar.indexOf("%u") != -1) {
		                byteLength += 3;
		            } else if (oneChar.indexOf("%") != -1) {
		                byteLength += oneChar.length/3;
		            }
		        }
		        return byteLength;
		        
		    },
		    /**
		     * 숫자나 문자열을 통화(Money) 형식으로 만든다.( 쉼표(,) 찍는다는 소리.. )
		     * @param	amount	"1234567"
		     * @return	currencyString "1,234,567"
		     */
		    formatCurrency : function (amount) {
		        amount = new String(amount);
		        var amountLength = amount.length;
		        var modulus = amountLength % 3;
		        var currencyString = amount.substr(0,modulus);
		        for(i=modulus; i<amountLength; i=i+3) {
		            if(currencyString != "")
		                currencyString += ",";
		            currencyString += amount.substr(i, 3);
		        }
		        return currencyString;
		    }
		    
		}

/*********************************************************
*  End userDefineCommon.js
*********************************************************/
/*********************************************************
*  Start prototype.js
*********************************************************/
	/*  Prototype JavaScript framework, version 1.6.0.3
	 *  (c) 2005-2008 Sam Stephenson
	 *
	 *  Prototype is freely distributable under the terms of an MIT-style license.
	 *  For details, see the Prototype web site: http://www.prototypejs.org/
	 *
	 *--------------------------------------------------------------------------*/


	var Prototype = {
	  Version: '1.6.0.3',

	  Browser: {
	    IE:     !!(window.attachEvent &&
	      navigator.userAgent.indexOf('Opera') === -1),
	    Opera:  navigator.userAgent.indexOf('Opera') > -1,
	    WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
	    Gecko:  navigator.userAgent.indexOf('Gecko') > -1 &&
	      navigator.userAgent.indexOf('KHTML') === -1,
	    MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
	  },

	  BrowserFeatures: {
	    XPath: !!document.evaluate,
	    SelectorsAPI: !!document.querySelector,
	    ElementExtensions: !!window.HTMLElement,
	    SpecificElementExtensions:
	      document.createElement('div')['__proto__'] &&
	      document.createElement('div')['__proto__'] !==
	        document.createElement('form')['__proto__']
	  },

	  ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
	  JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,

	  emptyFunction: function() { },
	  K: function(x) { return x }
	};

	if (Prototype.Browser.MobileSafari)
	  Prototype.BrowserFeatures.SpecificElementExtensions = false;


	/* Based on Alex Arnell's inheritance implementation. */
	var Class = {
	  create: function() {
	    var parent = null, properties = $A(arguments);
	    if (Object.isFunction(properties[0]))
	      parent = properties.shift();

	    function klass() {
	      this.initialize.apply(this, arguments);
	    }

	    Object.extend(klass, Class.Methods);
	    klass.superclass = parent;
	    klass.subclasses = [];

	    if (parent) {
	      var subclass = function() { };
	      subclass.prototype = parent.prototype;
	      klass.prototype = new subclass;
	      parent.subclasses.push(klass);
	    }

	    for (var i = 0; i < properties.length; i++)
	      klass.addMethods(properties[i]);

	    if (!klass.prototype.initialize)
	      klass.prototype.initialize = Prototype.emptyFunction;

	    klass.prototype.constructor = klass;

	    return klass;
	  }
	};

	Class.Methods = {
	  addMethods: function(source) {
	    var ancestor   = this.superclass && this.superclass.prototype;
	    var properties = Object.keys(source);

	    if (!Object.keys({ toString: true }).length)
	      properties.push("toString", "valueOf");

	    for (var i = 0, length = properties.length; i < length; i++) {
	      var property = properties[i], value = source[property];
	      if (ancestor && Object.isFunction(value) &&
	          value.argumentNames().first() == "$super") {
	        var method = value;
	        value = (function(m) {
	          return function() { return ancestor[m].apply(this, arguments) };
	        })(property).wrap(method);

	        value.valueOf = method.valueOf.bind(method);
	        value.toString = method.toString.bind(method);
	      }
	      this.prototype[property] = value;
	    }

	    return this;
	  }
	};

	var Abstract = { };

	Object.extend = function(destination, source) {
	  for (var property in source)
	    destination[property] = source[property];
	  return destination;
	};

	Object.extend(Object, {
	  inspect: function(object) {
	    try {
	      if (Object.isUndefined(object)) return 'undefined';
	      if (object === null) return 'null';
	      return object.inspect ? object.inspect() : String(object);
	    } catch (e) {
	      if (e instanceof RangeError) return '...';
	      throw e;
	    }
	  },

	  toJSON: function(object) {
	    var type = typeof object;
	    switch (type) {
	      case 'undefined':
	      case 'function':
	      case 'unknown': return;
	      case 'boolean': return object.toString();
	    }

	    if (object === null) return 'null';
	    if (object.toJSON) return object.toJSON();
	    if (Object.isElement(object)) return;

	    var results = [];
	    for (var property in object) {
	      var value = Object.toJSON(object[property]);
	      if (!Object.isUndefined(value))
	        results.push(property.toJSON() + ': ' + value);
	    }

	    return '{' + results.join(', ') + '}';
	  },

	  toQueryString: function(object) {
	    return $H(object).toQueryString();
	  },

	  toHTML: function(object) {
	    return object && object.toHTML ? object.toHTML() : String.interpret(object);
	  },

	  keys: function(object) {
	    var keys = [];
	    for (var property in object)
	      keys.push(property);
	    return keys;
	  },

	  values: function(object) {
	    var values = [];
	    for (var property in object)
	      values.push(object[property]);
	    return values;
	  },

	  clone: function(object) {
	    return Object.extend({ }, object);
	  },

	  isElement: function(object) {
	    return !!(object && object.nodeType == 1);
	  },

	  isArray: function(object) {
	    return object != null && typeof object == "object" &&
	      'splice' in object && 'join' in object;
	  },

	  isHash: function(object) {
	    return object instanceof Hash;
	  },

	  isFunction: function(object) {
	    return typeof object == "function";
	  },

	  isString: function(object) {
	    return typeof object == "string";
	  },

	  isNumber: function(object) {
	    return typeof object == "number";
	  },

	  isUndefined: function(object) {
	    return typeof object == "undefined";
	  }
	});

	Object.extend(Function.prototype, {
	  argumentNames: function() {
	    var names = this.toString().match(/^[\s\(]*function[^(]*\(([^\)]*)\)/)[1]
	      .replace(/\s+/g, '').split(',');
	    return names.length == 1 && !names[0] ? [] : names;
	  },

	  bind: function() {
	    if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
	    var __method = this, args = $A(arguments), object = args.shift();
	    return function() {
	      return __method.apply(object, args.concat($A(arguments)));
	    }
	  },

	  bindAsEventListener: function() {
	    var __method = this, args = $A(arguments), object = args.shift();
	    return function(event) {
	      return __method.apply(object, [event || window.event].concat(args));
	    }
	  },

	  curry: function() {
	    if (!arguments.length) return this;
	    var __method = this, args = $A(arguments);
	    return function() {
	      return __method.apply(this, args.concat($A(arguments)));
	    }
	  },

	  delay: function() {
	    var __method = this, args = $A(arguments), timeout = args.shift() * 1000;
	    return window.setTimeout(function() {
	      return __method.apply(__method, args);
	    }, timeout);
	  },

	  defer: function() {
	    var args = [0.01].concat($A(arguments));
	    return this.delay.apply(this, args);
	  },

	  wrap: function(wrapper) {
	    var __method = this;
	    return function() {
	      return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));
	    }
	  },

	  methodize: function() {
	    if (this._methodized) return this._methodized;
	    var __method = this;
	    return this._methodized = function() {
	      return __method.apply(null, [this].concat($A(arguments)));
	    };
	  }
	});

	Date.prototype.toJSON = function() {
	  return '"' + this.getUTCFullYear() + '-' +
	    (this.getUTCMonth() + 1).toPaddedString(2) + '-' +
	    this.getUTCDate().toPaddedString(2) + 'T' +
	    this.getUTCHours().toPaddedString(2) + ':' +
	    this.getUTCMinutes().toPaddedString(2) + ':' +
	    this.getUTCSeconds().toPaddedString(2) + 'Z"';
	};

	var Try = {
	  these: function() {
	    var returnValue;

	    for (var i = 0, length = arguments.length; i < length; i++) {
	      var lambda = arguments[i];
	      try {
	        returnValue = lambda();
	        break;
	      } catch (e) { }
	    }

	    return returnValue;
	  }
	};

	RegExp.prototype.match = RegExp.prototype.test;

	RegExp.escape = function(str) {
	  return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
	};

	/*--------------------------------------------------------------------------*/

	var PeriodicalExecuter = Class.create({
	  initialize: function(callback, frequency) {
	    this.callback = callback;
	    this.frequency = frequency;
	    this.currentlyExecuting = false;

	    this.registerCallback();
	  },

	  registerCallback: function() {
	    this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
	  },

	  execute: function() {
	    this.callback(this);
	  },

	  stop: function() {
	    if (!this.timer) return;
	    clearInterval(this.timer);
	    this.timer = null;
	  },

	  onTimerEvent: function() {
	    if (!this.currentlyExecuting) {
	      try {
	        this.currentlyExecuting = true;
	        this.execute();
	      } finally {
	        this.currentlyExecuting = false;
	      }
	    }
	  }
	});
	Object.extend(String, {
	  interpret: function(value) {
	    return value == null ? '' : String(value);
	  },
	  specialChar: {
	    '\b': '\\b',
	    '\t': '\\t',
	    '\n': '\\n',
	    '\f': '\\f',
	    '\r': '\\r',
	    '\\': '\\\\'
	  }
	});

	Object.extend(String.prototype, {
	  gsub: function(pattern, replacement) {
	    var result = '', source = this, match;
	    replacement = arguments.callee.prepareReplacement(replacement);

	    while (source.length > 0) {
	      if (match = source.match(pattern)) {
	        result += source.slice(0, match.index);
	        result += String.interpret(replacement(match));
	        source  = source.slice(match.index + match[0].length);
	      } else {
	        result += source, source = '';
	      }
	    }
	    return result;
	  },

	  sub: function(pattern, replacement, count) {
	    replacement = this.gsub.prepareReplacement(replacement);
	    count = Object.isUndefined(count) ? 1 : count;

	    return this.gsub(pattern, function(match) {
	      if (--count < 0) return match[0];
	      return replacement(match);
	    });
	  },

	  scan: function(pattern, iterator) {
	    this.gsub(pattern, iterator);
	    return String(this);
	  },

	  truncate: function(length, truncation) {
	    length = length || 30;
	    truncation = Object.isUndefined(truncation) ? '...' : truncation;
	    return this.length > length ?
	      this.slice(0, length - truncation.length) + truncation : String(this);
	  },

	  strip: function() {
	    return this.replace(/^\s+/, '').replace(/\s+$/, '');
	  },

	  stripTags: function() {
	    return this.replace(/<\/?[^>]+>/gi, '');
	  },

	  stripScripts: function() {
	    return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
	  },

	  extractScripts: function() {
	    var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
	    var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
	    return (this.match(matchAll) || []).map(function(scriptTag) {
	      return (scriptTag.match(matchOne) || ['', ''])[1];
	    });
	  },

	  evalScripts: function() {
	    return this.extractScripts().map(function(script) { return eval(script) });
	  },

	  escapeHTML: function() {
	    var self = arguments.callee;
	    self.text.data = this;
	    return self.div.innerHTML;
	  },

	  unescapeHTML: function() {
	    var div = new Element('div');
	    div.innerHTML = this.stripTags();
	    return div.childNodes[0] ? (div.childNodes.length > 1 ?
	      $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
	      div.childNodes[0].nodeValue) : '';
	  },

	  toQueryParams: function(separator) {
	    var match = this.strip().match(/([^?#]*)(#.*)?$/);
	    if (!match) return { };

	    return match[1].split(separator || '&').inject({ }, function(hash, pair) {
	      if ((pair = pair.split('='))[0]) {
	        var key = decodeURIComponent(pair.shift());
	        var value = pair.length > 1 ? pair.join('=') : pair[0];
	        if (value != undefined) value = decodeURIComponent(value);

	        if (key in hash) {
	          if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
	          hash[key].push(value);
	        }
	        else hash[key] = value;
	      }
	      return hash;
	    });
	  },

	  toArray: function() {
	    return this.split('');
	  },

	  succ: function() {
	    return this.slice(0, this.length - 1) +
	      String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
	  },

	  times: function(count) {
	    return count < 1 ? '' : new Array(count + 1).join(this);
	  },

	  camelize: function() {
	    var parts = this.split('-'), len = parts.length;
	    if (len == 1) return parts[0];

	    var camelized = this.charAt(0) == '-'
	      ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
	      : parts[0];

	    for (var i = 1; i < len; i++)
	      camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);

	    return camelized;
	  },

	  capitalize: function() {
	    return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
	  },

	  underscore: function() {
	    return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
	  },

	  dasherize: function() {
	    return this.gsub(/_/,'-');
	  },

	  inspect: function(useDoubleQuotes) {
	    var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
	      var character = String.specialChar[match[0]];
	      return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
	    });
	    if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
	    return "'" + escapedString.replace(/'/g, '\\\'') + "'";
	  },

	  toJSON: function() {
	    return this.inspect(true);
	  },

	  unfilterJSON: function(filter) {
	    return this.sub(filter || Prototype.JSONFilter, '#{1}');
	  },

	  isJSON: function() {
	    var str = this;
	    if (str.blank()) return false;
	    str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
	    return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
	  },

	  evalJSON: function(sanitize) {
	    var json = this.unfilterJSON();
	    try {
	      if (!sanitize || json.isJSON()) return eval('(' + json + ')');
	    } catch (e) { }
	    throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
	  },

	  include: function(pattern) {
	    return this.indexOf(pattern) > -1;
	  },

	  startsWith: function(pattern) {
	    return this.indexOf(pattern) === 0;
	  },

	  endsWith: function(pattern) {
	    var d = this.length - pattern.length;
	    return d >= 0 && this.lastIndexOf(pattern) === d;
	  },

	  empty: function() {
	    return this == '';
	  },

	  blank: function() {
	    return /^\s*$/.test(this);
	  },

	  interpolate: function(object, pattern) {
	    return new Template(this, pattern).evaluate(object);
	  }
	});

	if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
	  escapeHTML: function() {
	    return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
	  },
	  unescapeHTML: function() {
	    return this.stripTags().replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>');
	  }
	});

	String.prototype.gsub.prepareReplacement = function(replacement) {
	  if (Object.isFunction(replacement)) return replacement;
	  var template = new Template(replacement);
	  return function(match) { return template.evaluate(match) };
	};

	String.prototype.parseQuery = String.prototype.toQueryParams;

	Object.extend(String.prototype.escapeHTML, {
	  div:  document.createElement('div'),
	  text: document.createTextNode('')
	});

	String.prototype.escapeHTML.div.appendChild(String.prototype.escapeHTML.text);

	var Template = Class.create({
	  initialize: function(template, pattern) {
	    this.template = template.toString();
	    this.pattern = pattern || Template.Pattern;
	  },

	  evaluate: function(object) {
	    if (Object.isFunction(object.toTemplateReplacements))
	      object = object.toTemplateReplacements();

	    return this.template.gsub(this.pattern, function(match) {
	      if (object == null) return '';

	      var before = match[1] || '';
	      if (before == '\\') return match[2];

	      var ctx = object, expr = match[3];
	      var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
	      match = pattern.exec(expr);
	      if (match == null) return before;

	      while (match != null) {
	        var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1];
	        ctx = ctx[comp];
	        if (null == ctx || '' == match[3]) break;
	        expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
	        match = pattern.exec(expr);
	      }

	      return before + String.interpret(ctx);
	    });
	  }
	});
	Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;

	var $break = { };

	var Enumerable = {
	  each: function(iterator, context) {
	    var index = 0;
	    try {
	      this._each(function(value) {
	        iterator.call(context, value, index++);
	      });
	    } catch (e) {
	      if (e != $break) throw e;
	    }
	    return this;
	  },

	  eachSlice: function(number, iterator, context) {
	    var index = -number, slices = [], array = this.toArray();
	    if (number < 1) return array;
	    while ((index += number) < array.length)
	      slices.push(array.slice(index, index+number));
	    return slices.collect(iterator, context);
	  },

	  all: function(iterator, context) {
	    iterator = iterator || Prototype.K;
	    var result = true;
	    this.each(function(value, index) {
	      result = result && !!iterator.call(context, value, index);
	      if (!result) throw $break;
	    });
	    return result;
	  },

	  any: function(iterator, context) {
	    iterator = iterator || Prototype.K;
	    var result = false;
	    this.each(function(value, index) {
	      if (result = !!iterator.call(context, value, index))
	        throw $break;
	    });
	    return result;
	  },

	  collect: function(iterator, context) {
	    iterator = iterator || Prototype.K;
	    var results = [];
	    this.each(function(value, index) {
	      results.push(iterator.call(context, value, index));
	    });
	    return results;
	  },

	  detect: function(iterator, context) {
	    var result;
	    this.each(function(value, index) {
	      if (iterator.call(context, value, index)) {
	        result = value;
	        throw $break;
	      }
	    });
	    return result;
	  },

	  findAll: function(iterator, context) {
	    var results = [];
	    this.each(function(value, index) {
	      if (iterator.call(context, value, index))
	        results.push(value);
	    });
	    return results;
	  },

	  grep: function(filter, iterator, context) {
	    iterator = iterator || Prototype.K;
	    var results = [];

	    if (Object.isString(filter))
	      filter = new RegExp(filter);

	    this.each(function(value, index) {
	      if (filter.match(value))
	        results.push(iterator.call(context, value, index));
	    });
	    return results;
	  },

	  include: function(object) {
	    if (Object.isFunction(this.indexOf))
	      if (this.indexOf(object) != -1) return true;

	    var found = false;
	    this.each(function(value) {
	      if (value == object) {
	        found = true;
	        throw $break;
	      }
	    });
	    return found;
	  },

	  inGroupsOf: function(number, fillWith) {
	    fillWith = Object.isUndefined(fillWith) ? null : fillWith;
	    return this.eachSlice(number, function(slice) {
	      while(slice.length < number) slice.push(fillWith);
	      return slice;
	    });
	  },

	  inject: function(memo, iterator, context) {
	    this.each(function(value, index) {
	      memo = iterator.call(context, memo, value, index);
	    });
	    return memo;
	  },

	  invoke: function(method) {
	    var args = $A(arguments).slice(1);
	    return this.map(function(value) {
	      return value[method].apply(value, args);
	    });
	  },

	  max: function(iterator, context) {
	    iterator = iterator || Prototype.K;
	    var result;
	    this.each(function(value, index) {
	      value = iterator.call(context, value, index);
	      if (result == null || value >= result)
	        result = value;
	    });
	    return result;
	  },

	  min: function(iterator, context) {
	    iterator = iterator || Prototype.K;
	    var result;
	    this.each(function(value, index) {
	      value = iterator.call(context, value, index);
	      if (result == null || value < result)
	        result = value;
	    });
	    return result;
	  },

	  partition: function(iterator, context) {
	    iterator = iterator || Prototype.K;
	    var trues = [], falses = [];
	    this.each(function(value, index) {
	      (iterator.call(context, value, index) ?
	        trues : falses).push(value);
	    });
	    return [trues, falses];
	  },

	  pluck: function(property) {
	    var results = [];
	    this.each(function(value) {
	      results.push(value[property]);
	    });
	    return results;
	  },

	  reject: function(iterator, context) {
	    var results = [];
	    this.each(function(value, index) {
	      if (!iterator.call(context, value, index))
	        results.push(value);
	    });
	    return results;
	  },

	  sortBy: function(iterator, context) {
	    return this.map(function(value, index) {
	      return {
	        value: value,
	        criteria: iterator.call(context, value, index)
	      };
	    }).sort(function(left, right) {
	      var a = left.criteria, b = right.criteria;
	      return a < b ? -1 : a > b ? 1 : 0;
	    }).pluck('value');
	  },

	  toArray: function() {
	    return this.map();
	  },

	  zip: function() {
	    var iterator = Prototype.K, args = $A(arguments);
	    if (Object.isFunction(args.last()))
	      iterator = args.pop();

	    var collections = [this].concat(args).map($A);
	    return this.map(function(value, index) {
	      return iterator(collections.pluck(index));
	    });
	  },

	  size: function() {
	    return this.toArray().length;
	  },

	  inspect: function() {
	    return '#<Enumerable:' + this.toArray().inspect() + '>';
	  }
	};

	Object.extend(Enumerable, {
	  map:     Enumerable.collect,
	  find:    Enumerable.detect,
	  select:  Enumerable.findAll,
	  filter:  Enumerable.findAll,
	  member:  Enumerable.include,
	  entries: Enumerable.toArray,
	  every:   Enumerable.all,
	  some:    Enumerable.any
	});
	function $A(iterable) {
	  if (!iterable) return [];
	  if (iterable.toArray) return iterable.toArray();
	  var length = iterable.length || 0, results = new Array(length);
	  while (length--) results[length] = iterable[length];
	  return results;
	}

	if (Prototype.Browser.WebKit) {
	  $A = function(iterable) {
	    if (!iterable) return [];
	    // In Safari, only use the `toArray` method if it's not a NodeList.
	    // A NodeList is a function, has an function `item` property, and a numeric
	    // `length` property. Adapted from Google Doctype.
	    if (!(typeof iterable === 'function' && typeof iterable.length ===
	        'number' && typeof iterable.item === 'function') && iterable.toArray)
	      return iterable.toArray();
	    var length = iterable.length || 0, results = new Array(length);
	    while (length--) results[length] = iterable[length];
	    return results;
	  };
	}

	Array.from = $A;

	Object.extend(Array.prototype, Enumerable);

	if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse;

	Object.extend(Array.prototype, {
	  _each: function(iterator) {
	    for (var i = 0, length = this.length; i < length; i++)
	      iterator(this[i]);
	  },

	  clear: function() {
	    this.length = 0;
	    return this;
	  },

	  first: function() {
	    return this[0];
	  },

	  last: function() {
	    return this[this.length - 1];
	  },

	  compact: function() {
	    return this.select(function(value) {
	      return value != null;
	    });
	  },

	  flatten: function() {
	    return this.inject([], function(array, value) {
	      return array.concat(Object.isArray(value) ?
	        value.flatten() : [value]);
	    });
	  },

	  without: function() {
	    var values = $A(arguments);
	    return this.select(function(value) {
	      return !values.include(value);
	    });
	  },

	  reverse: function(inline) {
	    return (inline !== false ? this : this.toArray())._reverse();
	  },

	  reduce: function() {
	    return this.length > 1 ? this : this[0];
	  },

	  uniq: function(sorted) {
	    return this.inject([], function(array, value, index) {
	      if (0 == index || (sorted ? array.last() != value : !array.include(value)))
	        array.push(value);
	      return array;
	    });
	  },

	  intersect: function(array) {
	    return this.uniq().findAll(function(item) {
	      return array.detect(function(value) { return item === value });
	    });
	  },

	  clone: function() {
	    return [].concat(this);
	  },

	  size: function() {
	    return this.length;
	  },

	  inspect: function() {
	    return '[' + this.map(Object.inspect).join(', ') + ']';
	  },

	  toJSON: function() {
	    var results = [];
	    this.each(function(object) {
	      var value = Object.toJSON(object);
	      if (!Object.isUndefined(value)) results.push(value);
	    });
	    return '[' + results.join(', ') + ']';
	  }
	});

	// use native browser JS 1.6 implementation if available
	if (Object.isFunction(Array.prototype.forEach))
	  Array.prototype._each = Array.prototype.forEach;

	if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) {
	  i || (i = 0);
	  var length = this.length;
	  if (i < 0) i = length + i;
	  for (; i < length; i++)
	    if (this[i] === item) return i;
	  return -1;
	};

	if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) {
	  i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
	  var n = this.slice(0, i).reverse().indexOf(item);
	  return (n < 0) ? n : i - n - 1;
	};

	Array.prototype.toArray = Array.prototype.clone;

	function $w(string) {
	  if (!Object.isString(string)) return [];
	  string = string.strip();
	  return string ? string.split(/\s+/) : [];
	}

	if (Prototype.Browser.Opera){
	  Array.prototype.concat = function() {
	    var array = [];
	    for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
	    for (var i = 0, length = arguments.length; i < length; i++) {
	      if (Object.isArray(arguments[i])) {
	        for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
	          array.push(arguments[i][j]);
	      } else {
	        array.push(arguments[i]);
	      }
	    }
	    return array;
	  };
	}
	Object.extend(Number.prototype, {
	  toColorPart: function() {
	    return this.toPaddedString(2, 16);
	  },

	  succ: function() {
	    return this + 1;
	  },

	  times: function(iterator, context) {
	    $R(0, this, true).each(iterator, context);
	    return this;
	  },

	  toPaddedString: function(length, radix) {
	    var string = this.toString(radix || 10);
	    return '0'.times(length - string.length) + string;
	  },

	  toJSON: function() {
	    return isFinite(this) ? this.toString() : 'null';
	  }
	});

	$w('abs round ceil floor').each(function(method){
	  Number.prototype[method] = Math[method].methodize();
	});
	function $H(object) {
	  return new Hash(object);
	};

	var Hash = Class.create(Enumerable, (function() {

	  function toQueryPair(key, value) {
	    if (Object.isUndefined(value)) return key;
	    return key + '=' + encodeURIComponent(String.interpret(value));
	  }

	  return {
	    initialize: function(object) {
	      this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
	    },

	    _each: function(iterator) {
	      for (var key in this._object) {
	        var value = this._object[key], pair = [key, value];
	        pair.key = key;
	        pair.value = value;
	        iterator(pair);
	      }
	    },

	    set: function(key, value) {
	      return this._object[key] = value;
	    },

	    get: function(key) {
	      // simulating poorly supported hasOwnProperty
	      if (this._object[key] !== Object.prototype[key])
	        return this._object[key];
	    },

	    unset: function(key) {
	      var value = this._object[key];
	      delete this._object[key];
	      return value;
	    },

	    toObject: function() {
	      return Object.clone(this._object);
	    },

	    keys: function() {
	      return this.pluck('key');
	    },

	    values: function() {
	      return this.pluck('value');
	    },

	    index: function(value) {
	      var match = this.detect(function(pair) {
	        return pair.value === value;
	      });
	      return match && match.key;
	    },

	    merge: function(object) {
	      return this.clone().update(object);
	    },

	    update: function(object) {
	      return new Hash(object).inject(this, function(result, pair) {
	        result.set(pair.key, pair.value);
	        return result;
	      });
	    },

	    toQueryString: function() {
	      return this.inject([], function(results, pair) {
	        var key = encodeURIComponent(pair.key), values = pair.value;

	        if (values && typeof values == 'object') {
	          if (Object.isArray(values))
	            return results.concat(values.map(toQueryPair.curry(key)));
	        } else results.push(toQueryPair(key, values));
	        return results;
	      }).join('&');
	    },

	    inspect: function() {
	      return '#<Hash:{' + this.map(function(pair) {
	        return pair.map(Object.inspect).join(': ');
	      }).join(', ') + '}>';
	    },

	    toJSON: function() {
	      return Object.toJSON(this.toObject());
	    },

	    clone: function() {
	      return new Hash(this);
	    }
	  }
	})());

	Hash.prototype.toTemplateReplacements = Hash.prototype.toObject;
	Hash.from = $H;
	var ObjectRange = Class.create(Enumerable, {
	  initialize: function(start, end, exclusive) {
	    this.start = start;
	    this.end = end;
	    this.exclusive = exclusive;
	  },

	  _each: function(iterator) {
	    var value = this.start;
	    while (this.include(value)) {
	      iterator(value);
	      value = value.succ();
	    }
	  },

	  include: function(value) {
	    if (value < this.start)
	      return false;
	    if (this.exclusive)
	      return value < this.end;
	    return value <= this.end;
	  }
	});

	var $R = function(start, end, exclusive) {
	  return new ObjectRange(start, end, exclusive);
	};

	var Ajax = {
	  getTransport: function() {
	    return Try.these(
	      function() {return new XMLHttpRequest()},
	      function() {return new ActiveXObject('Msxml2.XMLHTTP')},
	      function() {return new ActiveXObject('Microsoft.XMLHTTP')}
	    ) || false;
	  },

	  activeRequestCount: 0
	};

	Ajax.Responders = {
	  responders: [],

	  _each: function(iterator) {
	    this.responders._each(iterator);
	  },

	  register: function(responder) {
	    if (!this.include(responder))
	      this.responders.push(responder);
	  },

	  unregister: function(responder) {
	    this.responders = this.responders.without(responder);
	  },

	  dispatch: function(callback, request, transport, json) {
	    this.each(function(responder) {
	      if (Object.isFunction(responder[callback])) {
	        try {
	          responder[callback].apply(responder, [request, transport, json]);
	        } catch (e) { }
	      }
	    });
	  }
	};

	Object.extend(Ajax.Responders, Enumerable);

	Ajax.Responders.register({
	  onCreate:   function() { Ajax.activeRequestCount++ },
	  onComplete: function() { Ajax.activeRequestCount-- }
	});

	Ajax.Base = Class.create({
	  initialize: function(options) {
	    this.options = {
	      method:       'post',
	      asynchronous: false,
	      contentType:  'application/x-www-form-urlencoded',
	      encoding:     'UTF-8',
	      parameters:   '',
	      evalJSON:     true,
	      evalJS:       true
	    };
	    Object.extend(this.options, options || { });

	    this.options.method = this.options.method.toLowerCase();

	    if (Object.isString(this.options.parameters))
	      this.options.parameters = this.options.parameters.toQueryParams();
	    else if (Object.isHash(this.options.parameters))
	      this.options.parameters = this.options.parameters.toObject();
	  }
	});

	Ajax.Request = Class.create(Ajax.Base, {
	  _complete: false,

	  initialize: function($super, url, options) {
	    $super(options);
	    this.transport = Ajax.getTransport();
	    this.request(url);
	  },

	  request: function(url) {
	    this.url = url;
	    this.method = this.options.method;
	    var params = Object.clone(this.options.parameters);

	    if (!['get', 'post'].include(this.method)) {
	      // simulate other verbs over post
	      params['_method'] = this.method;
	      this.method = 'post';
	    }

	    this.parameters = params;

	    if (params = Object.toQueryString(params)) {
	      // when GET, append parameters to URL
	      if (this.method == 'get')
	        this.url += (this.url.include('?') ? '&' : '?') + params;
	      else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
	        params += '&_=';
	    }

	    try {
	      var response = new Ajax.Response(this);
	      if (this.options.onCreate) this.options.onCreate(response);
	      Ajax.Responders.dispatch('onCreate', this, response);

	      this.transport.open(this.method.toUpperCase(), this.url,
	        this.options.asynchronous);

	      if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);

	      this.transport.onreadystatechange = this.onStateChange.bind(this);
	      this.setRequestHeaders();

	      this.body = this.method == 'post' ? (this.options.postBody || params) : null;
	      this.transport.send(this.body);

	      /* Force Firefox to handle ready state 4 for synchronous requests */
	      if (!this.options.asynchronous && this.transport.overrideMimeType)
	        this.onStateChange();

	    }
	    catch (e) {
	      this.dispatchException(e);
	    }
	  },

	  onStateChange: function() {
	    var readyState = this.transport.readyState;
	    if (readyState > 1 && !((readyState == 4) && this._complete))
	      this.respondToReadyState(this.transport.readyState);
	  },

	  setRequestHeaders: function() {
	    var headers = {
	      'X-Requested-With': 'XMLHttpRequest',
	      'X-Prototype-Version': Prototype.Version,
	      'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
	    };

	    if (this.method == 'post') {
	      headers['Content-type'] = this.options.contentType +
	        (this.options.encoding ? '; charset=' + this.options.encoding : '');

	      /* Force "Connection: close" for older Mozilla browsers to work
	       * around a bug where XMLHttpRequest sends an incorrect
	       * Content-length header. See Mozilla Bugzilla #246651.
	       */
	      if (this.transport.overrideMimeType &&
	          (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
	            headers['Connection'] = 'close';
	    }

	    // user-defined headers
	    if (typeof this.options.requestHeaders == 'object') {
	      var extras = this.options.requestHeaders;

	      if (Object.isFunction(extras.push))
	        for (var i = 0, length = extras.length; i < length; i += 2)
	          headers[extras[i]] = extras[i+1];
	      else
	        $H(extras).each(function(pair) { headers[pair.key] = pair.value });
	    }

	    for (var name in headers)
	      this.transport.setRequestHeader(name, headers[name]);
	  },

	  success: function() {
	    var status = this.getStatus();
	    return !status || (status >= 200 && status < 300);
	  },

	  getStatus: function() {
	    try {
	      return this.transport.status || 0;
	    } catch (e) { return 0 }
	  },

	  respondToReadyState: function(readyState) {
	    var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);

	    if (state == 'Complete') {
	      try {
	        this._complete = true;
	        (this.options['on' + response.status]
	         || this.options['on' + (this.success() ? 'Success' : 'Failure')]
	         || Prototype.emptyFunction)(response, response.headerJSON);
	      } catch (e) {
	        this.dispatchException(e);
	      }

	      var contentType = response.getHeader('Content-type');
	      if (this.options.evalJS == 'force'
	          || (this.options.evalJS && this.isSameOrigin() && contentType
	          && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
	        this.evalResponse();
	    }

	    try {
	      (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
	      Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
	    } catch (e) {
	      this.dispatchException(e);
	    }

	    if (state == 'Complete') {
	      // avoid memory leak in MSIE: clean up
	      this.transport.onreadystatechange = Prototype.emptyFunction;
	    }
	  },

	  isSameOrigin: function() {
	    var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
	    return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
	      protocol: location.protocol,
	      domain: document.domain,
	      port: location.port ? ':' + location.port : ''
	    }));
	  },

	  getHeader: function(name) {
	    try {
	      return this.transport.getResponseHeader(name) || null;
	    } catch (e) { return null }
	  },

	  evalResponse: function() {
	    try {
	      return eval((this.transport.responseText || '').unfilterJSON());
	    } catch (e) {
	      this.dispatchException(e);
	    }
	  },

	  dispatchException: function(exception) {
	    (this.options.onException || Prototype.emptyFunction)(this, exception);
	    Ajax.Responders.dispatch('onException', this, exception);
	  }
	});

	Ajax.Request.Events =
	  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];

	Ajax.Response = Class.create({
	  initialize: function(request){
	    this.request = request;
	    var transport  = this.transport  = request.transport,
	        readyState = this.readyState = transport.readyState;

	    if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
	      this.status       = this.getStatus();
	      this.statusText   = this.getStatusText();
	      this.responseText = String.interpret(transport.responseText);
	      this.headerJSON   = this._getHeaderJSON();
	    }

	    if(readyState == 4) {
	      var xml = transport.responseXML;
	      this.responseXML  = Object.isUndefined(xml) ? null : xml;
	      this.responseJSON = this._getResponseJSON();
	    }
	  },

	  status:      0,
	  statusText: '',

	  getStatus: Ajax.Request.prototype.getStatus,

	  getStatusText: function() {
	    try {
	      return this.transport.statusText || '';
	    } catch (e) { return '' }
	  },

	  getHeader: Ajax.Request.prototype.getHeader,

	  getAllHeaders: function() {
	    try {
	      return this.getAllResponseHeaders();
	    } catch (e) { return null }
	  },

	  getResponseHeader: function(name) {
	    return this.transport.getResponseHeader(name);
	  },

	  getAllResponseHeaders: function() {
	    return this.transport.getAllResponseHeaders();
	  },

	  _getHeaderJSON: function() {
	    var json = this.getHeader('X-JSON');
	    if (!json) return null;
	    json = decodeURIComponent(escape(json));
	    try {
	      return json.evalJSON(this.request.options.sanitizeJSON ||
	        !this.request.isSameOrigin());
	    } catch (e) {
	      this.request.dispatchException(e);
	    }
	  },

	  _getResponseJSON: function() {
	    var options = this.request.options;
	    if (!options.evalJSON || (options.evalJSON != 'force' &&
	      !(this.getHeader('Content-type') || '').include('application/json')) ||
	        this.responseText.blank())
	          return null;
	    try {
	      return this.responseText.evalJSON(options.sanitizeJSON ||
	        !this.request.isSameOrigin());
	    } catch (e) {
	      this.request.dispatchException(e);
	    }
	  }
	});

	Ajax.Updater = Class.create(Ajax.Request, {
	  initialize: function($super, container, url, options) {
	    this.container = {
	      success: (container.success || container),
	      failure: (container.failure || (container.success ? null : container))
	    };

	    options = Object.clone(options);
	    var onComplete = options.onComplete;
	    options.onComplete = (function(response, json) {
	      this.updateContent(response.responseText);
	      if (Object.isFunction(onComplete)) onComplete(response, json);
	    }).bind(this);

	    $super(url, options);
	  },

	  updateContent: function(responseText) {
	    var receiver = this.container[this.success() ? 'success' : 'failure'],
	        options = this.options;

	    if (!options.evalScripts) responseText = responseText.stripScripts();

	    if (receiver = $(receiver)) {
	      if (options.insertion) {
	        if (Object.isString(options.insertion)) {
	          var insertion = { }; insertion[options.insertion] = responseText;
	          receiver.insert(insertion);
	        }
	        else options.insertion(receiver, responseText);
	      }
	      else receiver.update(responseText);
	    }
	  }
	});

	Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
	  initialize: function($super, container, url, options) {
	    $super(options);
	    this.onComplete = this.options.onComplete;

	    this.frequency = (this.options.frequency || 2);
	    this.decay = (this.options.decay || 1);

	    this.updater = { };
	    this.container = container;
	    this.url = url;

	    this.start();
	  },

	  start: function() {
	    this.options.onComplete = this.updateComplete.bind(this);
	    this.onTimerEvent();
	  },

	  stop: function() {
	    this.updater.options.onComplete = undefined;
	    clearTimeout(this.timer);
	    (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
	  },

	  updateComplete: function(response) {
	    if (this.options.decay) {
	      this.decay = (response.responseText == this.lastText ?
	        this.decay * this.options.decay : 1);

	      this.lastText = response.responseText;
	    }
	    this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
	  },

	  onTimerEvent: function() {
	    this.updater = new Ajax.Updater(this.container, this.url, this.options);
	  }
	});
	function $(element) {
	  if (arguments.length > 1) {
	    for (var i = 0, elements = [], length = arguments.length; i < length; i++)
	      elements.push($(arguments[i]));
	    return elements;
	  }
	  if (Object.isString(element))
	    element = document.getElementById(element);
	  return Element.extend(element);
	}

	if (Prototype.BrowserFeatures.XPath) {
	  document._getElementsByXPath = function(expression, parentElement) {
	    var results = [];
	    var query = document.evaluate(expression, $(parentElement) || document,
	      null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
	    for (var i = 0, length = query.snapshotLength; i < length; i++)
	      results.push(Element.extend(query.snapshotItem(i)));
	    return results;
	  };
	}

	/*--------------------------------------------------------------------------*/

	if (!window.Node) var Node = { };

	if (!Node.ELEMENT_NODE) {
	  // DOM level 2 ECMAScript Language Binding
	  Object.extend(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
	  });
	}

	(function() {
	  var element = this.Element;
	  this.Element = function(tagName, attributes) {
	    attributes = attributes || { };
	    tagName = tagName.toLowerCase();
	    var cache = Element.cache;
	    if (Prototype.Browser.IE && attributes.name) {
	      tagName = '<' + tagName + ' name="' + attributes.name + '">';
	      delete attributes.name;
	      return Element.writeAttribute(document.createElement(tagName), attributes);
	    }
	    if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
	    return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);
	  };
	  Object.extend(this.Element, element || { });
	  if (element) this.Element.prototype = element.prototype;
	}).call(window);

	Element.cache = { };

	Element.Methods = {
	  visible: function(element) {
	    return $(element).style.display != 'none';
	  },

	  toggle: function(element) {
	    element = $(element);
	    Element[Element.visible(element) ? 'hide' : 'show'](element);
	    return element;
	  },

	  hide: function(element) {
	    element = $(element);
	    element.style.display = 'none';
	    return element;
	  },

	  show: function(element) {
	    element = $(element);
	    element.style.display = '';
	    return element;
	  },

	  remove: function(element) {
	    element = $(element);
	    element.parentNode.removeChild(element);
	    return element;
	  },

	  update: function(element, content) {
	    element = $(element);
	    if (content && content.toElement) content = content.toElement();
	    if (Object.isElement(content)) return element.update().insert(content);
	    content = Object.toHTML(content);
	    element.innerHTML = content.stripScripts();
	    content.evalScripts.bind(content).defer();
	    return element;
	  },

	  replace: function(element, content) {
	    element = $(element);
	    if (content && content.toElement) content = content.toElement();
	    else if (!Object.isElement(content)) {
	      content = Object.toHTML(content);
	      var range = element.ownerDocument.createRange();
	      range.selectNode(element);
	      content.evalScripts.bind(content).defer();
	      content = range.createContextualFragment(content.stripScripts());
	    }
	    element.parentNode.replaceChild(content, element);
	    return element;
	  },

	  insert: function(element, insertions) {
	    element = $(element);

	    if (Object.isString(insertions) || Object.isNumber(insertions) ||
	        Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
	          insertions = {bottom:insertions};

	    var content, insert, tagName, childNodes;

	    for (var position in insertions) {
	      content  = insertions[position];
	      position = position.toLowerCase();
	      insert = Element._insertionTranslations[position];

	      if (content && content.toElement) content = content.toElement();
	      if (Object.isElement(content)) {
	        insert(element, content);
	        continue;
	      }

	      content = Object.toHTML(content);

	      tagName = ((position == 'before' || position == 'after')
	        ? element.parentNode : element).tagName.toUpperCase();

	      childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());

	      if (position == 'top' || position == 'after') childNodes.reverse();
	      childNodes.each(insert.curry(element));

	      content.evalScripts.bind(content).defer();
	    }

	    return element;
	  },

	  wrap: function(element, wrapper, attributes) {
	    element = $(element);
	    if (Object.isElement(wrapper))
	      $(wrapper).writeAttribute(attributes || { });
	    else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);
	    else wrapper = new Element('div', wrapper);
	    if (element.parentNode)
	      element.parentNode.replaceChild(wrapper, element);
	    wrapper.appendChild(element);
	    return wrapper;
	  },

	  inspect: function(element) {
	    element = $(element);
	    var result = '<' + element.tagName.toLowerCase();
	    $H({'id': 'id', 'className': 'class'}).each(function(pair) {
	      var property = pair.first(), attribute = pair.last();
	      var value = (element[property] || '').toString();
	      if (value) result += ' ' + attribute + '=' + value.inspect(true);
	    });
	    return result + '>';
	  },

	  recursivelyCollect: function(element, property) {
	    element = $(element);
	    var elements = [];
	    while (element = element[property])
	      if (element.nodeType == 1)
	        elements.push(Element.extend(element));
	    return elements;
	  },

	  ancestors: function(element) {
	    return $(element).recursivelyCollect('parentNode');
	  },

	  descendants: function(element) {
	    return $(element).select("*");
	  },

	  firstDescendant: function(element) {
	    element = $(element).firstChild;
	    while (element && element.nodeType != 1) element = element.nextSibling;
	    return $(element);
	  },

	  immediateDescendants: function(element) {
	    if (!(element = $(element).firstChild)) return [];
	    while (element && element.nodeType != 1) element = element.nextSibling;
	    if (element) return [element].concat($(element).nextSiblings());
	    return [];
	  },

	  previousSiblings: function(element) {
	    return $(element).recursivelyCollect('previousSibling');
	  },

	  nextSiblings: function(element) {
	    return $(element).recursivelyCollect('nextSibling');
	  },

	  siblings: function(element) {
	    element = $(element);
	    return element.previousSiblings().reverse().concat(element.nextSiblings());
	  },

	  match: function(element, selector) {
	    if (Object.isString(selector))
	      selector = new Selector(selector);
	    return selector.match($(element));
	  },

	  up: function(element, expression, index) {
	    element = $(element);
	    if (arguments.length == 1) return $(element.parentNode);
	    var ancestors = element.ancestors();
	    return Object.isNumber(expression) ? ancestors[expression] :
	      Selector.findElement(ancestors, expression, index);
	  },

	  down: function(element, expression, index) {
	    element = $(element);
	    if (arguments.length == 1) return element.firstDescendant();
	    return Object.isNumber(expression) ? element.descendants()[expression] :
	      Element.select(element, expression)[index || 0];
	  },

	  previous: function(element, expression, index) {
	    element = $(element);
	    if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
	    var previousSiblings = element.previousSiblings();
	    return Object.isNumber(expression) ? previousSiblings[expression] :
	      Selector.findElement(previousSiblings, expression, index);
	  },

	  next: function(element, expression, index) {
	    element = $(element);
	    if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
	    var nextSiblings = element.nextSiblings();
	    return Object.isNumber(expression) ? nextSiblings[expression] :
	      Selector.findElement(nextSiblings, expression, index);
	  },

	  select: function() {
	    var args = $A(arguments), element = $(args.shift());
	    return Selector.findChildElements(element, args);
	  },

	  adjacent: function() {
	    var args = $A(arguments), element = $(args.shift());
	    return Selector.findChildElements(element.parentNode, args).without(element);
	  },

	  identify: function(element) {
	    element = $(element);
	    var id = element.readAttribute('id'), self = arguments.callee;
	    if (id) return id;
	    do { id = 'anonymous_element_' + self.counter++ } while ($(id));
	    element.writeAttribute('id', id);
	    return id;
	  },

	  readAttribute: function(element, name) {
	    element = $(element);
	    if (Prototype.Browser.IE) {
	      var t = Element._attributeTranslations.read;
	      if (t.values[name]) return t.values[name](element, name);
	      if (t.names[name]) name = t.names[name];
	      if (name.include(':')) {
	        return (!element.attributes || !element.attributes[name]) ? null :
	         element.attributes[name].value;
	      }
	    }
	    return element.getAttribute(name);
	  },

	  writeAttribute: function(element, name, value) {
	    element = $(element);
	    var attributes = { }, t = Element._attributeTranslations.write;

	    if (typeof name == 'object') attributes = name;
	    else attributes[name] = Object.isUndefined(value) ? true : value;

	    for (var attr in attributes) {
	      name = t.names[attr] || attr;
	      value = attributes[attr];
	      if (t.values[attr]) name = t.values[attr](element, value);
	      if (value === false || value === null)
	        element.removeAttribute(name);
	      else if (value === true)
	        element.setAttribute(name, name);
	      else element.setAttribute(name, value);
	    }
	    return element;
	  },

	  getHeight: function(element) {
	    return $(element).getDimensions().height;
	  },

	  getWidth: function(element) {
	    return $(element).getDimensions().width;
	  },

	  classNames: function(element) {
	    return new Element.ClassNames(element);
	  },

	  hasClassName: function(element, className) {
	    if (!(element = $(element))) return;
	    var elementClassName = element.className;
	    return (elementClassName.length > 0 && (elementClassName == className ||
	      new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));
	  },

	  addClassName: function(element, className) {
	    if (!(element = $(element))) return;
	    if (!element.hasClassName(className))
	      element.className += (element.className ? ' ' : '') + className;
	    return element;
	  },

	  removeClassName: function(element, className) {
	    if (!(element = $(element))) return;
	    element.className = element.className.replace(
	      new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();
	    return element;
	  },

	  toggleClassName: function(element, className) {
	    if (!(element = $(element))) return;
	    return element[element.hasClassName(className) ?
	      'removeClassName' : 'addClassName'](className);
	  },

	  // removes whitespace-only text node children
	  cleanWhitespace: function(element) {
	    element = $(element);
	    var node = element.firstChild;
	    while (node) {
	      var nextNode = node.nextSibling;
	      if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
	        element.removeChild(node);
	      node = nextNode;
	    }
	    return element;
	  },

	  empty: function(element) {
	    return $(element).innerHTML.blank();
	  },

	  descendantOf: function(element, ancestor) {
	    element = $(element), ancestor = $(ancestor);

	    if (element.compareDocumentPosition)
	      return (element.compareDocumentPosition(ancestor) & 8) === 8;

	    if (ancestor.contains)
	      return ancestor.contains(element) && ancestor !== element;

	    while (element = element.parentNode)
	      if (element == ancestor) return true;

	    return false;
	  },

	  scrollTo: function(element) {
	    element = $(element);
	    var pos = element.cumulativeOffset();
	    window.scrollTo(pos[0], pos[1]);
	    return element;
	  },

	  getStyle: function(element, style) {
	    element = $(element);
	    style = style == 'float' ? 'cssFloat' : style.camelize();
	    var value = element.style[style];
	    if (!value || value == 'auto') {
	      var css = document.defaultView.getComputedStyle(element, null);
	      value = css ? css[style] : null;
	    }
	    if (style == 'opacity') return value ? parseFloat(value) : 1.0;
	    return value == 'auto' ? null : value;
	  },

	  getOpacity: function(element) {
	    return $(element).getStyle('opacity');
	  },

	  setStyle: function(element, styles) {
	    element = $(element);
	    var elementStyle = element.style, match;
	    if (Object.isString(styles)) {
	      element.style.cssText += ';' + styles;
	      return styles.include('opacity') ?
	        element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element;
	    }
	    for (var property in styles)
	      if (property == 'opacity') element.setOpacity(styles[property]);
	      else
	        elementStyle[(property == 'float' || property == 'cssFloat') ?
	          (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') :
	            property] = styles[property];

	    return element;
	  },

	  setOpacity: function(element, value) {
	    element = $(element);
	    element.style.opacity = (value == 1 || value === '') ? '' :
	      (value < 0.00001) ? 0 : value;
	    return element;
	  },

	  getDimensions: function(element) {
	    element = $(element);
	    var display = element.getStyle('display');
	    if (display != 'none' && display != null) // Safari bug
	      return {width: element.offsetWidth, height: element.offsetHeight};

	    // All *Width and *Height properties give 0 on elements with display none,
	    // so enable the element temporarily
	    var els = element.style;
	    var originalVisibility = els.visibility;
	    var originalPosition = els.position;
	    var originalDisplay = els.display;
	    els.visibility = 'hidden';
	    els.position = 'absolute';
	    els.display = 'block';
	    var originalWidth = element.clientWidth;
	    var originalHeight = element.clientHeight;
	    els.display = originalDisplay;
	    els.position = originalPosition;
	    els.visibility = originalVisibility;
	    return {width: originalWidth, height: originalHeight};
	  },

	  makePositioned: function(element) {
	    element = $(element);
	    var pos = Element.getStyle(element, 'position');
	    if (pos == 'static' || !pos) {
	      element._madePositioned = true;
	      element.style.position = 'relative';
	      // Opera returns the offset relative to the positioning context, when an
	      // element is position relative but top and left have not been defined
	      if (Prototype.Browser.Opera) {
	        element.style.top = 0;
	        element.style.left = 0;
	      }
	    }
	    return element;
	  },

	  undoPositioned: function(element) {
	    element = $(element);
	    if (element._madePositioned) {
	      element._madePositioned = undefined;
	      element.style.position =
	        element.style.top =
	        element.style.left =
	        element.style.bottom =
	        element.style.right = '';
	    }
	    return element;
	  },

	  makeClipping: function(element) {
	    element = $(element);
	    if (element._overflow) return element;
	    element._overflow = Element.getStyle(element, 'overflow') || 'auto';
	    if (element._overflow !== 'hidden')
	      element.style.overflow = 'hidden';
	    return element;
	  },

	  undoClipping: function(element) {
	    element = $(element);
	    if (!element._overflow) return element;
	    element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
	    element._overflow = null;
	    return element;
	  },

	  cumulativeOffset: function(element) {
	    var valueT = 0, valueL = 0;
	    do {
	      valueT += element.offsetTop  || 0;
	      valueL += element.offsetLeft || 0;
	      element = element.offsetParent;
	    } while (element);
	    return Element._returnOffset(valueL, valueT);
	  },

	  positionedOffset: function(element) {
	    var valueT = 0, valueL = 0;
	    do {
	      valueT += element.offsetTop  || 0;
	      valueL += element.offsetLeft || 0;
	      element = element.offsetParent;
	      if (element) {
	        if (element.tagName.toUpperCase() == 'BODY') break;
	        var p = Element.getStyle(element, 'position');
	        if (p !== 'static') break;
	      }
	    } while (element);
	    return Element._returnOffset(valueL, valueT);
	  },

	  absolutize: function(element) {
	    element = $(element);
	    if (element.getStyle('position') == 'absolute') return element;
	    // Position.prepare(); // To be done manually by Scripty when it needs it.

	    var offsets = element.positionedOffset();
	    var top     = offsets[1];
	    var left    = offsets[0];
	    var width   = element.clientWidth;
	    var height  = element.clientHeight;

	    element._originalLeft   = left - parseFloat(element.style.left  || 0);
	    element._originalTop    = top  - parseFloat(element.style.top || 0);
	    element._originalWidth  = element.style.width;
	    element._originalHeight = element.style.height;

	    element.style.position = 'absolute';
	    element.style.top    = top + 'px';
	    element.style.left   = left + 'px';
	    element.style.width  = width + 'px';
	    element.style.height = height + 'px';
	    return element;
	  },

	  relativize: function(element) {
	    element = $(element);
	    if (element.getStyle('position') == 'relative') return element;
	    // Position.prepare(); // To be done manually by Scripty when it needs it.

	    element.style.position = 'relative';
	    var top  = parseFloat(element.style.top  || 0) - (element._originalTop || 0);
	    var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);

	    element.style.top    = top + 'px';
	    element.style.left   = left + 'px';
	    element.style.height = element._originalHeight;
	    element.style.width  = element._originalWidth;
	    return element;
	  },

	  cumulativeScrollOffset: function(element) {
	    var valueT = 0, valueL = 0;
	    do {
	      valueT += element.scrollTop  || 0;
	      valueL += element.scrollLeft || 0;
	      element = element.parentNode;
	    } while (element);
	    return Element._returnOffset(valueL, valueT);
	  },

	  getOffsetParent: function(element) {
	    if (element.offsetParent) return $(element.offsetParent);
	    if (element == document.body) return $(element);

	    while ((element = element.parentNode) && element != document.body)
	      if (Element.getStyle(element, 'position') != 'static')
	        return $(element);

	    return $(document.body);
	  },

	  viewportOffset: function(forElement) {
	    var valueT = 0, valueL = 0;

	    var element = forElement;
	    do {
	      valueT += element.offsetTop  || 0;
	      valueL += element.offsetLeft || 0;

	      // Safari fix
	      if (element.offsetParent == document.body &&
	        Element.getStyle(element, 'position') == 'absolute') break;

	    } while (element = element.offsetParent);

	    element = forElement;
	    do {
	      if (!Prototype.Browser.Opera || (element.tagName && (element.tagName.toUpperCase() == 'BODY'))) {
	        valueT -= element.scrollTop  || 0;
	        valueL -= element.scrollLeft || 0;
	      }
	    } while (element = element.parentNode);

	    return Element._returnOffset(valueL, valueT);
	  },

	  clonePosition: function(element, source) {
	    var options = Object.extend({
	      setLeft:    true,
	      setTop:     true,
	      setWidth:   true,
	      setHeight:  true,
	      offsetTop:  0,
	      offsetLeft: 0
	    }, arguments[2] || { });

	    // find page position of source
	    source = $(source);
	    var p = source.viewportOffset();

	    // find coordinate system to use
	    element = $(element);
	    var delta = [0, 0];
	    var parent = null;
	    // delta [0,0] will do fine with position: fixed elements,
	    // position:absolute needs offsetParent deltas
	    if (Element.getStyle(element, 'position') == 'absolute') {
	      parent = element.getOffsetParent();
	      delta = parent.viewportOffset();
	    }

	    // correct by body offsets (fixes Safari)
	    if (parent == document.body) {
	      delta[0] -= document.body.offsetLeft;
	      delta[1] -= document.body.offsetTop;
	    }

	    // set position
	    if (options.setLeft)   element.style.left  = (p[0] - delta[0] + options.offsetLeft) + 'px';
	    if (options.setTop)    element.style.top   = (p[1] - delta[1] + options.offsetTop) + 'px';
	    if (options.setWidth)  element.style.width = source.offsetWidth + 'px';
	    if (options.setHeight) element.style.height = source.offsetHeight + 'px';
	    return element;
	  }
	};

	Element.Methods.identify.counter = 1;

	Object.extend(Element.Methods, {
	  getElementsBySelector: Element.Methods.select,
	  childElements: Element.Methods.immediateDescendants
	});

	Element._attributeTranslations = {
	  write: {
	    names: {
	      className: 'class',
	      htmlFor:   'for'
	    },
	    values: { }
	  }
	};

	if (Prototype.Browser.Opera) {
	  Element.Methods.getStyle = Element.Methods.getStyle.wrap(
	    function(proceed, element, style) {
	      switch (style) {
	        case 'left': case 'top': case 'right': case 'bottom':
	          if (proceed(element, 'position') === 'static') return null;
	        case 'height': case 'width':
	          // returns '0px' for hidden elements; we want it to return null
	          if (!Element.visible(element)) return null;

	          // returns the border-box dimensions rather than the content-box
	          // dimensions, so we subtract padding and borders from the value
	          var dim = parseInt(proceed(element, style), 10);

	          if (dim !== element['offset' + style.capitalize()])
	            return dim + 'px';

	          var properties;
	          if (style === 'height') {
	            properties = ['border-top-width', 'padding-top',
	             'padding-bottom', 'border-bottom-width'];
	          }
	          else {
	            properties = ['border-left-width', 'padding-left',
	             'padding-right', 'border-right-width'];
	          }
	          return properties.inject(dim, function(memo, property) {
	            var val = proceed(element, property);
	            return val === null ? memo : memo - parseInt(val, 10);
	          }) + 'px';
	        default: return proceed(element, style);
	      }
	    }
	  );

	  Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(
	    function(proceed, element, attribute) {
	      if (attribute === 'title') return element.title;
	      return proceed(element, attribute);
	    }
	  );
	}

	else if (Prototype.Browser.IE) {
	  // IE doesn't report offsets correctly for static elements, so we change them
	  // to "relative" to get the values, then change them back.
	  Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(
	    function(proceed, element) {
	      element = $(element);
	      // IE throws an error if element is not in document
	      try { element.offsetParent }
	      catch(e) { return $(document.body) }
	      var position = element.getStyle('position');
	      if (position !== 'static') return proceed(element);
	      element.setStyle({ position: 'relative' });
	      var value = proceed(element);
	      element.setStyle({ position: position });
	      return value;
	    }
	  );

	  $w('positionedOffset viewportOffset').each(function(method) {
	    Element.Methods[method] = Element.Methods[method].wrap(
	      function(proceed, element) {
	        element = $(element);
	        try { element.offsetParent }
	        catch(e) { return Element._returnOffset(0,0) }
	        var position = element.getStyle('position');
	        if (position !== 'static') return proceed(element);
	        // Trigger hasLayout on the offset parent so that IE6 reports
	        // accurate offsetTop and offsetLeft values for position: fixed.
	        var offsetParent = element.getOffsetParent();
	        if (offsetParent && offsetParent.getStyle('position') === 'fixed')
	          offsetParent.setStyle({ zoom: 1 });
	        element.setStyle({ position: 'relative' });
	        var value = proceed(element);
	        element.setStyle({ position: position });
	        return value;
	      }
	    );
	  });

	  Element.Methods.cumulativeOffset = Element.Methods.cumulativeOffset.wrap(
	    function(proceed, element) {
	      try { element.offsetParent }
	      catch(e) { return Element._returnOffset(0,0) }
	      return proceed(element);
	    }
	  );

	  Element.Methods.getStyle = function(element, style) {
	    element = $(element);
	    style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
	    var value = element.style[style];
	    if (!value && element.currentStyle) value = element.currentStyle[style];

	    if (style == 'opacity') {
	      if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
	        if (value[1]) return parseFloat(value[1]) / 100;
	      return 1.0;
	    }

	    if (value == 'auto') {
	      if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
	        return element['offset' + style.capitalize()] + 'px';
	      return null;
	    }
	    return value;
	  };

	  Element.Methods.setOpacity = function(element, value) {
	    function stripAlpha(filter){
	      return filter.replace(/alpha\([^\)]*\)/gi,'');
	    }
	    element = $(element);
	    var currentStyle = element.currentStyle;
	    if ((currentStyle && !currentStyle.hasLayout) ||
	      (!currentStyle && element.style.zoom == 'normal'))
	        element.style.zoom = 1;

	    var filter = element.getStyle('filter'), style = element.style;
	    if (value == 1 || value === '') {
	      (filter = stripAlpha(filter)) ?
	        style.filter = filter : style.removeAttribute('filter');
	      return element;
	    } else if (value < 0.00001) value = 0;
	    style.filter = stripAlpha(filter) +
	      'alpha(opacity=' + (value * 100) + ')';
	    return element;
	  };

	  Element._attributeTranslations = {
	    read: {
	      names: {
	        'class': 'className',
	        'for':   'htmlFor'
	      },
	      values: {
	        _getAttr: function(element, attribute) {
	          return element.getAttribute(attribute, 2);
	        },
	        _getAttrNode: function(element, attribute) {
	          var node = element.getAttributeNode(attribute);
	          return node ? node.value : "";
	        },
	        _getEv: function(element, attribute) {
	          attribute = element.getAttribute(attribute);
	          return attribute ? attribute.toString().slice(23, -2) : null;
	        },
	        _flag: function(element, attribute) {
	          return $(element).hasAttribute(attribute) ? attribute : null;
	        },
	        style: function(element) {
	          return element.style.cssText.toLowerCase();
	        },
	        title: function(element) {
	          return element.title;
	        }
	      }
	    }
	  };

	  Element._attributeTranslations.write = {
	    names: Object.extend({
	      cellpadding: 'cellPadding',
	      cellspacing: 'cellSpacing'
	    }, Element._attributeTranslations.read.names),
	    values: {
	      checked: function(element, value) {
	        element.checked = !!value;
	      },

	      style: function(element, value) {
	        element.style.cssText = value ? value : '';
	      }
	    }
	  };

	  Element._attributeTranslations.has = {};

	  $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +
	      'encType maxLength readOnly longDesc frameBorder').each(function(attr) {
	    Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;
	    Element._attributeTranslations.has[attr.toLowerCase()] = attr;
	  });

	  (function(v) {
	    Object.extend(v, {
	      href:        v._getAttr,
	      src:         v._getAttr,
	      type:        v._getAttr,
	      action:      v._getAttrNode,
	      disabled:    v._flag,
	      checked:     v._flag,
	      readonly:    v._flag,
	      multiple:    v._flag,
	      onload:      v._getEv,
	      onunload:    v._getEv,
	      onclick:     v._getEv,
	      ondblclick:  v._getEv,
	      onmousedown: v._getEv,
	      onmouseup:   v._getEv,
	      onmouseover: v._getEv,
	      onmousemove: v._getEv,
	      onmouseout:  v._getEv,
	      onfocus:     v._getEv,
	      onblur:      v._getEv,
	      onkeypress:  v._getEv,
	      onkeydown:   v._getEv,
	      onkeyup:     v._getEv,
	      onsubmit:    v._getEv,
	      onreset:     v._getEv,
	      onselect:    v._getEv,
	      onchange:    v._getEv
	    });
	  })(Element._attributeTranslations.read.values);
	}

	else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {
	  Element.Methods.setOpacity = function(element, value) {
	    element = $(element);
	    element.style.opacity = (value == 1) ? 0.999999 :
	      (value === '') ? '' : (value < 0.00001) ? 0 : value;
	    return element;
	  };
	}

	else if (Prototype.Browser.WebKit) {
	  Element.Methods.setOpacity = function(element, value) {
	    element = $(element);
	    element.style.opacity = (value == 1 || value === '') ? '' :
	      (value < 0.00001) ? 0 : value;

	    if (value == 1)
	      if(element.tagName.toUpperCase() == 'IMG' && element.width) {
	        element.width++; element.width--;
	      } else try {
	        var n = document.createTextNode(' ');
	        element.appendChild(n);
	        element.removeChild(n);
	      } catch (e) { }

	    return element;
	  };

	  // Safari returns margins on body which is incorrect if the child is absolutely
	  // positioned.  For performance reasons, redefine Element#cumulativeOffset for
	  // KHTML/WebKit only.
	  Element.Methods.cumulativeOffset = function(element) {
	    var valueT = 0, valueL = 0;
	    do {
	      valueT += element.offsetTop  || 0;
	      valueL += element.offsetLeft || 0;
	      if (element.offsetParent == document.body)
	        if (Element.getStyle(element, 'position') == 'absolute') break;

	      element = element.offsetParent;
	    } while (element);

	    return Element._returnOffset(valueL, valueT);
	  };
	}

	if (Prototype.Browser.IE || Prototype.Browser.Opera) {
	  // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements
	  Element.Methods.update = function(element, content) {
	    element = $(element);

	    if (content && content.toElement) content = content.toElement();
	    if (Object.isElement(content)) return element.update().insert(content);

	    content = Object.toHTML(content);
	    var tagName = element.tagName.toUpperCase();

	    if (tagName in Element._insertionTranslations.tags) {
	      $A(element.childNodes).each(function(node) { element.removeChild(node) });
	      Element._getContentFromAnonymousElement(tagName, content.stripScripts())
	        .each(function(node) { element.appendChild(node) });
	    }
	    else element.innerHTML = content.stripScripts();

	    content.evalScripts.bind(content).defer();
	    return element;
	  };
	}

	if ('outerHTML' in document.createElement('div')) {
	  Element.Methods.replace = function(element, content) {
	    element = $(element);

	    if (content && content.toElement) content = content.toElement();
	    if (Object.isElement(content)) {
	      element.parentNode.replaceChild(content, element);
	      return element;
	    }

	    content = Object.toHTML(content);
	    var parent = element.parentNode, tagName = parent.tagName.toUpperCase();

	    if (Element._insertionTranslations.tags[tagName]) {
	      var nextSibling = element.next();
	      var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
	      parent.removeChild(element);
	      if (nextSibling)
	        fragments.each(function(node) { parent.insertBefore(node, nextSibling) });
	      else
	        fragments.each(function(node) { parent.appendChild(node) });
	    }
	    else element.outerHTML = content.stripScripts();

	    content.evalScripts.bind(content).defer();
	    return element;
	  };
	}

	Element._returnOffset = function(l, t) {
	  var result = [l, t];
	  result.left = l;
	  result.top = t;
	  return result;
	};

	Element._getContentFromAnonymousElement = function(tagName, html) {
	  var div = new Element('div'), t = Element._insertionTranslations.tags[tagName];
	  if (t) {
	    div.innerHTML = t[0] + html + t[1];
	    t[2].times(function() { div = div.firstChild });
	  } else div.innerHTML = html;
	  return $A(div.childNodes);
	};

	Element._insertionTranslations = {
	  before: function(element, node) {
	    element.parentNode.insertBefore(node, element);
	  },
	  top: function(element, node) {
	    element.insertBefore(node, element.firstChild);
	  },
	  bottom: function(element, node) {
	    element.appendChild(node);
	  },
	  after: function(element, node) {
	    element.parentNode.insertBefore(node, element.nextSibling);
	  },
	  tags: {
	    TABLE:  ['<table>',                '</table>',                   1],
	    TBODY:  ['<table><tbody>',         '</tbody></table>',           2],
	    TR:     ['<table><tbody><tr>',     '</tr></tbody></table>',      3],
	    TD:     ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
	    SELECT: ['<select>',               '</select>',                  1]
	  }
	};

	(function() {
	  Object.extend(this.tags, {
	    THEAD: this.tags.TBODY,
	    TFOOT: this.tags.TBODY,
	    TH:    this.tags.TD
	  });
	}).call(Element._insertionTranslations);

	Element.Methods.Simulated = {
	  hasAttribute: function(element, attribute) {
	    attribute = Element._attributeTranslations.has[attribute] || attribute;
	    var node = $(element).getAttributeNode(attribute);
	    return !!(node && node.specified);
	  }
	};

	Element.Methods.ByTag = { };

	Object.extend(Element, Element.Methods);

	if (!Prototype.BrowserFeatures.ElementExtensions &&
	    document.createElement('div')['__proto__']) {
	  window.HTMLElement = { };
	  window.HTMLElement.prototype = document.createElement('div')['__proto__'];
	  Prototype.BrowserFeatures.ElementExtensions = true;
	}

	Element.extend = (function() {
	  if (Prototype.BrowserFeatures.SpecificElementExtensions)
	    return Prototype.K;

	  var Methods = { }, ByTag = Element.Methods.ByTag;

	  var extend = Object.extend(function(element) {
	    if (!element || element._extendedByPrototype ||
	        element.nodeType != 1 || element == window) return element;

	    var methods = Object.clone(Methods),
	      tagName = element.tagName.toUpperCase(), property, value;

	    // extend methods for specific tags
	    if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);

	    for (property in methods) {
	      value = methods[property];
	      if (Object.isFunction(value) && !(property in element))
	        element[property] = value.methodize();
	    }

	    element._extendedByPrototype = Prototype.emptyFunction;
	    return element;

	  }, {
	    refresh: function() {
	      // extend methods for all tags (Safari doesn't need this)
	      if (!Prototype.BrowserFeatures.ElementExtensions) {
	        Object.extend(Methods, Element.Methods);
	        Object.extend(Methods, Element.Methods.Simulated);
	      }
	    }
	  });

	  extend.refresh();
	  return extend;
	})();

	Element.hasAttribute = function(element, attribute) {
	  if (element.hasAttribute) return element.hasAttribute(attribute);
	  return Element.Methods.Simulated.hasAttribute(element, attribute);
	};

	Element.addMethods = function(methods) {
	  var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;

	  if (!methods) {
	    Object.extend(Form, Form.Methods);
	    Object.extend(Form.Element, Form.Element.Methods);
	    Object.extend(Element.Methods.ByTag, {
	      "FORM":     Object.clone(Form.Methods),
	      "INPUT":    Object.clone(Form.Element.Methods),
	      "SELECT":   Object.clone(Form.Element.Methods),
	      "TEXTAREA": Object.clone(Form.Element.Methods)
	    });
	  }

	  if (arguments.length == 2) {
	    var tagName = methods;
	    methods = arguments[1];
	  }

	  if (!tagName) Object.extend(Element.Methods, methods || { });
	  else {
	    if (Object.isArray(tagName)) tagName.each(extend);
	    else extend(tagName);
	  }

	  function extend(tagName) {
	    tagName = tagName.toUpperCase();
	    if (!Element.Methods.ByTag[tagName])
	      Element.Methods.ByTag[tagName] = { };
	    Object.extend(Element.Methods.ByTag[tagName], methods);
	  }

	  function copy(methods, destination, onlyIfAbsent) {
	    onlyIfAbsent = onlyIfAbsent || false;
	    for (var property in methods) {
	      var value = methods[property];
	      if (!Object.isFunction(value)) continue;
	      if (!onlyIfAbsent || !(property in destination))
	        destination[property] = value.methodize();
	    }
	  }

	  function findDOMClass(tagName) {
	    var klass;
	    var trans = {
	      "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
	      "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
	      "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
	      "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
	      "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
	      "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
	      "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
	      "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
	      "FrameSet", "IFRAME": "IFrame"
	    };
	    if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
	    if (window[klass]) return window[klass];
	    klass = 'HTML' + tagName + 'Element';
	    if (window[klass]) return window[klass];
	    klass = 'HTML' + tagName.capitalize() + 'Element';
	    if (window[klass]) return window[klass];

	    window[klass] = { };
	    window[klass].prototype = document.createElement(tagName)['__proto__'];
	    return window[klass];
	  }

	  if (F.ElementExtensions) {
	    copy(Element.Methods, HTMLElement.prototype);
	    copy(Element.Methods.Simulated, HTMLElement.prototype, true);
	  }

	  if (F.SpecificElementExtensions) {
	    for (var tag in Element.Methods.ByTag) {
	      var klass = findDOMClass(tag);
	      if (Object.isUndefined(klass)) continue;
	      copy(T[tag], klass.prototype);
	    }
	  }

	  Object.extend(Element, Element.Methods);
	  delete Element.ByTag;

	  if (Element.extend.refresh) Element.extend.refresh();
	  Element.cache = { };
	};

	document.viewport = {
	  getDimensions: function() {
	    var dimensions = { }, B = Prototype.Browser;
	    $w('width height').each(function(d) {
	      var D = d.capitalize();
	      if (B.WebKit && !document.evaluate) {
	        // Safari <3.0 needs self.innerWidth/Height
	        dimensions[d] = self['inner' + D];
	      } else if (B.Opera && parseFloat(window.opera.version()) < 9.5) {
	        // Opera <9.5 needs document.body.clientWidth/Height
	        dimensions[d] = document.body['client' + D]
	      } else {
	        dimensions[d] = document.documentElement['client' + D];
	      }
	    });
	    return dimensions;
	  },

	  getWidth: function() {
	    return this.getDimensions().width;
	  },

	  getHeight: function() {
	    return this.getDimensions().height;
	  },

	  getScrollOffsets: function() {
	    return Element._returnOffset(
	      window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
	      window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
	  }
	};
	/* Portions of the Selector class are derived from Jack Slocum's DomQuery,
	 * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
	 * license.  Please see http://www.yui-ext.com/ for more information. */

	var Selector = Class.create({
	  initialize: function(expression) {
	    this.expression = expression.strip();

	    if (this.shouldUseSelectorsAPI()) {
	      this.mode = 'selectorsAPI';
	    } else if (this.shouldUseXPath()) {
	      this.mode = 'xpath';
	      this.compileXPathMatcher();
	    } else {
	      this.mode = "normal";
	      this.compileMatcher();
	    }

	  },

	  shouldUseXPath: function() {
	    if (!Prototype.BrowserFeatures.XPath) return false;

	    var e = this.expression;

	    // Safari 3 chokes on :*-of-type and :empty
	    if (Prototype.Browser.WebKit &&
	     (e.include("-of-type") || e.include(":empty")))
	      return false;

	    // XPath can't do namespaced attributes, nor can it read
	    // the "checked" property from DOM nodes
	    if ((/(\[[\w-]*?:|:checked)/).test(e))
	      return false;

	    return true;
	  },

	  shouldUseSelectorsAPI: function() {
	    if (!Prototype.BrowserFeatures.SelectorsAPI) return false;

	    if (!Selector._div) Selector._div = new Element('div');

	    // Make sure the browser treats the selector as valid. Test on an
	    // isolated element to minimize cost of this check.
	    try {
	      Selector._div.querySelector(this.expression);
	    } catch(e) {
	      return false;
	    }

	    return true;
	  },

	  compileMatcher: function() {
	    var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
	        c = Selector.criteria, le, p, m;

	    if (Selector._cache[e]) {
	      this.matcher = Selector._cache[e];
	      return;
	    }

	    this.matcher = ["this.matcher = function(root) {",
	                    "var r = root, h = Selector.handlers, c = false, n;"];

	    while (e && le != e && (/\S/).test(e)) {
	      le = e;
	      for (var i in ps) {
	        p = ps[i];
	        if (m = e.match(p)) {
	          this.matcher.push(Object.isFunction(c[i]) ? c[i](m) :
	            new Template(c[i]).evaluate(m));
	          e = e.replace(m[0], '');
	          break;
	        }
	      }
	    }

	    this.matcher.push("return h.unique(n);\n}");
	    eval(this.matcher.join('\n'));
	    Selector._cache[this.expression] = this.matcher;
	  },

	  compileXPathMatcher: function() {
	    var e = this.expression, ps = Selector.patterns,
	        x = Selector.xpath, le, m;

	    if (Selector._cache[e]) {
	      this.xpath = Selector._cache[e]; return;
	    }

	    this.matcher = ['.//*'];
	    while (e && le != e && (/\S/).test(e)) {
	      le = e;
	      for (var i in ps) {
	        if (m = e.match(ps[i])) {
	          this.matcher.push(Object.isFunction(x[i]) ? x[i](m) :
	            new Template(x[i]).evaluate(m));
	          e = e.replace(m[0], '');
	          break;
	        }
	      }
	    }

	    this.xpath = this.matcher.join('');
	    Selector._cache[this.expression] = this.xpath;
	  },

	  findElements: function(root) {
	    root = root || document;
	    var e = this.expression, results;

	    switch (this.mode) {
	      case 'selectorsAPI':
	        // querySelectorAll queries document-wide, then filters to descendants
	        // of the context element. That's not what we want.
	        // Add an explicit context to the selector if necessary.
	        if (root !== document) {
	          var oldId = root.id, id = $(root).identify();
	          e = "#" + id + " " + e;
	        }

	        results = $A(root.querySelectorAll(e)).map(Element.extend);
	        root.id = oldId;

	        return results;
	      case 'xpath':
	        return document._getElementsByXPath(this.xpath, root);
	      default:
	       return this.matcher(root);
	    }
	  },

	  match: function(element) {
	    this.tokens = [];

	    var e = this.expression, ps = Selector.patterns, as = Selector.assertions;
	    var le, p, m;

	    while (e && le !== e && (/\S/).test(e)) {
	      le = e;
	      for (var i in ps) {
	        p = ps[i];
	        if (m = e.match(p)) {
	          // use the Selector.assertions methods unless the selector
	          // is too complex.
	          if (as[i]) {
	            this.tokens.push([i, Object.clone(m)]);
	            e = e.replace(m[0], '');
	          } else {
	            // reluctantly do a document-wide search
	            // and look for a match in the array
	            return this.findElements(document).include(element);
	          }
	        }
	      }
	    }

	    var match = true, name, matches;
	    for (var i = 0, token; token = this.tokens[i]; i++) {
	      name = token[0], matches = token[1];
	      if (!Selector.assertions[name](element, matches)) {
	        match = false; break;
	      }
	    }

	    return match;
	  },

	  toString: function() {
	    return this.expression;
	  },

	  inspect: function() {
	    return "#<Selector:" + this.expression.inspect() + ">";
	  }
	});

	Object.extend(Selector, {
	  _cache: { },

	  xpath: {
	    descendant:   "//*",
	    child:        "/*",
	    adjacent:     "/following-sibling::*[1]",
	    laterSibling: '/following-sibling::*',
	    tagName:      function(m) {
	      if (m[1] == '*') return '';
	      return "[local-name()='" + m[1].toLowerCase() +
	             "' or local-name()='" + m[1].toUpperCase() + "']";
	    },
	    className:    "[contains(concat(' ', @class, ' '), ' #{1} ')]",
	    id:           "[@id='#{1}']",
	    attrPresence: function(m) {
	      m[1] = m[1].toLowerCase();
	      return new Template("[@#{1}]").evaluate(m);
	    },
	    attr: function(m) {
	      m[1] = m[1].toLowerCase();
	      m[3] = m[5] || m[6];
	      return new Template(Selector.xpath.operators[m[2]]).evaluate(m);
	    },
	    pseudo: function(m) {
	      var h = Selector.xpath.pseudos[m[1]];
	      if (!h) return '';
	      if (Object.isFunction(h)) return h(m);
	      return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m);
	    },
	    operators: {
	      '=':  "[@#{1}='#{3}']",
	      '!=': "[@#{1}!='#{3}']",
	      '^=': "[starts-with(@#{1}, '#{3}')]",
	      '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']",
	      '*=': "[contains(@#{1}, '#{3}')]",
	      '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]",
	      '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]"
	    },
	    pseudos: {
	      'first-child': '[not(preceding-sibling::*)]',
	      'last-child':  '[not(following-sibling::*)]',
	      'only-child':  '[not(preceding-sibling::* or following-sibling::*)]',
	      'empty':       "[count(*) = 0 and (count(text()) = 0)]",
	      'checked':     "[@checked]",
	      'disabled':    "[(@disabled) and (@type!='hidden')]",
	      'enabled':     "[not(@disabled) and (@type!='hidden')]",
	      'not': function(m) {
	        var e = m[6], p = Selector.patterns,
	            x = Selector.xpath, le, v;

	        var exclusion = [];
	        while (e && le != e && (/\S/).test(e)) {
	          le = e;
	          for (var i in p) {
	            if (m = e.match(p[i])) {
	              v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m);
	              exclusion.push("(" + v.substring(1, v.length - 1) + ")");
	              e = e.replace(m[0], '');
	              break;
	            }
	          }
	        }
	        return "[not(" + exclusion.join(" and ") + ")]";
	      },
	      'nth-child':      function(m) {
	        return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m);
	      },
	      'nth-last-child': function(m) {
	        return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m);
	      },
	      'nth-of-type':    function(m) {
	        return Selector.xpath.pseudos.nth("position() ", m);
	      },
	      'nth-last-of-type': function(m) {
	        return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m);
	      },
	      'first-of-type':  function(m) {
	        m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m);
	      },
	      'last-of-type':   function(m) {
	        m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m);
	      },
	      'only-of-type':   function(m) {
	        var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m);
	      },
	      nth: function(fragment, m) {
	        var mm, formula = m[6], predicate;
	        if (formula == 'even') formula = '2n+0';
	        if (formula == 'odd')  formula = '2n+1';
	        if (mm = formula.match(/^(\d+)$/)) // digit only
	          return '[' + fragment + "= " + mm[1] + ']';
	        if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
	          if (mm[1] == "-") mm[1] = -1;
	          var a = mm[1] ? Number(mm[1]) : 1;
	          var b = mm[2] ? Number(mm[2]) : 0;
	          predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " +
	          "((#{fragment} - #{b}) div #{a} >= 0)]";
	          return new Template(predicate).evaluate({
	            fragment: fragment, a: a, b: b });
	        }
	      }
	    }
	  },

	  criteria: {
	    tagName:      'n = h.tagName(n, r, "#{1}", c);      c = false;',
	    className:    'n = h.className(n, r, "#{1}", c);    c = false;',
	    id:           'n = h.id(n, r, "#{1}", c);           c = false;',
	    attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;',
	    attr: function(m) {
	      m[3] = (m[5] || m[6]);
	      return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m);
	    },
	    pseudo: function(m) {
	      if (m[6]) m[6] = m[6].replace(/"/g, '\\"');
	      return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m);
	    },
	    descendant:   'c = "descendant";',
	    child:        'c = "child";',
	    adjacent:     'c = "adjacent";',
	    laterSibling: 'c = "laterSibling";'
	  },

	  patterns: {
	    // combinators must be listed first
	    // (and descendant needs to be last combinator)
	    laterSibling: /^\s*~\s*/,
	    child:        /^\s*>\s*/,
	    adjacent:     /^\s*\+\s*/,
	    descendant:   /^\s/,

	    // selectors follow
	    tagName:      /^\s*(\*|[\w\-]+)(\b|$)?/,
	    id:           /^#([\w\-\*]+)(\b|$)/,
	    className:    /^\.([\w\-\*]+)(\b|$)/,
	    pseudo:
	/^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/,
	    attrPresence: /^\[((?:[\w]+:)?[\w]+)\]/,
	    attr:         /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/
	  },

	  // for Selector.match and Element#match
	  assertions: {
	    tagName: function(element, matches) {
	      return matches[1].toUpperCase() == element.tagName.toUpperCase();
	    },

	    className: function(element, matches) {
	      return Element.hasClassName(element, matches[1]);
	    },

	    id: function(element, matches) {
	      return element.id === matches[1];
	    },

	    attrPresence: function(element, matches) {
	      return Element.hasAttribute(element, matches[1]);
	    },

	    attr: function(element, matches) {
	      var nodeValue = Element.readAttribute(element, matches[1]);
	      return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]);
	    }
	  },

	  handlers: {
	    // UTILITY FUNCTIONS
	    // joins two collections
	    concat: function(a, b) {
	      for (var i = 0, node; node = b[i]; i++)
	        a.push(node);
	      return a;
	    },

	    // marks an array of nodes for counting
	    mark: function(nodes) {
	      var _true = Prototype.emptyFunction;
	      for (var i = 0, node; node = nodes[i]; i++)
	        node._countedByPrototype = _true;
	      return nodes;
	    },

	    unmark: function(nodes) {
	      for (var i = 0, node; node = nodes[i]; i++)
	        node._countedByPrototype = undefined;
	      return nodes;
	    },

	    // mark each child node with its position (for nth calls)
	    // "ofType" flag indicates whether we're indexing for nth-of-type
	    // rather than nth-child
	    index: function(parentNode, reverse, ofType) {
	      parentNode._countedByPrototype = Prototype.emptyFunction;
	      if (reverse) {
	        for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
	          var node = nodes[i];
	          if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
	        }
	      } else {
	        for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
	          if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
	      }
	    },

	    // filters out duplicates and extends all nodes
	    unique: function(nodes) {
	      if (nodes.length == 0) return nodes;
	      var results = [], n;
	      for (var i = 0, l = nodes.length; i < l; i++)
	        if (!(n = nodes[i])._countedByPrototype) {
	          n._countedByPrototype = Prototype.emptyFunction;
	          results.push(Element.extend(n));
	        }
	      return Selector.handlers.unmark(results);
	    },

	    // COMBINATOR FUNCTIONS
	    descendant: function(nodes) {
	      var h = Selector.handlers;
	      for (var i = 0, results = [], node; node = nodes[i]; i++)
	        h.concat(results, node.getElementsByTagName('*'));
	      return results;
	    },

	    child: function(nodes) {
	      var h = Selector.handlers;
	      for (var i = 0, results = [], node; node = nodes[i]; i++) {
	        for (var j = 0, child; child = node.childNodes[j]; j++)
	          if (child.nodeType == 1 && child.tagName != '!') results.push(child);
	      }
	      return results;
	    },

	    adjacent: function(nodes) {
	      for (var i = 0, results = [], node; node = nodes[i]; i++) {
	        var next = this.nextElementSibling(node);
	        if (next) results.push(next);
	      }
	      return results;
	    },

	    laterSibling: function(nodes) {
	      var h = Selector.handlers;
	      for (var i = 0, results = [], node; node = nodes[i]; i++)
	        h.concat(results, Element.nextSiblings(node));
	      return results;
	    },

	    nextElementSibling: function(node) {
	      while (node = node.nextSibling)
	        if (node.nodeType == 1) return node;
	      return null;
	    },

	    previousElementSibling: function(node) {
	      while (node = node.previousSibling)
	        if (node.nodeType == 1) return node;
	      return null;
	    },

	    // TOKEN FUNCTIONS
	    tagName: function(nodes, root, tagName, combinator) {
	      var uTagName = tagName.toUpperCase();
	      var results = [], h = Selector.handlers;
	      if (nodes) {
	        if (combinator) {
	          // fastlane for ordinary descendant combinators
	          if (combinator == "descendant") {
	            for (var i = 0, node; node = nodes[i]; i++)
	              h.concat(results, node.getElementsByTagName(tagName));
	            return results;
	          } else nodes = this[combinator](nodes);
	          if (tagName == "*") return nodes;
	        }
	        for (var i = 0, node; node = nodes[i]; i++)
	          if (node.tagName.toUpperCase() === uTagName) results.push(node);
	        return results;
	      } else return root.getElementsByTagName(tagName);
	    },

	    id: function(nodes, root, id, combinator) {
	      var targetNode = $(id), h = Selector.handlers;
	      if (!targetNode) return [];
	      if (!nodes && root == document) return [targetNode];
	      if (nodes) {
	        if (combinator) {
	          if (combinator == 'child') {
	            for (var i = 0, node; node = nodes[i]; i++)
	              if (targetNode.parentNode == node) return [targetNode];
	          } else if (combinator == 'descendant') {
	            for (var i = 0, node; node = nodes[i]; i++)
	              if (Element.descendantOf(targetNode, node)) return [targetNode];
	          } else if (combinator == 'adjacent') {
	            for (var i = 0, node; node = nodes[i]; i++)
	              if (Selector.handlers.previousElementSibling(targetNode) == node)
	                return [targetNode];
	          } else nodes = h[combinator](nodes);
	        }
	        for (var i = 0, node; node = nodes[i]; i++)
	          if (node == targetNode) return [targetNode];
	        return [];
	      }
	      return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : [];
	    },

	    className: function(nodes, root, className, combinator) {
	      if (nodes && combinator) nodes = this[combinator](nodes);
	      return Selector.handlers.byClassName(nodes, root, className);
	    },

	    byClassName: function(nodes, root, className) {
	      if (!nodes) nodes = Selector.handlers.descendant([root]);
	      var needle = ' ' + className + ' ';
	      for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) {
	        nodeClassName = node.className;
	        if (nodeClassName.length == 0) continue;
	        if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle))
	          results.push(node);
	      }
	      return results;
	    },

	    attrPresence: function(nodes, root, attr, combinator) {
	      if (!nodes) nodes = root.getElementsByTagName("*");
	      if (nodes && combinator) nodes = this[combinator](nodes);
	      var results = [];
	      for (var i = 0, node; node = nodes[i]; i++)
	        if (Element.hasAttribute(node, attr)) results.push(node);
	      return results;
	    },

	    attr: function(nodes, root, attr, value, operator, combinator) {
	      if (!nodes) nodes = root.getElementsByTagName("*");
	      if (nodes && combinator) nodes = this[combinator](nodes);
	      var handler = Selector.operators[operator], results = [];
	      for (var i = 0, node; node = nodes[i]; i++) {
	        var nodeValue = Element.readAttribute(node, attr);
	        if (nodeValue === null) continue;
	        if (handler(nodeValue, value)) results.push(node);
	      }
	      return results;
	    },

	    pseudo: function(nodes, name, value, root, combinator) {
	      if (nodes && combinator) nodes = this[combinator](nodes);
	      if (!nodes) nodes = root.getElementsByTagName("*");
	      return Selector.pseudos[name](nodes, value, root);
	    }
	  },

	  pseudos: {
	    'first-child': function(nodes, value, root) {
	      for (var i = 0, results = [], node; node = nodes[i]; i++) {
	        if (Selector.handlers.previousElementSibling(node)) continue;
	          results.push(node);
	      }
	      return results;
	    },
	    'last-child': function(nodes, value, root) {
	      for (var i = 0, results = [], node; node = nodes[i]; i++) {
	        if (Selector.handlers.nextElementSibling(node)) continue;
	          results.push(node);
	      }
	      return results;
	    },
	    'only-child': function(nodes, value, root) {
	      var h = Selector.handlers;
	      for (var i = 0, results = [], node; node = nodes[i]; i++)
	        if (!h.previousElementSibling(node) && !h.nextElementSibling(node))
	          results.push(node);
	      return results;
	    },
	    'nth-child':        function(nodes, formula, root) {
	      return Selector.pseudos.nth(nodes, formula, root);
	    },
	    'nth-last-child':   function(nodes, formula, root) {
	      return Selector.pseudos.nth(nodes, formula, root, true);
	    },
	    'nth-of-type':      function(nodes, formula, root) {
	      return Selector.pseudos.nth(nodes, formula, root, false, true);
	    },
	    'nth-last-of-type': function(nodes, formula, root) {
	      return Selector.pseudos.nth(nodes, formula, root, true, true);
	    },
	    'first-of-type':    function(nodes, formula, root) {
	      return Selector.pseudos.nth(nodes, "1", root, false, true);
	    },
	    'last-of-type':     function(nodes, formula, root) {
	      return Selector.pseudos.nth(nodes, "1", root, true, true);
	    },
	    'only-of-type':     function(nodes, formula, root) {
	      var p = Selector.pseudos;
	      return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);
	    },

	    // handles the an+b logic
	    getIndices: function(a, b, total) {
	      if (a == 0) return b > 0 ? [b] : [];
	      return $R(1, total).inject([], function(memo, i) {
	        if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i);
	        return memo;
	      });
	    },

	    // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type
	    nth: function(nodes, formula, root, reverse, ofType) {
	      if (nodes.length == 0) return [];
	      if (formula == 'even') formula = '2n+0';
	      if (formula == 'odd')  formula = '2n+1';
	      var h = Selector.handlers, results = [], indexed = [], m;
	      h.mark(nodes);
	      for (var i = 0, node; node = nodes[i]; i++) {
	        if (!node.parentNode._countedByPrototype) {
	          h.index(node.parentNode, reverse, ofType);
	          indexed.push(node.parentNode);
	        }
	      }
	      if (formula.match(/^\d+$/)) { // just a number
	        formula = Number(formula);
	        for (var i = 0, node; node = nodes[i]; i++)
	          if (node.nodeIndex == formula) results.push(node);
	      } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
	        if (m[1] == "-") m[1] = -1;
	        var a = m[1] ? Number(m[1]) : 1;
	        var b = m[2] ? Number(m[2]) : 0;
	        var indices = Selector.pseudos.getIndices(a, b, nodes.length);
	        for (var i = 0, node, l = indices.length; node = nodes[i]; i++) {
	          for (var j = 0; j < l; j++)
	            if (node.nodeIndex == indices[j]) results.push(node);
	        }
	      }
	      h.unmark(nodes);
	      h.unmark(indexed);
	      return results;
	    },

	    'empty': function(nodes, value, root) {
	      for (var i = 0, results = [], node; node = nodes[i]; i++) {
	        // IE treats comments as element nodes
	        if (node.tagName == '!' || node.firstChild) continue;
	        results.push(node);
	      }
	      return results;
	    },

	    'not': function(nodes, selector, root) {
	      var h = Selector.handlers, selectorType, m;
	      var exclusions = new Selector(selector).findElements(root);
	      h.mark(exclusions);
	      for (var i = 0, results = [], node; node = nodes[i]; i++)
	        if (!node._countedByPrototype) results.push(node);
	      h.unmark(exclusions);
	      return results;
	    },

	    'enabled': function(nodes, value, root) {
	      for (var i = 0, results = [], node; node = nodes[i]; i++)
	        if (!node.disabled && (!node.type || node.type !== 'hidden'))
	          results.push(node);
	      return results;
	    },

	    'disabled': function(nodes, value, root) {
	      for (var i = 0, results = [], node; node = nodes[i]; i++)
	        if (node.disabled) results.push(node);
	      return results;
	    },

	    'checked': function(nodes, value, root) {
	      for (var i = 0, results = [], node; node = nodes[i]; i++)
	        if (node.checked) results.push(node);
	      return results;
	    }
	  },

	  operators: {
	    '=':  function(nv, v) { return nv == v; },
	    '!=': function(nv, v) { return nv != v; },
	    '^=': function(nv, v) { return nv == v || nv && nv.startsWith(v); },
	    '$=': function(nv, v) { return nv == v || nv && nv.endsWith(v); },
	    '*=': function(nv, v) { return nv == v || nv && nv.include(v); },
	    '$=': function(nv, v) { return nv.endsWith(v); },
	    '*=': function(nv, v) { return nv.include(v); },
	    '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },
	    '|=': function(nv, v) { return ('-' + (nv || "").toUpperCase() +
	     '-').include('-' + (v || "").toUpperCase() + '-'); }
	  },

	  split: function(expression) {
	    var expressions = [];
	    expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
	      expressions.push(m[1].strip());
	    });
	    return expressions;
	  },

	  matchElements: function(elements, expression) {
	    var matches = $$(expression), h = Selector.handlers;
	    h.mark(matches);
	    for (var i = 0, results = [], element; element = elements[i]; i++)
	      if (element._countedByPrototype) results.push(element);
	    h.unmark(matches);
	    return results;
	  },

	  findElement: function(elements, expression, index) {
	    if (Object.isNumber(expression)) {
	      index = expression; expression = false;
	    }
	    return Selector.matchElements(elements, expression || '*')[index || 0];
	  },

	  findChildElements: function(element, expressions) {
	    expressions = Selector.split(expressions.join(','));
	    var results = [], h = Selector.handlers;
	    for (var i = 0, l = expressions.length, selector; i < l; i++) {
	      selector = new Selector(expressions[i].strip());
	      h.concat(results, selector.findElements(element));
	    }
	    return (l > 1) ? h.unique(results) : results;
	  }
	});

	if (Prototype.Browser.IE) {
	  Object.extend(Selector.handlers, {
	    // IE returns comment nodes on getElementsByTagName("*").
	    // Filter them out.
	    concat: function(a, b) {
	      for (var i = 0, node; node = b[i]; i++)
	        if (node.tagName !== "!") a.push(node);
	      return a;
	    },

	    // IE improperly serializes _countedByPrototype in (inner|outer)HTML.
	    unmark: function(nodes) {
	      for (var i = 0, node; node = nodes[i]; i++)
	        node.removeAttribute('_countedByPrototype');
	      return nodes;
	    }
	  });
	}

	function $$() {
	  return Selector.findChildElements(document, $A(arguments));
	}
	var Form = {
	  reset: function(form) {
	    $(form).reset();
	    return form;
	  },

	  serializeElements: function(elements, options) {
	    if (typeof options != 'object') options = { hash: !!options };
	    else if (Object.isUndefined(options.hash)) options.hash = true;
	    var key, value, submitted = false, submit = options.submit;

	    var data = elements.inject({ }, function(result, element) {
	      if (!element.disabled && element.name) {
	        key = element.name; value = $(element).getValue();
	        if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted &&
	            submit !== false && (!submit || key == submit) && (submitted = true)))) {
	          if (key in result) {
	            // a key is already present; construct an array of values
	            if (!Object.isArray(result[key])) result[key] = [result[key]];
	            result[key].push(value);
	          }
	          else result[key] = value;
	        }
	      }
	      return result;
	    });

	    return options.hash ? data : Object.toQueryString(data);
	  }
	};

	Form.Methods = {
	  serialize: function(form, options) {
	    return Form.serializeElements(Form.getElements(form), options);
	  },

	  getElements: function(form) {
	    return $A($(form).getElementsByTagName('*')).inject([],
	      function(elements, child) {
	        if (Form.Element.Serializers[child.tagName.toLowerCase()])
	          elements.push(Element.extend(child));
	        return elements;
	      }
	    );
	  },

	  getInputs: function(form, typeName, name) {
	    form = $(form);
	    var inputs = form.getElementsByTagName('input');

	    if (!typeName && !name) return $A(inputs).map(Element.extend);

	    for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
	      var input = inputs[i];
	      if ((typeName && input.type != typeName) || (name && input.name != name))
	        continue;
	      matchingInputs.push(Element.extend(input));
	    }

	    return matchingInputs;
	  },

	  disable: function(form) {
	    form = $(form);
	    Form.getElements(form).invoke('disable');
	    return form;
	  },

	  enable: function(form) {
	    form = $(form);
	    Form.getElements(form).invoke('enable');
	    return form;
	  },

	  findFirstElement: function(form) {
	    var elements = $(form).getElements().findAll(function(element) {
	      return 'hidden' != element.type && !element.disabled;
	    });
	    var firstByIndex = elements.findAll(function(element) {
	      return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
	    }).sortBy(function(element) { return element.tabIndex }).first();

	    return firstByIndex ? firstByIndex : elements.find(function(element) {
	      return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
	    });
	  },

	  focusFirstElement: function(form) {
	    form = $(form);
	    form.findFirstElement().activate();
	    return form;
	  },

	  request: function(form, options) {
	    form = $(form), options = Object.clone(options || { });

	    var params = options.parameters, action = form.readAttribute('action') || '';
	    if (action.blank()) action = window.location.href;
	    options.parameters = form.serialize(true);

	    if (params) {
	      if (Object.isString(params)) params = params.toQueryParams();
	      Object.extend(options.parameters, params);
	    }

	    if (form.hasAttribute('method') && !options.method)
	      options.method = form.method;

	    return new Ajax.Request(action, options);
	  }
	};

	/*--------------------------------------------------------------------------*/

	Form.Element = {
	  focus: function(element) {
	    $(element).focus();
	    return element;
	  },

	  select: function(element) {
	    $(element).select();
	    return element;
	  }
	};

	Form.Element.Methods = {
	  serialize: function(element) {
	    element = $(element);
	    if (!element.disabled && element.name) {
	      var value = element.getValue();
	      if (value != undefined) {
	        var pair = { };
	        pair[element.name] = value;
	        return Object.toQueryString(pair);
	      }
	    }
	    return '';
	  },

	  getValue: function(element) {
	    element = $(element);
	    var method = element.tagName.toLowerCase();
	    return Form.Element.Serializers[method](element);
	  },

	  setValue: function(element, value) {
	    element = $(element);
	    var method = element.tagName.toLowerCase();
	    Form.Element.Serializers[method](element, value);
	    return element;
	  },

	  clear: function(element) {
	    $(element).value = '';
	    return element;
	  },

	  present: function(element) {
	    return $(element).value != '';
	  },

	  activate: function(element) {
	    element = $(element);
	    try {
	      element.focus();
	      if (element.select && (element.tagName.toLowerCase() != 'input' ||
	          !['button', 'reset', 'submit'].include(element.type)))
	        element.select();
	    } catch (e) { }
	    return element;
	  },

	  disable: function(element) {
	    element = $(element);
	    element.disabled = true;
	    return element;
	  },

	  enable: function(element) {
	    element = $(element);
	    element.disabled = false;
	    return element;
	  }
	};

	/*--------------------------------------------------------------------------*/

	var Field = Form.Element;
	var $F = Form.Element.Methods.getValue;

	/*--------------------------------------------------------------------------*/

	Form.Element.Serializers = {
	  input: function(element, value) {
	    switch (element.type.toLowerCase()) {
	      case 'checkbox':
	      case 'radio':
	        return Form.Element.Serializers.inputSelector(element, value);
	      default:
	        return Form.Element.Serializers.textarea(element, value);
	    }
	  },

	  inputSelector: function(element, value) {
	    if (Object.isUndefined(value)) return element.checked ? element.value : null;
	    else element.checked = !!value;
	  },

	  textarea: function(element, value) {
	    if (Object.isUndefined(value)) return element.value;
	    else element.value = value;
	  },

	  select: function(element, value) {
	    if (Object.isUndefined(value))
	      return this[element.type == 'select-one' ?
	        'selectOne' : 'selectMany'](element);
	    else {
	      var opt, currentValue, single = !Object.isArray(value);
	      for (var i = 0, length = element.length; i < length; i++) {
	        opt = element.options[i];
	        currentValue = this.optionValue(opt);
	        if (single) {
	          if (currentValue == value) {
	            opt.selected = true;
	            return;
	          }
	        }
	        else opt.selected = value.include(currentValue);
	      }
	    }
	  },

	  selectOne: function(element) {
	    var index = element.selectedIndex;
	    return index >= 0 ? this.optionValue(element.options[index]) : null;
	  },

	  selectMany: function(element) {
	    var values, length = element.length;
	    if (!length) return null;

	    for (var i = 0, values = []; i < length; i++) {
	      var opt = element.options[i];
	      if (opt.selected) values.push(this.optionValue(opt));
	    }
	    return values;
	  },

	  optionValue: function(opt) {
	    // extend element because hasAttribute may not be native
	    return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
	  }
	};

	/*--------------------------------------------------------------------------*/

	Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
	  initialize: function($super, element, frequency, callback) {
	    $super(callback, frequency);
	    this.element   = $(element);
	    this.lastValue = this.getValue();
	  },

	  execute: function() {
	    var value = this.getValue();
	    if (Object.isString(this.lastValue) && Object.isString(value) ?
	        this.lastValue != value : String(this.lastValue) != String(value)) {
	      this.callback(this.element, value);
	      this.lastValue = value;
	    }
	  }
	});

	Form.Element.Observer = Class.create(Abstract.TimedObserver, {
	  getValue: function() {
	    return Form.Element.getValue(this.element);
	  }
	});

	Form.Observer = Class.create(Abstract.TimedObserver, {
	  getValue: function() {
	    return Form.serialize(this.element);
	  }
	});

	/*--------------------------------------------------------------------------*/

	Abstract.EventObserver = Class.create({
	  initialize: function(element, callback) {
	    this.element  = $(element);
	    this.callback = callback;

	    this.lastValue = this.getValue();
	    if (this.element.tagName.toLowerCase() == 'form')
	      this.registerFormCallbacks();
	    else
	      this.registerCallback(this.element);
	  },

	  onElementEvent: function() {
	    var value = this.getValue();
	    if (this.lastValue != value) {
	      this.callback(this.element, value);
	      this.lastValue = value;
	    }
	  },

	  registerFormCallbacks: function() {
	    Form.getElements(this.element).each(this.registerCallback, this);
	  },

	  registerCallback: function(element) {
	    if (element.type) {
	      switch (element.type.toLowerCase()) {
	        case 'checkbox':
	        case 'radio':
	          Event.observe(element, 'click', this.onElementEvent.bind(this));
	          break;
	        default:
	          Event.observe(element, 'change', this.onElementEvent.bind(this));
	          break;
	      }
	    }
	  }
	});

	Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
	  getValue: function() {
	    return Form.Element.getValue(this.element);
	  }
	});

	Form.EventObserver = Class.create(Abstract.EventObserver, {
	  getValue: function() {
	    return Form.serialize(this.element);
	  }
	});
	if (!window.Event) var Event = { };

	Object.extend(Event, {
	  KEY_BACKSPACE: 8,
	  KEY_TAB:       9,
	  KEY_RETURN:   13,
	  KEY_ESC:      27,
	  KEY_LEFT:     37,
	  KEY_UP:       38,
	  KEY_RIGHT:    39,
	  KEY_DOWN:     40,
	  KEY_DELETE:   46,
	  KEY_HOME:     36,
	  KEY_END:      35,
	  KEY_PAGEUP:   33,
	  KEY_PAGEDOWN: 34,
	  KEY_INSERT:   45,

	  cache: { },

	  relatedTarget: function(event) {
	    var element;
	    switch(event.type) {
	      case 'mouseover': element = event.fromElement; break;
	      case 'mouseout':  element = event.toElement;   break;
	      default: return null;
	    }
	    return Element.extend(element);
	  }
	});

	Event.Methods = (function() {
	  var isButton;

	  if (Prototype.Browser.IE) {
	    var buttonMap = { 0: 1, 1: 4, 2: 2 };
	    isButton = function(event, code) {
	      return event.button == buttonMap[code];
	    };

	  } else if (Prototype.Browser.WebKit) {
	    isButton = function(event, code) {
	      switch (code) {
	        case 0: return event.which == 1 && !event.metaKey;
	        case 1: return event.which == 1 && event.metaKey;
	        default: return false;
	      }
	    };

	  } else {
	    isButton = function(event, code) {
	      return event.which ? (event.which === code + 1) : (event.button === code);
	    };
	  }

	  return {
	    isLeftClick:   function(event) { return isButton(event, 0) },
	    isMiddleClick: function(event) { return isButton(event, 1) },
	    isRightClick:  function(event) { return isButton(event, 2) },

	    element: function(event) {
	      event = Event.extend(event);

	      var node          = event.target,
	          type          = event.type,
	          currentTarget = event.currentTarget;

	      if (currentTarget && currentTarget.tagName) {
	        // Firefox screws up the "click" event when moving between radio buttons
	        // via arrow keys. It also screws up the "load" and "error" events on images,
	        // reporting the document as the target instead of the original image.
	        if (type === 'load' || type === 'error' ||
	          (type === 'click' && currentTarget.tagName.toLowerCase() === 'input'
	            && currentTarget.type === 'radio'))
	              node = currentTarget;
	      }
	      if (node.nodeType == Node.TEXT_NODE) node = node.parentNode;
	      return Element.extend(node);
	    },

	    findElement: function(event, expression) {
	      var element = Event.element(event);
	      if (!expression) return element;
	      var elements = [element].concat(element.ancestors());
	      return Selector.findElement(elements, expression, 0);
	    },

	    pointer: function(event) {
	      var docElement = document.documentElement,
	      body = document.body || { scrollLeft: 0, scrollTop: 0 };
	      return {
	        x: event.pageX || (event.clientX +
	          (docElement.scrollLeft || body.scrollLeft) -
	          (docElement.clientLeft || 0)),
	        y: event.pageY || (event.clientY +
	          (docElement.scrollTop || body.scrollTop) -
	          (docElement.clientTop || 0))
	      };
	    },

	    pointerX: function(event) { return Event.pointer(event).x },
	    pointerY: function(event) { return Event.pointer(event).y },

	    stop: function(event) {
	      Event.extend(event);
	      event.preventDefault();
	      event.stopPropagation();
	      event.stopped = true;
	    }
	  };
	})();

	Event.extend = (function() {
	  var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
	    m[name] = Event.Methods[name].methodize();
	    return m;
	  });

	  if (Prototype.Browser.IE) {
	    Object.extend(methods, {
	      stopPropagation: function() { this.cancelBubble = true },
	      preventDefault:  function() { this.returnValue = false },
	      inspect: function() { return "[object Event]" }
	    });

	    return function(event) {
	      if (!event) return false;
	      if (event._extendedByPrototype) return event;

	      event._extendedByPrototype = Prototype.emptyFunction;
	      var pointer = Event.pointer(event);
	      Object.extend(event, {
	        target: event.srcElement,
	        relatedTarget: Event.relatedTarget(event),
	        pageX:  pointer.x,
	        pageY:  pointer.y
	      });
	      return Object.extend(event, methods);
	    };

	  } else {
	    Event.prototype = Event.prototype || document.createEvent("HTMLEvents")['__proto__'];
	    Object.extend(Event.prototype, methods);
	    return Prototype.K;
	  }
	})();

	Object.extend(Event, (function() {
	  var cache = Event.cache;

	  function getEventID(element) {
	    if (element._prototypeEventID) return element._prototypeEventID[0];
	    arguments.callee.id = arguments.callee.id || 1;
	    return element._prototypeEventID = [++arguments.callee.id];
	  }

	  function getDOMEventName(eventName) {
	    if (eventName && eventName.include(':')) return "dataavailable";
	    return eventName;
	  }

	  function getCacheForID(id) {
	    return cache[id] = cache[id] || { };
	  }

	  function getWrappersForEventName(id, eventName) {
	    var c = getCacheForID(id);
	    return c[eventName] = c[eventName] || [];
	  }

	  function createWrapper(element, eventName, handler) {
	    var id = getEventID(element);
	    var c = getWrappersForEventName(id, eventName);
	    if (c.pluck("handler").include(handler)) return false;

	    var wrapper = function(event) {
	      if (!Event || !Event.extend ||
	        (event.eventName && event.eventName != eventName))
	          return false;

	      Event.extend(event);
	      handler.call(element, event);
	    };

	    wrapper.handler = handler;
	    c.push(wrapper);
	    return wrapper;
	  }

	  function findWrapper(id, eventName, handler) {
	    var c = getWrappersForEventName(id, eventName);
	    return c.find(function(wrapper) { return wrapper.handler == handler });
	  }

	  function destroyWrapper(id, eventName, handler) {
	    var c = getCacheForID(id);
	    if (!c[eventName]) return false;
	    c[eventName] = c[eventName].without(findWrapper(id, eventName, handler));
	  }

	  function destroyCache() {
	    for (var id in cache)
	      for (var eventName in cache[id])
	        cache[id][eventName] = null;
	  }


	  // Internet Explorer needs to remove event handlers on page unload
	  // in order to avoid memory leaks.
	  if (window.attachEvent) {
	    window.attachEvent("onunload", destroyCache);
	  }

	  // Safari has a dummy event handler on page unload so that it won't
	  // use its bfcache. Safari <= 3.1 has an issue with restoring the "document"
	  // object when page is returned to via the back button using its bfcache.
	  if (Prototype.Browser.WebKit) {
	    window.addEventListener('unload', Prototype.emptyFunction, false);
	  }

	  return {
	    observe: function(element, eventName, handler) {
	      element = $(element);
	      var name = getDOMEventName(eventName);

	      var wrapper = createWrapper(element, eventName, handler);
	      if (!wrapper) return element;

	      if (element.addEventListener) {
	        element.addEventListener(name, wrapper, false);
	      } else {
	        element.attachEvent("on" + name, wrapper);
	      }

	      return element;
	    },

	    stopObserving: function(element, eventName, handler) {
	      element = $(element);
	      var id = getEventID(element), name = getDOMEventName(eventName);

	      if (!handler && eventName) {
	        getWrappersForEventName(id, eventName).each(function(wrapper) {
	          element.stopObserving(eventName, wrapper.handler);
	        });
	        return element;

	      } else if (!eventName) {
	        Object.keys(getCacheForID(id)).each(function(eventName) {
	          element.stopObserving(eventName);
	        });
	        return element;
	      }

	      var wrapper = findWrapper(id, eventName, handler);
	      if (!wrapper) return element;

	      if (element.removeEventListener) {
	        element.removeEventListener(name, wrapper, false);
	      } else {
	        element.detachEvent("on" + name, wrapper);
	      }

	      destroyWrapper(id, eventName, handler);

	      return element;
	    },

	    fire: function(element, eventName, memo) {
	      element = $(element);
	      if (element == document && document.createEvent && !element.dispatchEvent)
	        element = document.documentElement;

	      var event;
	      if (document.createEvent) {
	        event = document.createEvent("HTMLEvents");
	        event.initEvent("dataavailable", true, true);
	      } else {
	        event = document.createEventObject();
	        event.eventType = "ondataavailable";
	      }

	      event.eventName = eventName;
	      event.memo = memo || { };

	      if (document.createEvent) {
	        element.dispatchEvent(event);
	      } else {
	        element.fireEvent(event.eventType, event);
	      }

	      return Event.extend(event);
	    }
	  };
	})());

	Object.extend(Event, Event.Methods);

	Element.addMethods({
	  fire:          Event.fire,
	  observe:       Event.observe,
	  stopObserving: Event.stopObserving
	});

	Object.extend(document, {
	  fire:          Element.Methods.fire.methodize(),
	  observe:       Element.Methods.observe.methodize(),
	  stopObserving: Element.Methods.stopObserving.methodize(),
	  loaded:        false
	});

	(function() {
	  /* Support for the DOMContentLoaded event is based on work by Dan Webb,
	     Matthias Miller, Dean Edwards and John Resig. */

	  var timer;

	  function fireContentLoadedEvent() {
	    if (document.loaded) return;
	    if (timer) window.clearInterval(timer);
	    document.fire("dom:loaded");
	    document.loaded = true;
	  }

	  if (document.addEventListener) {
	    if (Prototype.Browser.WebKit) {
	      timer = window.setInterval(function() {
	        if (/loaded|complete/.test(document.readyState))
	          fireContentLoadedEvent();
	      }, 0);

	      Event.observe(window, "load", fireContentLoadedEvent);

	    } else {
	      document.addEventListener("DOMContentLoaded",
	        fireContentLoadedEvent, false);
	    }

	  } else {
	    document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>");
	    $("__onDOMContentLoaded").onreadystatechange = function() {
	      if (this.readyState == "complete") {
	        this.onreadystatechange = null;
	        fireContentLoadedEvent();
	      }
	    };
	  }
	})();
	/*------------------------------- DEPRECATED -------------------------------*/

	Hash.toQueryString = Object.toQueryString;

	var Toggle = { display: Element.toggle };

	Element.Methods.childOf = Element.Methods.descendantOf;

	var Insertion = {
	  Before: function(element, content) {
	    return Element.insert(element, {before:content});
	  },

	  Top: function(element, content) {
	    return Element.insert(element, {top:content});
	  },

	  Bottom: function(element, content) {
	    return Element.insert(element, {bottom:content});
	  },

	  After: function(element, content) {
	    return Element.insert(element, {after:content});
	  }
	};

	var $continue = new Error('"throw $continue" is deprecated, use "return" instead');

	// This should be moved to script.aculo.us; notice the deprecated methods
	// further below, that map to the newer Element methods.
	var Position = {
	  // set to true if needed, warning: firefox performance problems
	  // NOT neeeded for page scrolling, only if draggable contained in
	  // scrollable elements
	  includeScrollOffsets: false,

	  // must be called before calling withinIncludingScrolloffset, every time the
	  // page is scrolled
	  prepare: function() {
	    this.deltaX =  window.pageXOffset
	                || document.documentElement.scrollLeft
	                || document.body.scrollLeft
	                || 0;
	    this.deltaY =  window.pageYOffset
	                || document.documentElement.scrollTop
	                || document.body.scrollTop
	                || 0;
	  },

	  // caches x/y coordinate pair to use with overlap
	  within: function(element, x, y) {
	    if (this.includeScrollOffsets)
	      return this.withinIncludingScrolloffsets(element, x, y);
	    this.xcomp = x;
	    this.ycomp = y;
	    this.offset = Element.cumulativeOffset(element);

	    return (y >= this.offset[1] &&
	            y <  this.offset[1] + element.offsetHeight &&
	            x >= this.offset[0] &&
	            x <  this.offset[0] + element.offsetWidth);
	  },

	  withinIncludingScrolloffsets: function(element, x, y) {
	    var offsetcache = Element.cumulativeScrollOffset(element);

	    this.xcomp = x + offsetcache[0] - this.deltaX;
	    this.ycomp = y + offsetcache[1] - this.deltaY;
	    this.offset = Element.cumulativeOffset(element);

	    return (this.ycomp >= this.offset[1] &&
	            this.ycomp <  this.offset[1] + element.offsetHeight &&
	            this.xcomp >= this.offset[0] &&
	            this.xcomp <  this.offset[0] + element.offsetWidth);
	  },

	  // within must be called directly before
	  overlap: function(mode, element) {
	    if (!mode) return 0;
	    if (mode == 'vertical')
	      return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
	        element.offsetHeight;
	    if (mode == 'horizontal')
	      return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
	        element.offsetWidth;
	  },

	  // Deprecation layer -- use newer Element methods now (1.5.2).

	  cumulativeOffset: Element.Methods.cumulativeOffset,

	  positionedOffset: Element.Methods.positionedOffset,

	  absolutize: function(element) {
	    Position.prepare();
	    return Element.absolutize(element);
	  },

	  relativize: function(element) {
	    Position.prepare();
	    return Element.relativize(element);
	  },

	  realOffset: Element.Methods.cumulativeScrollOffset,

	  offsetParent: Element.Methods.getOffsetParent,

	  page: Element.Methods.viewportOffset,

	  clone: function(source, target, options) {
	    options = options || { };
	    return Element.clonePosition(target, source, options);
	  }
	};

	/*--------------------------------------------------------------------------*/

	if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){
	  function iter(name) {
	    return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";
	  }

	  instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
	  function(element, className) {
	    className = className.toString().strip();
	    var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);
	    return cond ? document._getElementsByXPath('.//*' + cond, element) : [];
	  } : function(element, className) {
	    className = className.toString().strip();
	    var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);
	    if (!classNames && !className) return elements;

	    var nodes = $(element).getElementsByTagName('*');
	    className = ' ' + className + ' ';

	    for (var i = 0, child, cn; child = nodes[i]; i++) {
	      if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||
	          (classNames && classNames.all(function(name) {
	            return !name.toString().blank() && cn.include(' ' + name + ' ');
	          }))))
	        elements.push(Element.extend(child));
	    }
	    return elements;
	  };

	  return function(className, parentElement) {
	    return $(parentElement || document.body).getElementsByClassName(className);
	  };
	}(Element.Methods);

	/*--------------------------------------------------------------------------*/

	Element.ClassNames = Class.create();
	Element.ClassNames.prototype = {
	  initialize: function(element) {
	    this.element = $(element);
	  },

	  _each: function(iterator) {
	    this.element.className.split(/\s+/).select(function(name) {
	      return name.length > 0;
	    })._each(iterator);
	  },

	  set: function(className) {
	    this.element.className = className;
	  },

	  add: function(classNameToAdd) {
	    if (this.include(classNameToAdd)) return;
	    this.set($A(this).concat(classNameToAdd).join(' '));
	  },

	  remove: function(classNameToRemove) {
	    if (!this.include(classNameToRemove)) return;
	    this.set($A(this).without(classNameToRemove).join(' '));
	  },

	  toString: function() {
	    return $A(this).join(' ');
	  }
	};

	Object.extend(Element.ClassNames.prototype, Enumerable);

	/*--------------------------------------------------------------------------*/

	Element.addMethods();
/*********************************************************
*  End prototype.js
*********************************************************/
/*********************************************************
*  Start validator.js 
*********************************************************/
	
	/**
     * 오류메시지를 경고창이 아닌 입력위치 바로 아래에 보여질 수 있는 기능을 기존의 기능과 함께 지원되도록 함수를 변경함.
	 * 만약 경고창이 아닌 화면상에서 바로 오류 메시지를 보여주기 위해서는 이 객체를 선언한 후 FormValidator의 validate함수를 호출할 때 매개변수로
	 * 같이 던져주면 된다. displayMap의 형식은 ECMAScript의 PropertyMap의 형식을 따른다. 키값은 form문의 input element의 name속성값을 사용하고,
	 * 키값에 짝지워진 값은 오류내용을 보여주는 element의 id속성값을 사용한다.
	 * 예)
	 * 
	 * var displayMap = { "input1Nm":"dispId1", "input2Nm":"dispId2" };
	 * var validatorDisplayMap validator.validate(displayMap);
	 */
	var ValidatorDisplayMap = Class.create({
		
		displayMap: undefined
	
		, initialize: function(displayMap)
		{
			this.displayMap = displayMap;
		}
	
		, findDisplayId: function(key)
		{
			return (this.displayMap) ? this.displayMap[key] : null;
		}
		
		, showMessage: function(key, msg)
		{
			var dispElmt = document.getElementById(this.findDisplayId(key));
			if ( dispElmt ) 
			{
				dispElmt.innerHTML = '<p class="checkError mt05">' + msg + '</p>';
				dispElmt.style.display = '';
			}
		}
		
		, clearMessage: function(key)
		{
			var dispElmt = document.getElementById(this.findDisplayId(key));
			if ( dispElmt ) 
			{
				dispElmt.innerHTML = '';
				dispElmt.style.display = 'none';
			}
		}
		
		, clearMessageAll: function()
		{
			for ( var id in this.displayMap.valueOf() ) 
			{
				if ( !this.displayMap[id] ) continue;
				elmt = document.getElementById(this.displayMap[id]);
				if ( elmt )
				{
					elmt.innerHTML = '';
					elmt.style.display = 'none';
				}
			}
		}
		
	});

	/**
	 * Form Validator Class
	 */
	var FormValidator = Class.create( {
	    /**
	     * Constructor for this class
	     *
	     * @author Myoungseok, Seo
	     * @param targetFormName
	     */
	    initialize : function(targetForm) {
	        this.targetForm = targetForm;
	        this.checkerList = [];
	    },

	    /**
	     * get target form name
	     */
	    getFormName : function() {
	        return this.targetForm;
	    },

	    
	    /**
	     * execute form validation
	     * @param displayMap 오류메시지를 보여지는 위치를 지정한다.(생략가능)
	     * @see ValidatorDisplayMap
	     */
	    validate : function(displayMap) 
	    {
	    	var	result = true;
	    	var focused = false;
	    	for ( var index = 0, length = this.checkerList.length ; index < length ; index++ ) {
	            var fieldChecker = this.checkerList[index];
				var target_elements = this.targetForm[fieldChecker.getFieldName()];
				// target_elements가 올바르지 못할 때는 그냥 넘어가게 함.
				if (target_elements) {
		            if (target_elements.name == undefined && target_elements.id == undefined) {
		            	continue;
		            }
				} else {
	            	continue;
				}
				// 오류가 발생하였다면 적당한 위치에 오류내용을 보여주도록 한다.
				if ( fieldChecker.check() == false ) 
				{
					result = false;
					
					if ( displayMap && target_elements && target_elements.name && displayMap.findDisplayId(target_elements.name) )
					{
						displayMap.showMessage(target_elements.name, fieldChecker.getErrorMessage());						
						if ( fieldChecker.isFocus() && target_elements && target_elements.focus && !focused ) 
						{
							target_elements.focus();
							focused = true;	// 처음발견한 자리로 맞춰지게 한다.
						}
					}
					else
					{
						if ( fieldChecker.isFocus() ) {
							//					var target_elements = this.targetForm[fieldChecker.getFieldName()];
							showOspWarningPopup("Check Field", fieldChecker.getErrorMessage(), target_elements);
						}else{
							showOspWarningPopup("Check Field", fieldChecker.getErrorMessage());                	
						}
						
						break; 
					}
				}
	        }
	        
	        return result;
	    },
	    
	    /**
	     * execute form validation
	     * @see ValidatorDisplayMap
	     */
	    validate2 : function() 
	    {
	    	var	result = true;
	    	var focused = false;
	    	for ( var index = 0, length = this.checkerList.length ; index < length ; index++ ) {
	            var fieldChecker = this.checkerList[index];
				var target_elements = this.targetForm[fieldChecker.getFieldName()];
				
				var fieldCheckerTemp = $(target_elements.id + '_temp');
				if(fieldCheckerTemp != null) setOuterHtml(fieldCheckerTemp, '');
				
				// target_elements가 올바르지 못할 때는 그냥 넘어가게 함.
				if (target_elements) {
		            if (target_elements.name == undefined && target_elements.id == undefined) {
		            	continue;
		            }
				} else {
	            	continue;
				}
				// 오류가 발생하였다면 적당한 위치에 오류내용을 보여주도록 한다.
				if ( fieldChecker.check() == false ) 
				{
					result = false;
					if ( fieldChecker.isFocus() ) {
						target_elements.insertAdjacentHTML("afterEnd","<p class='checkError' id='" + target_elements.id + "_temp' >" + fieldChecker.getErrorMessage() + "</p>");
						target_elements.focus();
					}else{
						showOspWarningPopup("Check Field", fieldChecker.getErrorMessage());
					}
					break; 
				}
	        }
	        
	        return result;
	    },

	    /**
	     * validate required field
	     */
	    checkRequired : function(fieldName, errorMessage, focus, label) {
	        this.checkerList.push(
	                new RequiredFieldChecker(this.targetForm, fieldName, errorMessage, focus, label));
	    },

	    /**
	     *
	     */
	    checkMaxLength : function(fieldName, maxLength, errorMessage, focus, label) {
	        this.checkerList.push(
	                new MaxLengthFieldChecker(this.targetForm, fieldName,
	                        maxLength, errorMessage, focus, label));
	    },

	    /**
	     *
	     */
	    checkMaxLengthByte : function(fieldName, maxLength, errorMessage, focus, label) {
	        this.checkerList.push(
	                new MaxLengthByteFieldChecker(this.targetForm, fieldName,
	                        maxLength, errorMessage, focus, label));
	    },

	    /**
	     *
	     */
	    checkMinLength : function(fieldName, minLength, errorMessage, focus, label) {
	        this.checkerList.push(
	                new MinLengthFieldChecker(this.targetForm, fieldName,
	                        minLength, errorMessage, focus, label));
	    },

	    /**
	     *
	     */
	    checkMinLengthByte : function(fieldName, minLength, errorMessage, focus, label) {
	        this.checkerList.push(
	                new MinLengthByteFieldChecker(this.targetForm, fieldName,
	                        minLength, errorMessage, focus, label));
	    },

	    checkRegex : function(fieldName, regex, errorMessage, focus, label) {
	        this.checkerList.push(
	                new RegexFieldChecker(this.targetForm, fieldName,
	                        regex, errorMessage, focus, label));
	    },

	    checkAlphaNum : function(fieldName, errorMessage, focus, label) {
	        this.checkerList.push(
	                new RegexFieldChecker(this.targetForm, fieldName,
	                        /^[a-zA-Z0-9]+$/, errorMessage, focus, label));
	    },

	    checkOnlyNumber : function(fieldName, errorMessage, focus, label) {
	        this.checkerList.push(
	                new RegexFieldChecker(this.targetForm, fieldName,
	                        /^[0-9]+$/, errorMessage, focus, label));
	    },

	    checkDecimal : function(fieldName, errorMessage, focus, label) {
	        this.checkerList.push(
	                new RegexFieldChecker(this.targetForm, fieldName,
	                        /^(\-)?[0-9]*(\.[0-9]*)?$/, errorMessage, focus, label));
	    },

	    checkEmail : function(fieldName, errorMessage, focus, label) {
	        this.checkerList.push(
	                new RegexFieldChecker(this.targetForm, fieldName,
	                		emailPattern, errorMessage, focus, label));
	    },

	    checkSelected : function(fieldName, firstIdx, errorMessage, focus, label) {
	        this.checkerList.push(
	                new SelectionFieldChecker(this.targetForm, fieldName,
	                        firstIdx, errorMessage, focus, label));
	    },

	    checkAtLeastOneChecked : function(fieldName, errorMessage, focus, label) {
	        this.checkerList.push(
	                new AtLeastOneCheckFieldChecker(this.targetForm, fieldName,
	                        errorMessage, focus, label));
	    },

		checkVersion : function(fieldName, errorMessage, focus, label) {
	        this.checkerList.push(
	                new RegexFieldChecker(this.targetForm, fieldName,
	                        /^[0-9]+\.[0-9]+$/, errorMessage, focus, label));
	    },

		checkVersionStr : function(fieldName, errorMessage, focus, label) {
	        this.checkerList.push(
	                new RegexFieldChecker(this.targetForm, fieldName,
	                        /^[0-9\.]*$/, errorMessage, focus, label));
	    },
	    
	    /* Form Object's all field value check */
	    checkPermittedPattern : function(errorMessage) {
	    	// 금지 기호 : #, ;, *, {, }, <, >, &, ./, ../ 와 같은 아홉가지 패턴 
	    	// (../는 ./ 포함되어 있기 때문에 별도로 추가하지 않음.)
	        var prohibitedRegExp = /[#;\*{}<>&]|\.\//;	
	                
	        /* Validation check For Input Tag, exclude type='radio' */
	        var _Input = this.targetForm.getElementsByTagName("INPUT");
	        for (var i=0;i < _Input.length ; i++)
	        {
	            //var formFieldObjectInput = _Input[i];
	            if ( _Input[i].type != 'radio' && _Input[i].type != 'checkbox'){
	                //alert("<input> name : " + formFieldObjectInput[l].name + " type : " + formFieldObjectInput[l].type);
	                this.checkerList.push(
	                        new ProhibitedPatternChecker(this.targetForm, _Input[i].name,
	                        		prohibitedRegExp, errorMessage, _Input[i], ""));
	            }
	        }

	        /* Validation check For Select Tag */ 
	        var _Select = this.targetForm.getElementsByTagName("SELECT");
	        for (var j=0;j < _Select.length ; j++)
	        {
	            //alert("<select> name : " + _Select[j].name);
	            this.checkerList.push(
	                new ProhibitedPatternChecker(this.targetForm, _Select[j].name,
	                		prohibitedRegExp, errorMessage, _Select[j], ""));      
	        }

	        /* Validation check For Textarea Tag */
	        var _Textarea = this.targetForm.getElementsByTagName("TEXTAREA");
	        for (var k=0;k < _Textarea.length ; k++)
	        {
	            //alert("<textarea> name : " + _Textarea[k].name);
	            this.checkerList.push(
	                new ProhibitedPatternChecker(this.targetForm, _Textarea[k].name,
	                		prohibitedRegExp, errorMessage, _Textarea[k], ""));
	        }
	    }
	});

	/**
	 * element가 여러개로 구성된 것인지 확인한다.
	 * @return 0이면 단일, 그이상이면 여러개.
	 */
	FormValidator.isMultiElement = function(elmt)
	{
		var len = 0;
		
		if ( elmt.length )
		{
			if ( elmt.tagName && elmt.tagName.toLowerCase() == 'select' )
			{
				len = (elmt[0].tagName && elmt[0].tagName.toLowerCase() == 'select') ? elmt.length : 0;
			}
			else
				len = elmt.length;
		}

		return len;
	}
	
	function getValidatorErrorMsg(msg, label)
	{
		if(label)
			return label + ' : ' + msg;
		else
			return msg;
	}

	/**
	 * Define a FieldChecker Module Class
	 */
	var FieldChecker = {
	    getFieldName : function() {
	        return this.fieldName;
	    },
	    getErrorMessage : function() {
	        return this.errorMessage;
	    },
	    isFocus : function() {
	        return this.focus;
	    },
	    getRedirect : function() {
	        return this.redirect;
	    }
	};

	/* 금지 패턴체크 : 금지된 문자가 있는지 체크함 */
	var ProhibitedPatternChecker = Class.create(FieldChecker, {
	    initialize : function(form, fieldName, regex, errorMessage, focus, label) {
	        this.form = form;
	        this.fieldName = fieldName;
	        this.regex = regex;
	        this.errorMessage = getValidatorErrorMsg(errorMessage, label);
	        this.focus = focus;
	    },

	    getRegex: function() {
	        return this.regex;
	    },

	    check : function() {
	    	var field = getCheckField(this);
	    	
	    	if ( !field || !field.value ) {
	    		return true;
	    	}

	    	var str = getCheckField(this).value;
	        if (str.length == 0) {
	            return true;
	        }
	        return ( str.search(this.regex) == -1 );
	    }
	});

	/**
	 * Required Field Checker Class
	 */
	var RequiredFieldChecker = Class.create(FieldChecker, {

	    /**
	     * Constructor for this class
	     *
	     * @param form          target form instance
	     * @param fieldName     target field name
	     * @param errorMessage  custom error message
	     * @param focus         whether or not field focusing
	     */
	    initialize : function(form, fieldName, errorMessage, focus, label) {
	        this.form = form;
	        this.fieldName = fieldName;
			this.errorMessage = getValidatorErrorMsg(errorMessage, label);
	        this.focus = focus;
	    },

	    check : function() {
	        return ( trim(this.form[this.fieldName].value) != '' );
	    }

	});


	/**
	 * Sql Injection Checker Class
	 */
	var SqlInjectionFieldChecker = Class.create(FieldChecker, {

	    /**
	     * Constructor for this class
	     *
	     * @param form          target form instance
	     * @param fieldName     target field name
	     * @param errorMessage  custom error message
	     * @param focus         whether or not field focusing
	     */
	    initialize : function(form, fieldName, errorMessage, focus) {
	        this.form = form;
	        this.fieldName = fieldName;
	        this.errorMessage = errorMessage;
	        this.focus = focus;
	    },

	    check : function() {
	        var fieldValue = this.form[this.fieldName].value;
	        if (fieldValue.indexOf("'") > -1 || fieldValue.indexOf("<") > -1
	                || fieldValue.indexOf(">") > -1) {
	            return false;
	        }
	        return true;
	    }

	});


	var MaxLengthFieldChecker = Class.create(FieldChecker, {

	    /**
	     * Constructor for this class
	     *
	     * @param form
	     *            target form instance
	     * @param fieldName
	     *            target field name
	     * @param maxLength
	     *            max length
	     * @param errorMessage
	     *            custom error message
	     * @param focus
	     *            whether or not field focusing
	     */
	    initialize : function(form, fieldName, maxLength, errorMessage, focus, label) {
	        this.form = form;
	        this.fieldName = fieldName;
	        this.maxLength = maxLength;
	        this.errorMessage = getValidatorErrorMsg(errorMessage, label);
	        this.focus = focus;
	    },

	    /**
	     * get max length
	     */
	    getMaxLength : function() {
	        return this.maxLength;
	    },

	    /**
	     * check max length
	     */
	    check : function() {
	        return (this.form[this.fieldName].value.length <= this.maxLength);
	    }

	});


	var MaxLengthByteFieldChecker = Class.create(FieldChecker, {

	    /**
	     * Constructor for this class
	     *
	     * @param form          target form instance
	     * @param fieldName     target field name
	     * @param maxLength     max byte length
	     * @param errorMessage  custom error message
	     * @param focus         whether or not field focusing
	     */
	    initialize : function(form, fieldName, maxLength, errorMessage, focus, label) {
	        this.form = form;
	        this.fieldName = fieldName;
	        this.maxLength = maxLength;
	        this.errorMessage = getValidatorErrorMsg(errorMessage, label);
	        this.focus = focus;
	    },

	    /**
	     * get max byte length
	     */
	    getMaxLength : function() {
	        return this.maxLength;
	    },

	    /**
	     * check max byte length
	     */
	    check : function() {
	        str = this.form[this.fieldName].value;
	        // UTF-8은 한글 1자가  3바이트이므로, 3으로 count하도록 수정.
	        return ((str.length + ((escape(str) + "%u").match(/%u/g).length - 1) * 2) <= this.maxLength);
	    }

	});


	var MinLengthFieldChecker = Class.create(FieldChecker, {

	    /**
	     * Constructor for this class
	     *
	     * @param form
	     *            target form instance
	     * @param fieldName
	     *            target field name
	     * @param minLength
	     *            min length
	     * @param errorMessage
	     *            custom error message
	     * @param focus
	     *            whether or not field focusing
	     */
	    initialize : function(form, fieldName, minLength, errorMessage, focus, label) {
	        this.form = form;
	        this.fieldName = fieldName;
	        this.minLength = minLength;
	        this.errorMessage = getValidatorErrorMsg(errorMessage, label);
	        this.focus = focus;
	    },

	    /**
	     * get minimum length
	     */
	    getMinLength : function() {
	        return this.minLength;
	    },

	    /**
	     * check minimum length for target field value
	     */
	    check : function() {
	        return (this.form[this.fieldName].value.length >= this.minLength);
	    }

	});


	var MinLengthByteFieldChecker = Class.create(FieldChecker, {
	    /**
	     * Constructor for this class
	     *
	     * @param form          target form instance
	     * @param fieldName     target field name
	     * @param minLength     min byte length
	     * @param errorMessage  custom error message
	     * @param focus         whether or not focus on field
	     */
	    initialize : function(form, fieldName, minLength, errorMessage, focus, label) {
	        this.form = form;
	        this.fieldName = fieldName;
	        this.minLength = minLength;
	        this.errorMessage = getValidatorErrorMsg(errorMessage, label);
	        this.focus = focus;
	    },

	    /**
	     * get minimum byte length
	     */
	    getMinLength : function() {
	        return this.minLength;
	    },

	    /**
	     * check minimum byte length for target field value
	     */
	    check : function() {
	        str = this.form[this.fieldName].value;
	        return ((str.length + (escape(str) + "%u").match(/%u/g).length - 1) >= this.minLength);
	    }

	});


	var RegexFieldChecker = Class.create(FieldChecker, {

	    initialize : function(form, fieldName, regex, errorMessage, focus, label) {
	        this.form = form;
	        this.fieldName = fieldName;
	        this.regex = regex;
	        this.errorMessage = getValidatorErrorMsg(errorMessage, label);
	        this.focus = focus;
	    },

	    getRegex: function() {
	        return this.regex;
	    },

	    check : function() {
	    	var field = getCheckField(this);
	    	
	    	if ( !field || !field.value ) {
	    		return true;
	    	}

		    var str = getCheckField(this).value;
	        if (str.length == 0) {
	            return true;
	        }
	        return ( str.search(this.regex) != -1 );
	    }

	});


	var SelectionFieldChecker = Class.create(FieldChecker, {

	    initialize: function(form, fieldName, firstIdx, errorMessage, focus, label) {
	        this.form = form;
	        this.fieldName = fieldName;
	        this.firstIdx = firstIdx;
	        this.errorMessage = getValidatorErrorMsg(errorMessage, label);
	        this.focus = focus;
	    },

	    getFirstIndex: function() {
	        return this.firstIdx;
	    },

	    check : function() {
	    	var dispYN = this.form[this.fieldName].style.display;
	        var selectedIndex = this.form[this.fieldName].selectedIndex;
	        return ( selectedIndex >= this.firstIdx );
	    }

	});

	var AtLeastOneCheckFieldChecker = Class.create(FieldChecker, {

	    initialize: function(form, fieldName, errorMessage, focus, label) {
	        this.form = form;
	        this.fieldName = fieldName;
	        this.errorMessage = getValidatorErrorMsg(errorMessage, label);

	        if ( focus == true || focus == false ) {
	            this.focus = focus;
	        } else {
	            this.focus = false;
	            this.redirect = focus;
	        }
	    },

	    check: function () {
	        var ele = this.form[this.fieldName];
	        if ( typeof(ele[0]) != "undefined" ) {
	            for (var idxe = 0 ; idxe < ele.length ; idxe++) {
	                if (ele[idxe].checked == true) {
	                    return true;
	                }
	            }
	            return false;
	        } else {
	            return ele.checked == true;
	        }
	    }

	});

	/**
	 * form의 field 가져오기.
	 */
	function getCheckField(checker) {
	    var formField = checker.form[checker.fieldName];
	    if (formField && formField.length && formField.length > 1) {
	        return formField[0];
	    } else if (formField){
	        return formField
	    } else {
	        return document.getElementById(checker.fieldName);
	    }
	}

/*********************************************************
*  End validator.js
*********************************************************/

/*********************************************************
*  Start datepicker.js
*********************************************************/
	var datePickerConfig = {
		    idPrefix: "osp-datepicker-",
		    fieldSuffixs: ["Year", "Month", "Date"]
		};

		var datePickerHandler = {
		    datePicker: null,
		    toggle: function(obj, target) {
		        if (!this.datePicker) {
		            this.datePicker = new DatePicker();
		        }
		        this.datePicker.toggle(obj, target);
		    },
		    close: function() {
		        this.datePicker.close();
		    },
		    prevYear: function(year, month) {
		        this.datePicker.build(year, month);
		    },
		    nextYear: function(year, month) {
		        this.datePicker.build(year, month);
		    },
		    prevMonth: function(year, month) {
		        this.datePicker.build(year, month);
		    },
		    nextMonth: function(year, month) {
		        this.datePicker.build(year, month);
		    },
		    selectDate: function(newYear, newMonth, newDate) {
		        this.datePicker.select(newYear, newMonth, newDate);
		    }
		};

		var DatePicker = Class.create();
		DatePicker.prototype = {
		    container: null,
		    initialize: function() {
		        if ( !this.container ) {
		            this.container = new Element('div', { 'id': datePickerConfig.idPrefix + "container" });
		            this.container.setStyle({ 'display': 'none', 'background' : '#fff' });
		            this.container.absolutize();
		            document.body.appendChild(this.container);

		            this.calendar = new Element('div', { 'id': datePickerConfig.idPrefix + "calendar" });
		            this.calendar.setStyle({ 'z-index': 9999, display: 'block', 'background' : '#fff' });
		            this.calendar.absolutize();
		            this.container.appendChild(this.calendar);
		        }
		        this.today = new Date();
		        this.selected = new Date();
		    },
		    select: function(newYear, newMonth, newDate) {
		        this.updateTarget(newYear, newMonth, newDate);
		        this.container.hide();
		    },
		    updateTarget: function(newYear, newMonth, newDate) {
		        var yOpts = $(this.targetPrefix + "Year").options;
		        for ( var i = 0, l = yOpts.length ; i < l ; i++ ) {
		            if ( yOpts[i].value == newYear ) {
		                 yOpts[i].selected = true;
		            }
		        }

		        var mOpts = $(this.targetPrefix + "Month").options;
		        for ( var i = 0, l = mOpts.length ; i < l ; i++ ) {
		            if ( mOpts[i].value == newMonth ) {
		                 mOpts[i].selected = true;
		            }
		        }

		        var dOpts = $(this.targetPrefix + "Date").options;
		        for ( var i = 0, l = dOpts.length ; i < l ; i++ ) {
		            if ( dOpts[i].value == newDate ) {
		                 dOpts[i].selected = true;
		            }
		        }
		    },
		    close: function() {
		        this.container.hide();
		    },
		    build: function(year, month) {
		        var src = "<table class=\"calPopTableBox\" id=\"" + datePickerConfig.idPrefix + "tablebox\">";
		            src += "    <tr>";
		            src += "        <td style=\"background: #fff;\">";
		            src += "            <div class=\"calPopClose\"><a href=\"javascript:datePickerHandler.close();\"><img src=\"../en_US/images/common/btn/btn_cal_close.gif\" alt=\"close\" /></a></div>";
		            src += "            <div class=\"calPopSelect\">";
		            src += "                <a href=\"javascript:datePickerHandler.prevYear(" + (year - 1 ) +", " + month + ")\"><img src=\"../en_US/images/common/btn/btn_cal_left.gif\" alt=\"\" /></a>";
		            src += "                <span class=\"calYear\">"+year+"</span>";
		            src += "                <a href=\"javascript:datePickerHandler.nextYear(" + (year + 1) + ", " + month + ")\"><img src=\"../en_US/images/common/btn/btn_cal_right.gif\" alt=\"\" /></a>&nbsp;&nbsp;";

		            var prevYear = year;
		            var prevMonth = month -1;
		            if ( prevMonth == 0 ) {
		                prevMonth = 12;
		                prevYear = prevYear - 1;
		            }
		            src += "                <a href=\"javascript:datePickerHandler.prevMonth(" + prevYear + ", " + prevMonth + ")\"><img src=\"../en_US/images/common/btn/btn_cal_left.gif\" alt=\"\" /></a>";
		            src += "                <span class=\"calDay\">" + (month < 10 ? "0" + month : month) + "</span>";

		            var nextYear = year;
		            var nextMonth = month + 1;
		            if ( nextMonth == 13 ) {
		                nextMonth = 1;
		                nextYear = year + 1;
		            }
		            src += "                <a href=\"javascript:datePickerHandler.nextMonth(" + nextYear + ", " + nextMonth + ")\"><img src=\"../en_US/images/common/btn/btn_cal_right.gif\" alt=\"\" /></a>";
		            src += "            </div>";

		            src += "            <table class=\"calTable\">";
		            src += "                <tr>";
		            src += "                    <th>S</th>";
		            src += "                    <th>M</th>";
		            src += "                    <th>T</th>";
		            src += "                    <th>W</th>";
		            src += "                    <th>T</th>";
		            src += "                    <th>F</th>";
		            src += "                    <th>S</th>";
		            src += "                </tr>";

		            var firstDate = new Date();
		            firstDate.setFullYear(year, month - 1, 1);

		            var lastDate = new Date();
		            lastDate.setFullYear(year, month, 0);

		            var calRow = 0;

		            var firstDay = firstDate.getDay();
		            for ( var i = 0 ; i < firstDay ; i++ ) {
		                if ( i == 0 ) {
		                    src += "                <tr>";
		                    src += "                    <td class=\"sunDay\"></td>";
		                    calRow++;
		                } else {
		                    src += "                    <td></td>";
		                }
		            }

		            var cellClass = "";
		            for ( var i = firstDate.getDate(),
		                      l = lastDate.getDate() + 1,
		                      day = firstDay ; i < l ; i++, day++ ) {
		                if ( day % 7 == 0 ) {
		                    src += "                <tr>";
		                    cellClass = "sunDay";
		                    calRow++;
		                }
		                src += "                    <td";
		                if (cellClass != "") {
		                    src += " class=\"" + cellClass + "\"";
		                }
		                src += " title=\"" + year + (month < 10 ? "0" + month : month) + (i < 10 ? "0" + i : i) + "\"";
		                src += " onclick=\"datePickerHandler.selectDate(" + year + ", " + month + ", " + i + ")\"";
		                src += " style=\"cursor: pointer;\">";

		                if ( i == this.selected.getDate() ) {
		                    src += "<a href=\"#\" class=\"daySelected\">"+i+"</a>";
		                } else {
		                    src += i;
		                }


		                src += "</td>";
		                if ( day % 7 == 6 ) {
		                    src += "                </tr>";
		                }
		            }

		            for ( var i = lastDate.getDay() + 1 ; i < 7 ; i++ ) {
		                src += "                    <td></td>";
		                if ( i == 6 ) {
		                    src += "                </tr>";
		                }
		            }

		            src += "            </table>";
		            src += "        </td>";
		            src += "    </tr>";
		            src += "</table>";

		        this.calendar.innerHTML = this.wrap(src);

		        if ( Prototype.Browser.IE ) {
		            $(datePickerConfig.idPrefix + "supportframe").style.height = ( 153 - ((6 - calRow) * 18) + 4) + "px";
		        }
		    },
		    wrap: function(src) {
		        if ( !Prototype.Browser.IE ) {
		            return src;
		        }

		        var w = "<iframe id=\"" + datePickerConfig.idPrefix + "supportframe\" width='168' height='158' marginwidth='0' marginheight='0' frameborder='0' src='/en_US/images/common/space.gif' style='filter:alpha(Opacity=50); position: absolute; z-index: 9998; top: 0px; left: 0px;'></iframe><div style=\"position:absolute; top: 0px; left: 0px; z-index: 9999;\">";
		        w += src;
		        w += "</div>";

		        return w;
		    },
		    toggle: function(obj, target) {
		        if ( this.targetPrefix != target) {
		            this.container.hide();
		        }

		        this.targetPrefix = target;
		        var year = parseInt($(this.targetPrefix + "Year").value);
		        var month = parseInt($(this.targetPrefix + "Month").value);
		        var date = parseInt($(this.targetPrefix + "Date").value);

		        this.selected.setFullYear(year, month - 1, date);
		        this.build(year, month);

		        this.container.style.left = (this.calculateOffsetLeft(obj) - 168) + "px";
		        this.container.style.top = (this.calculateOffsetTop(obj) + 19) + "px";
		        this.container.toggle();
		    },
		    calculateOffsetLeft: function(field) {
		        return this.calculateOffset(field, "offsetLeft");
		    },
		    calculateOffsetTop: function(field) {
		        return this.calculateOffset(field, "offsetTop");
		    },
		    calculateOffset: function(field, attr) {
		        var offset = 0;
		        while ( field ) {
		            offset += field[attr];
		            field = field.offsetParent;
		        }
		        return offset;
		    }
		};

		function toggleDatePicker(obj, target) {
		datePickerHandler.toggle(obj, target);
		}

/*********************************************************
*  End datepicker.js
*********************************************************/
/*********************************************************
*  Start paging.js
*********************************************************/
		/**
		 * osp paging config singleton
		 */
		var ospPagingConfig = {
		    defaultFirstImage :"../en_US/images/common/btn/btn_page_first.gif",
		    defaultLastImage :"../en_US/images/common/btn/btn_page_end.gif",
		    defaultPrevImage :"../en_US/images/common/btn/btn_page_back.gif",
		    defaultNextImage :"../en_US/images/common/btn/btn_page_next.gif",
		    defaultRowCount :10,
		    defaultPagingCount :10,
		    defaultAction :"javascript:void(0)",
		    defaultActionName : "goPage"
		};

		/**
		 * OSP Paging Class
		 */
		var OspPaging = Class.create( {
		    /**
		     * Constructor for this class
		     *
		     * @param pageNo        current page no
		     * @param totalCount    total list count
		     * @param rowCount      display row count
		     * @param pagingCount   display paging count
		     */
		    initialize : function(pageNo, totalCount, actionName, rowCount, pagingCount) {
		        this.pageNo = pageNo;
		        this.totalCount = totalCount;
		        this.actionName = actionName || ospPagingConfig.defaultActionName;
		        this.rowCount = rowCount || ospPagingConfig.defaultRowCount;
		        this.pagingCount = pagingCount || ospPagingConfig.defaultPagingCount;

		        /* eval total page count */
		        this.totalPageCount = Math.ceil(totalCount / this.rowCount);

		        /* eval total page group */
		        this.totalPageGroup = Math.ceil(this.totalPageCount / this.pagingCount);

		        /* eval current page gorup */
		        this.currentPageGroup = Math.ceil(pageNo / this.pagingCount);

		        /* eval start page and end page */
		        this.startPage = (this.currentPageGroup - 1) * this.pagingCount + 1;
		        this.endPage = this.currentPageGroup * this.pagingCount;
		        if (this.totalPageCount < this.endPage) {
		            this.endPage = this.totalPageCount;
		        }
		    },

		    /**
		     * render paging html
		     */
		    render2Html : function() {
		        var htmlCode = "<table width=\"700\" class=\"tablePaging\">";
		        htmlCode += "<tr>";
		        htmlCode += "    <td>";

		        var actionEvent = null;

		        /* ============================ */
		        /* render first page image link */
		        /* ============================ */
		        if (this.pageNo > 1) {
		            actionEvent = "javascript:" + this.actionName + "(1)";
		        } else {
		            actionEvent = ospPagingConfig.defaultAction;
		        }
		        htmlCode += "        <a href=\"#\" onclick=\"" + actionEvent + "\">";
		        htmlCode += "<img src=\"" + this.getFirstImage() + "\" alt=\"First Page\" />";
		        htmlCode += "</a>";

		        /* ================================= */
		        /* render prev page group image link */
		        /* ================================= */
		        if (this.currentPageGroup > 1) {
		            var prevPageNo = this.startPage - this.pagingCount;
		            actionEvent = "javascript:" + this.actionName + "(" + prevPageNo + ")";
		        } else {
		            actionEvent = ospPagingConfig.defaultAction;
		        }
		        htmlCode += "        <a href=\"#\" onclick=\"" + actionEvent + "\">";
		        htmlCode += "<img src=\"" + this.getPrevImage() + "\" alt=\"Previous Page Group\" />";
		        htmlCode += "</a>";

		        /* ================== */
		        /* render paging link */
		        /* ================== */
		        for ( var index = this.startPage; index <= this.endPage; index++) {
		            if (this.pageNo == index) {
		                htmlCode += "        <span class=\"pagingSelected\">" + index + "</span>";
		            } else {
		                htmlCode += "        <span><a href=\"javascript:" + this.actionName + "(" + index + ")\">";
		                htmlCode += index + "</a></span>";
		            }

		            if (index != this.endPage) {
		                htmlCode += "        <span>|</span>";
		            }
		        }

		        /* ================================= */
		        /* render next page group image link */
		        /* ================================= */
		        if (this.currentPageGroup < this.totalPageGroup) {
		            var nextPageNo = ((this.endPage + 1) > this.totalPageCount ? this.totalPageCount
		                    : this.endPage + 1);
		            actionEvent = "javascript:" + this.actionName + "(" + nextPageNo + ")";
		        } else {
		            actionEvent = ospPagingConfig.defaultAction;
		        }
		        htmlCode += "        <a href=\"#\" onclick=\"" + actionEvent + "\">";
		        htmlCode += "<img src=\"" + this.getNextImage() + "\" alt=\"\" />";
		        htmlCode += "</a>";

		        /* =========================== */
		        /* render last page image link */
		        /* =========================== */
		        if (this.pageNo < this.totalPageCount) {
		            actionEvent = "javascript:" + this.actionName + "(" + this.totalPageCount + ")";
		        } else {
		            actionEvent = ospPagingConfig.defaultAction;
		        }
		        htmlCode += "        <a href=\"#\" onclick=\"" + actionEvent + "\">";
		        htmlCode += "<img src=\"../en_US/images/common/btn/btn_page_end.gif\" alt=\"\" />";
		        htmlCode += "</a>";

		        htmlCode += "    </td>";
		        htmlCode += "</tr>";
		        htmlCode += "</table>";

		        return htmlCode;
		    },

		    /**
		     * render out to document
		     */
		    render : function() {
		        document.write(this.render2Html());
		    },

		    /**
		     * render out to target object as innerHTML
		     *
		     * @param targetId
		     *            target object id
		     */
		    renderTo : function(targetId) {
		        $(targetId).innerHTML = this.render2Html();
		    },

		    /**
		     * 기본 이미지 이외의 다른 이미지를 지정한다.
		     *
		     * @param firstImage
		     *            url for first link image
		     * @param lastImage
		     *            url for last link image
		     * @param prevImage
		     *            url for previous page group image
		     * @param nextImage
		     *            url for next page group image
		     */
		    setImageSet : function(firstImage, lastImage, prevImage, nextImage) {
		        this.firstImage = firstImage || ospPagingConfig.defaultFirstImage;
		        this.lastImage = lastImage || ospPagingConfig.defaultLastImage;
		        this.prevImage = prevImage || ospPagingConfig.defaultPrevImage;
		        this.nextImage = nextImage || ospPagingConfig.defaultNextImage;
		    },

		    /**
		     * get first image url
		     */
		    getFirstImage : function() {
		        return (this.firstImage || ospPagingConfig.defaultFirstImage);
		    },

		    /**
		     * get first image url
		     */
		    getLastImage : function() {
		        return (this.lastImage || ospPagingConfig.defaultLastImage);
		    },

		    /**
		     * get previous page group image url
		     */
		    getPrevImage : function() {
		        return (this.prevImage || ospPagingConfig.defaultPrevImage);
		    },

		    /**
		     * get next page group image url
		     */
		    getNextImage : function() {
		        return (this.nextImage || ospPagingConfig.defaultNextImage);
		    },

		    setRowCount : function(/* int */rowCount) {
		        this.rowCount = rowCount || ospPagingConfig.defaultRowCount;
		    },

		    setPagingCount : function(/* int */pagingCount) {
		        this.pagingCount = pagingCount || ospPagingConfig.defaultPagingCount;
		    }
		});

		// 이 이후의 코드는 validator.js와 중복되므로 삭제하였음!		
/*********************************************************
*  End paging.js
*********************************************************/
/*********************************************************
*  Start util.js
*********************************************************/
		/*
		 * A-Store JavaScript Util file
		 *
		 * @author Jihoon, Sang
		 */

		var EMPTY = "";
		var strHanEmptyAddr1 = "동/읍/면, 번지를 입력하여 주세요.";
		var strHanEmptyCity = "시/도, 구/군을 입력하여 주세요.";
		var strHanEmptyZIP = "‘-’ 를 포함해 7자리로 입력하여 주세요.";

		/**
		 * 문자열 Trim
		 * 
		 * @param str / Trim 대상
		 * @return boolean / Trim된 문자열
		 */
		function trim(str) {
			return str.replace(/^\s+|\s+$/g,"");
		}

		/**
		 * 공백 문자열 검사
		 * 
		 * @param str / 검사 문자열
		 * @return boolean / 공백 == false, 문자열 == true
		 */
		function isEmpty(str) {
			str = trim(str);
			return isNull(str);
		}

		/**
		 * Value 값 유/무 검사
		 * 
		 * @param str / 검사 문자열
		 * @return boolean / null == false, 문자열 == true
		 */
		function isNull(str) {
			if( str!=null && str.length > 0 )
				return false;
			else
				return true;
		}

		/**
		 * E-mail 검사
		 * 
		 * @param email / E-mail 형식 체크 대상
		 * @return boolean / 사용불가 E-mail == false, 사용가능 E-mail == true
		 */
		function chkEmail(email) {

			if (emailPattern.test(email))
				return true;
			else
				return false;
		}

		/**
		 * Permitted Pattern Check
		 * 
		 * @param pattern
		 * @return
		 */
		function checkPermittedPattern(pattern) {
			var prohibitedRegExp = /[#;\*{}<>&]|\.\//;
		    if ( prohibitedRegExp.test(pattern) ) {
		        return false;
		    }
		    else {
		        return true;
		    }
		}

		/**
		 * OSP 가입 가능 ID 검사
		 * 
		 * @param email / E-mail ID
		 * @return boolean / 사용불가 E-mail == false, 사용가능 E-mail == true
		 */
		function validOspID(emailID) {		
			var validFlag = false;
			
			new Ajax.Request('/join/checkEmail.as?emailID='+emailID,   {     
				method:'get',     
				onSuccess: function(result){      
					if(result.responseText=="@TRUE"){
						validFlag = true;
					}
				},     
				onFailure: function(){
					showOspWarningPopup('System Error', 'Email check fail.');			
				}   
			});
			
			return validFlag;
		}

		/**
		 * Password 패턴 검사.
		 * 
		 * @param password / Password 형식 체크 대상
		 * @return boolean / 사용불가 password == false, 사용가능 password == true
		 */
		function chkPasswordPattern(password) {
			var filter=/^[\w+!+@+$+^]{6,15}$/;

			if (filter.test(password))
				return true;
			else
				return false;	
		}

		/**
		 * 카드의 유효기간을 검사
		 * 
		 * @param cardYear / 카드 유효기간 년
		 * @param cardMonth / 카드 유효기간 월
		 * @return boolean / 유효기간 만료 == false, 유효한 카드 == true
		 */
		function chkCardExpiryDate(cardYear, cardMonth) {
			var now = new Date();
			var nowYear = now.getYear();
			var nowMonth = now.getMonth() + 1;
			var validationFlag = true;
			
			if(nowYear < 1900) nowYear += 1900;
			
			if( cardYear < nowYear ) {
				validationFlag = false;
			}
			else if ( nowYear == cardYear) {
				if(cardMonth < nowMonth )
					validationFlag = false;
			}

			return validationFlag;
		}


		/**
		 * 현재 사용 브라우저가 IE6인지 여부를 반환한다.
		 * 
		 * @return boolean / IE6아님 == false, IE6 == true
		 */
		function isIE6() {
			return (navigator.userAgent.toLowerCase().indexOf('msie 6') != -1 && navigator.userAgent.toLowerCase().indexOf('msie 7') == -1);
		}

		/**
		 * Select box option Element 생성
		 * 
		 * @param objSelect / Select Object
		 * @param text / Option Text
		 * @param value / Option Value
		 */
		function createOption(objSelect, text, value) {
			var objOption = document.createElement("option");
			objSelect.options.add(objOption);
			objOption.innerHTML = text;
			objOption.value = value;
			return objOption;
		}

		/**
		 * 숫자만 입력 가능하도록 Key Down Event를 제한
		 * 첫자리에 "0" 이 올 수 있음
		 */
		function handlerNumeral(e) {

			var keyCode = ( window.event ) ? window.event.keyCode : e.which;
			var shift = ( window.event ) ? window.event.shiftKey  : e.shiftKey;
			
			if( !shift && 
				( ( 48 <= keyCode && keyCode <= 57 ) || ( 96 <= keyCode && keyCode <= 105 ) ||
		          keyCode == 8 || keyCode == 9 || keyCode == 17 || keyCode == 18 || 
		          keyCode == 37 || keyCode == 39 || keyCode == 46 )
			  )
		        return;
		    else {
				if( window.event )
					window.event.returnValue = false;
				else 
				{
					e.preventDefault();
					e.stopPropagation();
				}
			}
		}

		/**
		 * 숫자만 입력 가능하도록 Key Down Event를 제한
		 * 첫자리에 "0" 이 올 수 있음
		 */
		function handlerPhoneNum(e) {

			var keyCode = ( window.event ) ? window.event.keyCode : e.which;
			var shift = ( window.event ) ? window.event.shiftKey  : e.shiftKey;
			if( !shift && 
				( ( 48 <= keyCode && keyCode <= 57 ) || ( 96 <= keyCode && keyCode <= 105 ) ||
		          keyCode == 8 || keyCode == 9 || keyCode == 17 || keyCode == 18 || 
		          keyCode == 37 || keyCode == 39 || keyCode == 46 || keyCode == 189 || keyCode == 109 )
			  )
		        return;
		    else {
				if( window.event )
					window.event.returnValue = false;
				else 
				{
					e.preventDefault();
					e.stopPropagation();
				}
			}
		}


		/**
		*  한글 입력  check 
		*	-한글 입력 방지 : 한글 이 입력되면  false return
		*/
		function checkKorean( obj ) {
			
			var chrTmp;
			var strTmp = obj.value;
			var strLen = strTmp.length;
			var resString = '';

			if ( strLen > 0 ) {
				
				for ( var i = 0 ; i < strTmp.length ; i++ ) {
					
					chrTmp = strTmp.charCodeAt(i);
					
					if ( (chrTmp >= 0x3130 && chrTmp <= 0x318F) || (chrTmp >= 0xAC00 && chrTmp <= 0xD7A3) ) {

							showOspWarningPopup("Validation Check Message", 'Not permitted character');
							obj.focus();
							obj.value="";
							return false;
							
					} // if
					 
				} // for
			}
		}


		String.prototype.trim = function() {
			return this.replace(/^\s+|\s+$/g,"");
		};
		 
		String.prototype.isEmpty = function() {
			//alert(this);
			var str = this.trim();

			if( str!=null && str.length > 0 )
				return false;
			else
				return true;
		};

		String.prototype.chkEmail = function() {
			var filter=/^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/;

			if (filter.test(this))
				return true;
			else
				return false;
		};

/*********************************************************
*  End util.js
*********************************************************/
/*********************************************************
*  Start calendarPopup.js
*********************************************************/

		/* SOURCE FILE: AnchorPosition.js */

		/* 
		AnchorPosition.js
		Author: Matt Kruse
		Last modified: 10/11/02

		DESCRIPTION: These functions find the position of an <A> tag in a document,
		so other elements can be positioned relative to it.

		COMPATABILITY: Netscape 4.x,6.x,Mozilla, IE 5.x,6.x on Windows. Some small
		positioning errors - usually with Window positioning - occur on the 
		Macintosh platform.

		FUNCTIONS:
		getAnchorPosition(anchorname)
		  Returns an Object() having .x and .y properties of the pixel coordinates
		  of the upper-left corner of the anchor. Position is relative to the PAGE.

		getAnchorWindowPosition(anchorname)
		  Returns an Object() having .x and .y properties of the pixel coordinates
		  of the upper-left corner of the anchor, relative to the WHOLE SCREEN.

		NOTES:

		1) For popping up separate browser windows, use getAnchorWindowPosition. 
		   Otherwise, use getAnchorPosition

		2) Your anchor tag MUST contain both NAME and ID attributes which are the 
		   same. For example:
		   <A NAME="test" ID="test"> </A>

		3) There must be at least a space between <A> </A> for IE5.5 to see the 
		   anchor tag correctly. Do not do <A></A> with no space.
		*/ 

		// getAnchorPosition(anchorname)
		//   This function returns an object having .x and .y properties which are the coordinates
		//   of the named anchor, relative to the page.
		function getAnchorPosition(anchorname) {
			// This function will return an Object with x and y properties
			var useWindow=false;
			var coordinates=new Object();
			var x=0,y=0;
			// Browser capability sniffing
			var use_gebi=false, use_css=false, use_layers=false;
			if (document.getElementById) { use_gebi=true; }
			else if (document.all) { use_css=true; }
			else if (document.layers) { use_layers=true; }
			// Logic to find position
		 	if (use_gebi && document.all) {
				x=AnchorPosition_getPageOffsetLeft(document.all[anchorname]);
				y=AnchorPosition_getPageOffsetTop(document.all[anchorname]);
				}
			else if (use_gebi) {
				var o=document.getElementById(anchorname);
				x=AnchorPosition_getPageOffsetLeft(o);
				y=AnchorPosition_getPageOffsetTop(o);
				}
		 	else if (use_css) {
				x=AnchorPosition_getPageOffsetLeft(document.all[anchorname]);
				y=AnchorPosition_getPageOffsetTop(document.all[anchorname]);
				}
			else if (use_layers) {
				var found=0;
				for (var i=0; i<document.anchors.length; i++) {
					if (document.anchors[i].name==anchorname) { found=1; break; }
					}
				if (found==0) {
					coordinates.x=0; coordinates.y=0; return coordinates;
					}
				x=document.anchors[i].x;
				y=document.anchors[i].y;
				}
			else {
				coordinates.x=0; coordinates.y=0; return coordinates;
				}
			coordinates.x=x;
			coordinates.y=y;
			return coordinates;
			}

		// getAnchorWindowPosition(anchorname)
		//   This function returns an object having .x and .y properties which are the coordinates
		//   of the named anchor, relative to the window
		function getAnchorWindowPosition(anchorname) {
			var coordinates=getAnchorPosition(anchorname);
			var x=0;
			var y=0;
			if (document.getElementById) {
				if (isNaN(window.screenX)) {
					x=coordinates.x-document.body.scrollLeft+window.screenLeft;
					y=coordinates.y-document.body.scrollTop+window.screenTop;
					}
				else {
					x=coordinates.x+window.screenX+(window.outerWidth-window.innerWidth)-window.pageXOffset;
					y=coordinates.y+window.screenY+(window.outerHeight-24-window.innerHeight)-window.pageYOffset;
					}
				}
			else if (document.all) {
				x=coordinates.x-document.body.scrollLeft+window.screenLeft;
				y=coordinates.y-document.body.scrollTop+window.screenTop;
				}
			else if (document.layers) {
				x=coordinates.x+window.screenX+(window.outerWidth-window.innerWidth)-window.pageXOffset;
				y=coordinates.y+window.screenY+(window.outerHeight-24-window.innerHeight)-window.pageYOffset;
				}
			coordinates.x=x;
			coordinates.y=y;
			return coordinates;
			}

		// Functions for IE to get position of an object
		function AnchorPosition_getPageOffsetLeft (el) {
			var ol=el.offsetLeft;
			while ((el=el.offsetParent) != null) { ol += el.offsetLeft; }
			return ol;
			}
		function AnchorPosition_getWindowOffsetLeft (el) {
			return AnchorPosition_getPageOffsetLeft(el)-document.body.scrollLeft;
			}	
		function AnchorPosition_getPageOffsetTop (el) {
			var ot=el.offsetTop;
			while((el=el.offsetParent) != null) { ot += el.offsetTop; }
			return ot;
			}
		function AnchorPosition_getWindowOffsetTop (el) {
			return AnchorPosition_getPageOffsetTop(el)-document.body.scrollTop;
			}

		/* SOURCE FILE: date.js */

		// HISTORY
		// ------------------------------------------------------------------
		// May 17, 2003: Fixed bug in parseDate() for dates <1970
		// March 11, 2003: Added parseDate() function
		// March 11, 2003: Added "NNN" formatting option. Doesn't match up
//		                 perfectly with SimpleDateFormat formats, but 
//		                 backwards-compatability was required.

		// ------------------------------------------------------------------
		// These functions use the same 'format' strings as the 
		// java.text.SimpleDateFormat class, with minor exceptions.
		// The format string consists of the following abbreviations:
		// 
		// Field        | Full Form          | Short Form
		// -------------+--------------------+-----------------------
		// Year         | yyyy (4 digits)    | yy (2 digits), y (2 or 4 digits)
		// Month        | MMM (name or abbr.)| MM (2 digits), M (1 or 2 digits)
//		              | NNN (abbr.)        |
		// Day of Month | dd (2 digits)      | d (1 or 2 digits)
		// Day of Week  | EE (name)          | E (abbr)
		// Hour (1-12)  | hh (2 digits)      | h (1 or 2 digits)
		// Hour (0-23)  | HH (2 digits)      | H (1 or 2 digits)
		// Hour (0-11)  | KK (2 digits)      | K (1 or 2 digits)
		// Hour (1-24)  | kk (2 digits)      | k (1 or 2 digits)
		// Minute       | mm (2 digits)      | m (1 or 2 digits)
		// Second       | ss (2 digits)      | s (1 or 2 digits)
		// AM/PM        | a                  |
		//
		// NOTE THE DIFFERENCE BETWEEN MM and mm! Month=MM, not mm!
		// Examples:
		//  "MMM d, y" matches: January 01, 2000
//		                      Dec 1, 1900
//		                      Nov 20, 00
		//  "M/d/yy"   matches: 01/20/00
//		                      9/2/00
		//  "MMM dd, yyyy hh:mm:ssa" matches: "January 01, 2000 12:30:45AM"
		// ------------------------------------------------------------------

		var MONTH_NAMES=new Array('January','February','March','April','May','June','July','August','September','October','November','December','Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
		var DAY_NAMES=new Array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sun','Mon','Tue','Wed','Thu','Fri','Sat');
		function LZ(x) {return(x<0||x>9?"":"0")+x}

		// ------------------------------------------------------------------
		// isDate ( date_string, format_string )
		// Returns true if date string matches format of format string and
		// is a valid date. Else returns false.
		// It is recommended that you trim whitespace around the value before
		// passing it to this function, as whitespace is NOT ignored!
		// ------------------------------------------------------------------
		function isDate(val,format) {
			var date=getDateFromFormat(val,format);
			if (date==0) { return false; }
			return true;
			}

		// -------------------------------------------------------------------
		// compareDates(date1,date1format,date2,date2format)
		//   Compare two date strings to see which is greater.
		//   Returns:
		//   1 if date1 is greater than date2
		//   0 if date2 is greater than date1 of if they are the same
		//  -1 if either of the dates is in an invalid format
		// -------------------------------------------------------------------
		function compareDates(date1,dateformat1,date2,dateformat2) {
			var d1=getDateFromFormat(date1,dateformat1);
			var d2=getDateFromFormat(date2,dateformat2);
			if (d1==0 || d2==0) {
				return -1;
				}
			else if (d1 > d2) {
				return 1;
				}
			return 0;
			}

		// ------------------------------------------------------------------
		// formatDate (date_object, format)
		// Returns a date in the output format specified.
		// The format string uses the same abbreviations as in getDateFromFormat()
		// ------------------------------------------------------------------
		function formatDate(date,format) {
			format=format+"";
			var result="";
			var i_format=0;
			var c="";
			var token="";
			var y=date.getYear()+"";
			var M=date.getMonth()+1;
			var d=date.getDate();
			var E=date.getDay();
			var H=date.getHours();
			var m=date.getMinutes();
			var s=date.getSeconds();
			var yyyy,yy,MMM,MM,dd,hh,h,mm,ss,ampm,HH,H,KK,K,kk,k;
			// Convert real date parts into formatted versions
			var value=new Object();
			if (y.length < 4) {y=""+(y-0+1900);}
			value["y"]=""+y;
			value["yyyy"]=y;
			value["yy"]=y.substring(2,4);
			value["M"]=M;
			value["MM"]=LZ(M);
			value["MMM"]=MONTH_NAMES[M-1];
			value["NNN"]=MONTH_NAMES[M+11];
			value["d"]=d;
			value["dd"]=LZ(d);
			value["E"]=DAY_NAMES[E+7];
			value["EE"]=DAY_NAMES[E];
			value["H"]=H;
			value["HH"]=LZ(H);
			if (H==0){value["h"]=12;}
			else if (H>12){value["h"]=H-12;}
			else {value["h"]=H;}
			value["hh"]=LZ(value["h"]);
			if (H>11){value["K"]=H-12;} else {value["K"]=H;}
			value["k"]=H+1;
			value["KK"]=LZ(value["K"]);
			value["kk"]=LZ(value["k"]);
			if (H > 11) { value["a"]="PM"; }
			else { value["a"]="AM"; }
			value["m"]=m;
			value["mm"]=LZ(m);
			value["s"]=s;
			value["ss"]=LZ(s);
			while (i_format < format.length) {
				c=format.charAt(i_format);
				token="";
				while ((format.charAt(i_format)==c) && (i_format < format.length)) {
					token += format.charAt(i_format++);
					}
				if (value[token] != null) { result=result + value[token]; }
				else { result=result + token; }
				}
			return result;
			}
			
		// ------------------------------------------------------------------
		// Utility functions for parsing in getDateFromFormat()
		// ------------------------------------------------------------------
		function _isInteger(val) {
			var digits="1234567890";
			for (var i=0; i < val.length; i++) {
				if (digits.indexOf(val.charAt(i))==-1) { return false; }
				}
			return true;
			}
		function _getInt(str,i,minlength,maxlength) {
			for (var x=maxlength; x>=minlength; x--) {
				var token=str.substring(i,i+x);
				if (token.length < minlength) { return null; }
				if (_isInteger(token)) { return token; }
				}
			return null;
			}
			
		// ------------------------------------------------------------------
		// getDateFromFormat( date_string , format_string )
		//
		// This function takes a date string and a format string. It matches
		// If the date string matches the format string, it returns the 
		// getTime() of the date. If it does not match, it returns 0.
		// ------------------------------------------------------------------
		function getDateFromFormat(val,format) {
			val=val+"";
			format=format+"";
			var i_val=0;
			var i_format=0;
			var c="";
			var token="";
			var token2="";
			var x,y;
			var now=new Date();
			var year=now.getYear();
			var month=now.getMonth()+1;
			var date=1;
			var hh=now.getHours();
			var mm=now.getMinutes();
			var ss=now.getSeconds();
			var ampm="";
			
			while (i_format < format.length) {
				// Get next token from format string
				c=format.charAt(i_format);
				token="";
				while ((format.charAt(i_format)==c) && (i_format < format.length)) {
					token += format.charAt(i_format++);
					}
				// Extract contents of value based on format token
				if (token=="yyyy" || token=="yy" || token=="y") {
					if (token=="yyyy") { x=4;y=4; }
					if (token=="yy")   { x=2;y=2; }
					if (token=="y")    { x=2;y=4; }
					year=_getInt(val,i_val,x,y);
					if (year==null) { return 0; }
					i_val += year.length;
					if (year.length==2) {
						if (year > 70) { year=1900+(year-0); }
						else { year=2000+(year-0); }
						}
					}
				else if (token=="MMM"||token=="NNN"){
					month=0;
					for (var i=0; i<MONTH_NAMES.length; i++) {
						var month_name=MONTH_NAMES[i];
						if (val.substring(i_val,i_val+month_name.length).toLowerCase()==month_name.toLowerCase()) {
							if (token=="MMM"||(token=="NNN"&&i>11)) {
								month=i+1;
								if (month>12) { month -= 12; }
								i_val += month_name.length;
								break;
								}
							}
						}
					if ((month < 1)||(month>12)){return 0;}
					}
				else if (token=="EE"||token=="E"){
					for (var i=0; i<DAY_NAMES.length; i++) {
						var day_name=DAY_NAMES[i];
						if (val.substring(i_val,i_val+day_name.length).toLowerCase()==day_name.toLowerCase()) {
							i_val += day_name.length;
							break;
							}
						}
					}
				else if (token=="MM"||token=="M") {
					month=_getInt(val,i_val,token.length,2);
					if(month==null||(month<1)||(month>12)){return 0;}
					i_val+=month.length;}
				else if (token=="dd"||token=="d") {
					date=_getInt(val,i_val,token.length,2);
					if(date==null||(date<1)||(date>31)){return 0;}
					i_val+=date.length;}
				else if (token=="hh"||token=="h") {
					hh=_getInt(val,i_val,token.length,2);
					if(hh==null||(hh<1)||(hh>12)){return 0;}
					i_val+=hh.length;}
				else if (token=="HH"||token=="H") {
					hh=_getInt(val,i_val,token.length,2);
					if(hh==null||(hh<0)||(hh>23)){return 0;}
					i_val+=hh.length;}
				else if (token=="KK"||token=="K") {
					hh=_getInt(val,i_val,token.length,2);
					if(hh==null||(hh<0)||(hh>11)){return 0;}
					i_val+=hh.length;}
				else if (token=="kk"||token=="k") {
					hh=_getInt(val,i_val,token.length,2);
					if(hh==null||(hh<1)||(hh>24)){return 0;}
					i_val+=hh.length;hh--;}
				else if (token=="mm"||token=="m") {
					mm=_getInt(val,i_val,token.length,2);
					if(mm==null||(mm<0)||(mm>59)){return 0;}
					i_val+=mm.length;}
				else if (token=="ss"||token=="s") {
					ss=_getInt(val,i_val,token.length,2);
					if(ss==null||(ss<0)||(ss>59)){return 0;}
					i_val+=ss.length;}
				else if (token=="a") {
					if (val.substring(i_val,i_val+2).toLowerCase()=="am") {ampm="AM";}
					else if (val.substring(i_val,i_val+2).toLowerCase()=="pm") {ampm="PM";}
					else {return 0;}
					i_val+=2;}
				else {
					if (val.substring(i_val,i_val+token.length)!=token) {return 0;}
					else {i_val+=token.length;}
					}
				}
			// If there are any trailing characters left in the value, it doesn't match
			if (i_val != val.length) { return 0; }
			// Is date valid for month?
			if (month==2) {
				// Check for leap year
				if ( ( (year%4==0)&&(year%100 != 0) ) || (year%400==0) ) { // leap year
					if (date > 29){ return 0; }
					}
				else { if (date > 28) { return 0; } }
				}
			if ((month==4)||(month==6)||(month==9)||(month==11)) {
				if (date > 30) { return 0; }
				}
			// Correct hours value
			if (hh<12 && ampm=="PM") { hh=hh-0+12; }
			else if (hh>11 && ampm=="AM") { hh-=12; }
			var newdate=new Date(year,month-1,date,hh,mm,ss);
			return newdate.getTime();
			}

		// ------------------------------------------------------------------
		// parseDate( date_string [, prefer_euro_format] )
		//
		// This function takes a date string and tries to match it to a
		// number of possible date formats to get the value. It will try to
		// match against the following international formats, in this order:
		// y-M-d   MMM d, y   MMM d,y   y-MMM-d   d-MMM-y  MMM d
		// M/d/y   M-d-y      M.d.y     MMM-d     M/d      M-d
		// d/M/y   d-M-y      d.M.y     d-MMM     d/M      d-M
		// A second argument may be passed to instruct the method to search
		// for formats like d/M/y (european format) before M/d/y (American).
		// Returns a Date object or null if no patterns match.
		// ------------------------------------------------------------------
		function parseDate(val) {
			var preferEuro=(arguments.length==2)?arguments[1]:false;
			generalFormats=new Array('y-M-d','MMM d, y','MMM d,y','y-MMM-d','d-MMM-y','MMM d');
			monthFirst=new Array('M/d/y','M-d-y','M.d.y','MMM-d','M/d','M-d');
			dateFirst =new Array('d/M/y','d-M-y','d.M.y','d-MMM','d/M','d-M');
			var checkList=new Array('generalFormats',preferEuro?'dateFirst':'monthFirst',preferEuro?'monthFirst':'dateFirst');
			var d=null;
			for (var i=0; i<checkList.length; i++) {
				var l=window[checkList[i]];
				for (var j=0; j<l.length; j++) {
					d=getDateFromFormat(val,l[j]);
					if (d!=0) { return new Date(d); }
					}
				}
			return null;
			}

		/* SOURCE FILE: PopupWindow.js */

		/* 
		PopupWindow.js
		Author: Matt Kruse
		Last modified: 02/16/04

		DESCRIPTION: This object allows you to easily and quickly popup a window
		in a certain place. The window can either be a DIV or a separate browser
		window.

		COMPATABILITY: Works with Netscape 4.x, 6.x, IE 5.x on Windows. Some small
		positioning errors - usually with Window positioning - occur on the 
		Macintosh platform. Due to bugs in Netscape 4.x, populating the popup 
		window with <STYLE> tags may cause errors.

		USAGE:
		// Create an object for a WINDOW popup
		var win = new PopupWindow(); 

		// Create an object for a DIV window using the DIV named 'mydiv'
		var win = new PopupWindow('mydiv'); 

		// Set the window to automatically hide itself when the user clicks 
		// anywhere else on the page except the popup
		win.autoHide(); 

		// Show the window relative to the anchor name passed in
		win.showPopup(anchorname);

		// Hide the popup
		win.hidePopup();

		// Set the size of the popup window (only applies to WINDOW popups
		win.setSize(width,height);

		// Populate the contents of the popup window that will be shown. If you 
		// change the contents while it is displayed, you will need to refresh()
		win.populate(string);

		// set the URL of the window, rather than populating its contents
		// manually
		win.setUrl("http://www.site.com/");

		// Refresh the contents of the popup
		win.refresh();

		// Specify how many pixels to the right of the anchor the popup will appear
		win.offsetX = 50;

		// Specify how many pixels below the anchor the popup will appear
		win.offsetY = 100;

		NOTES:
		1) Requires the functions in AnchorPosition.js

		2) Your anchor tag MUST contain both NAME and ID attributes which are the 
		   same. For example:
		   <A NAME="test" ID="test"> </A>

		3) There must be at least a space between <A> </A> for IE5.5 to see the 
		   anchor tag correctly. Do not do <A></A> with no space.

		4) When a PopupWindow object is created, a handler for 'onmouseup' is
		   attached to any event handler you may have already defined. Do NOT define
		   an event handler for 'onmouseup' after you define a PopupWindow object or
		   the autoHide() will not work correctly.
		*/ 

		// Set the position of the popup window based on the anchor
		function PopupWindow_getXYPosition(anchorname) {
			var coordinates;
			if (this.type == "WINDOW") {
				coordinates = getAnchorWindowPosition(anchorname);
				}
			else {
				coordinates = getAnchorPosition(anchorname);
				}
			this.x = coordinates.x;
			this.y = coordinates.y;
			}
		// Set width/height of DIV/popup window
		function PopupWindow_setSize(width,height) {
			this.width = width;
			this.height = height;
			}
		// Fill the window with contents
		function PopupWindow_populate(contents) {
			this.contents = contents;
			this.populated = false;
			}
		// Set the URL to go to
		function PopupWindow_setUrl(url) {
			this.url = url;
			}
		// Set the window popup properties
		function PopupWindow_setWindowProperties(props) {
			this.windowProperties = props;
			}
		// Refresh the displayed contents of the popup
		function PopupWindow_refresh() {
			if (this.divName != null) {
				// refresh the DIV object
				if (this.use_gebi) {
					document.getElementById(this.divName).innerHTML = this.contents;
					}
				else if (this.use_css) { 
					document.all[this.divName].innerHTML = this.contents;
					}
				else if (this.use_layers) { 
					var d = document.layers[this.divName]; 
					d.document.open();
					d.document.writeln(this.contents);
					d.document.close();
					}
				}
			else {
				if (this.popupWindow != null && !this.popupWindow.closed) {
					if (this.url!="") {
						this.popupWindow.location.href=this.url;
						}
					else {
						this.popupWindow.document.open();
						this.popupWindow.document.writeln(this.contents);
						this.popupWindow.document.close();
					}
					this.popupWindow.focus();
					}
				}
			}
		// Position and show the popup, relative to an anchor object
		function PopupWindow_showPopup(anchorname) {
			this.getXYPosition(anchorname);
			this.x += this.offsetX;
			this.y += this.offsetY;
			
//			alert("this.x : "+this.x);
//			alert("this.y : "+this.y);
			
//			this.x = this.x - 200;
//			this.y = this.y - 180;
			
//			alert("treat this.x : "+this.x);
//			alert("treat this.y : "+this.y);
			
			
			
			if (!this.populated && (this.contents != "")) {
				this.populated = true;
				this.refresh();
				}
			if (this.divName != null) {
				// Show the DIV object
				if (this.use_gebi) {
					document.getElementById(this.divName).style.left = this.x + "px";
					document.getElementById(this.divName).style.top = this.y + "px";
					document.getElementById(this.divName).style.visibility = "visible";
					}
				else if (this.use_css) {
					document.all[this.divName].style.left = this.x;
					document.all[this.divName].style.top = this.y;
					document.all[this.divName].style.visibility = "visible";
					}
				else if (this.use_layers) {
					document.layers[this.divName].left = this.x;
					document.layers[this.divName].top = this.y;
					document.layers[this.divName].visibility = "visible";
					}
				}
			else {
				if (this.popupWindow == null || this.popupWindow.closed) {
					// If the popup window will go off-screen, move it so it doesn't
					if (this.x<0) { this.x=0; }
					if (this.y<0) { this.y=0; }
					if (screen && screen.availHeight) {
						if ((this.y + this.height) > screen.availHeight) {
							this.y = screen.availHeight - this.height;
							}
						}
					if (screen && screen.availWidth) {
						if ((this.x + this.width) > screen.availWidth) {
							this.x = screen.availWidth - this.width;
							}
						}
					var avoidAboutBlank = window.opera || ( document.layers && !navigator.mimeTypes['*'] ) || navigator.vendor == 'KDE' || ( document.childNodes && !document.all && !navigator.taintEnabled );
					this.popupWindow = window.open(avoidAboutBlank?"":"about:blank","window_"+anchorname,this.windowProperties+",width="+this.width+",height="+this.height+",screenX="+this.x+",left="+this.x+",screenY="+this.y+",top="+this.y+"");
					}
				this.refresh();
				}
			}
		// Hide the popup
		function PopupWindow_hidePopup() {
			if (this.divName != null) {
				if (this.use_gebi) {
					document.getElementById(this.divName).style.visibility = "hidden";
					}
				else if (this.use_css) {
					document.all[this.divName].style.visibility = "hidden";
					}
				else if (this.use_layers) {
					document.layers[this.divName].visibility = "hidden";
					}
				}
			else {
				if (this.popupWindow && !this.popupWindow.closed) {
					this.popupWindow.close();
					this.popupWindow = null;
					}
				}
			}
		// Pass an event and return whether or not it was the popup DIV that was clicked
		function PopupWindow_isClicked(e) {
			if (this.divName != null) {
				if (this.use_layers) {
					var clickX = e.pageX;
					var clickY = e.pageY;
					var t = document.layers[this.divName];
					if ((clickX > t.left) && (clickX < t.left+t.clip.width) && (clickY > t.top) && (clickY < t.top+t.clip.height)) {
						return true;
						}
					else { return false; }
					}
				else if (document.all) { // Need to hard-code this to trap IE for error-handling
					var t = window.event.srcElement;
					while (t.parentElement != null) {
						if (t.id==this.divName) {
							return true;
							}
						t = t.parentElement;
						}
					return false;
					}
				else if (this.use_gebi && e) {
					var t = e.target;
					
					try{
						while (t.parentNode != null) {
							if (t.id==this.divName) {
								return true;
								}
							t = t.parentNode;
							}
					}catch(exception){
						//alert('Exception caught:\n' + exception);
					}
					return false;
					}
				return false;
				}
			return false;
			}

		// Check an onMouseDown event to see if we should hide
		function PopupWindow_hideIfNotClicked(e) {
			if (this.autoHideEnabled && !this.isClicked(e)) {
				this.hidePopup();
				}
			}
		// Call this to make the DIV disable automatically when mouse is clicked outside it
		function PopupWindow_autoHide() {
			this.autoHideEnabled = true;
			}
		// This global function checks all PopupWindow objects onmouseup to see if they should be hidden
		function PopupWindow_hidePopupWindows(e) {
			for (var i=0; i<popupWindowObjects.length; i++) {
				if (popupWindowObjects[i] != null) {
					var p = popupWindowObjects[i];
					p.hideIfNotClicked(e);
					}
				}
			}
		// Run this immediately to attach the event listener
		function PopupWindow_attachListener() {
			if (document.layers) {
				document.captureEvents(Event.MOUSEUP);
				}
			window.popupWindowOldEventListener = document.onmouseup;
			if (window.popupWindowOldEventListener != null) {
				document.onmouseup = new Function("window.popupWindowOldEventListener(); PopupWindow_hidePopupWindows();");
				}
			else {
				document.onmouseup = PopupWindow_hidePopupWindows;
				}
			}
		// CONSTRUCTOR for the PopupWindow object
		// Pass it a DIV name to use a DHTML popup, otherwise will default to window popup
		function PopupWindow() {
			if (!window.popupWindowIndex) { window.popupWindowIndex = 0; }
			if (!window.popupWindowObjects) { window.popupWindowObjects = new Array(); }
			if (!window.listenerAttached) {
				window.listenerAttached = true;
				PopupWindow_attachListener();
				}
			this.index = popupWindowIndex++;
			popupWindowObjects[this.index] = this;
			this.divName = null;
			this.popupWindow = null;
			this.width=0;
			this.height=0;
			this.populated = false;
			this.visible = false;
			this.autoHideEnabled = false;
			
			this.contents = "";
			this.url="";
			this.windowProperties="toolbar=no,location=no,status=no,menubar=no,scrollbars=auto,resizable,alwaysRaised,dependent,titlebar=no";
			if (arguments.length>0) {
				this.type="DIV";
				this.divName = arguments[0];
				}
			else {
				this.type="WINDOW";
				}
			this.use_gebi = false;
			this.use_css = false;
			this.use_layers = false;
			if (document.getElementById) { this.use_gebi = true; }
			else if (document.all) { this.use_css = true; }
			else if (document.layers) { this.use_layers = true; }
			else { this.type = "WINDOW"; }
			this.offsetX = 0;
			this.offsetY = 0;
			// Method mappings
			this.getXYPosition = PopupWindow_getXYPosition;
			this.populate = PopupWindow_populate;
			this.setUrl = PopupWindow_setUrl;
			this.setWindowProperties = PopupWindow_setWindowProperties;
			this.refresh = PopupWindow_refresh;
			this.showPopup = PopupWindow_showPopup;
			this.hidePopup = PopupWindow_hidePopup;
			this.setSize = PopupWindow_setSize;
			this.isClicked = PopupWindow_isClicked;
			this.autoHide = PopupWindow_autoHide;
			this.hideIfNotClicked = PopupWindow_hideIfNotClicked;
			}

		/* SOURCE FILE: CalendarPopup.js */

		// HISTORY
		// ------------------------------------------------------------------
		// Feb 7, 2005: Fixed a CSS styles to use px unit
		// March 29, 2004: Added check in select() method for the form field
//		      being disabled. If it is, just return and don't do anything.
		// March 24, 2004: Fixed bug - when month name and abbreviations were
//		      changed, date format still used original values.
		// January 26, 2004: Added support for drop-down month and year
//		      navigation (Thanks to Chris Reid for the idea)
		// September 22, 2003: Fixed a minor problem in YEAR calendar with
//		      CSS prefix.
		// August 19, 2003: Renamed the function to get styles, and made it
//		      work correctly without an object reference
		// August 18, 2003: Changed showYearNavigation and 
//		      showYearNavigationInput to optionally take an argument of
//		      true or false
		// July 31, 2003: Added text input option for year navigation.
//		      Added a per-calendar CSS prefix option to optionally use 
//		      different styles for different calendars.
		// July 29, 2003: Fixed bug causing the Today link to be clickable 
//		      even though today falls in a disabled date range.
//		      Changed formatting to use pure CSS, allowing greater control
//		      over look-and-feel options.
		// June 11, 2003: Fixed bug causing the Today link to be unselectable
//		      under certain cases when some days of week are disabled
		// March 14, 2003: Added ability to disable individual dates or date
//		      ranges, display as light gray and strike-through
		// March 14, 2003: Removed dependency on graypixel.gif and instead 
		///     use table border coloring
		// March 12, 2003: Modified showCalendar() function to allow optional
//		      start-date parameter
		// March 11, 2003: Modified select() function to allow optional
//		      start-date parameter
		/* 
		DESCRIPTION: This object implements a popup calendar to allow the user to
		select a date, month, quarter, or year.

		COMPATABILITY: Works with Netscape 4.x, 6.x, IE 5.x on Windows. Some small
		positioning errors - usually with Window positioning - occur on the 
		Macintosh platform.
		The calendar can be modified to work for any location in the world by 
		changing which weekday is displayed as the first column, changing the month
		names, and changing the column headers for each day.

		USAGE:
		// Create a new CalendarPopup object of type WINDOW
		var cal = new CalendarPopup(); 

		// Create a new CalendarPopup object of type DIV using the DIV named 'mydiv'
		var cal = new CalendarPopup('mydiv'); 

		// Easy method to link the popup calendar with an input box. 
		cal.select(inputObject, anchorname, dateFormat);
		// Same method, but passing a default date other than the field's current value
		cal.select(inputObject, anchorname, dateFormat, '01/02/2000');
		// This is an example call to the popup calendar from a link to populate an 
		// input box. Note that to use this, date.js must also be included!!
		<A HREF="#" onClick="cal.select(document.forms[0].date,'anchorname','MM/dd/yyyy'); return false;">Select</A>

		// Set the type of date select to be used. By default it is 'date'.
		cal.setDisplayType(type);

		// When a date, month, quarter, or year is clicked, a function is called and
		// passed the details. You must write this function, and tell the calendar
		// popup what the function name is.
		// Function to be called for 'date' select receives y, m, d
		cal.setReturnFunction(functionname);
		// Function to be called for 'month' select receives y, m
		cal.setReturnMonthFunction(functionname);
		// Function to be called for 'quarter' select receives y, q
		cal.setReturnQuarterFunction(functionname);
		// Function to be called for 'year' select receives y
		cal.setReturnYearFunction(functionname);

		// Show the calendar relative to a given anchor
		cal.showCalendar(anchorname);

		// Hide the calendar. The calendar is set to autoHide automatically
		cal.hideCalendar();

		// Set the month names to be used. Default are English month names
		cal.setMonthNames("January","February","March",...);

		// Set the month abbreviations to be used. Default are English month abbreviations
		cal.setMonthAbbreviations("Jan","Feb","Mar",...);

		// Show navigation for changing by the year, not just one month at a time
		cal.showYearNavigation();

		// Show month and year dropdowns, for quicker selection of month of dates
		cal.showNavigationDropdowns();

		// Set the text to be used above each day column. The days start with 
		// sunday regardless of the value of WeekStartDay
		cal.setDayHeaders("S","M","T",...);

		// Set the day for the first column in the calendar grid. By default this
		// is Sunday (0) but it may be changed to fit the conventions of other
		// countries.
		cal.setWeekStartDay(1); // week is Monday - Sunday

		// Set the weekdays which should be disabled in the 'date' select popup. You can
		// then allow someone to only select week end dates, or Tuedays, for example
		cal.setDisabledWeekDays(0,1); // To disable selecting the 1st or 2nd days of the week

		// Selectively disable individual days or date ranges. Disabled days will not
		// be clickable, and show as strike-through text on current browsers.
		// Date format is any format recognized by parseDate() in date.js
		// Pass a single date to disable:
		cal.addDisabledDates("2003-01-01");
		// Pass null as the first parameter to mean "anything up to and including" the
		// passed date:
		cal.addDisabledDates(null, "01/02/03");
		// Pass null as the second parameter to mean "including the passed date and
		// anything after it:
		cal.addDisabledDates("Jan 01, 2003", null);
		// Pass two dates to disable all dates inbetween and including the two
		cal.addDisabledDates("January 01, 2003", "Dec 31, 2003");

		// When the 'year' select is displayed, set the number of years back from the 
		// current year to start listing years. Default is 2.
		// This is also used for year drop-down, to decide how many years +/- to display
		cal.setYearSelectStartOffset(2);

		// Text for the word "Today" appearing on the calendar
		cal.setTodayText("Today");

		// The calendar uses CSS classes for formatting. If you want your calendar to
		// have unique styles, you can set the prefix that will be added to all the
		// classes in the output.
		// For example, normal output may have this:
//		     <SPAN CLASS="cpTodayTextDisabled">Today<SPAN>
		// But if you set the prefix like this:
		cal.setCssPrefix("Test");
		// The output will then look like:
//		     <SPAN CLASS="TestcpTodayTextDisabled">Today<SPAN>
		// And you can define that style somewhere in your page.

		// When using Year navigation, you can make the year be an input box, so
		// the user can manually change it and jump to any year
		cal.showYearNavigationInput();

		// Set the calendar offset to be different than the default. By default it
		// will appear just below and to the right of the anchorname. So if you have
		// a text box where the date will go and and anchor immediately after the
		// text box, the calendar will display immediately under the text box.
		cal.offsetX = 20;
		cal.offsetY = 20;

		NOTES:
		1) Requires the functions in AnchorPosition.js and PopupWindow.js

		2) Your anchor tag MUST contain both NAME and ID attributes which are the 
		   same. For example:
		   <A NAME="test" ID="test"> </A>

		3) There must be at least a space between <A> </A> for IE5.5 to see the 
		   anchor tag correctly. Do not do <A></A> with no space.

		4) When a CalendarPopup object is created, a handler for 'onmouseup' is
		   attached to any event handler you may have already defined. Do NOT define
		   an event handler for 'onmouseup' after you define a CalendarPopup object 
		   or the autoHide() will not work correctly.
		   
		5) The calendar popup display uses style sheets to make it look nice.

		*/ 

		// Quick fix for FF3
		function CP_stop(e) { if (e && e.stopPropagation) { e.stopPropagation(); } }

		// CONSTRUCTOR for the CalendarPopup Object
		function CalendarPopup() {
			var c;
			if (arguments.length>0) {
				c = new PopupWindow(arguments[0]);
				}
			else {
				c = new PopupWindow();
				c.setSize(150,175);
				}
			c.offsetX = -152;
			c.offsetY = 25;
			c.autoHide();
			// Calendar-specific properties
			c.monthNames = new Array("January","February","March","April","May","June","July","August","September","October","November","December");
			c.monthAbbreviations = new Array("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec");
			c.dayHeaders = new Array("Sun","Mon","Tue","Wed","Thu","Fri","Sat");
			c.returnFunction = "CP_tmpReturnFunction";
			c.returnMonthFunction = "CP_tmpReturnMonthFunction";
			c.returnQuarterFunction = "CP_tmpReturnQuarterFunction";
			c.returnYearFunction = "CP_tmpReturnYearFunction";
			c.weekStartDay = 0;
			c.isShowYearNavigation = false;
			c.displayType = "date";
			c.disabledWeekDays = new Object();
			c.disabledDatesExpression = "";
			c.yearSelectStartOffset = 2;
			c.currentDate = null;
			c.todayText="Today";
			c.cssPrefix="";
			c.isShowNavigationDropdowns=false;
			c.isShowYearNavigationInput=false;
			window.CP_calendarObject = null;
			window.CP_targetInput = null;
			window.CP_dateFormat = "MM/dd/yyyy";
			// Method mappings
			c.copyMonthNamesToWindow = CP_copyMonthNamesToWindow;
			c.setReturnFunction = CP_setReturnFunction;
			c.setReturnMonthFunction = CP_setReturnMonthFunction;
			c.setReturnQuarterFunction = CP_setReturnQuarterFunction;
			c.setReturnYearFunction = CP_setReturnYearFunction;
			c.setMonthNames = CP_setMonthNames;
			c.setMonthAbbreviations = CP_setMonthAbbreviations;
			c.setDayHeaders = CP_setDayHeaders;
			c.setWeekStartDay = CP_setWeekStartDay;
			c.setDisplayType = CP_setDisplayType;
			c.setDisabledWeekDays = CP_setDisabledWeekDays;
			c.addDisabledDates = CP_addDisabledDates;
			c.setYearSelectStartOffset = CP_setYearSelectStartOffset;
			c.setTodayText = CP_setTodayText;
			c.showYearNavigation = CP_showYearNavigation;
			c.showCalendar = CP_showCalendar;
			c.hideCalendar = CP_hideCalendar;
			c.getStyles = getCalendarStyles;
			c.refreshCalendar = CP_refreshCalendar;
			c.getCalendar = CP_getCalendar;
			c.select = CP_select;
			c.setCssPrefix = CP_setCssPrefix;
			c.showNavigationDropdowns = CP_showNavigationDropdowns;
			c.showYearNavigationInput = CP_showYearNavigationInput;
			c.copyMonthNamesToWindow();
			// Return the object
			return c;
			}
		function CP_copyMonthNamesToWindow() {
			// Copy these values over to the date.js 
			if (typeof(window.MONTH_NAMES)!="undefined" && window.MONTH_NAMES!=null) {
				window.MONTH_NAMES = new Array();
				for (var i=0; i<this.monthNames.length; i++) {
					window.MONTH_NAMES[window.MONTH_NAMES.length] = this.monthNames[i];
				}
				for (var i=0; i<this.monthAbbreviations.length; i++) {
					window.MONTH_NAMES[window.MONTH_NAMES.length] = this.monthAbbreviations[i];
				}
			}
		}
		// Temporary default functions to be called when items clicked, so no error is thrown
		function CP_tmpReturnFunction(y,m,d) {
			if (window.CP_targetInput!=null) {
				var dt = new Date(y,m-1,d,0,0,0);
				if (window.CP_calendarObject!=null) { window.CP_calendarObject.copyMonthNamesToWindow(); }
				window.CP_targetInput.value = formatDate(dt,window.CP_dateFormat);
				}
			else {
				alert('Use setReturnFunction() to define which function will get the clicked results!'); 
				}
			}
		function CP_tmpReturnMonthFunction(y,m) { 
			alert('Use setReturnMonthFunction() to define which function will get the clicked results!\nYou clicked: year='+y+' , month='+m); 
			}
		function CP_tmpReturnQuarterFunction(y,q) { 
			alert('Use setReturnQuarterFunction() to define which function will get the clicked results!\nYou clicked: year='+y+' , quarter='+q); 
			}
		function CP_tmpReturnYearFunction(y) { 
			alert('Use setReturnYearFunction() to define which function will get the clicked results!\nYou clicked: year='+y); 
			}

		// Set the name of the functions to call to get the clicked item
		function CP_setReturnFunction(name) { this.returnFunction = name; }
		function CP_setReturnMonthFunction(name) { this.returnMonthFunction = name; }
		function CP_setReturnQuarterFunction(name) { this.returnQuarterFunction = name; }
		function CP_setReturnYearFunction(name) { this.returnYearFunction = name; }

		// Over-ride the built-in month names
		function CP_setMonthNames() {
			for (var i=0; i<arguments.length; i++) { this.monthNames[i] = arguments[i]; }
			this.copyMonthNamesToWindow();
			}

		// Over-ride the built-in month abbreviations
		function CP_setMonthAbbreviations() {
			for (var i=0; i<arguments.length; i++) { this.monthAbbreviations[i] = arguments[i]; }
			this.copyMonthNamesToWindow();
			}

		// Over-ride the built-in column headers for each day
		function CP_setDayHeaders() {
			for (var i=0; i<arguments.length; i++) { this.dayHeaders[i] = arguments[i]; }
			}

		// Set the day of the week (0-7) that the calendar display starts on
		// This is for countries other than the US whose calendar displays start on Monday(1), for example
		function CP_setWeekStartDay(day) { this.weekStartDay = day; }

		// Show next/last year navigation links
		function CP_showYearNavigation() { this.isShowYearNavigation = (arguments.length>0)?arguments[0]:true; }

		// Which type of calendar to display
		function CP_setDisplayType(type) {
			if (type!="date"&&type!="week-end"&&type!="month"&&type!="quarter"&&type!="year") { alert("Invalid display type! Must be one of: date,week-end,month,quarter,year"); return false; }
			this.displayType=type;
			}

		// How many years back to start by default for year display
		function CP_setYearSelectStartOffset(num) { this.yearSelectStartOffset=num; }

		// Set which weekdays should not be clickable
		function CP_setDisabledWeekDays() {
			this.disabledWeekDays = new Object();
			for (var i=0; i<arguments.length; i++) { this.disabledWeekDays[arguments[i]] = true; }
			}
			
		// Disable individual dates or ranges
		// Builds an internal logical test which is run via eval() for efficiency
		function CP_addDisabledDates(start, end) {
			if (arguments.length==1) { end=start; }
			if (start==null && end==null) { return; }
			if (this.disabledDatesExpression!="") { this.disabledDatesExpression+= "||"; }
			if (start!=null) { start = parseDate(start); start=""+start.getFullYear()+LZ(start.getMonth()+1)+LZ(start.getDate());}
			if (end!=null) { end=parseDate(end); end=""+end.getFullYear()+LZ(end.getMonth()+1)+LZ(end.getDate());}
			if (start==null) { this.disabledDatesExpression+="(ds<="+end+")"; }
			else if (end  ==null) { this.disabledDatesExpression+="(ds>="+start+")"; }
			else { this.disabledDatesExpression+="(ds>="+start+"&&ds<="+end+")"; }
			}
			
		// Set the text to use for the "Today" link
		function CP_setTodayText(text) {
			this.todayText = text;
			}

		// Set the prefix to be added to all CSS classes when writing output
		function CP_setCssPrefix(val) { 
			this.cssPrefix = val; 
			}

		// Show the navigation as an dropdowns that can be manually changed
		function CP_showNavigationDropdowns() { this.isShowNavigationDropdowns = (arguments.length>0)?arguments[0]:true; }

		// Show the year navigation as an input box that can be manually changed
		function CP_showYearNavigationInput() { this.isShowYearNavigationInput = (arguments.length>0)?arguments[0]:true; }

		// Hide a calendar object
		function CP_hideCalendar() {
			if (arguments.length > 0) { window.popupWindowObjects[arguments[0]].hidePopup(); }
			else { this.hidePopup(); }
			}

		// Refresh the contents of the calendar display
		function CP_refreshCalendar(index) {
			var calObject = window.popupWindowObjects[index];
			if (arguments.length>1) { 
				calObject.populate(calObject.getCalendar(arguments[1],arguments[2],arguments[3],arguments[4],arguments[5]));
				}
			else {
				calObject.populate(calObject.getCalendar());
				}
			calObject.refresh();
			}

		// Populate the calendar and display it
		function CP_showCalendar(anchorname) {
			if (arguments.length>1) {
				if (arguments[1]==null||arguments[1]=="") {
					this.currentDate=new Date();
					}
				else {
					this.currentDate=new Date(parseDate(arguments[1]));
					}
				}
			this.populate(this.getCalendar());
			this.showPopup(anchorname);
			}

		// Simple method to interface popup calendar with a text-entry box
		function CP_select(inputobj, linkname, format) {
			var selectedDate=(arguments.length>3)?arguments[3]:null;
			if (!window.getDateFromFormat) {
				alert("calendar.select: To use this method you must also include 'date.js' for date formatting");
				return;
				}
			if (this.displayType!="date"&&this.displayType!="week-end") {
				alert("calendar.select: This function can only be used with displayType 'date' or 'week-end'");
				return;
				}
			if (inputobj.type!="text" && inputobj.type!="hidden" && inputobj.type!="textarea") { 
				alert("calendar.select: Input object passed is not a valid form input object"); 
				window.CP_targetInput=null;
				return;
				}
			if (inputobj.disabled) { return; } // Can't use calendar input on disabled form input!
			window.CP_targetInput = inputobj;
			window.CP_calendarObject = this;
			this.currentDate=null;
			var time=0;
			if (selectedDate!=null) {
				time = getDateFromFormat(selectedDate,format)
				}
			else if (inputobj.value!="") {
				time = getDateFromFormat(inputobj.value,format);
				}
			if (selectedDate!=null || inputobj.value!="") {
				if (time==0) { this.currentDate=null; }
				else { this.currentDate=new Date(time); }
				}
			window.CP_dateFormat = format;
			this.showCalendar(linkname);
			}
			
		// Get style block needed to display the calendar correctly
		function getCalendarStyles() {
			var result = "";
			var p = "";
			if (this!=null && typeof(this.cssPrefix)!="undefined" && this.cssPrefix!=null && this.cssPrefix!="") { p=this.cssPrefix; }
//			result += "<STYLE>\n";
//			result += "."+p+"cpYearNavigation,."+p+"cpMonthNavigation { background-color:#C0C0C0; text-align:center; vertical-align:center; text-decoration:none; color:#000000; font-weight:bold; }\n";
//			result += "."+p+"cpDayColumnHeader, ."+p+"cpYearNavigation,."+p+"cpMonthNavigation,."+p+"cpCurrentMonthDate,."+p+"cpCurrentMonthDateDisabled,."+p+"cpOtherMonthDate,."+p+"cpOtherMonthDateDisabled,."+p+"cpCurrentDate,."+p+"cpCurrentDateDisabled,."+p+"cpTodayText,."+p+"cpTodayTextDisabled,."+p+"cpText { font-family:arial; font-size:8pt; }\n";
//			result += "TD."+p+"cpDayColumnHeader { text-align:right; border:solid thin #C0C0C0;border-width:0px 0px 1px 0px; }\n";
//			result += "."+p+"cpCurrentMonthDate, ."+p+"cpOtherMonthDate, ."+p+"cpCurrentDate  { text-align:right; text-decoration:none; }\n";
//			result += "."+p+"cpCurrentMonthDateDisabled, ."+p+"cpOtherMonthDateDisabled, ."+p+"cpCurrentDateDisabled { color:#D0D0D0; text-align:right; text-decoration:line-through; }\n";
//			result += "."+p+"cpCurrentMonthDate, .cpCurrentDate { color:#000000; }\n";
//			result += "."+p+"cpOtherMonthDate { color:#808080; }\n";
//			result += "TD."+p+"cpCurrentDate { color:white; background-color: #C0C0C0; border-width:1px; border:solid thin #800000; }\n";
//			result += "TD."+p+"cpCurrentDateDisabled { border-width:1px; border:solid thin #FFAAAA; }\n";
//			result += "TD."+p+"cpTodayText, TD."+p+"cpTodayTextDisabled { border:solid thin #C0C0C0; border-width:1px 0px 0px 0px;}\n";
//			result += "A."+p+"cpTodayText, SPAN."+p+"cpTodayTextDisabled { height:20px; }\n";
//			result += "A."+p+"cpTodayText { color:black; }\n";
//			result += "."+p+"cpTodayTextDisabled { color:#D0D0D0; }\n";
//			result += "."+p+"cpBorder { border:solid thin #808080; }\n";
//			result += "</STYLE>\n";
			return result;
			}

		// Return a string containing all the calendar code to be displayed
		function CP_getCalendar() {
			var now = new Date();
			// Reference to window
			if (this.type == "WINDOW") { var windowref = "window.opener."; }
			else { var windowref = ""; }
			var result = "";
			// If POPUP, write entire HTML document
			if (this.type == "WINDOW") {
//				result += "<HTML><HEAD><TITLE>Calendar</TITLE>"+this.getStyles()+"</HEAD><BODY MARGINWIDTH=0 MARGINHEIGHT=0 TOPMARGIN=0 RIGHTMARGIN=0 LEFTMARGIN=0>\n";
//				result += '<CENTER><TABLE WIDTH=100% BORDER=0 BORDERWIDTH=0 CELLSPACING=0 CELLPADDING=0>\n';
				}
			else {
//				result += '<TABLE CLASS="'+this.cssPrefix+'cpBorder" WIDTH=144 BORDER=1 BORDERWIDTH=1 CELLSPACING=0 CELLPADDING=1>\n';
//				result += '<TR><TD ALIGN=CENTER>\n';
//				result += '<CENTER>\n';
				}
			
			
			result += "<div id=\"calPop\" class=\"layerPopupUserDefine\" style=\"background-color:#ebebec;z-index:0;width:260px;display:block;border:1px #000 solid;\">";
			result += "<div id=\"Layer-Contents\">";
			
			result += "<p id='calendarPopupTitle' class=\"popTitle_cal\" style=\"background:url(../en_US/images/common/poplayer/title_dot.gif) no-repeat 0 3px; \">Select Date</p>";
			
			result += "<div class=\"lineBoxLT\">";
			result += "<div class=\"lineBoxRT\">";
			result += "<div class=\"lineBoxLB\">";
			result += "<div class=\"lineBoxRB\">";
			result += "<div class=\"popGuide\">";
			result += "<div class=\"calendarCtrl\">";
			
			
			
			// Code for DATE display (default)
			// -------------------------------
			if (this.displayType=="date" || this.displayType=="week-end") {
				if (this.currentDate==null) { this.currentDate = now; }
				if (arguments.length > 0) { var month = arguments[0]; }
					else { var month = this.currentDate.getMonth()+1; }
				if (arguments.length > 1 && arguments[1]>0 && arguments[1]-0==arguments[1]) { var year = arguments[1]; }
					else { var year = this.currentDate.getFullYear(); }
				var daysinmonth= new Array(0,31,28,31,30,31,30,31,31,30,31,30,31);
				if ( ( (year%4 == 0)&&(year%100 != 0) ) || (year%400 == 0) ) {
					daysinmonth[2] = 29;
					}
				var current_month = new Date(year,month-1,1);
				var display_year = year;
				var display_month = month;
				var display_date = 1;
				var weekday= current_month.getDay();
				var offset = 0;
				
				offset = (weekday >= this.weekStartDay) ? weekday-this.weekStartDay : 7-this.weekStartDay+weekday ;
				if (offset > 0) {
					display_month--;
					if (display_month < 1) { display_month = 12; display_year--; }
					display_date = daysinmonth[display_month]-offset+1;
					}
				var next_month = month+1;
				var next_month_year = year;
				if (next_month > 12) { next_month=1; next_month_year++; }
				var last_month = month-1;
				var last_month_year = year;
				if (last_month < 1) { last_month=12; last_month_year--; }
				var date_class;
//				if (this.type!="WINDOW") {
//					result += "<TABLE WIDTH=144 BORDER=0 BORDERWIDTH=0 CELLSPACING=0 CELLPADDING=0>";
//					}
//				result += '<TR>\n';
				var refresh = windowref+'CP_refreshCalendar';
				var refreshLink = 'javascript:' + refresh;
				if (this.isShowNavigationDropdowns) {
					result += '<p class="fl"><a HREF="'+refreshLink+'('+this.index+','+last_month+','+last_month_year+');"><img src="' + Global_DepthPathImage + '/en_US/images/common/ico/ico_callender_prev.gif" alt="" /></a></p>';
					result += '<div class="selectYearMonth">';
					/*select part */

					result += '<select name="cpYear" onmouseup="CP_stop(event)" onChange="'+refresh+'('+this.index+','+month+',this.options[this.selectedIndex].value-0);">';
					for( var yearCounter=year-this.yearSelectStartOffset; yearCounter<=year+this.yearSelectStartOffset; yearCounter++ ) {
						var selected = (yearCounter==year) ? 'SELECTED' : '';
						result += '<option value="'+yearCounter+'" '+selected+'>'+yearCounter+'</option>';
						}
//					result += '</select></TD>';
					result += '</select>&nbsp;&nbsp;&nbsp;';
					
					result += '<select name="cpMonth" onmouseup="CP_stop(event)" onChange="'+refresh+'('+this.index+',this.options[this.selectedIndex].value-0,'+(year-0)+');">';
					for( var monthCounter=1; monthCounter<=12; monthCounter++ ) {
						var selected = (monthCounter==month) ? 'SELECTED' : '';
						result += '<option value="'+monthCounter+'" '+selected+'>'+this.monthNames[monthCounter-1]+'</option>';
						}
					result += '</select></div>';
					result += '<p class="fr"><a HREF="'+refreshLink+'('+this.index+','+next_month+','+next_month_year+');"><img src="' + Global_DepthPathImage + '/en_US/images/common/ico/ico_callender_next.gif" alt="" /></a></p>';
					result += '</div>';
					
					}
				else {
					if (this.isShowYearNavigation) {
//						result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="10"><A CLASS="'+this.cssPrefix+'cpMonthNavigation" HREF="'+refreshLink+'('+this.index+','+last_month+','+last_month_year+');">&lt;</A></TD>';
//						result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="58"><SPAN CLASS="'+this.cssPrefix+'cpMonthNavigation">'+this.monthNames[month-1]+'</SPAN></TD>';
//						result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="10"><A CLASS="'+this.cssPrefix+'cpMonthNavigation" HREF="'+refreshLink+'('+this.index+','+next_month+','+next_month_year+');">&gt;</A></TD>';
//						result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="10">&nbsp;</TD>';
		//
//						result += '<TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="10"><A CLASS="'+this.cssPrefix+'cpYearNavigation" HREF="'+refreshLink+'('+this.index+','+month+','+(year-1)+');">&lt;</A></TD>';
						if (this.isShowYearNavigationInput) {
//							result += '<TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="36"><INPUT NAME="cpYear" CLASS="'+this.cssPrefix+'cpYearNavigation" SIZE="4" MAXLENGTH="4" VALUE="'+year+'" onBlur="'+refresh+'('+this.index+','+month+',this.value-0);"></TD>';
							}
						else {
//							result += '<TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="36"><SPAN CLASS="'+this.cssPrefix+'cpYearNavigation">'+year+'</SPAN></TD>';
							}
//						result += '<TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="10"><A CLASS="'+this.cssPrefix+'cpYearNavigation" HREF="'+refreshLink+'('+this.index+','+month+','+(year+1)+');">&gt;</A></TD>';
						}
					else {
//						result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="22"><A CLASS="'+this.cssPrefix+'cpMonthNavigation" HREF="'+refreshLink+'('+this.index+','+last_month+','+last_month_year+');">&lt;&lt;</A></TD>\n';
//						result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="100"><SPAN CLASS="'+this.cssPrefix+'cpMonthNavigation">'+this.monthNames[month-1]+' '+year+'</SPAN></TD>\n';
//						result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="22"><A CLASS="'+this.cssPrefix+'cpMonthNavigation" HREF="'+refreshLink+'('+this.index+','+next_month+','+next_month_year+');">&gt;&gt;</A></TD>\n';
						}
					}
//				result += '</TR></TABLE>\n';
//				result += '<TABLE WIDTH=120 BORDER=0 CELLSPACING=0 CELLPADDING=1 ALIGN=CENTER>\n';
//				result += '<TR>\n';
				result += '<table class=\"calendarTblUserDefine\" summary=\"\">\n';
				result += '<caption>a calendar</caption><thead><tr>';
				for (var j=0; j<7; j++) {

//					result += '<TD CLASS="'+this.cssPrefix+'cpDayColumnHeader" WIDTH="14%"><SPAN CLASS="'+this.cssPrefix+'cpDayColumnHeader">'+this.dayHeaders[(this.weekStartDay+j)%7]+'</TD>\n';
					result += '<th>'+this.dayHeaders[(this.weekStartDay+j)%7]+'</th>\n';
					}
				result += '</TR>\n';
				result += '</thead>';
				result += '<tbody>';
				
				
				for (var row=1; row<=6; row++) {
					if(dateClass=="cpOtherMonthDate"){ 
						
					}
					result += '<TR>\n';
					for (var col=1; col<=7; col++) {
						var disabled=false;
						if (this.disabledDatesExpression!="") {
							var ds=""+display_year+LZ(display_month)+LZ(display_date);
							eval("disabled=("+this.disabledDatesExpression+")");
							}
						var dateClass = "";
						if ((display_month == this.currentDate.getMonth()+1) && (display_date==this.currentDate.getDate()) && (display_year==this.currentDate.getFullYear())) {
							// ���� �� ��¥�� �߰��Ǵ� ���� ����
							if( display_month == month)
							dateClass = "cpCurrentDate";
							else
								dateClass = "cpOtherMonthDate";
							}
						else if (display_month == month) {
							dateClass = "cpCurrentMonthDate";
							}
						else {
							dateClass = "cpOtherMonthDate";
							}
						if (disabled || this.disabledWeekDays[col-1]) {
//							result += '	<TD CLASS="'+this.cssPrefix+dateClass+'"><SPAN CLASS="'+this.cssPrefix+dateClass+'Disabled">'+display_date+'</SPAN></TD>\n';
							result += '	<TD>'+display_date+'</TD>\n';
							}
						else {
							var selected_date = display_date;
							var selected_month = display_month;
							var selected_year = display_year;
							if (this.displayType=="week-end") {
								var d = new Date(selected_year,selected_month-1,selected_date,0,0,0,0);
								d.setDate(d.getDate() + (7-col));
								selected_year = d.getYear();
								if (selected_year < 1000) { selected_year += 1900; }
								selected_month = d.getMonth()+1;
								selected_date = d.getDate();
								}
//							result += '	<TD CLASS="'+this.cssPrefix+dateClass+'"><A HREF="javascript:'+windowref+this.returnFunction+'('+selected_year+','+selected_month+','+selected_date+');'+windowref+'CP_hideCalendar(\''+this.index+'\');" CLASS="'+this.cssPrefix+dateClass+'">'+display_date+'</A></TD>\n';
							
							//Sunday management
							var tdClass="";
							if(col == 1){
								tdClass = "sun";
							}
							
							//if(dateClass=="cpOtherMonthDate") display_date = '99';
							
								if(dateClass=="cpOtherMonthDate"){
									result += '	<TD class='+tdClass+'></TD>\n';
									
								}else{
									// ���� ��¥ or ���� ��¥�� <b>~</b> �±׸� ���̴� �ڵ� �߰�
									var currentDate_Year = this.currentDate.getFullYear();
									var currentDate_Month = this.currentDate.getMonth() + 1;
									var currentDate_Day = this.currentDate.getDate();
									//var display_Date = new Date(selected_year, selected_month, selected_date);
									if( currentDate_Year == selected_year && currentDate_Month == selected_month && currentDate_Day == selected_date)
										result += '	<TD class='+tdClass+'><b><A HREF="javascript:'+windowref+this.returnFunction+'('+selected_year+','+selected_month+','+selected_date+');'+windowref+'CP_hideCalendar(\''+this.index+'\');">'+display_date+'</A></b></TD>\n';
									else
									result += '	<TD class='+tdClass+'><A HREF="javascript:'+windowref+this.returnFunction+'('+selected_year+','+selected_month+','+selected_date+');'+windowref+'CP_hideCalendar(\''+this.index+'\');">'+display_date+'</A></TD>\n';
								}
							}
						display_date++;
						if (display_date > daysinmonth[display_month]) {
							display_date=1;
							display_month++;
							}
						if (display_month > 12) {
							display_month=1;
							display_year++;
							}
						}
					result += '</TR>';
					}
				
				result += '</tbody></table>';
				result += '</div></div></div></div></div>';
				result += '<p class="popClose2"><a href="#" onclick="fnLayerClose(\'calPop\'); return false;"><img src="' + Global_DepthPathImage + '/en_US/images/common/poplayer/btn_close.gif" alt="close" /></a></p>';
				result += '<iframe src="/en_US/images/common/space.gif" frameborder="0" style=\'border:0px; width:300px;height:280px;filter:Alpha(Opacity=0)\'></iframe></div></div>';
//				result += "</BODY></HTML>\n";
				
				var current_weekday = now.getDay() - this.weekStartDay;
				if (current_weekday < 0) {
					current_weekday += 7;
					}
//				result += '<TR>\n';
//				result += '	<TD COLSPAN=7 ALIGN=CENTER CLASS="'+this.cssPrefix+'cpTodayText">\n';
				if (this.disabledDatesExpression!="") {
					var ds=""+now.getFullYear()+LZ(now.getMonth()+1)+LZ(now.getDate());
					eval("disabled=("+this.disabledDatesExpression+")");
					}
				if (disabled || this.disabledWeekDays[current_weekday+1]) {
//					result += '		<SPAN CLASS="'+this.cssPrefix+'cpTodayTextDisabled">'+this.todayText+'</SPAN>\n';
					}
				else {
//					result += '		<A CLASS="'+this.cssPrefix+'cpTodayText" HREF="javascript:'+windowref+this.returnFunction+'(\''+now.getFullYear()+'\',\''+(now.getMonth()+1)+'\',\''+now.getDate()+'\');'+windowref+'CP_hideCalendar(\''+this.index+'\');">'+this.todayText+'</A>\n';
					}
//				result += '		<BR>\n';
//				result += '	</TD></TR></TABLE></CENTER></TD></TR></TABLE>\n';
			}

			// Code common for MONTH, QUARTER, YEAR
			// ------------------------------------
			if (this.displayType=="month" || this.displayType=="quarter" || this.displayType=="year") {
				if (arguments.length > 0) { var year = arguments[0]; }
				else { 
					if (this.displayType=="year") {	var year = now.getFullYear()-this.yearSelectStartOffset; }
					else { var year = now.getFullYear(); }
					}
				if (this.displayType!="year" && this.isShowYearNavigation) {
//					result += "<TABLE WIDTH=144 BORDER=0 BORDERWIDTH=0 CELLSPACING=0 CELLPADDING=0>";
//					result += '<TR>\n';
//					result += '	<TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="22"><A CLASS="'+this.cssPrefix+'cpYearNavigation" HREF="javascript:'+windowref+'CP_refreshCalendar('+this.index+','+(year-1)+');">&lt;&lt;</A></TD>\n';
//					result += '	<TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="100">'+year+'</TD>\n';
//					result += '	<TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="22"><A CLASS="'+this.cssPrefix+'cpYearNavigation" HREF="javascript:'+windowref+'CP_refreshCalendar('+this.index+','+(year+1)+');">&gt;&gt;</A></TD>\n';
//					result += '</TR></TABLE>\n';
					}
				}
				
			// Code for MONTH display 
			// ----------------------
			if (this.displayType=="month") {
				// If POPUP, write entire HTML document
//				result += '<TABLE WIDTH=120 BORDER=0 CELLSPACING=1 CELLPADDING=0 ALIGN=CENTER>\n';
				for (var i=0; i<4; i++) {
//					result += '<TR>';
					for (var j=0; j<3; j++) {
						var monthindex = ((i*3)+j);
//						result += '<TD WIDTH=33% ALIGN=CENTER><A CLASS="'+this.cssPrefix+'cpText" HREF="javascript:'+windowref+this.returnMonthFunction+'('+year+','+(monthindex+1)+');'+windowref+'CP_hideCalendar(\''+this.index+'\');" CLASS="'+date_class+'">'+this.monthAbbreviations[monthindex]+'</A></TD>';
						}
//					result += '</TR>';
					}
//				result += '</TABLE></CENTER></TD></TR></TABLE>\n';
				}
			
			// Code for QUARTER display
			// ------------------------
			if (this.displayType=="quarter") {
//				result += '<BR><TABLE WIDTH=120 BORDER=1 CELLSPACING=0 CELLPADDING=0 ALIGN=CENTER>\n';
				for (var i=0; i<2; i++) {
//					result += '<TR>';
					for (var j=0; j<2; j++) {
						var quarter = ((i*2)+j+1);
//						result += '<TD WIDTH=50% ALIGN=CENTER><BR><A CLASS="'+this.cssPrefix+'cpText" HREF="javascript:'+windowref+this.returnQuarterFunction+'('+year+','+quarter+');'+windowref+'CP_hideCalendar(\''+this.index+'\');" CLASS="'+date_class+'">Q'+quarter+'</A><BR><BR></TD>';
						}
//					result += '</TR>';
					}
//				result += '</TABLE></CENTER></TD></TR></TABLE>\n';
				}

			// Code for YEAR display
			// ---------------------
			if (this.displayType=="year") {
				var yearColumnSize = 4;
//				result += "<TABLE WIDTH=144 BORDER=0 BORDERWIDTH=0 CELLSPACING=0 CELLPADDING=0>";
//				result += '<TR>\n';
//				result += '	<TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="50%"><A CLASS="'+this.cssPrefix+'cpYearNavigation" HREF="javascript:'+windowref+'CP_refreshCalendar('+this.index+','+(year-(yearColumnSize*2))+');">&lt;&lt;</A></TD>\n';
//				result += '	<TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="50%"><A CLASS="'+this.cssPrefix+'cpYearNavigation" HREF="javascript:'+windowref+'CP_refreshCalendar('+this.index+','+(year+(yearColumnSize*2))+');">&gt;&gt;</A></TD>\n';
//				result += '</TR></TABLE>\n';
//				result += '<TABLE WIDTH=120 BORDER=0 CELLSPACING=1 CELLPADDING=0 ALIGN=CENTER>\n';
				for (var i=0; i<yearColumnSize; i++) {
					for (var j=0; j<2; j++) {
						var currentyear = year+(j*yearColumnSize)+i;
//						result += '<TD WIDTH=50% ALIGN=CENTER><A CLASS="'+this.cssPrefix+'cpText" HREF="javascript:'+windowref+this.returnYearFunction+'('+currentyear+');'+windowref+'CP_hideCalendar(\''+this.index+'\');" CLASS="'+date_class+'">'+currentyear+'</A></TD>';
						}
//					result += '</TR>';
					}
//				result += '</TABLE></CENTER></TD></TR></TABLE>\n';
				}
			// Common
			if (this.type == "WINDOW") {
//				result += "</BODY></HTML>\n";
//				result += '<p class="popClose2"><a href="#" onclick="fnLayerClose(\'calPop\'); return false;"><img src="${initParam.CONTEXT_PATH}/en_US/images/common/poplayer/btn_close.gif" alt="close" /></a></p>';
//				result += '<iframe frameborder="0" style=\'border:0px; width:300px;height:280px;filter:Alpha(Opacity=0)\'></iframe></div></div>';
//				result += "</BODY></HTML>\n";
				}
			//alert(result);
			return result;
			}

			function fnLayerClose(id){
				cal.hideCalendar();
			}
/*********************************************************
*  End calendarPopup.js
*********************************************************/
/*********************************************************
*  Start commonPopup.js
*********************************************************/
			// popup attributes
			var ospPopupWidth = 300;
			var ospAlertPopupWidth = ospPopupWidth;
			var ospConfirmPopupWidth = ospPopupWidth;
			var ospWarnigPopupWidth = 250;
			var ospTablePopupWidth = 280;
			var ospSmiPopupWidth = 290;
			var ospCvcPopupWidth = 270;

			var ospRealPopupWidth;
			var ospRealPopupHeight;

			var ospPopupBackgroundLayerID = "bg_osppopup";
			var ospPopupBackgroundLayerID_IE6 = "bg_osppopup_ie6";

			var ospPopupLayerID = "dialog_osppopup";

			/* 이미지 경로!! */
			var ospPopupImgUrlBase = Global_DepthPathImage + "/en_US/images/common";

			// popup object
			var ospPopupObject;

			// user function - show alert popup
			function showOspAlertPopup(title, content, focusObj)
			{	
				ospPopupObject = new createOspCommonPopup('alert', title, content, focusObj);
				
				// 가운데로 자리 이동
				MP_OnWindowResize();
			}

			//user function - show alert popup
			function showOspWarningPopup(title, content, focusObj)
			{	
				ospPopupObject = new createOspCommonPopup('warning', title, content, focusObj);
				
				// 가운데로 자리 이동
				MP_OnWindowResize();
			}


			// user function - show confirm popup
			function showOspConfirmPopup(title, content, yesHandler, noHandler)
			{
				ospPopupObject = new createOspCommonPopup('confirm', title, content, yesHandler, noHandler);

				// 가운데로 자리 이동
				MP_OnWindowResize();
			}


			function showOspTablePopup(title, content)
			{	
				ospPopupObject = new createOspCommonPopup('table', title, content);
				
				// 가운데로 자리 이동
				MP_OnWindowResize();
			}


			function showSmiLoginPopup(title, content)
			{	
				ospPopupObject = new createOspCommonPopup('smi', title, content);
				
				// 가운데로 자리 이동
				MP_OnWindowResize();
			}

			function showCardCvcInfoPopup()
			{	
				ospPopupObject = new createOspCommonPopup('cvc');
				
				// 가운데로 자리 이동
				MP_OnWindowResize();
			}


			// popup object create function
			function createOspCommonPopup(popuptype, title, content, yesHandler, noHandler) {
				
				// create background / popup layer
				if( MP_getIsIE6() )
					this.ospPopupBackgroundLayerID = ospPopupBackgroundLayerID_IE6;
				else
					this.ospPopupBackgroundLayerID = ospPopupBackgroundLayerID;

				//alert(this.ospPopupBackgroundLayerID);

				createOspCommonPopupLayer(this.ospPopupBackgroundLayerID);
				createOspCommonPopupLayer(ospPopupLayerID);

				// configure settings
				this.popuptype = popuptype;
				this.width = getOspPopupWidth(popuptype);
				this.title = title;
				this.content = content;

				this.closeButtonOspPopupHandler = MP_closeButtonOspPopupHandler;
				this.okButtonOspPopupHandler = null;
				this.yesButtonOspPopupHandler = null;
				this.noButtonOspPopupHandler = null;
				this.closeButtonOspPopupHandler = MP_closeButtonOspPopupHandler;	
				
				this.focusObj = null;
				
				if( getIsOspConfirmPopup(popuptype) && arguments.length > 3 )
				{
					this.yesButtonOspPopupHandler = yesHandler;
					this.noButtonOspPopupHandler = noHandler;
				}else if( getIsOspAlertPopup(popuptype) && arguments.length > 3 ){
					this.focusObj =  yesHandler;
				}else if( getIsOspWarningPopup(popuptype) && arguments.length > 3 ){
					this.focusObj =  yesHandler;
				}

				this.showPopup = MP_showPopup;
				this.getLayerHtmlContents = MP_getLayerHtmlContents;
				this.layerHtmlContents = null;
				this.imgUrlBase = ospPopupImgUrlBase;
				this.getAlertPopupHtmlContents = MP_getAlertPopupHtmlContents;
				this.getWarningPopupHtmlContents = MP_getWarningPopupHtmlContents;
				this.getConfirmPopupHtmlContents = MP_getConfirmPopupHtmlContents;
				this.getTablePopupHtmlContents = MP_getTablePopupHtmlContents;
				this.getSmiPopupHtmlContents = MP_getSmiPopupHtmlContents;
				this.getCardCvcInfoHtmlContents = MP_getCardCvcInfoHtmlContents;
				this.makePopupLayerShow = MP_makePopupLayerShow;
				this.makeBackgroundGray = MP_makeBackgroundGray;
				//this.onWindowResize = MP_OnWindowResize;
				this.makeBackgroundWhite = MP_makeBackgroundWhite;
				this.makePopupLayerHidden = MP_makePopupLayerHidden;
					

				// event handler 등록
				if (window.attachEvent)
					window.attachEvent('onresize', MP_OnWindowResize);
				else if (window.addEventListener)
					window.addEventListener('resize', MP_OnWindowResize, false);
				else
					window.onresize = MP_OnWindowResize;
				
				// show popup
				this.showPopup();
				return this;
			}

			// show popup
			function MP_showPopup()
			{
				var debugStr = this.popuptype + " " + this.width + " " + this.title + " " + this.content;
				
				// Get layer html
				var htmlPopupContents = this.getLayerHtmlContents();

				// open popup layer
				this.makePopupLayerShow();

				// make background color black and blocking
				this.makeBackgroundGray();	
			}

			// HTML 내용을 긁어 온다
			function MP_getLayerHtmlContents()
			{
				if( getIsOspAlertPopup(this.popuptype) )
				{
					this.getAlertPopupHtmlContents();
				}
				else if ( getIsOspWarningPopup(this.popuptype) )
				{
					this.getWarningPopupHtmlContents();
				}	
				else if ( getIsOspConfirmPopup(this.popuptype) )
				{
					this.getConfirmPopupHtmlContents();
				}
				else if ( getIsOspTablePopup(this.popuptype) )
				{
					this.getTablePopupHtmlContents();
				}
				else if ( getIsOspSmiPopup(this.popuptype) )
				{
					this.getSmiPopupHtmlContents();
				}
				else if ( getIsOspCvcPopup(this.popuptype) )
				{
					this.getCardCvcInfoHtmlContents();
				}	
				
			}

			// popup property-related functions
			function getOspPopupWidth(popuptype)
			{
				if( popuptype == 'alert')
					return ospAlertPopupWidth;
				else if( popuptype == 'warning')
					return ospWarnigPopupWidth;	
				else if( popuptype == 'confirm')
					return ospConfirmPopupWidth;
				else if( popuptype == 'table')
					return ospTablePopupWidth;	
				else if( popuptype == 'smi')
					return ospSmiPopupWidth;
				else if( popuptype == 'cvc')
					return ospCvcPopupWidth;	
				else
					return 0;
			}

			function getIsOspAlertPopup(popuptype)
			{
				return (popuptype == 'alert');
			}

			function getIsOspWarningPopup(popuptype)
			{
				return (popuptype == 'warning');
			}

			function getIsOspConfirmPopup(popuptype)
			{
				return (popuptype == 'confirm');
			}

			function getIsOspTablePopup(popuptype)
			{
				return (popuptype == 'table');
			}

			function getIsOspSmiPopup(popuptype)
			{
				return (popuptype == 'smi');
			}

			function getIsOspCvcPopup(popuptype)
			{
				return (popuptype == 'cvc');
			}

			// create popup / background layer
			function createOspCommonPopupLayer(layerID)
			{
				// 이미 있으면 만들지 않는다...
				if ( document.getElementById( layerID ) != null )
					return;
				else
				{	
					var div2= document.createElement("div");

					if( layerID == ospPopupBackgroundLayerID || layerID == ospPopupBackgroundLayerID_IE6)
					{
						div2.id = layerID;
						div2.innerHTML = "<!--[if lte IE 6.5]><iframe class='iframeOspPopup' src='/en_US/images/common/space.gif'></iframe><![endif]-->";// selectbox 등을 가리기 위하여 추가함
					}
					else
					{	
						var div2_position = null;

						if( MP_getIsIE6() )
							div2_position = "absolute";
						else
							div2_position = "fixed";
						
						div2.innerHTML="<div id='" + layerID + "' style='display:none;position: " + div2_position + ";'/>";
					}
					
					document.body.appendChild(div2);	
				}
			}

			function MP_getAlertPopupHtmlContents()
			{
				// image 경로 처리 추가해야!!!!

				var result = "<div id='contentCheckMsg' class='layerPopupOspPopup' style='display:block'>";
				result += "<p class='popTitleOspPopup'>" + this.title + "</p>";
				result += "<div class='lineBoxLTOspPopup'>";
				result += "<div class='lineBoxRTOspPopup'>";
				result += "<div class='lineBoxLBOspPopup'>";
				result += "<div class='lineBoxRBOspPopup'>";
				result += "<div class='popGuideOspPopup'>";
				result += "<p>";
				result += this.content;
				result += "</p>";
				result += "</div>";
				result += "</div></div></div></div>";
				result += "<p class='popBtnAreaOspPopup'>";
				result += "<a href='#' onclick='MP_okButtonOspPopupHandler(); return false;' class='btnGrayOspPopup'><span>OK</span></a>";
				result += "</p>";
				result += "<p class='popCloseOspPopup' style='right:10px;'><a href='#' onclick='MP_closeButtonOspPopupHandler(); return false;'><img src='" + this.imgUrlBase + "/poplayer/btn_close.gif' alt='close' /></a></p>"
				result += "</div>";
				
				this.layerHtmlContents = result;
			}

			function MP_getWarningPopupHtmlContents()
			{
				var result = "<div id='comment' class='layerPopup' style='display:block'>";
				result += "<p class='popTitle'>" + this.title + "</p>";
				result += "<div class='lineBoxLT'>";
				result += "<div class='lineBoxRT'>";
				result += "<div class='lineBoxLB'>";
				result += "<div class='lineBoxRB'>";
				result += "<div class='popGuide'>";
				result += "<p class='caution'>Warning</p>";
				result += "<p id='popMessage'>";
				result += this.content;
				result += "</p>";
				result += "</div>";
				result += "</div></div></div></div>";
				result += "<p class='popBtnArea'>";
				result += "<a href='javascript:MP_okButtonOspPopupHandler()' class='btnGray'><span>OK</span></a>";
				result += "</p>";
				result += "<p class='popClose'><a href='javascript:MP_okButtonOspPopupHandler()' ><img src='" + this.imgUrlBase + "/poplayer/btn_close.gif' alt='close' /></a></p>"
				result += "</div>";
				
				this.layerHtmlContents = result;
			}

			function MP_getConfirmPopupHtmlContents()
			{
				var result = "<div id='confirmMsg' class='layerPopupOspPopup' style='display:block;'>";
				result += "<p class='popTitleOspPopup'>" + this.title + "</p>";
				result += "<div class='lineBoxLTOspPopup'>";
				result += "<div class='lineBoxRTOspPopup'>";
				result += "<div class='lineBoxLBOspPopup'>";
				result += "<div class='lineBoxRBOspPopup'>";
				result += "<div class='popGuideOspPopup'>";
				result += "<p class='cautionOspPopup'>Warning</p>";
				result += "<p>";
				result += this.content;
				result += "</p>";
				result += "</div>";
				result += "</div></div></div></div>";
				result += "<p class='popBtnAreaOspPopup'>";
				result += "<a href='#' onclick='MP_yesButtonOspPopupHandler(); return false;' class='btnBlue'><span>Yes</span></a>";
				result += "<a href='#' onclick='MP_noButtonOspPopupHandler(); return false;' class='btnGrayOspPopup'><span>No</span></a>";
				result += "</p>";
				result += "<p class='popCloseOspPopup' style='right:10px;'><a href='#' onclick='MP_closeButtonOspPopupHandler(); return false;'><img src='" + this.imgUrlBase + "/poplayer/btn_close.gif' alt='close' /></a></p>";
				result += "</div>";

				this.layerHtmlContents = result;
			}


			function MP_getTablePopupHtmlContents()
			{
				var result = "<div id='contentCheckMsg' class='layerPopup' style='display:block'>";
				result += "<p class='popTitle'>" + this.title + "</p>";
				result += "<div class='lineBoxLT'>";
				result += "<div class='lineBoxRT'>";
				result += "<div class='lineBoxLB'>";
				result += "<div class='lineBoxRB'>";
				result += "<div class='popGuide'>";
				result += "<p>";
				result += this.content;
				result += "</p>";
				result += "</div>";
				result += "</div></div></div></div>";
				result += "<p id='popupBtnAreaTag' class='popBtnArea'>";
				result += "<a href='javascript:MP_closeButtonOspPopupHandler()' class='btnGray'><span>OK</span></a>";
				result += "</p>";
				result += "<p class='popClose'><a href='javascript:MP_closeButtonOspPopupHandler()'><img src='" + this.imgUrlBase + "/poplayer/btn_close.gif' alt='close' /></a></p>"
				result += "</div>";	
				
				this.layerHtmlContents = result;
			}

			function MP_getSmiPopupHtmlContents()
			{
				var result = '<div id="smimLogin" class="layerPopup"  style="display:block">';
				result += "<p class='popTitle'>" + this.title + "</p>";
				result += "<div class='lineBoxLT'>";
				result += "<div class='lineBoxRT'>";
				result += "<div class='lineBoxLB'>";
				result += "<div class='lineBoxRB'>";
				result += "<div class='popGuide'>";
				result += "<p>";
				result += this.content;
				result += "</p>";	
				result += '<fieldset class="signInlayer" style="_left:20px; _top:10px;">';
				result += '<dl class="insTbl">';
				result += '<dt><span>ID</span></dt>';
				result += '<dd><input name="smiID" id="smiID" type="text" value="" class="input" /></dd>';
				result += '</dl>';
				result += '<dl class="insTbl">';
				result += '<dt><span>Password</span></dt>';
				result += '<dd><input name="smiPassword" type="password" id="smiPassword" value="" class="input" onkeydown="enterKeySubmit(event)"/></dd>';
				result += '</dl>';
				result += '<p id="errSMI" class="checkError"></p>';	
				result += '</fieldset>';
				result += "</div>";		
				result += "</div></div></div></div>";
				result += "<p class='popBtnArea'>";
				result += "<a href='javascript:smiAuth()' class='btnBlue'><span style='width:40px;'>OK</span></a>"
				result += "<a href='javascript:MP_closeButtonOspPopupHandler()' class='btnGray'><span style='width:40px;'>Cancel</span></a>"
				result += "</p>";
				result += "<p class='popClose'><a href='javascript:MP_closeButtonOspPopupHandler()'><img src='" + this.imgUrlBase + "/poplayer/btn_close.gif' alt='close' /></a></p>"
				result += "</div>";	
				
				this.layerHtmlContents = result;
			}

			function MP_getCardCvcInfoHtmlContents()
			{
				var result = '<div id="continue" class="layerPopup" style="display:block">';
				result += "<p class='popTitle'>Visa / Master Card</p>";
				result += "<div class='lineBoxLT'>";
				result += "<div class='lineBoxRT'>";
				result += "<div class='lineBoxLB'>";
				result += "<div class='lineBoxRB'>";
				result += "<div class='popGuide'>";
				result += "<p><img src='"+Global_DepthPathImage+"/en_US/images/CVCimg.gif' /></p>";
				result += "<p>For Visa/Master cards this is the final 3 digit nurmber found on the back of the card on the signature panel</p>";	
				result += "</div>";		
				result += "</div></div></div></div>";
				result += "<p class='popClose'><a href='javascript:MP_closeButtonOspPopupHandler()'><img src='" + this.imgUrlBase + "/poplayer/btn_close.gif' alt='close' /></a></p>"	
				result += "</div>";	
				
				this.layerHtmlContents = result;
			}

			function MP_makePopupLayerShow()
			{
				// dialog_osppopup layer style setting
				MP_setLayerStyleAttributes(ospPopupLayerID, "block", 6200, 40, 150);
				
				// odialog_osppopup의 내부 html을 세팅하고 가로크기를 고정시킨다 
				var ospPopupLayer = document.getElementById(ospPopupLayerID);
				
				if( ospPopupLayer )
				{
					// layer html 세팅
					ospPopupLayer.innerHTML = this.layerHtmlContents;
					
					// child element의 width를 다뤄야 가로크기가 고정됨!!
					ospPopupLayer.firstChild.style.width = this.width + "px";
				}
			}

			function MP_makePopupLayerHidden()
			{
				MP_setLayerStyleAttributes(ospPopupLayerID, "none", 1900);
			}

			function MP_makeBackgroundGray()
			{
				MP_setLayerStyleAttributes(this.ospPopupBackgroundLayerID, 'block', 6100);
			}

			function MP_makeBackgroundWhite()
			{
				MP_setLayerStyleAttributes(this.ospPopupBackgroundLayerID, 'none', 1900);
			}

			// Alert Popup에서 OK 버튼을 눌렀을 때의 handler
			function MP_okButtonOspPopupHandler()
			{
				ospPopupObject.closeButtonOspPopupHandler();

				if( ospPopupObject.okButtonOspPopupHandler != null )
					ospPopupObject.okButtonOspPopupHandler();
			}

			// 모든 Popup에서 OK 버튼을 눌렀을 때의 handler
			function MP_closeButtonOspPopupHandler()
			{
				ospPopupObject.closeButtonOspPopupHandler();
			}

			// Confirm Popup에서 Yes 버튼을 눌렀을 때의 handler
			function MP_yesButtonOspPopupHandler() 
			{	
				ospPopupObject.closeButtonOspPopupHandler();
				if( ospPopupObject.yesButtonOspPopupHandler != null )
					ospPopupObject.yesButtonOspPopupHandler();
			}

			// Confirm Popup에서 No 버튼을 눌렀을 때의 handler
			function MP_noButtonOspPopupHandler()
			{
				ospPopupObject.closeButtonOspPopupHandler();

				if( ospPopupObject.noButtonOspPopupHandler != null )
					ospPopupObject.noButtonOspPopupHandler();
			}

			// popup을 사라지게 하고, background를 원래 상태로 복귀시킴
			function MP_closeButtonOspPopupHandler()
			{
				ospPopupObject.makePopupLayerHidden();
				ospPopupObject.makeBackgroundWhite();
				
				if ( getIsOspAlertPopup(this.popuptype) || getIsOspWarningPopup(this.popuptype) ) {
					if ( this.focusObj != null ) {
						if ( this.focusObj.focus ) {
							this.focusObj.focus();
						}
						else {
							this.focusObj();
						}
					}
				}
			}

			function MP_setLayerStyleAttributes(id, display, zIndex, top, left)
			{
				var ospLayer = document.getElementById(id);
				var ospLayerStyle = ospLayer.style;

				if ( ospLayer ) {
					ospLayerStyle.zIndex = zIndex;
					ospLayerStyle.display = display;		

					if( arguments.length > 3)
					{
						ospLayerStyle.top = top + "px";
						ospLayerStyle.left = left + "px";
					}
				}
			}

			function MP_getIsIE6()
			{
				return (navigator.userAgent.toLowerCase().indexOf('msie 6') != -1 && navigator.userAgent.toLowerCase().indexOf('msie 7') == -1);
			}

			// resize 시 팝업의 중심을 잡아 주는 함수
			function MP_OnWindowResize()
			{
				var ospPopupLayerObject = document.getElementById(ospPopupLayerID);

				var left = window.XMLHttpRequest == null ? document.documentElement.scrollLeft : 0;
				var top = window.XMLHttpRequest == null ? document.documentElement.scrollTop : 0;
				var div = document.getElementById(ospPopupLayerID);

				var layerWidth = ospPopupLayerObject.childNodes[0].clientWidth;
				var layerHeight = ospPopupLayerObject.childNodes[0].clientHeight;
				
				// ospPopupObject를 쓸 수 없어서 ospPopupWidth를 불가피하게 사용하였음!!
				div.style.left = Math.max((left + (MP_GetWindowWidth() - layerWidth) / 2), 0) + 'px';
				div.style.top = Math.max((top + (MP_GetWindowHeight() - layerHeight ) / 2)-40, 0) + 'px';
			}

			function MP_GetWindowWidth()
			{
				var width =
					document.documentElement && document.documentElement.clientWidth ||
					document.body && document.body.clientWidth ||
					document.body && document.body.parentNode && document.body.parentNode.clientWidth ||
					0;
					
				return width;
			}

			function MP_GetWindowHeight()
			{
			    var height =
					document.documentElement && document.documentElement.clientHeight ||
					document.body && document.body.clientHeight ||
			  		document.body && document.body.parentNode && document.body.parentNode.clientHeight ||
			  		0;
			  		
			  	return height;
			}

		    function smiMemberAuth(returnURL){
		          url="https://innovator.samsungmobile.com/mbr/smiAstoreLink.do?returnURL=";
		          paramValue=encodeURIComponent(returnURL); 
		          x="392";
		          y="328";
		          window.open(url + paramValue,"smiMemberAuth","toolbar=no,width="+x+",height="+y + ",top="+ (screen.availheight- y )/2+",left="+(screen.availwidth- x)/2 +",status=no,scrollbars=no,resizable=no");
		    }   			
/*********************************************************
*  End commonPopup.js
*********************************************************/
/*********************************************************
*  Start gERPPostalCodeChecker.js
*********************************************************/
			/* G-ERP 연동관련 우편번호 체크 함수를 사용하려면,
			 * 이 파일을 사용하는 페이지에 추가해서 아래의 <script> 코드를  <head> 태그에 넣어 사용하세요~ 
			<script>
			<ast:countryList var="allCountryList" returnValueType="countryList" useFlag="N" />
			var postalCodeRuleSet = {};
			<c:forEach var="countryVO" items="${allCountryList}" >
				postalCodeRuleSet.${countryVO.countryCode} = { postalCodeLength : '${countryVO.postalCodeLength}', ruleForThePostaCodeFieldCheck : '${countryVO.ruleForThePostaCodeFieldCheck}' };  
			</c:forEach>
			</script>
			*/

			/**
			 * G-ERP 연동을 위한 우편번호 체크 클래스.
			 * @return
			 */
			function PostalCodeChecker() {
			    var resultMessage;

			    function regExpChecker(postalCode, regExp) {
			        return ( postalCode.search(regExp) != -1 );
			    }

			    function checkMaxLen(postalCode, maxLength) {
			        var isOK = postalCode.length <= maxLength;
			        if (!isOK) {
			            resultMessage = "Too long postal Code. Maximum code length is " + maxLength + ".";  
			        }
			        return isOK;
			    }
			    
			    function checkSameLen(postalCode, maxLength) {
			        var isOK = postalCode.length == maxLength;
			        if (!isOK) {
			            resultMessage = "The Postal Code length must be " + maxLength + "!";    
			        }
			        return isOK;
			    }

			    function checkNumberOnly(postalCode) {
			        var isOK = regExpChecker(postalCode, /^[0-9]+$/);
			        if (!isOK) {
			            resultMessage = "Only number is allowed for the postal Code.";  
			        }
			        return isOK;
			    }

			    function checkNoSpace(postalCode) {
			        var isOK = ( postalCode.search(' ') < 0 );
			        if (!isOK) {
			            resultMessage = "No space is allowed for the postal Code.";     
			        }
			        return isOK;
			    }

			    /* 11: 미국 우편번호 체크 
			     * 12345 또는 12345-1234
			     * 즉 
				 * "다섯자리 숫자"
				 * "다섯자리 숫자 - 네자리 숫자"  (총 10자리)
			     * */
			    function exactlyNNNNNorNNNNNhyphenNNNN(postalCode) {
			        var isOK1 = regExpChecker(postalCode, /^[0-9][0-9][0-9][0-9][0-9]$/);
			        var isOK2 = regExpChecker(postalCode, /^[0-9][0-9][0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]$/);
			        var isOK = isOK1 || isOK2;
			        if (!isOK) {
			            resultMessage = "The postal Code format is not proper. The format is 'NNNNN' or 'NNNNN-NNNN";    
			        }
			        return isOK;
			    }
			    /* 12: 브라질 우편번호 체크 
			     * 12345-123
			     * 즉 
				 * "다섯자리 숫자 - 세자리 숫자"  (총 9자리)
			     * */
			    function exactlyNNNNNhyphenNNN(postalCode) {
			        var isOK = regExpChecker(postalCode, /^[0-9][0-9][0-9][0-9][0-9]-[0-9][0-9][0-9]$/);
			        if (!isOK) {
			            resultMessage = "The postal Code format is not proper. The format is 'NNNNN-NNN";    
			        }
			        return isOK;
			    }
			    /* 901: ANA NAN 체크 */
			    function exactlyANAspaceNAN(postalCode) {
			        var isOK = regExpChecker(postalCode, /^[a-zA-Z][0-9][a-zA-Z] [0-9][a-zA-Z][0-9]$/);
			        if (!isOK) {
			            resultMessage = "The postal Code format is not proper. The format is 'ANA NAN'";    
			        }
			        return isOK;
			    }

			    /* 902: NNN NN 체크 */
			    /* 905: NNN NN 체크 */
			    /* 906: NNN NN 체크 */
			    function exactlyNNNspaceNN(postalCode) {
			        var isOK = regExpChecker(postalCode, /^[0-9][0-9][0-9] [0-9][0-9]$/);
			        if (!isOK) {
			            resultMessage = "The postal Code format is not proper. The format is 'NNN NN'";     
			        }
			        return isOK;
			    }

			    /* 903: NNNN AA 체크 */
			    function exactlyNNNNspaceAA(postalCode) {
			        var isOK = regExpChecker(postalCode, /^[0-9][0-9][0-9][0-9] [a-zA-Z][a-zA-Z]$/);
			        if (!isOK) {
			            resultMessage = "The postal Code format is not proper. The format is 'NNNN AA'";    
			        }
			        return isOK;
			    }

			    /* 904: NN-NNN 체크 */
			    function exactlyNNhyphenNNN(postalCode) {
			        var isOK = regExpChecker(postalCode, /^[0-9][0-9]-[0-9][0-9][0-9]$/);
			        if (!isOK) {
			            resultMessage = "The postal Code format is not proper. The format is 'NN-NNN'";     
			        }
			        return isOK;
			    }

			    /* 이하 public mehtod */
			    /**
			     *  우편번호 체크 메소드.
			     */
			    this.check = function(postalCode, checkCode, maxLength) {
			    	resultMessage = "OK";
			        switch (parseInt(checkCode)) {
			        case 1:
			            return checkMaxLen(postalCode, maxLength) && checkNoSpace(postalCode);
			        case 4:         
			            return checkSameLen(postalCode, maxLength) && checkNumberOnly(postalCode) && checkNoSpace(postalCode);      
			        case 5:         
			            return checkMaxLen(postalCode, maxLength);       
			        case 6:         
			            return checkMaxLen(postalCode, maxLength) && checkNumberOnly(postalCode);       
			        case 7:         
			            return checkSameLen(postalCode, maxLength);     
			        case 11:         
			            return exactlyNNNNNorNNNNNhyphenNNNN(postalCode); 
			        case 12:	// for Brazil?         
			            return exactlyNNNNNhyphenNNN(postalCode);  			            
			        case 901:           
			            return exactlyANAspaceNAN(postalCode);      
			        case 902:           
			        case 905:
			        case 906:
			            return exactlyNNNspaceNN(postalCode);       
			        case 903:           
			            return exactlyNNNNspaceAA(postalCode);      
			        case 904:           
			            return exactlyNNhyphenNNN(postalCode);      
			        default:
			        	// check Rule은 없고 max길이만 있는 경우는  case 4의 경우와 같은 체크를 하도록 한다.
			        	if (maxLength) {
			        		return checkSameLen(postalCode, maxLength) && checkNumberOnly(postalCode) && checkNoSpace(postalCode);
			        	}
			        	// 룰도 없고, max길이도 없는 경우는 체크를 하지 않는 것으로 하여 성공으로 본다.
			        }
			        return true;
			    };
			    
			    /**
			     *  우편번호 체크 결과 메시지를 반환하는 메소드.
			     *  반드시 chekc() 메소드를 수행 한 후에 호출해야함.
			     */
			    this.getResultMessage = function() {
			        return resultMessage;
			    };
			}   

			// G-ERP 연동을 위한 우편번호 체크 인스턴스.
			// 간단하게 String으로 된 우편번호의 정상 여부만 체크 할 때는,
			// postalCodeChecker.check(postalCode, checkCode, maxLength)와 
			// 같이 바로 호출할 수 있음.
			var postalCodeChecker = new PostalCodeChecker();

			/**
			 * G-ERP 연동을 위한 우편번호를 체크하는 함수.
			 * 리턴값으로 룰에 걸린 우편번호일 경우 
			 * input text에 focus를 주고 에러메시지를 반환 하는데,
			 * 그 메시지를 alert 창이나 표시가 필요한 곳에 표시할 수 있음.
			 *  
			 * @param postalCodeElement 우편번호를 입력받는 input text 태그 객체 (객체 이름이 아님)
			 * @param countryCode 국가코드.
			 * @return 우편번호가 정상이면 "OK",  비정상이면 에러 메시지를 반환함.
			 */
			function checkPostalCode(postalCodeElement, countryCode) {

				if (!postalCodeRuleSet) {
					alert("RuleSet 미지정!!! gERPPostalCodeChecker.js 파일의 맨위 주석을 읽고 조치를 취해주세요~");
					return;
				}
				
				var countryObject = postalCodeRuleSet[countryCode];
				
				if (! countryObject ) {
					return "Not a country suported!";
				}
				
				// checkCode 우편번호 체크 룰 code
				var checkCode = countryObject.ruleForThePostaCodeFieldCheck;
				
				// maxLength 우편번호 제한길이
				var maxLength = countryObject.postalCodeLength;
				
				// 우편번호
			    var postalCode = postalCodeElement.value;

			    var isOK = postalCodeChecker.check(postalCode, checkCode, maxLength);
			    if (!isOK) {
			       // postalCodeElement.focus();
			    }
			    
			    return postalCodeChecker.getResultMessage();
			}
			
/*********************************************************
*  End gERPPostalCodeChecker.js
*********************************************************/
// Firefox Check //// insertAdjacentElement
	if(typeof HTMLElement!="undefined" && !	HTMLElement.prototype.insertAdjacentElement){
		HTMLElement.prototype.insertAdjacentElement = function(where,parsedNode)
		{
			switch (where){
			case 'beforeBegin':
				this.parentNode.insertBefore(parsedNode,this)
				break;
			case 'afterBegin':
				this.insertBefore(parsedNode,this.firstChild);
				break;
			case 'beforeEnd':
				this.appendChild(parsedNode);
				break;
			case 'afterEnd':
				if (this.nextSibling) this.parentNode.insertBefore(parsedNode,this.nextSibling);
				else this.parentNode.appendChild(parsedNode);
				break;
			}
		}
	
		HTMLElement.prototype.insertAdjacentHTML = function(where,htmlStr)
		{
			var r = this.ownerDocument.createRange();
			r.setStartBefore(this);
			var parsedHTML = r.createContextualFragment(htmlStr);
			this.insertAdjacentElement(where,parsedHTML)
		}
	
		HTMLElement.prototype.insertAdjacentText = function(where,txtStr)
		{
			var parsedText = document.createTextNode(txtStr)
			this.insertAdjacentElement(where,parsedText)
		}
	}
	// insertAdjacentElement
	function getouterHtml(obj)
	{
		var html = null;
		if (obj == null) {
			return null; //널처리
		}
		if (typeof(obj.outerHTML) == "string") html =  obj.outerHTML; //스트링값을 가져온다면 IE로 가정함
		else	html = (new XMLSerializer).serializeToString(obj); 
		return html;
	}
	
	//ff대응 outerhtml 삽입
	function setOuterHtml(obj, html)
	{
		if (obj == null) return; //null처리
		if (typeof(obj.outerHTML) == "string")
		{//스트링값을 가져온다면 IE로 가정함
			obj.outerHTML = html;
		}
		else{
			var el = document.createElement('div');
			el.innerHTML = html;
			var range = document.createRange();
			range.selectNodeContents(el);
			var documentFragment = range.extractContents();
			obj.parentNode.insertBefore(documentFragment, obj);
			obj.parentNode.removeChild(obj);
		}
	}
///////////////////////