﻿
//생성자
function JSJ() { };

JSJ.fn = JSJ.prototype = {

    //DOM 로딩 기다리기-Start---------------------------------------------------------------------------------------
    domReady: function(f) {
        //만일 DOM이 이미 로딩돼었다면 즉시 함수를 실행한다.
        if (JSJ.fn.domReady.done) return f();

        //만일 이미 어떤 함수를 추가한 적이 있다면
        if (JSJ.fn.domReady.timer) {
            //실행될 함수 목록에 그 함수를 추가한다.
            JSJ.fn.domReady.ready.push(f);
        } else {
            //단지 페이지 로딩이 먼저 끝날 경우를 대비하여
            //페이지 로딩이 끝나는 시점에 대한 이벤트를 추가한다.
            JSJ.fn.addEvent(window, "load", JSJ.fn.isDOMReady);

            //실행될 함수들의 배열을 초기화한다.
            JSJ.fn.domReady.ready = [f];

            //DOM이 준비되었는지 최대한 빨리 확인한다.
            JSJ.fn.domReady.timer = setInterval(JSJ.fn.isDOMReady, 13);
        }
    },

    isDOMReady: function() {
        //만일 이 페이지가 준비되었다고 이미 파악했다면 무시한다.
        if (JSJ.fn.domReady.done) return false;

        //여러 가지 함수와 엘리먼트에 접근할 수 있는지 확인한다.
        if (document && document.getElementsByTagName &&
          document.getElementById && document.body) {

            //만일 접근할 수 있다면 확인을 중지해도 좋다.
            clearInterval(JSJ.fn.domReady.timer);
            JSJ.fn.domReady.timer = null;

            //대기중인 모든 함수를 실행한다.
            for (var i = 0; i < JSJ.fn.domReady.ready.length; i++)
                JSJ.fn.domReady.ready[i]();

            JSJ.fn.domReady.ready = null;
            JSJ.fn.domReady.done = true;
        }
    },
    //DOM 로딩 기다리기-End---------------------------------------------------------------------------------------

    //이벤트등록-Start---------------------------------------------------------------------------------------
    addEvent: function(element, type, handler) {
        //각 이벤트 처리기에 고유의 ID를 부여한다.
        if (!handler.$$guid) handler.$$guid = JSJ.fn.guid++;

        //대상 엘리먼트의 이벤트 타입들에 대해 해시 테이블을 생성한다.
        if (!element.events) element.events = {};

        //엘리번트 / 이벤트 쌍에 대해 이벤트 처리기들의 해시 테이블을 생성한다.
        var handlers = element.events[type];


        if (!handlers) {
            handlers = element.events[type] = {};
            //만일 존재한다면 기존의 이벤트 처리기를 저장한다.
            if (element["on" + type]) {
                handlers[0] = element["on" + type];

            }
        }

        //이벤트 처리기를 해시테이블에 저장한다.
        handlers[handler.$$guid] = handler;

        //모든 작업을 담당하는 전역 이벤트 처리기를 할당한다.
        element["on" + type] = JSJ.fn.handleEvent;

    },

    //고유한 ID를 부여하기 위한 카운터
    guid: 1,


    removeEvent: function(element, type, handler) {
        //해시 테이블에서 이벤트처리기를 삭제한다.
        if (element.events && element.events[type]) {
            delete element.events[type][handler.$$guid];
        }
    },

    handleEvent: function(event) {
        var returnValue = true;

        //이벤트 객체를 얻는다 (IE에서는 전역 이벤트 객체를 사용한다).
        event = event || JSJ.fn.fixEvent(window.event);

        //이벤트 처리기들을 담고 있는 해시 테이블에 대한 참조를 얻는다.
        var handlers = this.events[event.type];

        //이벤트 처리기를 실행한다
        for (var i in handlers) {
            this.$$handleEvent = handlers[i];
            if (this.$$handleEvent(event) == false) {
                returnValue = false;
            }
        }

        return returnValue;
    },

    //IE의 이벤트 객체에 "빠진" 메서드 몇 종류를 추가한다.
    fixEvent: function(event) {
        //w3c의 표준 이벤트 메서드들을 추가한다.
        event.preventDefault = JSJ.fn.preventDefault;
        event.stopPropagaion = JSJ.fn.stopPropagation;
        return event;
    },

    preventDefault: function() {
        this.returnValue = false;
    },

    stopPropagation: function() {
        this.cancelBubble = true;
    },

    /*
    addEvent(window, "load", function(){
    addEvent(document.body, "keypress", function(e){
    if(e.keyCode == 32 && e.ctrlKey){
    this.getElementsByTagName("div")[0].style.display = "none";

			e.preventDefault();
    }
    });
    });
    */
    //이벤트등록-End---------------------------------------------------------------------------------------

    //일반함수-Start---------------------------------------------------------------------------------------
    //속성설정
    attr: function(elem, name, value) {
        //if(!name || name.constructor != String) return ' ';
        try {
            if (!name) return ' ';

            name = { 'for': 'htmlFor', 'class': 'className'}[name] || name;

            if (value != null) {
                elem[name] = value;

                if (elem.setAttribute) {
                    elem.setAttribute(name, value);
                }
            }
            else if (typeof name == "object" && value == undefined) {
                for (sub in name) {
                    if (elem.setAttribute) {
                        elem.setAttribute(sub, name[sub]);
                    }
                }
            }

            return elem[name] || elem.getAttribute(name) || ' ';

        }
        catch (e) {
            alert(e.message);
            return ' ';
        }

    },

    //기존 클래스에서 삭제
    removeClass: function(elem, name) {
        //대응하는 클래스가 있는지 검사한다.
        var re = new RegExp("(^|\\s)" + name + "(\\s|$)");

        //엘리먼트에 클래스가 주어져 있는지 검사하고 삭제
        if (re.test(elem.className)) {
            elem.className = elem.className.replace(name, "");
        }
    },

    //기존클래스에 추가
    addClass: function(elem, name) {
        //대응하는 클래스가 있는지 검사한다.
        var re = new RegExp("(^|\\s)" + name + "(\\s|$)");

        //엘리먼트에 클래스가 주어져 있는지 검사하고 삭제
        if (!re.test(elem.className)) {
            elem.className = elem.className + " " + name;
        }
    },


	//객체의 클래스를 배열로 반환
	getElemClassArray : function(elem){
		var elemArr = [];

		if(elem.className != undefined && elem.className != null)
		{
			 var cName  = elem.className.split(" ");

			 for(var i = 0; i < cName.length; i++){
				
					elemArr.push(cName[i]);
			 }
		}

		return elemArr;
	},


	//객체에 대응하는 클래스가 존재하는지
	haveClass : function(elem, name)
	{
		 var retVal = false;

		//대응하는 클래스가 있는지 검사한다.
		  var re = new RegExp("(^|\\s)" + name + "(\\s|$)");


        //엘리먼트에 클래스가 주어져 있는지 검사
        if (re.test(elem.className)) {
             retVal = true;
        }

		return retVal;
		
	},


    //스타일설정
    css: function(elem, name, value) {
        try {
            //name 값이 이상이 없다면..
            if (!name) return ' ';

            if (value != null) {
                elem.style[name] = value;
            }
            else if (typeof name == "object" && value == undefined) {
				
                for (sub in name) {
                    elem.style[sub] = name[sub];
                }
            }

            return elem[name] || ' ';
        }
        catch (e) {
            alert(e.message);
            return ' ';
        }
    },

    //Name 객체 가져오기
    tag: function(name) {
        return document.getElementsByTagName(name);
    },

    //공백제거
    trim: function(text) {
        return (text || "").replace(/^\s+|\s+$/g, "");
    },

    //Id 객체 가져오기
    id: function(name) {
        return document.getElementById(name);
    },

    //이전 Element가져오기
    prev: function(elem) {
        do {
            elem = elem.previousSibling;
        } while (elem && elem.nodeType != 1);
        return elem;
    },

    //마지막자식 Element가져오기
    last: function(elem) {
        elem = elem.lastChild;
        return elem && elem.nodeType != 1 ?
        JSJ.fn.prevSibling(elem) : elem;
    },

    //부모 Element 가져오기
    parent: function(elem, num) {
        num = num || 1;
        for (var i = 0; i < num; i++)
            if (elem != null) elem = elem.parentNode;
        return elem;
    },

    //첫번째 Element가져오기
    first: function(elem) {
        elem = elem.firstChild;
        return elem && elem.nodeType != 1 ?
		JSJ.fn.nextSibling(elem) : elem;
    },

    //다음 Element가져오기
    next: function(elem) {
        do {
            elem = elem.nextSibling;
        } while (elem && elem.nodeType != 1);
        return elem;
    },

    //주어진 엘리먼트의 style 프로퍼티를 얻어오기
    getStyle: function(elem, name) {
        //배열 style[]에 프로퍼티가 존재하면 최근에 값이 설정된것임.
        if (elem.style[name])
            return elem.style[name];
        //그렇지 않으면 IE의 메서드를 사용하려고 시도한다.
        else if (elem.currentStyle) {
            return elem.currentStyle[name];
        }
        //IE용 메서드를 사용할 수 없으면 W3C 메서드를 사용한다(존재할경우)
        else if (document.defaultView && document.defaultView.getComputedStyle) {
            //이 메서드는 textAlign 대신 text-align 형태의 문법을 사용한다.
            name = name.replace(/([A-Z])/g, "-$1");
            name = name.toLowerCase();

            //style 객체를 얻은 후 프로퍼티의 값(존재할경우)을 얻는다.
            var s = document.defaultView.getComputedStyle(elem, "");
            return s && s.getPropertyValue(name);
        }
        //그 외의 경우는 다른 종류의 브라우져를 사용하고 있는것임.
        else
            return null;
    },


    //엘리먼트의 최대 높이를 구한다(현재높이가 아님)
    fullHeight: function(elem) {
        //엘리먼트가 화면에 출력중이면, offsetHeight를 사용하고
        //그 외에는 getHeight()를 사용한다.
        if (JSJ.fn.getStyle(elem, 'display') != 'none')
            return elem.offsetHeight || getHeight(elem);

        //그렇지 않으면 엘리먼트의 display가 none으로 설정된 경우를 처리해야 한다.
        //따라서 좀더 정확한 값을 얻기 위해 css 프로퍼티의 값을 재설정한다.
        var old = JSJ.fn.resetCss(elem, {
            display: '',
            visibility: 'hidden',
            position: 'absolute'
        });

        //clientHeight를 사용하여 엘리먼트의 최대 높이를 알아낸다.
        //이것이 안된다면 getHeight함수를 사용한다.
        var h = elem.clientHeight || JSJ.fn.getHeight(elem);

        //마지막으로 css 프로퍼티의 값을 원래대로 복구한다.
        JSJ.fn.restoreCss(elem, old);

        return h;
    },

    //엘리먼트의 최대 너비를 구한다(현재 너비가 아님)
    fullWidth: function(elem) {
        //엘리먼트가 화면에 출력중이면 offsetHeight를 사용한다.
        //그외에는 getWidth를 사용한다.
        if (JSJ.fn.getStyle(elem, 'display') != 'none')
            return elem.offsetWidth || JSJ.fn.getWidth(elem);

        //그렇지 않으면 엘리먼트의 display가 none으로 설정된 경우를 처리해야한다.
        //따라서 좀더 정확한 값을 얻기 위해 css 프로퍼티의 값을 재설정한다.
        var old = JSJ.fn.resetCss(elem, {
            display: '',
            visibility: 'hidden',
            position: 'absolute'
        });

        //clientwidth를 사용하여 엘리먼트의 최대 너비를 알아낸다.
        //이것이 작동되지 않을때는 getWidth를 사용한다.
        var w = elem.clientWidth || JSJ.fn.getWidth(elem);

        //css 프로퍼티의 값을 원래 대로 복구한다.
        JSJ.fn.restoreCass(elem, old);

        return w;
    },

    //css 프로퍼티들의 값을 설정하는 함수이다
    //이 함수로 값을 재설정한 프로퍼티들은 나중에 원래 값으로 복구할 수 있다.
    resetCss: function(elem, prop) {
        var old = {};

        //각 프로퍼티에 대해 다음을 실행한다.
        for (var i in prop) {
            //기존값들을 기억해 둔다.
            old[i] = elem.style[i];
            //새로운값을 설정한다.
            elem.style[i] = prop[i];

        }

        //변경된 값들을 반환하여 restoreCss에서 사용할 수 있게 한다.
        return old;
    },

    //resetCss 함수의 실행 결과를 복구하는 함수.
    restoreCss: function(elem, prop) {
        for (var i in prop) {
            elem.style[i] = prop[i];
        }
    },

    //현재 엘리먼트를 숨기기 위한 함수
    hide: function(elem) {
        //현재 display의 상태가 무엇인지 알아낸다.
        var curDisplay = JSJ.fn.getStyle(elem, 'display');

        //나중을 위해 display의 현재 값을 기억해둔다.
        if (curDisplay != 'none')
            elem.$oldDisplay = curDisplay;

        //display를 none으로 설정한다
        elem.style.display = 'none';

    },

    //엘리먼트를 보여주기 위한  함수
    show: function(elem) {
        //display 프로퍼티를 원래 값으로 되돌리거나 원래값이 저장되어있지 않으면
        //block으로 설정한다.
        elem.style.display = elem.$oldDisplay || 'block';
    },

    //현재 웹페이지의 길이 반환
    pageHeight: function() {
        return document.body.scrollHeight;
    },

    //현재 웹페이지의 너비 반환
    pageWidth: function() {
        return document.body.scrollWidth;
    },


    //브라우저가 좌우로 얼마나 스크롤 되었는지 알아내는 함수
    scrollX: function() {

        //인터넷 익스프로러 6이 strict mode 로 돌아갈 때를 대비한 단축 코드
        var de = document.documentElement;

        //브라우저가 pageXOffset을 지원하면 바로 사용한다.
        return self.pageXOffset ||
        //그렇지 않으면, 루트노드를 기준으로 왼쪽으로 얼마나 스크롤되었는지를 구한다.
			(de && de.scrollLeft) ||
        //마지막으로 body 엘리먼트를 기준으로 왼쪽으로 얼마나 스크롤되었는지를 구한다.
			document.body.scrollLeft;
    },

    //브라우저가 아래위로 얼마나 스크롤되었는지 알아내는 함수
    scrollY: function() {

        //인터넷 익스프로러 6이 strict mode 로 돌아갈 때를 대비한 단축 코드
        var de = document.documentElement;

        //브라우저가 pageYOffset을 지원하면 바로 사용한다.
        return self.pageYOffset ||
        //그렇지 않으면, 루트노드를 기준으로 왼쪽으로 얼마나 스크롤되었는지를 구한다.
			(de && de.scrollTop) ||
        //마지막으로 body 엘리먼트를 기준으로 왼쪽으로 얼마나 스크롤되었는지를 구한다.
			document.body.scrollTop;
    },

    //일반함수-End---------------------------------------------------------------------------------------

    //파일관련 함수-Start---------------------------------------------------------------------------------------
    GetFileName: function(path) {
        var fileName = "";

        if (path != null) {
            var arrCnt = path.split("/");

            if (arrCnt != '') {
                fileName = arrCnt[arrCnt.length - 1];
            }
        }

        return fileName;
    },

    //파일확장자 가져오기
    GetExtension: function(path) {
        var Extension = "";

        var fileName = JSJ.fn.GetFileName(path);

        if (fileName != "") {
            var arrExten = fileName.split(".");

            Extension = arrExten[arrExten.length - 1];
        }
        return Extension;
    },

    //확장자 없이 파일명가져오기
    GetFileNameWithoutExtension: function(path) {
        var WithoutExFileName = "";

        var fileName = JSJ.fn.GetFileName(path);

        if (fileName != "") {
            var length = fileName.lastIndexOf('.');

            WithoutExFileName = fileName.substring(0, length);
        }

        return WithoutExFileName;
    },
    //파일관련 함수-End---------------------------------------------------------------------------------------

    //폼체크 함수-Start---------------------------------------------------------------------------------------
    errMsg: {
        // 주어진 필드가 필수 항목인지 검사한다.
        //!JSJ.fn.errMsg[name].test(elem, load)
        required: {
            msg: "필수 입력 항목입니다.",
            test: function(obj) {
                //필드에 입력된 텍스트가 없고 페이지가 로드되는 중에는 검사를
                //수행하지 않는다. (페이지가 로드될 때 '필수 입력 항목입니다.'
                //라는 메세지를 출력하면 약간 성가실 수 있기 때문
                //return obj.value || load || obj.value == obj.defaultValue;
                return obj.value;
            }
        },

        // 필드의 이메일 주소가 올바른지 검사한다.
        email: {
            msg: "이메일 주소가 유효하지 않습니다.",
            test: function(obj) {
                //입력된 값이 있으면, 이메일 주소인지 검사한다.
                return !obj.value ||
				/^[a-z0-9_+.-]+\@([a-z0-9-]+\.)+[a-z0-9]{2,4}$/i.test(obj.value);
            }
        },

        //필드에 입력된 값이 전화번호이면 특정 형식으로 자동 변환한다.
        phone: {
            msg: "전화번호 형식이 틀렸습니다.",
            test: function(obj) {

                var m = /(\d{2,3}).*(\d{3,4}).*(\d{4})/.exec(obj.value);

                if (m) obj.value = m[1] + m[2] + m[3];

                return !obj.value || m;
            }
        },

        // 필드에 입력된 값이 MM/DD/YYYY 형식의 올바른 날짜인지 검사한다.
        date: {
            msg: "날짜 형식이 틀렸습니다. YYYY-MM-DD.",
            test: function(obj) {
                //입력된 값이 있으면 MM/DD/YYYY 형식의 올바른 날짜인지 검사한다.
                return !obj.value || /^\d{4}\-\d{2}\-\d{2}$/.test(obj.value);
            }
        },

        // 필드에 올바른 URL이 입력되었는지검사한다.
        url: {
            msg: "URL형식이 틀렸습니다.",
            test: function(obj) {
                //입력된 값이 있으면, 기본 텍스트인 http://가 아닌지 검사한다.
                return !obj.value || obj.value == 'http://' ||
                //올바른 URL인지를 검사한다.
					/^https?:\/\/([a-z0-9-]+\.)+[a-z0-9]{2,4}.*$/.test(obj.value);
            }
        }
    },

    // 폼을 검증하고 엘러메세지를 출력하는 함수
    validateForm: function(form, formName, Art) {
		
        var valid = true;

        //엘리먼트 class에 더해진 폼이름
        var re = new RegExp("(^|\\s)" + formName + "(\\s|$)");
			
		
        //폼 내의 모든 필드를 순회한다.
        //form.elements는 폼 내의 모든 필드를 참조하는 배열
        for (var i = 0; i < form.elements.length; i++) {

            //출력중인 에러메시지를 중복해서 출력하지 않는다.
            JSJ.fn.hideErrors(form.elements[i]);
			
            //현재 폼체크에 해당되는 엘리먼트인지 체크
            if (re.test(form.elements[i].className)) {
                //필드에 입력된 값이 올바른 값인지 검사한다.
                if (!JSJ.fn.validateField(form.elements[i], Art))
                    valid = false;
            }

            if (Art != null && Art != "" && !valid)
                break;
        }

        return valid;
    },

    //단일 필드의 내용을 검증한다.
    validateField: function(elem, Art) {
        var errors = [];

        //출력중인 에러메시지를 중복해서 출력하지 않는다.
        JSJ.fn.hideErrors(elem);

        //사용가능한 모든 검증 기법들을 순회한다.
        for (var name in JSJ.fn.errMsg) {
            //에러 종류에 대응하는 클래스가 있는지 검사한다.
            var re = new RegExp("(^|\\s)" + name + "(\\s|$)");
            //엘리먼트에 클래스가 주어져 있는지 검사하고,
            //검증을 통과할 수 있는지 알아본다.
            if (re.test(elem.className) && !JSJ.fn.errMsg[name].test(elem)) {
			
                //검증에 실패하면 리스트에 에러메세지를 추가한다.
                errors.push(JSJ.fn.errMsg[name].msg);

                //alert 창 에러일경우
                if (Art != null) {
                    //각 컨트롤에 alt 값을 가져온다.
                    var alt = JSJ.fn.attr(elem, "alt");

                    //alt 가 null 이 아니고 "" 이 아니라면
                    if (alt != null && alt != "") {
                        //메세지 띄우기
                        alert(alt);
                        elem.focus();

                    }
                }
            }
        }

        //리턴 처리------------------------------------------------------

        //Alt 가 null 이 아니라면
        if (Art != null) {
            //에러메시지가 추가 된게 있다면
            if (errors.length)
            //false 를 리턴하여 더이상 루프를 돌지 않도록 한다.
                return false;
            else
                return true;
        } else {
            //출력해야 할 에러메세지가 있으면 화면에 보여준다.
            if (errors.length)
                JSJ.fn.showErrors(elem, errors);

            //하나라도 실패한 검증 작업이 있으면 false를 반환한다.
            return errors.length > 0;
        }

        //----------------------------------------------------------------------

    },


    //특정 폼 필드에 대한 에러메시지를 출력하거나 숨기는 함수들
    hideErrors: function(elem) {
        //현재 필드의 다음 엘리먼트를찾는다.
        var next = elem.nextSibling;

        //다음 엘리먼트가 ul 이고 에러와 관련된 클래스를 가지면 다음을 수행한다.
        if (next && next.nodeName == "UL" && next.className == "errors")

        //해당 엘리먼트를 제거한다. (에러 메시지 출력을 중지하는방법임)
            elem.parentNode.removeChild(next);
    },

    //폼 내의 특정 필드에 대한 에러 메시지 집합을 출력한다.
    showErrors: function(elem, errors) {
        //이 필드의 다음 엘리 먼트를 찾는다.
        var next = elem.nextSibling;

        //찾은 필드가 에러 출력에 사용할 엘리먼트가 아니면 다음을 수행한다.
        if (next && (next.nodeName != "UL" || next.className != "errors")) {

            //엘리먼트 하나를 새로 만든다.
            next = document.createElement("ul");

            next.className = "errors";

            //DOM의 현재 위치에 새로 만든 엘리먼트를 삽입한다.
            elem.parentNode.insertBefore(next, elem.nextSibling);
        }

        //에러를 출력할 UL 엘리먼트의 참조를 얻었다.
        //이제 모든 에러 메시지들을 순회한다.
        for (var i = 0; i < errors.length; i++) {

            //각 메시지마다 새로운 li 엘리먼트를 생성한다.
            var li = document.createElement("li");

            li.innerHTML = errors[i];

            //새로 생성한 엘리먼트를 DOM에 삽입한다.
            next.appendChild(li);
        }
    },

    //폼 검증 작업을 실행하기 위해 폼이 제출될 때까지 기다리는 함수
    watchForm: function(form, formName) {
        //폼이 제출되는지 감시한다.
        JSJ.fn.addEvent(form, 'submit', function() {

            //폼에 내용이 제대로 입력되었는지 검증한다.
            return JSJ.fn.validateForm(form, formName);
        });
    },

    //폼 검증을 시작하기 전에 필드 값의 변화를 살피는 함수
    watchFields: function(form, formName) {

        //엘리먼트 class에 더해진 폼이름
        var re = new RegExp("(^|\\s)" + formName + "(\\s|$)");

        //폼 내의 모든 필드 엘리먼트를 순회한다.
        for (var i = 0; i < form.elements.length; i++) {

            //현재 폼체크에 해당되는 엘리먼트인지 체크
            if (re.test(form.elements[i].className)) {

                //그리고 blur 이벤트 처리기를 설정한다.
                //이 이벤트 처리기는 입력 엘리먼트가 초점을 잃어버리는 시점을 감지한다.
                JSJ.fn.addEvent(form.elements[i], 'blur', function() {
                    //초점을 잃으면, 필드를 다시 검증한다.
                    return JSJ.fn.validateField(this);
                });

            }

        }
    },

    //폼 검증 작업을 실행하기 위해 폼이 제출될 때까지 기다리는 함수 Alert 스타일
    //폼,  전송객체,  이벤트, 검증이름, alert
    watchFormAlert: function(form, elem, e, formName, Art) {
        //폼이 제출되는지 감시한다.
		
        JSJ.fn.addEvent(elem, e, function() {

            //폼에 내용이 제대로 입력되었는지 검증한다.
            return JSJ.fn.validateForm(form, formName, Art);
        });
    },
    //폼체크 함수-End---------------------------------------------------------------------------------------

    //Ajax 함수-End---------------------------------------------------------------------------------------
    ajax: function(options) {
        options = {
            //HTTP 요청의 타입
            type: options.type || "POST",
            //요청을 전달할 URL
            url: options.url || "",
            //얼마나 오래 대기한후에 요청을 타임아웃으로 처리할지 지정한다.
            timeout: options.timeout || 5000,

            //요청이 실패, 성공, 완료 할때 호출할 함수들
            onComplete: options.onComplete || function() { },
            onError: options.onError || function() { },
            onSuccess: options.onSuccess || function() { },

            //서버에서 반환할 데이터타입
            //특별히 지정된 타입이 없는 경우에는 어떤 데이터가 반환되었는지 판단하여
            //적절히 작동하게 한다.
            data: options.data || ""
        };

        //요청 객체를 생성한다.
        var xml = new XMLHttpRequest();

        //비동기 요청을 생성한다.
        xml.open(options.type, options.url, true);

        // 5초간 대기한 후에 요청을 타임아웃으로 처리한다.
        var timeoutLength = options.timeout;

        //언제 요청이 성공적으로 끝났는지 기록한다.
        var requestDone = false;

        //현재 시각부터 5초후에 실행되는 콜백을 초기화한다.
        //이 콜백은 아직 수행중이라면 요청을 취소한다.

        setTimeout(function() {
            requestDone = true;
        }, timeoutLength);

        //문서의 상태가 언제 갱신되었는지 감시한다,
        xml.onreadystatechange = function() {

            //데이터가 전부 로딩될때 까지 기다린다.
            //그리고 요청이 이미 타임아웃 되지 않았는지 검사한다.
            if (xml.readyState == 4 && !requestDone) {

                //요청이 성공했는지 검사한다.
                if (httpSuccess(xml)) {
                    //서버에서 반환한 데이터와 함게 성공 콜백을 실행한다.
                    options.onSuccess(httpData(xml, options.type));

                    //이 외에는 에러가 발생한 것이므로 
                    //에러 콜백을 실행한다.
                }
                else {
                    options.onError();
                }

                //완료 콜백을 실행한다.
                options.onComplete();

                //메모리 누수 현상 방지를 위해 메모리 해제

                xml = null;
            }
        };

        xml.send();

        //XMLHttpRequest 객체가 '성공' 상태인지 검사하는 함수
        //XMLHttpRequest 객체를 전달인자로 받는다.
        function httpSuccess(r) {
            try {

                //만약 로컬 파일을 요청했을 때 서버 상태가 반환되지 않았다면
                //이를 성공으로 분류한다.
                return !r.status && location.protocol == "file:" ||

                //상태 코드값이 200번대라면 성공으로 분류한다.
				(r.status >= 200 && r.status < 300) ||

                //문서가 변경되지 않았으면 성공으로 분류한다.
				r.status == 304 ||



                //사파리는 파일이 변경되지 않았을때 빈 상태 코드를 반환한다.
				navigator.userAgent.indexOf("Safari") >= 0 &&
						typeof r.status == "undefined";
            } catch (e) {

                //만약 상태 검사가 실패하면 요청도 실패했다고 가정함
                return false;

            }
        }


        //Http 서버 응답에서 올바른 데이터를 추출하기 위한 함수
        function httpData(r, type) {
            //alert(type);
            //content-type 헤더를 받아온다
            var ct = r.getResponseHeader("content-type");

            //기본타입이 명시되지 않았다면
            //서버에서 받은 데이터가 어떤 XML형태인지 검사한다.
            var data = !type && ct && ct.indexOf("xml") >= 0;

            //서버에서 XML을 받았다면 xml Document 객체를 바아온다
            //이 외에는 서버에서 받은 텍스트를 반환한다.
            data = type == "xml" || data ? r.responseXML : r.responseText;

            //지정된 타입이 "script"이면 반환된 응답 데이터를 실행한다.
            if (type == "script")
                eval.call(window, data);

            //응답 데이터를 반환한다. 
            return data;
        }


    }
    //Ajax 함수-End---------------------------------------------------------------------------------------


};



//마우스위치이벤트-Start---------------------------------------------------------------------------------------
//마우스 생성자메서드
function MousePoint(event) {
    var browser = navigator.appName;

    var eX;
    var eY;

    if (browser == "Microsoft Internet Explorer") {
       eX = event.x;
        eY = event.y;
    }
    else {
        eX = event.clientX;
        eY = event.clientY;
    }


    this.elementX = (event && event.layerX) || window.event.offsetX;
    this.elementY = (event && event.layerY) || window.event.offsetY;

    this.mouseX = eX;
    this.mouseY = eY;
}

//마우스 x 좌표
MousePoint.prototype.getX = function() {
    return this.mouseX;
};

//마우스 y 좌표
MousePoint.prototype.getY = function() {
    return this.mouseY;
};

//엘리먼트에 상대적인 x 좌표
MousePoint.prototype.getElementX = function() {
    return this.elementX;
};

//엘리먼트에 상대적인 y 좌표
MousePoint.prototype.getElementY = function() {
    return this.elementY;
};
//마우스위치이벤트-End---------------------------------------------------------------------------------------
