/**
**    File: sonar.ui.js
**    Created by: Young Mok, Kim. (mailto::super-nova@beizix.com)
**    Created on: 2005-01-16
**    Last modified: 2008-03-01
**
**
**    License Information:
**    -------------------------------------------------------------------------
**    Copyright (C) 2009 beizix.com
**
**    This script is free library; you can redistribute it and/or modify it
**    under the terms of the GNU General Public License as published by the
**    Free Software Foundation; either version 2 of the License, or (at your
**    option) any later version.
**
**    This library is distributed in the hope that it will be useful, but
**    WITHOUT ANY WARRANTY; without even the implied warranty of
**    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
**    General Public License for more details.
**
**    You should have received a copy of the GNU General Public License along
**    with this program; if not, write to the Free Software Foundation, Inc.,
**    59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
**
*/
if (typeof(sonar) != "object" || sonar == null) sonar = {};
sonar.ui = {};

sonar.ui.drag_and_drop =   function () {

        var g_iMouseDown_       = false;    //  마우스를 눌렀을 때, true.
		var g_lMouseState_      = false;    //  마우수를 누른 채, Drag 중이라면 true.
		var g_iTrash;						//	현재 활성화된 Trash Container.
		var g_iDragCont;					//	현재 활성화된 Drag Container.
		var g_dragObject_       = null;

        var g_isDraggable_      = false;    //  Drag 가능 앨리먼트를 mousedown 했을 시에만 true.
        var g_mouseOffset_      = null;     //  Drag 앨리먼트 내부의 클릭지점 좌표.
        var g_dragElements_     = [];       //  Drag 앨리먼트들의 집합.
        var g_dragContainers_   = [];       //  Drag  container 들의 집합. index 별로 드래그범위가 구분되어있다.
        var g_trashContainers_  = [];       //  Trash container 들의 집합.

        var g_containerIndex_   = null;
        var g_curTarget_        = null;
        var g_curTarget_Info_   = {};
        var g_delCurTarget_     = false;    //  현재 타겟 삭제여부(Trash에 놓여있을 시)
		var g_lastTarget_       = null;
		var g_dragHelper_       = null;
		var g_rootParent_       = null;
		var g_rootSibling_      = null;
		var g_trash_catch_by	= null;
		var g_trash_catch_on , g_drag_inside, g_trash_mode, g_trash_cont_init ;
		var g_trash_send, g_dragElem_mousedown;

		var g_drag_onSuccess, g_trash_onSuccess, g_drag_helperInit, g_dragHelper_addFunc;

		var saveOption;
		if (arguments.length > 0) {
			saveOption = {};
			for (var i=0; i < arguments.length; i++) {
				for (key in arguments[i]) {
					saveOption[key] = arguments[i][key];
				}
			}
		}

		//	=========================================
		//	drag 앨리먼트 내부의 클릭지점 좌표를 반환.
		//	=========================================
		var getMouseOffset	=	function(target, ev){
			ev	=	ev	||	window.event;

			var mousePos	=	mouseCoords(ev);
            var docPos		=	getPosition(target);

			return { x	:	mousePos.x - docPos.x,  y :	mousePos.y - docPos.y };
		};

        //	======================================================
		//	document(스크롤 영역포함)를 기준으로 마우스 좌표반환.
		//	======================================================
		var mouseCoords	=	function (ev) {

			if (ev.pageX || ev.pageY)	//	Firefox and other browsers
			{
				return { x : ev.pageX, y : ev.pageY };
			}else{		//	IE
				return {
					x : ev.clientX + document.body.scrollLeft - document.body.clientLeft,
					y : ev.clientY + document.body.scrollTop  - document.body.clientTop
				};
			}
		};

		//	==============================================================================
		//	해당 앨리먼트(e)의 document(스크롤 영역제외)기준으로 부터의 좌표를 얻어 반환.
		//	==============================================================================
		var getPosition	=	function (e) {
			var	left	=	0;
			var top		=	0;

			while (e.offsetParent)	//	offsetParent : 해당 엘리먼트의 가장 가까운 부모 앨리먼트 반환.
			{
				left	+=	e.offsetLeft;
				top		+=	e.offsetTop;
				e		=	e.offsetParent;
			}

			left	+=	e.offsetLeft;
			top		+=	e.offsetTop;

			return { x : left , y : top };
		};

        //  ============================
        //  마우스를 눌렀을 때 처리함수
        //  ============================
        var mouseDown	=	function(ev){

            if( g_isDraggable_ )
            {
                var ev      =   ev || window.event;
                var target  =   ev.target || ev.srcElement;

                var _checkDragElement    =   function( element ){
                    for ( var i = 0 ; i < g_dragElements_.length ; i++ )
                    {
                        if( element === g_dragElements_[i] )
                            return true;
                    }
                };

                while ( target && target !== document.getElementsByTagName('body')[0] )
                {
                    if( target.getAttribute && _checkDragElement( target ) ){
                        g_dragObject_  =   target;
                        break;
                    }

                    target  =   target.parentNode;
                }

                g_iMouseDown_ = true;
                if( g_lastTarget_ ) return false;
           }
		};

		//	================================
		//	마우스를 때었을 때의 처리 함수.
		//	================================
		var mouseUp	=	function (ev) {

			if( g_curTarget_ ){
				// hide our helper object - it is no longer needed
				g_dragHelper_.style.display = 'none';

				// if the drag item is invisible put it back where it was before moving it
				if( g_curTarget_.style.display == 'none' ){
					if( g_rootSibling_ ){
						g_rootParent_.insertBefore(g_curTarget_, g_rootSibling_);
					}else{
						g_rootParent_.appendChild(g_curTarget_);
					}
				}

				// make sure the drag item is visible
				g_curTarget_.style.display		= '';
				g_curTarget_.style.visibility	= 'visible';


				// Drag Container 에 올바르게 놓였을 때 동작함수.
				if (g_iDragCont && g_drag_onSuccess) g_drag_onSuccess(g_iDragCont);

				// Trash 에 올바르게 놓였을 때 동작함수.
				if (g_iTrash && g_trash_onSuccess) g_trash_onSuccess(g_iTrash, g_curTarget_);
			}

            //  Drop 컨테이너에 떨어뜨렸다면, g_curTarget_ 을 삭제한다.
            if ( g_delCurTarget_ === true )
            {
                g_curTarget_.parentNode.removeChild(g_curTarget_);
            }

			// trash container 를 초기화 하는 함수가 있다면 실행.
			if (g_trash_cont_init) g_trash_cont_init(g_trashContainers_);

			g_curTarget_        =   null;
            g_dragObject_       =   null;
			g_iMouseDown_       =   false;
            g_isDraggable_      =   false;
            g_containerIndex_   =   null;
            g_delCurTarget_     =   false;
		};

		// g_dragElements setup
		var set_g_dragElements = function (source, cIndex) {
			var ele     =   null;
            for( var i = 0 ; i < source.drag_elements.length ; i++ )
            {
				ele = source.drag_elements[i];
                if(typeof source.drag_elements[i] == 'string') ele =  document.getElementById(source.drag_elements[i]);

				ele.style.cursor = 'move';

                ele.onmousedown =   function(index){
					return function(){
						g_isDraggable_ = true;
						g_containerIndex_ = cIndex;
						if (g_dragElem_mousedown) g_dragElem_mousedown(index);
					}
                }(i);

                g_dragElements_.push( ele );
            }
		};

        //	===============================================
		//	마우스 이동시 dragObject가 있다면 drag 시킨다.
		//	===============================================
		var mouseMove =	function (ev) {

			ev = ev || window.event;

			if (navigator.appName == 'Netscape') document.body.focus(); // Drag 되는 중 주변 텍스트가 선택되는 문제 해결.

			g_iTrash = null; // g_iTrash 는 언제나 초기화
			g_iDragCont = null;

			    /*  We are setting target to whatever item the mouse is currently on
			        Firefox uses event.target here, MSIE uses event.srcElement */
			var target   = ev.target || ev.srcElement;
			var mousePos = mouseCoords(ev);  // document 기준으로 현재 마우스 좌표 반환.

			    /*  mouseOut event - 마우스 아웃시 어떤 효과를 넣고 싶다면 이곳에
                    if(g_lastTarget_ && (target!==g_lastTarget_)){

                    } */

    		    //  if the mouse was moved over an element that is draggable //
			if( g_containerIndex_ != null ){

                    /*  mouseOver event - 필요하다면, 오버시 클래스명을 다르게 주어, 모습을 바꿀수 있다
                        if(target != g_lastTarget_){

                            var oClass = ( target.getAttribute ) ? target.getAttribute('overClass') : null;
                            if(oClass){
                                target.setAttribute('origClass', target.className);
                                target.className = oClass;
                            }
                        } */

				    // if the user is just starting to drag the element
				if( g_iMouseDown_ && !g_lMouseState_ ){

					    //  mouseDown target    //
					g_curTarget_     = g_dragObject_;

					    //  Record the mouse x and y offset for the element //
					g_rootParent_  = g_curTarget_.parentNode;
					g_rootSibling_ = g_curTarget_.nextSibling;

					g_mouseOffset_ = getMouseOffset(target, ev); // drag 앨리먼트 내부의 클릭지점 좌표 반환

					    //  We remove anything that is in our g_dragHelper_ DIV so we can put a new item in it. //
					for( var i = 0 ; i < g_dragHelper_.childNodes.length ; i++ ){
                        g_dragHelper_.removeChild(g_dragHelper_.childNodes[i]);
                    }

					    //  Make a copy of the current item and put it in our drag helper.  //
    				if (g_dragHelper_addFunc) {
						g_dragHelper_addFunc(g_dragHelper_, g_curTarget_.cloneNode(true));
					} else {
						g_dragHelper_.appendChild(g_curTarget_.cloneNode(true));
					}
					g_dragHelper_.style.display = 'block';

                        /*  만약, g_curTarget_ 의 모습에 변화를 주고 싶다면 이곳에 값을 넣는다
                            g_curTarget_.style.border = "3px dashed black"; */

                        /*  만약, g_dragHelper_ 의 모습에 변화를 주고 싶다면 이곳에 값을 넣는다
                            g_dragHelper_.firstChild.className = 'classname'; */
                    var cssValue = g_dragHelper_.firstChild.style.cssText;
					g_dragHelper_.firstChild.style.cssText = cssValue + "filter: alpha(opacity=70); opacity:0.7; -moz-opacity:0.7;";

					    /*  Record the current position of all drag/drop targets related
                            to the element.  We do this here so that we do not have to do
                            it on the general mouse move event which fires when the mouse
                            moves even 1 pixel.  If we don't do this here the script
                            would run much slower. */
					var dragCont_info = g_dragContainers_[g_containerIndex_];


                        /*  first record the width/height of our drag item.  Then hide it since
                            it is going to (potentially) be moved out of its parent. */
                    g_curTarget_Info_.startWidth =   parseInt(g_curTarget_.offsetWidth);
                    g_curTarget_Info_.startHeight=   parseInt(g_curTarget_.offsetHeight);

					g_curTarget_.style.display  = 'none';

					// loop through each possible drop container
					for( var i = 0 ; i < dragCont_info.length ; i++ ){

						var pos = getPosition( dragCont_info[i].ContElem );

                            /*  save the width, height and position of each container.
                                Even though we are saving the width and height of each
                                container back to the container this is much faster because
                                we are saving the number and do not have to run through
                                any calculations again.  Also, offsetHeight and offsetWidth
                                are both fairly slow.  You would never normally notice any
                                performance hit from these two functions but our code is
                                going to be running hundreds of times each second so every
                                little bit helps!

                                Note that the biggest performance gain here, by far, comes
                                from not having to run through the getPosition function
                                hundreds of times. */
                        dragCont_info[i].startWidth     = parseInt(dragCont_info[i].ContElem.offsetWidth);
                        dragCont_info[i].startHeight    = parseInt(dragCont_info[i].ContElem.offsetHeight);
                        dragCont_info[i].startLeft      = parseInt(pos.x);
                        dragCont_info[i].startTop       = parseInt(pos.y);

						    //  loop through each child element of each container    //
						for( var j=0 ; j < dragCont_info[i].ContElem.childNodes.length ; j++ ){

							if( (dragCont_info[i].ContElem.childNodes[j].nodeType !== 1) || (dragCont_info[i].ContElem.childNodes[j]==g_curTarget_)) continue;

							var pos = getPosition(dragCont_info[i].ContElem.childNodes[j]);

							    // save the width, height and position of each element
                            var c_obj   =   {};

                            c_obj.startWidth    =   parseInt(dragCont_info[i].ContElem.childNodes[j].offsetWidth);
                            c_obj.startHeight   =   parseInt(dragCont_info[i].ContElem.childNodes[j].offsetHeight);
                            c_obj.startLeft     =   pos.x;
                            c_obj.startTop      =   pos.y;

                            dragCont_info[i].childInfo.push(c_obj);
						}
					}
				}
			}

			// If we get in here we are dragging something
			if( g_curTarget_ ){
				// move our helper div to wherever the mouse is (adjusted by g_mouseOffset_)
				g_dragHelper_.style.top  = mousePos.y - g_mouseOffset_.y + 'px';
				g_dragHelper_.style.left = mousePos.x - g_mouseOffset_.x + 'px';

				var dragCont_info  = g_dragContainers_[g_containerIndex_];
				var activeCont = null;

				var xPos = mousePos.x - g_mouseOffset_.x + (parseInt(g_curTarget_Info_.startWidth) /2);
				var yPos = mousePos.y - g_mouseOffset_.y + (parseInt(g_curTarget_Info_.startHeight)/2);

				// check each drop container to see if our target object is "inside" the container
				var startLeft, startTop, startWidth, startHeight;
				for(var i=0; i < dragCont_info.length; i++) {

					startLeft	=	parseInt(dragCont_info[i].startLeft);
					startTop	=	parseInt(dragCont_info[i].startTop);
					startWidth	=	parseInt(dragCont_info[i].startWidth);
					startHeight	=	parseInt(dragCont_info[i].startHeight);

					// trashContainer 가 선언되고, trash_catch_by 옵션이 있다면,
					if (g_trashContainers_.length > 0 && g_trash_catch_by !== 'default') {

						var inTrash = false;
						for (var j = 0; j < g_trashContainers_.length; j++) {
							if (g_trashContainers_[j] == dragCont_info[i].ContElem) {
								inTrash = true;
								g_iTrash = g_trashContainers_[j];
								break;
							}
						}

						// trash container 에 놓여있구, trash_catch_by 옵션이 지정된 경우,
						if (inTrash && g_trash_catch_by !== 'default') {
						//console.log(' trash.offsetTop = '+ trash.offsetTop + ',trash.scrollHeight=' + trash.scrollHeight+ ', mousePos.y' + mousePos.y);
						//document.body.appendChild(document.createTextNode('getPosition = '+getPosition(trash).y+', trash.offsetTop = '+ trash.offsetTop + ',trash.scrollHeight=' + trash.scrollHeight+ ', mousePos.y' + mousePos.y));
							if (g_trash_catch_by == 'cursor') { // 옵션이 cursor 인 경우,

								if( ( getPosition(g_iTrash).x < mousePos.x) &&
									( mousePos.x < getPosition(g_iTrash).x + g_iTrash.scrollWidth) &&
									( getPosition(g_iTrash).y < mousePos.y) &&
									( mousePos.y < getPosition(g_iTrash).y + g_iTrash.scrollHeight)
									) {

									activeCont = dragCont_info[i];
									break;

								} else { // 다른 영역에 놓여져 있다면, g_iTrash 초기
									g_iTrash = null;
								}
							}
							// 옵션이 다른 경우,
							// .....

						// trash container 에 놓여있구, trash_catch_by 옵션이 따로 지정되지 않은경우,
						} else if (inTrash && trash_catch_by == 'default') {
							if( ( startLeft < xPos) &&
								( startTop  < yPos) &&
								( startLeft + startWidth  > xPos) &&
								( startTop  + startHeight > yPos) ) {

								activeCont = dragCont_info[i];
								break;
							} else {
								g_iTrash = null;
							}
						}

					// trash container 가 없는 가장 일반적인 경우.
					} else {

						if( ( startLeft < xPos) &&
							( startTop  < yPos) &&
							( startLeft + startWidth  > xPos) &&
							( startTop  + startHeight > yPos) ) {
							activeCont = dragCont_info[i];
							g_iDragCont = activeCont.ContElem;
							break;
						} else {
							g_iTrash = null;
						}
					}
				}

				// Our target object is in one of our containers.  Check to see where our div belongs
				if(activeCont) {
					// beforeNode will hold the first node AFTER where our div belongs
					var beforeNode = null;

					// loop through each child node (skipping text nodes).
					var startLeft, startTop, startWidth, startHeight;
                    var j   =   activeCont.childInfo.length;
					for( var i = activeCont.ContElem.childNodes.length - 1 ; i >= 0 ; i-- ){

						if( activeCont.ContElem.childNodes[i].nodeType !== 1 || (activeCont.ContElem.childNodes[i]==g_curTarget_)) continue;

                        j = j - 1;
						startLeft	=	parseInt(activeCont.childInfo[j].startLeft);
						startTop	=	parseInt(activeCont.childInfo[j].startTop);
						startWidth	=	parseInt(activeCont.childInfo[j].startWidth);
						startHeight	=	parseInt(activeCont.childInfo[j].startHeight);

						    // if the current item is "After" the item being dragged
						if(
							g_curTarget_ != activeCont.ContElem.childNodes[i]	&&
							startLeft + startWidth  > xPos			&&
							startTop  + startHeight > yPos
                           ){
								if(g_drag_inside == 'true') beforeNode = activeCont.ContElem.childNodes[i];
						}
					}


					    // g_curTarget_ 위치시키기 //
                    if(beforeNode){
						if( beforeNode != g_curTarget_.nextSibling ){
							activeCont.ContElem.insertBefore(g_curTarget_, beforeNode);
						}

					// Drag 앨리먼트가 해당 컨테이너의 맨아래에 붙을 때 or Drop 컨테이너에 놓여졌을 때 //
                  	} else {

                        if( g_curTarget_.nextSibling || g_curTarget_.parentNode !== activeCont.ContElem ){

							if (g_curTarget_.parentNode == activeCont.ContElem) { // 해당 컨테이너의 맨뒤에 붙은 경우,

								if(g_drag_inside == 'true') activeCont.ContElem.appendChild(g_curTarget_);

							} else { // trash container 에 붙은 경우.

								if (g_trash_catch_on == 'default') {
									activeCont.ContElem.appendChild(g_curTarget_);
								} else {
									g_trash_catch_on(activeCont.ContElem);
								}
							}
						}

                        //  ============================================================
                        //  curTarget 이 놓여진 컨테이너가 Trash container 인지 여부 판단.
                        //  맞다면, g_delCurTarget_ 에 true 값을 주어,
                        //  mouseup 시 g_curTarget_ 을 삭제한다.
                        //  ============================================================
                        for ( var i = 0 ; i < g_trashContainers_.length ; i++ )
                        {
                            if( activeCont.ContElem === g_trashContainers_[i] && g_trash_mode == 'remove') {
                                g_delCurTarget_ = true;
								break;
                            }
                        }

					}

					// make our drag item visible
					if (g_curTarget_.style.display != ''){
						g_curTarget_.style.display  = '';
					}

				// 현재 activeCont 내에서 활동하고 있지 않다면,
				} else {

					// our drag item is not in a container, so hide it.
					/*
					if (g_curTarget_.style.display != 'none') {
						if (g_trash_mode == 'remove') g_curTarget_.style.display  = 'none';
					}*/

					g_curTarget_.style.display  = '';

					// trash container 를 초기화 하는 함수가 있다면 실행.
					//if (g_trash_cont_init) g_trash_cont_init(g_trashContainers_);

                    g_delCurTarget_ =   false;
				}
			}

			// track the current mouse state so we can compare against it next time
			g_lMouseState_ = g_iMouseDown_;

			// mouseMove target
			g_lastTarget_  = target;

			// this helps prevent items on the page from being highlighted while dragging
			return false;
		};


		sonar.util.addEvent(document, 'mousemove', mouseMove, false);
		sonar.util.addEvent(document, 'mousedown', mouseDown, false);
		sonar.util.addEvent(document, 'mouseup', mouseUp, false);


        return {
            start :   function (source) {

				// 사용자 추가 변수
				if (saveOption) {
					for (key in saveOption) {
						this[key] = saveOption[key];
					}
				}

                try {
                        //  g_dragContainers_ 에 담길 컨테이너 그룹들은 cIndex 별로 구분된다 //
                    var cIndex        = g_dragContainers_.length;
                    g_dragContainers_[cIndex] = [];

                        //  g_dragContainers_ setup //
                    var cObj    =   null;
                    for( var i = 0 ; i < source.drag_container.length ; i++ )
                    {
                        cObj            =   {};
                        cObj.ContElem   =   document.getElementById(source.drag_container[i]);
                        cObj.DropObj    =   cIndex;
                        cObj.childInfo  =   [];

                        g_dragContainers_[cIndex].push(cObj);
                    }

	  					//  g_dragElements_ setup    //
					var drag_elems = source.drag_elements;

					if (drag_elems && drag_elems.constructor.toString().indexOf('Array') > -1) { // if it is Array

						set_g_dragElements(source, cIndex);

					} else {

						var child_e = null, drag_elems = [];
	                    for( var i = 0 ; i < source.drag_container.length ; i++ )
	                    {
	                        child_e = document.getElementById(source.drag_container[i]).childNodes;
							for (var j = 0; j < child_e.length ; j++) {
								if (child_e[j].nodeType == 1) drag_elems.push(child_e[j]);
							}

							source.drag_elements = drag_elems;
	                    }

						set_g_dragElements(source, cIndex);
					}


                        //  g_trashContainers_ setup //
                    if( source.trash_container ){

                        var dropObj =   null;
						var trashs = document.getElementById(source.trash_container).childNodes;

                        for( var i = 0 ; i < trashs.length ; i++){

                            if (trashs[i].nodeType !== 1) continue;

							dropObj =   trashs[i];
                            g_trashContainers_.push( dropObj );

                            cObj            =   {};
                            cObj.ContElem   =   dropObj;
                            cObj.DropObj    =   cIndex;
                            cObj.childInfo  =   [];

                            g_dragContainers_[cIndex].push(cObj);
                        }
                    }

                        //  cIndex가 0일때, g_dragHelper_ 생성  //
                    if (cIndex === 0)
                    {
                        if (g_drag_helperInit) {
							g_drag_helperInit(g_dragHelper_);
						} else {
							g_dragHelper_ = document.createElement('div');
							g_dragHelper_.style.cssText = 'position:absolute;display:none;';
							g_dragHelper_.style.width = '0px';
							document.body.appendChild(g_dragHelper_);
						}
                    }

					g_trash_catch_by = (source.trash_catch_by)? source.trash_catch_by : 'default';
					g_trash_catch_on = (source.trash_catch_on)? source.trash_catch_on : 'default';
					g_trash_mode = (source.trash_mode)? source.trash_mode : 'remove';
					g_drag_inside = (source.drag_inside)? source.drag_inside : 'true';
					g_trash_cont_init = (source.trash_cont_init)? source.trash_cont_init : null;
					g_trash_onSuccess = (source.trash_onSuccess)? source.trash_onSuccess : null;
					g_dragElem_mousedown = (source.dragElem_mousedown)? source.dragElem_mousedown : null;
					g_drag_onSuccess = (source.drag_onSuccess)? source.drag_onSuccess : null ;
					g_drag_helperInit = (source.drag_helperInit)? source.drag_helperInit : null;
					g_dragHelper_addFunc = (source.dragHelper_addFunc)? source.dragHelper_addFunc : null;

                } catch (e) {

                    alert(e + ', ("' + arguments[i] + '" ' + '는 존재하지 않는 앨리먼트 아이디입니다)'  );
                    g_dragContainers_ =   []; //  초기화.
                    g_dragElements_   =   [];
                }
            },
			add_dragElement : function (obj) {
				g_dragElements_.push(obj);
				obj.style.cursor = 'move';
				obj.onmousedown = function(){
					g_isDraggable_ = true;
					g_containerIndex_ = g_dragContainers_.length - 1;
                };
			},
			add_trashElement : function (obj) {
				g_trashContainers_.push( obj );

                var cObj = {};
                cObj.ContElem   =   obj;
                cObj.DropObj    =   g_dragContainers_.length - 1;
                cObj.childInfo  =   [];

                g_dragContainers_[g_dragContainers_.length - 1].push(cObj);
			}
        };
};

sonar.ui.modalMaker = function () {

	    var modal_dv, content_dv, dv_top, dv_left;
        var USER_OPTION;

	    //  IE6 check
	    var is_ie6  =   false;
		var userAgent = navigator.userAgent;
        if (/Opera /.test(userAgent))
        {
            is_ie6 = false;
        } else if (/MSIE 8/.test(userAgent))
		{
			is_ie6 = false;
		} else if (/MSIE 7/.test(userAgent))
		{
			is_ie6 = false;
		} else if (/MSIE 6/.test(userAgent))
		{
			is_ie6 = true;
		}

	    /*if ( navigator.appVersion.indexOf('MSIE 6.0') > -1 ){
	        is_ie6  =   true; window.IS_IE6 = true;
	    }*/

	    var set_IE6	=	function ( mode ) { //  if IE6, hide all selectboxes in the parent page.

	        var value	=	(mode === 'show')? 'visible' : 'hidden';

	        var select_s	=	et_('select');
	        var s_inModal   =   content_dv.getElementsByTagName('select');
	        var doHidden    =   true;

	        for ( var i = 0 ; i < select_s.length ; i++ ) {
	            doHidden    =   true;

	            if (s_inModal.length)
	            {
	                for (var j=0; j < s_inModal.length; j++)
	                {
	                    if (s_inModal[j] === select_s[i])
	                    {
	                        doHidden    =   false;
	                        continue;
	                    }
	                }
	            }

	            if(doHidden) select_s[i].style.visibility =	value;
	        }
	    };

	    //  resize 시, modal div 를 가운데 위치시킨다.
	    var set_modalPos   =   function( type ){
	        if (content_dv)
	        {
	            set_contentPosition(content_dv, type);

                modal_dv.style.width = '100%';
                modal_dv.style.height = get_totalHeight();

                if (type == 'onscroll')
                {
                    // 작은 창에서 가로 스크롤 이동하면 배경이 제대로 안먹히는 경우가 있다.
                    var docEle = parseInt(document.documentElement.scrollWidth);
                    var docBody = parseInt(document.body.scrollWidth);
                    var which;
                    if (docEle > docBody)
                    {
                        which = docEle;
                    } else {
                        which = docBody;
                    }

                    modal_dv.style.width = which + 'px';
                }
	        }
	    };

	    //  scroll 시
	    var set_modalSize = function(){
            set_modalPos('onscroll');
	    };

        var get_scrollInfo = function () {

            var result = {};
            var	sc_top = 0;
	        var sc_left = 0;

	        if(document.documentElement.scrollTop){	//	IE strict mode
	            sc_top	=	document.documentElement.scrollTop;
	            sc_left	=	document.documentElement.scrollLeft;
	        }else if(document.body.scrollTop){		//	IE quirks mode
	            sc_top	=	document.body.scrollTop;
	            sc_left	=	document.body.scrollLeft;
	        }else if(window.scrollY){	//	Netscape
	            sc_top	=	window.scrollY;
	            sc_left	=	window.scrollX;
	        }

            result.scrollTop = sc_top;
            result.scrollLeft = sc_left;

            return result;
        };

	    //  function for closing modal.
	    var closeModal  =   function(){

			if(dv_top){  rm_(dv_top); dv_top = null; }
	        if(dv_left){ rm_(dv_left); dv_left = null; }

	        if(is_ie6) set_IE6('show');

	        content_dv.style.display	=	"none";
	        plus_( document.body, content_dv );
	        rm_( modal_dv );
	    };

	    //	스크롤된 현재 영역에 모달이 보이도록 top, left 조절
	    var set_contentPosition	=	function(dv, type){

	        // onscroll 이벤트시 가운데 정렬일 경우,
            // content div 가 fixed 라면 조정할 필요가 없다.
            if (type == 'onscroll' && dv.style.position == 'fixed')
            {
                return;
            }

            var	sc_top = get_scrollInfo().scrollTop;
	        var sc_left = get_scrollInfo().scrollLeft;

	        var in_height, in_width;

	        if ( window.innerHeight ){
	            in_height    =   window.innerHeight;
	            in_width     =   window.innerWidth;
	        }else{
	            //  IE는 innerHeigt 를 지원하지 않기에, 다른 방법을 쓴다.
	            var d  =   document.createElement('div');

	            if (!dv_top && !dv_left)
	            {
	                dv_top = plus_( document.body, ce_('div', { 'style' : 'position:absolute; top:100%; left:100px; z-index:1; visibility:hidden;'}) );
	                dv_top.style.top = dv_top.offsetTop + 'px';

	                dv_left = plus_( document.body, ce_('div', { 'style' : 'position:absolute; top:100px; left:100%; z-index:1; visibility:hidden;'}) );
	                dv_left.style.left = dv_left.offsetLeft + 'px';
	            }
                //  ===============================================>
                // 중요 onresize 시 dv_top, dv_left 의 % 를 갱신해주면 현재 브라우저에서 보이는
                // 영역의 최단에 붙는다 ^^
                dv_top.style.top = '100%';
                dv_left.style.left = '100%';
				//  ===============================================>

	            if (!is_ie6)
	            {
					in_height = dv_top.offsetTop;
					in_width = dv_left.offsetLeft;
	            } else {
					in_height = dv_top.offsetTop;
					in_width = dv_left.offsetLeft;
				}

	        }

	        var sc_width = (dv.style.width)? dv.style.width : dv.scrollWidth;
	        //dv.style.width = sc_width;

	        var sc_height = (dv.style.height)? dv.style.height : dv.scrollHeight;
	        //dv.style.height = sc_height;

	        var realTop = sc_top + parseInt( (in_height / 2) - (parseInt(sc_height)/2) ) ;
	        if(realTop <= 0) realTop = '20';

            if (dv.style.position == 'fixed')
            {
                realTop = parseInt( (in_height / 2) - (parseInt(sc_height)/2) )  ;
            }

			// 전체화면에서 세로 스크롤을 하단으로 내린뒤,
			// 작은 화면으로 resize 될때에는,
			// scrollTop 값을 빼주어야 한다 !!!
			if (type == 'onresize')
			{
				realTop = parseInt( (in_height / 2) - (parseInt(sc_height)/2) ) ;
			}
	        var realLeft = sc_left + parseInt( (in_width / 2) - (parseInt(sc_width)/2) ) ;
	        if(realLeft <= 0) realLeft = '20';

            if (dv.style.position == 'fixed')
            {
                realLeft = parseInt( (in_width / 2) - (parseInt(sc_width)/2) );
            }

	        dv.style.top = realTop + 'px';
	        dv.style.left = realLeft + 'px';
	    };


	    var funzList = [];
	    var addFunz = function(f){
	        funzList.push(f);
	    };

	    // 어느 상황에서든, page 의 최대 높이값.
	    var get_totalHeight = function(){
	        var h = 0;
	        if (document.documentElement.scrollHeight < document.documentElement.clientHeight)
	        {
	            h = document.documentElement.clientHeight;
	        } else {
	            h = document.documentElement.scrollHeight;
	        }

	        return h + 'px';
	    };

	    return {
	        show	:	function( id, opt){	//	args : (컨텐츠 아이디, 유리판 클릭시 닫기여부, fixed 여부)

                if (this.IS_OPEN)
                {
                    return;
                }

                USER_OPTION = opt;
                if (!USER_OPTION)
                {
                    USER_OPTION = {};
                    USER_OPTION.change_byScroll = true;
                }

	            if(funzList.length > 0){
	                for ( var i = 0; i < funzList.length ; i++ )
	                {
	                    funzList[i]();
	                }
	            }

	            content_dv = e_(id);

	            if( !content_dv ){
	                alert(id + '는 존재하지 않는 태그 아이디입니다.');
	                return;
	            }

	            //  modal_dv setup
	            modal_dv = plus_(document.body, ce_('div', { style : 'position: absolute; z-index: 500; top:0; left:0; width:100%; background:black;-ms-filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=30); filter:Alpha(opacity=30); opacity:0.3' }));

                // Opera 8 의 경우, cssText 를 인식못한다.
                if (/Opera /.test(navigator.userAgent))
                {
                    modal_dv.style.position = 'absolute';
                    modal_dv.style.top = '0';
                    modal_dv.style.left = '0';
                    modal_dv.style.opacity = '0.3';
                    modal_dv.style.zIndex = '500';
                    modal_dv.style.width = '100%';
                    modal_dv.style.backgroundColor = 'black';
                }

                modal_dv.style.height = get_totalHeight();

	            if( opt && opt.mirror_close ) modal_dv.onclick	=	closeModal;

	            //  content_dv setup
	            csText  =   "position: fixed; z-index: 501; top: 0; left: 0; display: block; margin: 0 auto; background-color: white;";
                content_dv.style.cssText    =   content_dv.style.cssText + ';' +csText;

                // Opera 8 의 경우, cssText 를 인식못한다.
                if (/Opera /.test(navigator.userAgent))
                {
                    content_dv.style.position = 'fixed';
                    content_dv.style.top = '0';
                    content_dv.style.left = '0';
                    content_dv.style.display = 'block';
                    content_dv.style.zIndex = '501';
                    content_dv.style.margin = '0 auto';
                    content_dv.style.backgroundColor = 'white';
                }

                if (is_ie6)
                {
                    content_dv.style.position = 'absolute';
                }

                //  for IE8. input type='text' => background-color : white
                if (/MSIE 8/.test(navigator.userAgent))
                {	
                    var inputs = content_dv.getElementsByTagName('input');
                    for (var i = 0; i < inputs.length; i++)
                    {	
                        if (inputs[i].type == 'text' || inputs[i].type == 'password')
                        {
                            inputs[i].style.backgroundColor = 'white';
                        }
                    }
                }

	            plus_( document.body,  content_dv );

				set_contentPosition(content_dv); //  이곳에 놔야 IE6 가 올바른 값을 인식한다.

                //  onresize 이벤트 등록
				sonar.util.addEvent(window, 'resize', function () {
					set_modalPos('onresize');
				});
				sonar.util.addEvent(window, 'scroll', function () {
					set_modalSize();
				});

                this.IS_OPEN = true;	// public

				if (is_ie6)
                {
                    set_IE6('hide');
					if ( e_('content') )
					{
						if ( parseInt(e_('content').scrollHeight) > parseInt(e_('content').clientHeight) )
						{
							modal_dv.style.width = parseInt( modal_dv.scrollWidth ) - 15;
						}
					}
                }
	        },

	        close	:	function ( ) {
	            closeModal();
                this.IS_OPEN = false;	// public
	        },

	        addFunc :   function (f){
	            addFunz(f);
	        }
	    }
	}( );
