/* Minification failed. Returning unminified contents.
(8,1): run-time error CSS1019: Unexpected token, found '$'
(8,2): run-time error CSS1019: Unexpected token, found '('
(8,11): run-time error CSS1031: Expected selector, found ')'
(8,11): run-time error CSS1025: Expected comma or open brace, found ')'
(239,2): run-time error CSS1019: Unexpected token, found ')'
(251,17): run-time error CSS1031: Expected selector, found '='
(251,17): run-time error CSS1025: Expected comma or open brace, found '='
(271,10): run-time error CSS1031: Expected selector, found 'ajaxHandleError('
(271,10): run-time error CSS1025: Expected comma or open brace, found 'ajaxHandleError('
(306,10): run-time error CSS1031: Expected selector, found 'AddLog('
(306,10): run-time error CSS1025: Expected comma or open brace, found 'AddLog('
(339,10): run-time error CSS1031: Expected selector, found 'runAjax('
(339,10): run-time error CSS1025: Expected comma or open brace, found 'runAjax('
(405,10): run-time error CSS1031: Expected selector, found 'fileAjax('
(405,10): run-time error CSS1025: Expected comma or open brace, found 'fileAjax('
(465,12): run-time error CSS1031: Expected selector, found '='
(465,12): run-time error CSS1025: Expected comma or open brace, found '='
(535,10): run-time error CSS1031: Expected selector, found 'Alert('
(535,10): run-time error CSS1025: Expected comma or open brace, found 'Alert('
(553,10): run-time error CSS1031: Expected selector, found 'Confirm('
(553,10): run-time error CSS1025: Expected comma or open brace, found 'Confirm('
(568,10): run-time error CSS1031: Expected selector, found 'AlertIframe('
(568,10): run-time error CSS1025: Expected comma or open brace, found 'AlertIframe('
(581,10): run-time error CSS1031: Expected selector, found 'ConfirmIframe('
(581,10): run-time error CSS1025: Expected comma or open brace, found 'ConfirmIframe('
(596,18): run-time error CSS1031: Expected selector, found '='
(596,18): run-time error CSS1025: Expected comma or open brace, found '='
(715,20): run-time error CSS1031: Expected selector, found '='
(715,20): run-time error CSS1025: Expected comma or open brace, found '='
(821,10): run-time error CSS1031: Expected selector, found 'fnOnydecimal('
(821,10): run-time error CSS1025: Expected comma or open brace, found 'fnOnydecimal('
(850,10): run-time error CSS1031: Expected selector, found 'postData('
(850,10): run-time error CSS1025: Expected comma or open brace, found 'postData('
(888,10): run-time error CSS1031: Expected selector, found 'getComboDataSource('
(888,10): run-time error CSS1025: Expected comma or open brace, found 'getComboDataSource('
(895,10): run-time error CSS1031: Expected selector, found 'swapArray('
(895,10): run-time error CSS1025: Expected comma or open brace, found 'swapArray('
(914,10): run-time error CSS1031: Expected selector, found 'getFilePathOnly('
(914,10): run-time error CSS1025: Expected comma or open brace, found 'getFilePathOnly('
(933,1): run-time error CSS1019: Unexpected token, found '('
(933,11): run-time error CSS1031: Expected selector, found '('
(933,11): run-time error CSS1025: Expected comma or open brace, found '('
(1429,2): run-time error CSS1019: Unexpected token, found '('
(1429,9): run-time error CSS1031: Expected selector, found ')'
(1429,9): run-time error CSS1025: Expected comma or open brace, found ')'
(1450,10): run-time error CSS1031: Expected selector, found 'sMenu('
(1450,10): run-time error CSS1025: Expected comma or open brace, found 'sMenu('
(1505,10): run-time error CSS1031: Expected selector, found 'fnGridToExcel('
(1505,10): run-time error CSS1025: Expected comma or open brace, found 'fnGridToExcel('
(1552,1): run-time error CSS1019: Unexpected token, found '('
(1552,11): run-time error CSS1031: Expected selector, found '('
(1552,11): run-time error CSS1025: Expected comma or open brace, found '('
(1576,2): run-time error CSS1019: Unexpected token, found '('
(1576,9): run-time error CSS1031: Expected selector, found ')'
(1576,9): run-time error CSS1025: Expected comma or open brace, found ')'
(1587,1): run-time error CSS1019: Unexpected token, found '('
(1587,11): run-time error CSS1031: Expected selector, found '('
(1587,11): run-time error CSS1025: Expected comma or open brace, found '('
(1606,2): run-time error CSS1019: Unexpected token, found '('
(1606,9): run-time error CSS1031: Expected selector, found ')'
(1606,9): run-time error CSS1025: Expected comma or open brace, found ')'
(1618,23): run-time error CSS1031: Expected selector, found '='
(1618,23): run-time error CSS1025: Expected comma or open brace, found '='
(1639,25): run-time error CSS1031: Expected selector, found '='
(1639,25): run-time error CSS1025: Expected comma or open brace, found '='
(1665,23): run-time error CSS1031: Expected selector, found '='
(1665,23): run-time error CSS1025: Expected comma or open brace, found '='
(1687,25): run-time error CSS1031: Expected selector, found '='
(1687,25): run-time error CSS1025: Expected comma or open brace, found '='
(1688,21): run-time error CSS1031: Expected selector, found '='
(1688,21): run-time error CSS1025: Expected comma or open brace, found '='
(1689,21): run-time error CSS1031: Expected selector, found '='
(1689,21): run-time error CSS1025: Expected comma or open brace, found '='
(1701,10): run-time error CSS1031: Expected selector, found 'myRound2('
(1701,10): run-time error CSS1025: Expected comma or open brace, found 'myRound2('
(1734,10): run-time error CSS1031: Expected selector, found 'removeArrayIndex('
(1734,10): run-time error CSS1025: Expected comma or open brace, found 'removeArrayIndex('
(1769,10): run-time error CSS1031: Expected selector, found 'setNumberFormat('
(1769,10): run-time error CSS1025: Expected comma or open brace, found 'setNumberFormat('
(1775,10): run-time error CSS1031: Expected selector, found 'removeNumberFormat('
(1775,10): run-time error CSS1025: Expected comma or open brace, found 'removeNumberFormat('
(1781,10): run-time error CSS1031: Expected selector, found 'inputNumberFormat('
(1781,10): run-time error CSS1025: Expected comma or open brace, found 'inputNumberFormat('
(1790,10): run-time error CSS1031: Expected selector, found 'Shuttle('
(1790,10): run-time error CSS1025: Expected comma or open brace, found 'Shuttle('
(1831,10): run-time error CSS1031: Expected selector, found 'checkAllGridRows('
(1831,10): run-time error CSS1025: Expected comma or open brace, found 'checkAllGridRows('
(1862,10): run-time error CSS1031: Expected selector, found 'strToPascal('
(1862,10): run-time error CSS1025: Expected comma or open brace, found 'strToPascal('
(1886,10): run-time error CSS1031: Expected selector, found 'strToCamel('
(1886,10): run-time error CSS1025: Expected comma or open brace, found 'strToCamel('
(1907,10): run-time error CSS1031: Expected selector, found 'renderProcess('
(1907,10): run-time error CSS1025: Expected comma or open brace, found 'renderProcess('
(1940,10): run-time error CSS1031: Expected selector, found 'renderTab('
(1940,10): run-time error CSS1025: Expected comma or open brace, found 'renderTab('
(1966,1): run-time error CSS1019: Unexpected token, found '('
(1966,11): run-time error CSS1031: Expected selector, found '('
(1966,11): run-time error CSS1025: Expected comma or open brace, found '('
(1970,2): run-time error CSS1019: Unexpected token, found ')'
(1970,3): run-time error CSS1019: Unexpected token, found '('
(1970,10): run-time error CSS1031: Expected selector, found ')'
(1970,10): run-time error CSS1025: Expected comma or open brace, found ')'
(1973,1): run-time error CSS1019: Unexpected token, found '('
(1973,11): run-time error CSS1031: Expected selector, found '('
(1973,11): run-time error CSS1025: Expected comma or open brace, found '('
(1977,2): run-time error CSS1019: Unexpected token, found ')'
(1977,3): run-time error CSS1019: Unexpected token, found '('
(1977,10): run-time error CSS1031: Expected selector, found ')'
(1977,10): run-time error CSS1025: Expected comma or open brace, found ')'
(1989,10): run-time error CSS1031: Expected selector, found 'getErrMsg('
(1989,10): run-time error CSS1025: Expected comma or open brace, found 'getErrMsg('
(1995,10): run-time error CSS1031: Expected selector, found 'showErrMsg('
(1995,10): run-time error CSS1025: Expected comma or open brace, found 'showErrMsg('
(2010,10): run-time error CSS1031: Expected selector, found 'isNullOrEmpty('
(2010,10): run-time error CSS1025: Expected comma or open brace, found 'isNullOrEmpty('
(2017,10): run-time error CSS1031: Expected selector, found 'getEmptyIfNullOrUndefined('
(2017,10): run-time error CSS1025: Expected comma or open brace, found 'getEmptyIfNullOrUndefined('
(2025,10): run-time error CSS1031: Expected selector, found 'setTabMenu('
(2025,10): run-time error CSS1025: Expected comma or open brace, found 'setTabMenu('
(2041,10): run-time error CSS1031: Expected selector, found 'makePhoneNumFormat('
(2041,10): run-time error CSS1025: Expected comma or open brace, found 'makePhoneNumFormat('
(2070,1): run-time error CSS1019: Unexpected token, found '('
(2070,11): run-time error CSS1031: Expected selector, found '('
(2070,11): run-time error CSS1025: Expected comma or open brace, found '('
(2104,2): run-time error CSS1019: Unexpected token, found '('
(2104,9): run-time error CSS1031: Expected selector, found ')'
(2104,9): run-time error CSS1025: Expected comma or open brace, found ')'
(2106,10): run-time error CSS1031: Expected selector, found 'clone('
(2106,10): run-time error CSS1025: Expected comma or open brace, found 'clone('
(2111,10): run-time error CSS1031: Expected selector, found 'getFileName('
(2111,10): run-time error CSS1025: Expected comma or open brace, found 'getFileName('
(2283,1): run-time error CSS1019: Unexpected token, found '('
(2283,11): run-time error CSS1031: Expected selector, found '('
(2283,11): run-time error CSS1025: Expected comma or open brace, found '('
(2416,2): run-time error CSS1019: Unexpected token, found '('
(2416,9): run-time error CSS1031: Expected selector, found ')'
(2416,9): run-time error CSS1025: Expected comma or open brace, found ')'
(2420,10): run-time error CSS1031: Expected selector, found 'cellNumberCheck('
(2420,10): run-time error CSS1025: Expected comma or open brace, found 'cellNumberCheck('
(2428,10): run-time error CSS1031: Expected selector, found 'emailCheck('
(2428,10): run-time error CSS1025: Expected comma or open brace, found 'emailCheck('
(2435,10): run-time error CSS1031: Expected selector, found 'onlyNumber('
(2435,10): run-time error CSS1025: Expected comma or open brace, found 'onlyNumber('
(2445,10): run-time error CSS1031: Expected selector, found 'removeChar('
(2445,10): run-time error CSS1025: Expected comma or open brace, found 'removeChar('
(2455,10): run-time error CSS1031: Expected selector, found 'onlyNumber2('
(2455,10): run-time error CSS1025: Expected comma or open brace, found 'onlyNumber2('
(2465,10): run-time error CSS1031: Expected selector, found 'removeChar2('
(2465,10): run-time error CSS1025: Expected comma or open brace, found 'removeChar2('
(2471,10): run-time error CSS1031: Expected selector, found 'comma('
(2471,10): run-time error CSS1025: Expected comma or open brace, found 'comma('
(2476,10): run-time error CSS1031: Expected selector, found 'uncomma('
(2476,10): run-time error CSS1025: Expected comma or open brace, found 'uncomma('
(2482,10): run-time error CSS1031: Expected selector, found '_excelDown('
(2482,10): run-time error CSS1025: Expected comma or open brace, found '_excelDown('
 */
/*
작성자 : 박현일
작성일 : 2015-02-05
목적 : util을 사용하는 모든 페이지의 랜더링 후의 초기 설정.
사용법 :
*/

$(document).ready(function (e) {
    $("#print").click(function (e) {
        e.preventDefault();
        var $print;
        if ($("#ui-main-container").length > 0)
            $print = $("#ui-main-container").clone().addClass("MQprint").prependTo();
        else if ($("#layout-index").length > 0)
            $print = $("#layout-index").clone().addClass("MQprint").prependTo();

        if (typeof $print == "undefined")
            return;

        window.print();
        $print.remove();
    });
    $("#excel").click(function (e) {
        e.preventDefault();
        if ($("#igGrid").length <= 0) {
            Alert("엑셀파일을 다운로드 할 수 없습니다. 관리자에게 문의바랍니다.");
            return;
        }

        var rows = $("#igGrid").data("igGrid").dataSource._data;
        if (!rows || rows.length <= 0) {
            Alert("엑셀을 다운로드 할 데이터가 없습니다.")
            return;
        }

        var isSingleHeader = true;
        var features = $("#igGrid").igGrid("option", "features");
        var hasSelector = false;

        $.each(features, function (i, _option) {
            if (_option.name == "RowSelectors") {
                if (_option.enableCheckBoxes || _option.enableRowNumbering) {
                    if (_option.excelExportNot != null && _option.excelExportNot) {
                        hasSelector = false;
                    } else {
                        hasSelector = true;
                    }
                    //hasSelector = true;
                }
            }
            else if (_option.name == "MultiColumnHeaders") {
                isSingleHeader = false;
            }
        });
        //debugger
        //그리드 데이터 조회
        var excelData = {};
        excelData.Rows = [];
        var cols = $('#igGrid').igGrid('option', 'columns');
        $.each(rows, function (idx, row) {
            var gridRow = {};
            gridRow.RowData = {};
            gridRow.ChildNode = {};
            //자식노드 key값 검색
            var childKey = $("#igGrid").igGrid("option", "dataSourceLayoutKey");
            var i = 0;

            if (hasSelector)
                gridRow.RowData["empty"] = "";

            $.each(cols, function (i, col) {
                var key = col.key;
                if (col.unbound == undefined && col.unbound)
                    value = "";
                else
                    value = row[key];

                //hi 추가 했습니다.
                if (col.output != undefined && col.output)
                    value = row[key];

                if (value != null) {
                    value = value.toString().replace(/</g, '&lt;');
                    value = value.toString().replace(/>/g, '&gt;');
                }

                if (isSingleHeader) {
                    if (col.hidden != true && col.excelHidden != true) {
                        if (key == childKey && value != null)
                            gridRow.ChildNode = value;
                        else {
                            gridRow.RowData[key] = value;
                        }
                    }
                } else {
                    if (col.hidden != true && col.excelHidden != true) {
                        gridRow.RowData[key] = value;
                    }
                }
            });
            excelData.Rows.push(gridRow);
        });

        //excelData.Header = $("#igGrid").igGrid("option", "columns");
        excelData.Header = getExcelHeader($("#igGrid").igGrid("headersTable"));
        runAjax('/ExcelDownload/ExportExcel', { excel: excelData, title: $("li.end").text() }, true, 'post', function (result) {
            if (result.success)
                window.location = '/ExcelDownload/DownloadExcel?excelFileName=' + result.fileName;
        }, true);
    });

    //엑셀헤더 조회
    function getExcelHeader(_html) {
        var tmpHeaderList = [];     //임시 header리스트
        var $html = $(_html);
        var $trs = $html.find("tr");
        var template = [];
        var $colunms = $($trs[0]).find("th");

        //td 템플릿 생성
        $.each($colunms, function (i, column) {
            var $column = $(column);
            //if ($column.css("display") != "none") {
            var header = {};
            var key = $column.prop("id");
            var colspan = typeof ($column.attr("colspan")) == "undefined" ? 0 : $column.attr("colspan") - 1;
            header.key = "";
            header.hidden = "";
            header.rowspan = "";
            header.colspan = "";
            header.headerText = "";
            header.skip = false;
            header.posx = 0;
            header.posy = 0;
            template.push(header);

            //컬럼수만큼 td복제
            for (var j = 0; j < colspan; j++) {
                template.push(clone(header));
            }
            //}
        });

        //템플릿을 기반으로 메트릭스 생성 X*Y 개
        $.each($trs, function (i, tr) {
            tmpHeaderList.push(clone(template));
        });

        var cols = $('#igGrid').igGrid('option', 'columns');

        cols = $.grep(cols, function (col, i) {
            return col.hidden != true && col.excelHidden != true;
        });

        var displayKeys = $.map(cols, function (col) {
            return col.key;
        });

        var headersList = [];    //엑셀용 헤더리스트

        $.each($trs, function (i, tr) {
            var $tr = $(tr);
            var $columns = $tr.find("th");
            var tmpHeaders = tmpHeaderList[i];
            var j = 0;  //header의 index

            var headers = [];       //엑셀용 헤더
            for (var j2 = 0; j2 < $columns.length; j2) {
                var tmpHeader = tmpHeaders[j];
                if (tmpHeader.skip) {
                    j++;
                    continue;
                }

                var $column = $($columns[j2]);
                var rowspan = typeof ($column.attr("rowspan")) == "undefined" ? 0 : parseInt($column.attr("rowspan"));
                var colspan = typeof ($column.attr("colspan")) == "undefined" ? 0 : parseInt($column.attr("colspan"));
                var key = typeof ($column.prop("id")) == "undefined" ? "" : $column.prop("id").replace("igGrid_", "");


                //if (displayKeys.contains(key) == false ) {
                // colspan 이 2보다 크면 Header 그룹이 되어 있는 것이고
                // header 그룹은 key가 없다.
                // 그러므로 skip하여서는 안됨


                if (displayKeys.contains(key) == false && colspan < 2) {
                    j2++;
                    continue;
                }

                tmpHeader.key = typeof (key) == "undefined" ? "" : key.replace("igGrid_", "");
                tmpHeader.hidden = $column.css("display") == "none" ? "true" : "false";
                tmpHeader.rowspan = rowspan > 0 ? rowspan - 1 : 0;
                tmpHeader.colspan = colspan > 0 ? colspan - 1 : 0;
                tmpHeader.headerText = $column.find(".ui-iggrid-headertext").text();
                tmpHeader.posx = j + 1; //엑셀 x좌표값
                tmpHeader.posy = i + 1; //엑셀 y좌표값

                //엑셀용 헤더에 헤더 정보를 담는다.
                headers.push(clone(tmpHeader));

                //row병합시 처리
                var loop = i + rowspan;
                for (var i2 = i + 1; i2 < loop; i2++) {
                    tmpHeaderList[i2][j].skip = true;
                }

                j += colspan > 0 ? colspan : 1;
                j2++;
            }
            headersList.push(headers);
        });
        return headersList;
    }

    $("#help").click(function (e) {
        e.preventDefault();
        window.open('/Help/Index', "help", "width=700, height=500,resizable=no");
    });

    $("#hidden_menu").click(function (e) {
        e.preventDefault();
        if ($(this).find(".fa-arrow-circle-left").length > 0) {
            $("aside").hide();
            $("#ui-main-container").css("padding-left", "0px");
            $(this).find(".fa-arrow-circle-left").removeClass().addClass("fa fa-arrow-circle-right");
            $(this).addClass("on");
        }
        else if ($(this).find(".fa-arrow-circle-right").length > 0) {
            $("aside").show();
            $("#ui-main-container").css("padding-left", "180px");
            $(this).find(".fa-arrow-circle-right").removeClass().addClass("fa fa-arrow-circle-left");
            $(this).removeClass();
        }
    });

    $(".search").focus();
});

/*
작성자 : 박현일
작성일 : 2014-11-14
목적 : query string을 만든다. 
사용법 :
    var query = new QueryString();
    query.add("AnalClassNo", $("#AnalClassNo").val());
    query.add("AnalPointNo", "박현일");
    query.get()
*/
var QueryString = function () {

    var arrParam = [];

    this.add = function (_key, _value) {
        arrParam.push(_key + "=" + escape(_value));
    };

    this.get = function () {

        if (arrParam.length == 0)
            return;

        return "?" + arrParam.join("&");
    };
};

//작성자 : 신창호
//목적 : ajax 에러 발생시 사용자 정의 에러 처리 페이지로 이동
//작성일 : 2014-11-05
function ajaxHandleError(req, s, e) {
    if (typeof (req) == "undefined" || !req)
        return;

    var json = req.responseJSON;
    var defaultMsg = "에러가 발생했습니다. 관리자에게 문의바랍니다.";

    var params = {};
    if (typeof (json) == "undefined") {
        Alert(defaultMsg);
        //Ajax에서 발생한 에러 정보를 로그에 남김
        AddLog("Unknown Ajax Error", "Custom Ajax Error : " + req.status + "  error:" + e, req.responseText);
        return;
    }

    //에러처리할 경로정보가 없으면 로그를 남김
    if (typeof (json.errorController) == "undefined" || typeof (json.errorAction) == "undefined") {
        Alert(defaultMsg);
        AddLog("No Ajax Error Info", "Custom Ajax Error", "에러처리할 수 있는 경로 정보가 없음");
        return;
    }

    var errUrl = "/" + json.errorController + "/" + json.errorAction;
    var jsonParam = { "errorData": JSON.stringify(json) };

    if (typeof (postData) == "function")
        postData(errUrl, jsonParam);
}

/*
로그를 남기는 메써드
errorPath : 에러/로그 발생 경로
errorType : 에러/로그 타입
errorMsg : 에러/로그 메시지
*/
function AddLog(errorPath, errorType, errorMsg) {
    var params = {};
    params.errorPath = errorPath;
    params.errorType = errorType;
    params.errorMsg = errorMsg;
    runAjax("/Error/CustomErrorLog", params, true, "post");
}

/*
작성자 : 박현일
작성일 : 2014-11-04
목적 : string type을 DOM의 형태로
기본 값:
    _DOM : string or DOM
*/
//function _getDOMType(_DOM) {
//    if (typeof _grid == "string")
//        _DOM = $("#" + _DOM);
//    return _DOM;
//}

/*
작성자 : 박현일
작성일 : 20140-10-24
목적 : ajax 처리.
기본 값:
    _url : 필수
    _params : null
    _async : false
    _type : post
    _func : callback 함수를 넣어 준다. 
    _showLoader : 로딩바 표현 여부(로딩바는 비동기식이어야 함)
*/
function runAjax(_url, _params, _async, _type, _func, _showLoader) {
    var result;

    _showLoader = typeof (_showLoader) == "undefined" ? false : _showLoader;

    function successDefaultFunction(req) {
        result = req;
    }

    function beforeSendDefaultFunction() {
        
        if (_async && _showLoader) {
            loader.onLoad();
            loader.fn.showLoading();
        }
    }

    function completeDefaultFunction() {
        //비동기식이고 로딩바를 사용하겠다면 완료후 로딩바 숨기기
        if (_async && _showLoader) 
            loader.fn.hideLoading();
    }

    if ($.isEmptyObject(_params))
        _params = null;

    if (!_url) {
        return;
    } 

    if (typeof _type != "string" || _type.toLowerCase() != "get")
        _type = "post";

    if (_async != true)
        _async = false;

    if (!$.isFunction(_func))
        _func = successDefaultFunction;

    $.ajax({
        type: _type,
        url: _url,
        data: _params,
        contentType: "application/x-www-form-urlencoded; charset=UTF-8",
        async: _async,
        success: _func,
        beforeSend: beforeSendDefaultFunction,
        complete: completeDefaultFunction,
        error: ajaxHandleError
    });

    return result;
}

/*
작성자 : 신창호
작성일 : 2014-12-09
목적 : file용 ajax 처리.
기본 값:
    _url : 필수
    _params : null
    _async : false
    _type : post
    _func : callback 함수를 넣어 준다. 
*/

function fileAjax(_url, _params, _func, _async, _showLoader) {
    var result;

    _showLoader = typeof (_showLoader) == "undefined" ? false : _showLoader;

    function successDefaultFunction(req) {
        result = req;
    }

    //로딩바 보이기
    function beforeSendDefaultFunction() {
        if (_async && _showLoader) {
            loader.onLoad();
            loader.fn.showLoading();
        }
    }

    //완료후 로딩바 숨기기
    function completeDefaultFunction() {
        //비동기식이고 로딩바를 사용하겠다면 완료후 로딩바 숨기기
        if (_async && _showLoader)
            loader.fn.hideLoading();
    }

    if ($.isEmptyObject(_params))
        _params = null;

    if (!_url) {
        return;
    }

    if (typeof (_async) == "undefined")
        _async = false;

    if (!$.isFunction(_func))
        _func = successDefaultFunction;

    $.ajax({
        url: _url,
        type: "POST",
        contentType: false,
        processData: false,
        cache: false,
        data: _params,
        async: _async,
        success: _func,
        beforeSend: beforeSendDefaultFunction,
        complete: completeDefaultFunction,
        error: ajaxHandleError
    });

    return result;
}

/*
작성자 : 신창호
작성일 : 2014-12-16
목적 : 로딩바 생성 객체
기본 값:
*/
var loader = {
    divContainer: null, //loading container
    onLoad: function (objId) {
        this.initializeComponent(objId);
    },
    initializeComponent: function (objId) {
        var divContainer = $.find("#_divContainer");
        //현재 loading bar가 있으면 삭제
        if (divContainer.length > 0) {
            $("#_divContainer").remove();
        }
        
        //body > divContiner > divLoader > img
        //loading bar 동적 생성
        divContainer = document.createElement("div");
        $(divContainer).prop("id", "_divContainer");
        $(divContainer).addClass("wrap-loading");
        $(divContainer).addClass("display-none");

        if (typeof (objId) == "undefined")
            $(document.body).prepend(divContainer);
        else {
            $("#" + objId).append(divContainer);
        }

        var divLoader = document.createElement("div");
        $(divContainer).append(divLoader);
        var img = document.createElement("img");
        $(img).prop("src", "/Content/infragistics/css/structure/images/igLoadingSmall.gif");
        $(divLoader).append(img);
        loader.divContainer = $(divContainer);
    },
    fn: {
        showLoading: function () {
            $('.wrap-loading').removeClass('display-none');
        },
        hideLoading: function () {
            $('.wrap-loading').addClass('display-none');
        }
        //Ajax에서 loading 사용예제
        //testLoading: function () {
        //    $.ajax({
        //        type: "post",
        //        url: "test",
        //        data: null,
        //        contentType: "application/x-www-form-urlencoded; charset=UTF-8",
        //        async: false,
        //        success: function () {
        //        },
        //        beforeSend: function () {
        //            $('.wrap-loading').removeClass('display-none');
        //        },
        //        complete: function () {
        //            $('.wrap-loading').addClass('display-none');
        //        },
        //        error: function (e) {
        //            //alert(e.message);
        //        }
        //    });
        //}
    }
}


/*
작성자 : 신창호
작성일 : 2014-12-24
목적 : div 팝업을 이용한 alert 표시
기본 값: 안내 문구
*/
function Alert(msg, callBackFunc) {
    jqueryDialog.onLoad(msg).then(function () {
        if (typeof (callBackFunc) == "function")
            callBackFunc.call(this);
    });
    
    //사용자 정의 dialog 사용
    //customDivPopup.onLoad();
    //customDivPopup.fn.addErrorMsg(msg);
    //customDivPopup.fn.popup();
}

/*
작성자 : 신창호
작성일 : 2014-12-24
목적 : div 팝업을 이용한 확인창 표시
기본 값: 안내 문구, callback 함수
*/
function Confirm(msg, callBackFunc) {
    //버튼이 클릭될 때까지 대기 하고 있다가 callback 함수 실행
    jqueryDialog.onLoad(msg, true).then(function (res) {
        if (typeof (callBackFunc) == "function") {0
            callBackFunc.call(this, res);
        }
    });
}

/*
작성자 : 신창호
작성일 : 2015-01-05
목적 : activeX가 사용되는 페이지에서 div 팝업을 사용하면 activeX 아래로 메시지가 숨어버리는 현상 해결
기본 값: 안내 문구
*/
function AlertIframe(msg, callBackFunc) {
    jqueryDialog.onLoad(msg, false, true).then(function () {
        if (typeof (callBackFunc) == "function")
            callBackFunc.call(this);
    });
}

/*
작성자 : 신창호
작성일 : 2014-12-24
목적 : activeX가 사용되는 페이지에서 div 팝업을 사용하면 activeX 아래로 메시지가 숨어버리는 현상 해결
기본 값: 안내 문구, callback 함수
*/
function ConfirmIframe(msg, callBackFunc) {
    //버튼이 클릭될 때까지 대기 하고 있다가 callback 함수 실행
    jqueryDialog.onLoad(msg, true, true).then(function (res) {
        if (typeof (callBackFunc) == "function") {
            callBackFunc.call(this, res);
        }
    });
}

/*
작성자 : 신창호
작성일 : 2014-12-24
목적 : jquery ui를 사용한 dialog 생성
기본 값:
*/
var jqueryDialog = {
    divDialog: null,    //div dialog 개체를 담는 변수
    addIframe: false,   //iframe이 포함된 팝업
    onLoad: function (msg, isConfirm, addIframe) {
        this.addIframe = typeof (addIframe) == "undefined" ? false : addIframe;

        //확인/닫기와 같은 버튼 이벤트를 받기 위한 differ 생성(비동기식)
        var defer = $.Deferred();
        this.initializeComponent(msg, isConfirm);
        this.initializeEvent(defer, isConfirm);
        //이벤트 리스너 대기 후 버튼 클릭시 defer.resolve를 통해 해제
        return defer.promise();
    },
    initializeComponent: function (msg) {
        if (typeof (msg) == "undefined")
            return;

        var tmpDivDialog = $.find("#_divDialog");
        //기존 등록된 팝업이 있으면 삭제
        if ($(tmpDivDialog).length > 0) {
            $(tmpDivDialog).dialog("destroy");
        }

        //팝업 동적 생성
        //divDialog > spanMsg
        divDialog = document.createElement("div");
        $(divDialog).prop("id", "_divDialog");
        $(divDialog).css("z-index", 999);
        $(divDialog).css("padding", "30px");
        
        //개행문자 처리
        var msgSplit = msg.split("\n");
        $.each(msgSplit, function (index, text) {
            //안내 문구 표시
            var divMsg = document.createElement("div");
            $(divDialog).append(divMsg);
            $(divMsg).text(text);
        });
        
        if (this.addIframe) {
            var tmpDivIframe = $.find("#_divIframe");
            //기존 등록된 iframe이 있으면 제거
            if ($(tmpDivIframe).length > 0)
                $(tmpDivIframe).remove();

            $(divDialog).css("position", "relative");
            var divIfm = document.createElement("div");
            $(divIfm).prop("id", "_divIframe");
            $(divIfm).css("z-index", "98").css("position","absolute");
            var iframe = document.createElement("iframe");
            $(iframe).prop("frameborder", 1);
            $(iframe).css("opacity", "0").css("position", "absolute");
            $(iframe).css("width", window.innerWidth || document.body.clientWidth);
            $(iframe).css("height", window.innerHeight || document.body.clientHeight);
            $(divIfm).append(iframe);

            //최상위 div 가 있으면 포함 없으면 body에 포함
            if ($("#wrapperDiv").length > 0)
                $(divIfm).prependTo("#wrapperDiv");
            else
                $(document.body).prepend(divIfm);
        }
        jqueryDialog.divDialog = divDialog;
    },
    initializeEvent: function (defer, isConfirm) {
        var divDialog = jqueryDialog.divDialog;
        var title = '안내';//isConfirm ? '안내' : '경고';
        var buttons = isConfirm ? {
            "예": function () {
                $("#_divIframe").css("display", "none");
                $(divDialog).dialog("close");   //다이얼로그를 먼저 닫고
                defer.resolve(true);            //defer를 해제 시켜야 함(그렇지 않으면 jquery 오류 발생)
            },
            "아니요": function () {
                $("#_divIframe").css("display", "none");
                $(divDialog).dialog("close");
                defer.resolve(false);
            }
        } : {
            "닫기": function () {
                $("#_divIframe").css("display", "none");
                $(divDialog).dialog("close");
                defer.resolve(false);
            }
        };


        var appendTo = "";
        if ($("#ui-top-container").length > 0)
            appendTo = "#ui-top-container";
        else
            appendTo = "body";

        $(divDialog).dialog({
            autoOpen: true,
            modal: true,
            title: title,
            appendTo: appendTo,  //★★★전체 영역을 마스크로 씌울 수 있도록 상단메뉴에 추가
            draggable: false,               //드래그 방지
            buttons: buttons,
            close: function () {
                $("#_divIframe").css("display", "none");
                $(divDialog).remove();
            }
        });       
    },
    fn: {
        getDialogObject: function(){
            return jqueryDialog.divDialog;
        }
    }
};

/*
작성자 : 신창호
작성일 : 2014-12-18
목적 : 사용자 정의 팝업 윈도우 생성 객체
기본 값:
*/
var customDivPopup = {
    divContainer: null, //popup container
    callBackFunc: null, //confirm callBack 함수
    onLoad: function (isConfirm, callBackFunc) {
        if (!isConfirm)
            isConfirm = false;

        if (isConfirm && typeof(callBackFunc) == "function")
            this.callBackFunc = callBackFunc;
        this.initializeComponent(isConfirm);
    },
    initializeComponent: function (isConfirm) {
        var divContainer = $.find("#_divContainer");
        //현재 loading bar가 있으면 삭제
        if (divContainer.length > 0)
            $("#_divContainer").remove();

        //팝업 동적 생성
        //body > divContiner > divMsg > ul > liMsg
        //                                 > liBtn > anchConfirm 
        //                                         > anchClose
        divContainer = document.createElement("div");
        $(divContainer).prop("id", "_divContainer");
        $(divContainer).addClass("wrap-loading");
        $(divContainer).addClass("display-none");
        //body의 최상위 child로 추가
        $(document.body).prepend(divContainer);

        var divMsg = document.createElement("div");
        $(divContainer).append(divMsg);
        $(divMsg).prop("id", "divMsg");
        $(divMsg).css("width", "500px");
        $(divMsg).css("background-color", "#ffffff");
        $(divMsg).css("border", "1px dotted #000000");
        $(divMsg).css("padding-top", "50px");
        $(divMsg).css("padding-left", "50px");
        $(divMsg).css("padding-right", "50px");

        var ulO = document.createElement("ul");
        $(ulO).prop("id", "_msgList");
        $(divMsg).append(ulO);

        var liMsg = document.createElement("li");
        $(liMsg).css("list-style", "none");
        $(liMsg).prop("id", "_liMsg");

        $(ulO).append(liMsg);

        var liBtn = document.createElement("li");
        $(liBtn).prop("id", "_liBtn");
        $(liBtn).css("list-style", "none");
        $(liBtn).css("margin-top", "50px");
        $(liBtn).css("margin-right", "-20px");
        $(liBtn).css("text-align", "right");
        $(ulO).append(liBtn);

        if (isConfirm) {
            var anchConfirm = document.createElement("a");
            $(anchConfirm).text("예");
            $(anchConfirm).on("click", function () {
                if (divPopup.callBackFunc) 
                    divPopup.callBackFunc.call(this, true);
                divPopup.fn.closePopup();
            });
            $(liBtn).append(anchConfirm);
        }

        var anchClose = document.createElement("a");
        $(anchClose).prop("id","anchClose");
        $(anchClose).text(isConfirm ? "아니요" : "확인");
        $(anchClose).css("margin-left", "10px");
        $(anchClose).on("click", function () {
            if (divPopup.callBackFunc)
                divPopup.callBackFunc.call(this, true);
            divPopup.fn.closePopup();
        });
        $(liBtn).append(anchClose);

        divPopup.divContainer = $(divContainer);
    },
    initializeEvent: function(){

    },
    fn: {
        addErrorMsg: function (msg) {
            $("#_liMsg").text(msg);
            var mainHeight = parseInt($('#_divContainer').css("height"));
            var mainWidth = parseInt($('#_divContainer').css("width"));           

            var popWidth = parseInt($("#divMsg").css("width").split("px").join(""));
            var popHeight = parseInt($("#divMsg").css("height").split("px").join(""));

            var left = Math.round(mainWidth - popWidth) / 2;//Math.round((scrollWidth - parseInt($("#divMsg").prop("scrollWidth"))) / 2 );
            var top = Math.round(mainHeight - popHeight) / 2;

            $("#divMsg").css("left", left);
            $("#divMsg").css("top", top);
        },
        popup: function () {
            $('.wrap-loading').removeClass('display-none');
        },
        closePopup: function () {
            $('.wrap-loading').addClass('display-none');
        }
    }
}
function fnOnydecimal(obj) {

    if (event.which == 37 || event.which == 38 || event.which == 39 || event.which == 40) {
        return;
    }
    obj.value = obj.value.replace(/[^0-9\.]/g, '');

    var _pattern = /^(\d{1,10}([.]\d{0,3})?)?$/;

    var _value = event.srcElement.value;


    if (!_pattern.test(_value)) {

        alert("소수점 셋째자리까지만 허용됩니다.");

        event.srcElement.value = event.srcElement.value.toString().match(/^.*\.\d{3}/) || event.srcElement.value;

        event.srcElement.focus();
    }
}
/*
작성자 : 신창호
작성일 : 20140-11-05
목적 : 동적으로 post 처리하는 함수
기본 값:
    action: post url, 필수
    _jsonParam : json 형태의 파라미터(자식노드를 가지고 있으면 안됨)
*/
function postData(_action, _jsonParam) {
    if (typeof (_action) == "undefined" || !_action)
        return;

    var doc = document;
    var frm = doc.createElement("form");
    var frmName = "dynamicForm";
    frm.name = frmName;
    if (typeof (_jsonParam) != "undefined") {
        try{
            for (var paramNames in _jsonParam) {
                var hidInput = doc.createElement("input");
                hidInput.type = "hidden";
                hidInput.name = paramNames;
                hidInput.value = _jsonParam[paramNames];
                frm.appendChild(hidInput);
            }
        }
        catch (e) {
            var hidInput = doc.createElement("input");
            hidInput.type = "hidden";
            hidInput.value = e.message;
            frm.appendChild(hidInput);
        }
    }

    doc.body.appendChild(frm);
    frm.action = _action;
    frm.method = "post";
    frm.submit();

    var dynamicForms = doc.getElementsByName(frmName);
    for (var i = 0; i < dynamicForms.length; i++) {
        doc.body.removeChild(dynamicForms[i]);
    }
}


function getComboDataSource(_query, _conds){
    var optList = new QueryOptionList(_query); 
    optList.setConditions(_conds);    
    return optList.Jsonfill(["-1", "--전체--"]);
}


function swapArray(_arrayO, oldIdx, newIdx) {
    if (newIdx >= _arrayO.length) {
        alert("옮기고자 하는 위치가 배열의 크기보다 클 수 없습니다.");
        return _arrayO;
    }

    _arrayO.splice(newIdx, 0, this.splice(oldIdx, 1)[0]);
    return _arrayO;
}

/*
작성자 : 신창호
작성일 : 2014-12-30
목적 : 파일 경로만 가져오는 함수 
예 : 
    _fullPath : http://test_site.com/images/test.gif
    _dirDiv : "/" 
    return : http://test_site.com/images/
*/
function getFilePathOnly(_fullPath, _dirDiv) {
    if (typeof (_dirDiv) == "undefined")
        _dirDiv = "/";
    return _fullPath.substring(0, _fullPath.lastIndexOf(_dirDiv));
}

/*
작성자 : 박현일
작성일 : 2014-11-19
목적 : CheMir에서 공통으로 사용하는 물질분류
기본 값:
    <div id="regul" style="width:100%; height:150px;overflow:auto;"></div>
    $("#regul").ucRegulSearchBox({
        ControlType: "R",
        DataType: "CHEM",
        Flag: "ITEMS"
    });
    var value = ("#regul").ucRegulSearchBox("value");
*/
(function ($) {

    //물질 분류 조회
    $.fn.ucRegulSearchBox = function (options) {

        var container = this;
        var containerId = container.attr("id");
        /*
        RegulationBox의 초기화
        */
        var initContainer = function () {
            /*
            more 버튼 추가
            */
            function getMoreButton() {
                return '<div class="btn-table-area vertical-top"><a href="#" class="btn_ss_defult" id="btn' + containerId + 'More">more<em></em></a>';
            }
            /*
            container 안에 table 생성
            */
            function getTable() {

                var table = $("<table></table>");

                table.attr({
                    id: containerId + "_table",
                    cellpadding: 0,
                    border: 1
                }).css({
                    width: "98%",
                    'background-color': 'white'
                });

                return table;
            }
            /*
            json 형식의 데이터를 가져 온다.
            */
            function getRows() {

                var url = "/Common/GetRegulationData";
                return runAjax(url, options);

            }
            /*
            tr object 생성
            */
            function getTr(row) {

                var tr = $("<tr></tr>");

                tr.attr({
                    id: "regul_row_" + row.RegulItemCode
                });

                return tr;
            }
            /*
            Class에 해당하는 td 생성
            */
            function getTdClass(row) {

                var tdClass = $("<td></td>");

                tdClass.attr({
                    id: "regul_row_class_" + row.RegulClassCode,
                    rowspan: row.RowSpan
                }).css({
                    width: '20%'
                });

                tdClass.append(row.RegulClassName);

                return tdClass;
            }
            /*
            Item에 해당하는 td 생성
            */
            function getTdItem(row) {

                var tdItem = $("<td></td>");

                tdItem.attr({
                    id: "regul_row_item_" + row.RegulItemCode
                }).css({
                    width: '25%'
                });

                tdItem.append(row.RegulItemName);

                return tdItem;
            }
            /*
            value에 해당하는 td 생성
            */
            function getTdValue(row) {

                var tdValue = $("<td></td>");

                tdValue.attr({
                    id: "regul_row_value_" + row.RegulItemCode,
                    'DataType': row.DataType
                }).css({
                    width: '50%'
                });

                if (row.DataType == "T") {

                    var checkBox = $("<input>").attr({
                        type: 'checkbox',
                        value: row.RegulItemCode
                    });

                    tdValue.append(checkBox);
                }
                else {

                    $.each(row.RegulationCombos, function (idx, cbo) {

                        var checkBox = $("<input>").attr({
                            type: 'checkbox',
                            value: cbo.CboCode
                        });

                        tdValue.append(checkBox);
                        tdValue.append(cbo.CboName);

                    });

                }

                return tdValue;
            }

            container.before(getMoreButton());//컨테이너 위에 more버튼을 추가

            $(document).on("click", "#btn" + containerId + "More", function () {

                var display = container.css("display");

                if (display == "none")
                    container.css("display", "block");
                else
                    container.css("display", "none");

            });

            container.css('display', 'none');

            var table = getTable();//테이블 생성
            /*
            테이블에 add될 tr, td를 생성한다.
            */
            $.each(getRows(), function (idx, row) {

                var tr = getTr(row);

                if (row.RowSpan > 0)
                    tr.append(getTdClass(row));

                tr.append(getTdItem(row));
                tr.append(getTdValue(row));

                table.append(tr);

            });

            container.append(table);
        };
        /*
        RegulationBox의 값을 가져온다.
        */
        var getValue = function () {

            var arr = [];

            var rowLimit = '▣';
            var keyValueLimit = '■';
            var valuesLimit = '|';

            var TtypeList = container.find("td[id^='regul_row_value'][dataType='T'] input[type='checkbox']:checked");
            //일반적인 타입인경우..
            $.each(TtypeList, function (idx, checkbox) {
                arr.push(checkbox.value + keyValueLimit + "Y");
            });
            //배열형식인 경우.
            var tdList = container.find("td[id^='regul_row_value'][dataType!='T']");
            //td에 id가 있으므로 td에 접근.
            $.each(tdList, function (idx, td) {
                //td안에 여러개의 checkbox가 있고 그중 체크된것들만.
                var checkboxList = $(td).find("input[type='checkbox']:checked");
                //td안에 checkbox가 체크된게 없을견우.
                if (checkboxList.length == 0)
                    return true;

                //td안에 체크된게 있을경우..
                var arrValues = [];
                $.each(checkboxList, function (idx, checkbox) {
                    arrValues.push(checkbox.value);
                });

                arr.push(td.id.replace("regul_row_value_","") + keyValueLimit + arrValues.join(valuesLimit));
            });

            return arr.join(rowLimit);
        };

        if (options == "value")
            return getValue();

        if (typeof options == 'object') {
            initContainer();
        }
    };
    //물질 분류 입력
    $.fn.ucRegulUpdateBox = function (options) {

        var container = this;
        var containerId = container.attr("id");

        var initContainer = function () {

            /*
            container 안에 table 생성
            */
            function getTable() {

                var table = $("<table></table>");

                table.attr({
                    id: containerId + "_table",
                    cellpadding: 0,
                    border: 1
                }).css({
                    width: "98%",
                    'background-color': 'white'
                });

                return table;
            }
            /*
            json 형식의 데이터를 가져 온다.
            */
            function getRows() {

                var url = "/Common/GetRegulationData";
                return runAjax(url, options);

            }
            /*
            tr object 생성
            */
            function getTr(row) {

                var tr = $("<tr></tr>");

                tr.attr({
                    id: "regul_row_" + row.RegulItemCode
                });

                return tr;
            }
            /*
            Class에 해당하는 td 생성
            */
            function getTdClass(row) {

                var tdClass = $("<td></td>");

                tdClass.attr({
                    id: "regul_row_class_" + row.RegulClassCode,
                    rowspan: row.RowSpan
                }).css({
                    width: '20%'
                });

                tdClass.append(row.RegulClassName);

                return tdClass;
            }
            /*
            Item에 해당하는 td 생성
            */
            function getTdItem(row) {

                var tdItem = $("<td></td>");

                tdItem.attr({
                    id: "regul_row_item_" + row.RegulItemCode
                }).css({
                    width: '25%'
                });

                tdItem.append(row.RegulItemName);

                return tdItem;
            }
            /*
            목적: T Type일 경우 체크 되면 '해당없음'을 텍스트 박스에 찍어준다.
            */
            function getTdCheckBox(row) {
                var tdChk = $("<td></td>");
                tdChk.attr({
                    id: "regul_row_check_" + row.RegulItemCode,
                    'DataType': row.DataType
                }).css({
                    width: '5%',
                    'text-align': 'center'
                });

                if (row.DataType == "T") {

                    var checkBox = $("<input>").attr({
                        type: 'checkbox',
                        value: row.RegulItemCode
                    }).click(function () {

                        if (this.checked)
                            container.find("#regul_row_value_" + this.value).find("input").val("해당없음");
                        else
                            container.find("#regul_row_value_" + this.value).find("input").val("");
                    });

                    tdChk.append(checkBox);
                }

                return tdChk;
            }
            /*
            value에 해당하는 td 생성
            */
            function getTdValue(row) {

                var tdValue = $("<td></td>");

                tdValue.attr({
                    id: "regul_row_value_" + row.RegulItemCode,
                    'DataType': row.DataType
                }).css({
                    width: '45%'
                });

                if (row.DataType == "T") {

                    var checkBox = $("<input>").attr({
                        type: 'text',
                        value: row.DataValue,
                        id: row.RegulItemCode
                    }).css({
                        width: '100%'
                    });

                    tdValue.append(checkBox);
                }
                else if (row.DataType == "M") {
                
                    $.each(row.RegulationCombos, function (idx, cbo) {
                        
                        var checkBox = $("<input>").attr({
                            type: 'checkbox',
                            value: cbo.CboCode
                        });

                        if (row.DataValue.split("|").indexOf(cbo.CboCode) > -1)
                            checkBox.attr("checked", true);

                        tdValue.append(checkBox);
                        tdValue.append(cbo.CboName);

                    });

                } else if (row.DataType == 'S') {

                    var select = $("<select></select>").attr("id", row.RegulItemCode);
                    select.append("<option value=''>선택하세요</option>");

                    $.each(row.RegulationCombos, function (idx, cbo) {

                        var selectItem = $("<option></option>").attr({
                            value: cbo.CboCode
                        });
                        selectItem.append(cbo.CboName);
                        select.append(selectItem);
                    });

                    if (row.DataValue != "")
                        select.val(row.DataValue);

                    tdValue.append(select);
                }

                return tdValue;
            }

            var table = getTable();//테이블 생성
            /*
            테이블에 add될 tr, td를 생성한다.
            */
            $.each(getRows(), function (idx, row) {

                var tr = getTr(row);

                if (row.RowSpan > 0)
                    tr.append(getTdClass(row));

                tr.append(getTdItem(row));
                tr.append(getTdCheckBox(row));
                tr.append(getTdValue(row));

                table.append(tr);

            });

            container.append(table);
            container.attr(options);
        };

        /*
        RegulationBox의 값을 가져온다.
        */
        var getValue = function () {

            var jsonRet = [];//최종 결과를 json 형식으로 리턴한다.
            var dataType = container.attr("DataType");
            var seqNo = container.attr("SeqNo");

            //T 타입인경우..
            var TtypeList = container.find("td[id^='regul_row_value'][dataType='T'] input[type='text']").filter(function(){
                return this.value == "" ? false : true;
            });

            $.each(TtypeList, function (idx, textbox) {

                var oRet = {};

                oRet.DataType = dataType;
                oRet.RegulItemCode = textbox.id;
                oRet.SeqNo = seqNo;
                oRet.DataValue = textbox.value;

                jsonRet.push(oRet);
            });

            //S 타입인경우
            var STypeList = container.find("td[id^='regul_row_value'][dataType='S'] select").filter(function () {
                return this.value == "" ? false : true;
            });

            $.each(STypeList, function (idx, selectbox) {

                var oRet = {};

                oRet.DataType = dataType;
                oRet.RegulItemCode = selectbox.id;
                oRet.SeqNo = seqNo;
                oRet.DataValue = selectbox.value;

                jsonRet.push(oRet);
            });

            //배열형식인 경우.
            var tdList = container.find("td[id^='regul_row_value'][dataType='M']");
            //td에 id가 있으므로 td에 접근.
            $.each(tdList, function (idx, td) {
                //td안에 여러개의 checkbox가 있고 그중 체크된것들만.
                var checkboxList = $(td).find("input[type='checkbox']:checked");
                //td안에 checkbox가 체크된게 없을견우.
                if (checkboxList.length == 0)
                    return true;

                //td안에 체크된게 있을경우..
                var arrValues = [];
                $.each(checkboxList, function (idx, checkbox) {
                    arrValues.push(checkbox.value);
                });

                var oRet = {};

                oRet.DataType = dataType;
                oRet.RegulItemCode = td.id.replace("regul_row_value_", "");
                oRet.SeqNo = seqNo;
                oRet.DataValue = arrValues.join("|");//123/445/234 형식으로 만들어 주려고...

                jsonRet.push(oRet);
            });

            return jsonRet;
        };

        if (options == "value")
            return getValue();

        if (typeof options == 'object') {
            initContainer();
        }
    };
}(jQuery));

/*
작성자 : 박현일
작성일 : 2014-11-24
목적 : 그리드용 메뉴
기본 값:
    id: menu id
사용 방법
    $(document).on("click", "[content-type='menu']", function (event) {

        menu = new sMenu("sMenu");
        menu.initMenu(event.clientX, event.clientY);
        menu.addMenu("정보", "test('aa')", true);
        menu.addMenu("수정", "test('bb')", false);
        menu.show();

    }).on("blur", "[content-type='menu']", function (event) {
        $("#sMenu").remove();
    });
*/
function sMenu(id) {

    $("#" + id).remove();

    //menu 생성
    var _menu = $("<ul id='" + id + "'></ul>");
    //menu 기본설정
    _menu.css({
        width: '150px',//기본 넓이
        position: 'absolute',//메뉴 기폰 포지션
        'z-index': 101
    });

    this.initMenu = function (_left, _top) {
        //위치
        _menu.css({
            'left': _left + 15,
            'top': _top - 10
        });
    };
    //메뉴 추가
    this.addMenu = function (name, func, disabled) {
        var menuItem = $("<li></li>");

        menuItem.attr({
            onclick: func
        });

        if (disabled)
            menuItem.addClass("ui-state-disabled");

        menuItem.append(name);

        _menu.append(menuItem);
    };
    //메뉴를 보여줌
    this.show = function () {
        _menu.menu();
        $("body").append(_menu);
    };

}

/*
작성자 : 최대용
작성일 : 2014-12-08
목적 : 엑셀 다운로드
기본 값:
    id:  
사용 방법
    $("#btnExport").on("click", function (e) {  
        fnGridToExcel( $("#igGrid"));
    });
*/

function fnGridToExcel(oGrid){
    str = ""; 

    var ExcelApp = new ActiveXObject("Excel.Application");
    var ExcelWorkbook = ExcelApp.Workbooks.Add();
                
    var ExcelSheet = ExcelWorkbook.ActiveSheet; //new ActiveXObject("Excel.Sheet"); 

    ExcelApp.Visible = true;
                
    ExcelSheet.Range("A1", "Z1").Font.Bold = true;  
    ExcelSheet.Range("A1", "Z1").Font.ColorIndex = 2;
                
    //Format table headers
    var headersTable = oGrid.igGrid("headersTable")[0];
    for (var headerRowIndex = 0;
        headerRowIndex < headersTable.rows.length;
        headerRowIndex++) {
        var headerRow = headersTable.rows[headerRowIndex];
                     

        for (var headerCellIndex = 0;  headerCellIndex < headerRow.cells.length; headerCellIndex++) 
        {
            var headerCell = headerRow.cells[headerCellIndex];
                                   
            ExcelSheet.Cells(headerRowIndex + 1, headerCellIndex+1).Value = $(headerCell).text();
                        
            if(headerRowIndex==0)
            {
                ExcelSheet.Cells(headerRowIndex + 1, headerCellIndex+1).Interior.ColorIndex = 49;
                ExcelSheet.Rows(headerRowIndex+1).HorizontalAlignment =3; 
            }
        }
    }  
                
    ExcelSheet.Columns.AutoFit();//사이즈자동조절 
}

/*
작성자 : 박현일
작성일 : 2014-12-09
목적 : 텍스트박스에 숫자만 입력 받는다.
기본 값:

사용 방법
    $(".selector").ucNumericText();
*/
(function ($) {
    $.fn.ucNumericText = function () {
        this.css("IME-MODE: disabled;");
        this.keydown(function (e) {
            // 허용: backspace, delete, tab, escape, enter and .
            if ($.inArray(e.keyCode, [46, 8, 9, 27, 13, 110, 190]) !== -1 ||
                // 허용: Ctrl+A
                (e.keyCode == 65 && e.ctrlKey === true) ||
                // 허용: 첫번째 - 부호
                (this.value.length == 0 && e.keyCode == 189) ||
                // 허용: home, end, left, right, down, up
                (e.keyCode >= 35 && e.keyCode <= 40)) {
                // let it happen, don't do anything
                return;
            }
            // Ensure that it is a number and stop the keypress
            if ((e.shiftKey || (e.keyCode < 48 || e.keyCode > 57)) && (e.keyCode < 96 || e.keyCode > 105)) {
                e.preventDefault();
            }
        });
        this.change(function (e) {
            this.value = this.value.replace(/[^0-9\.]/g, '');
        });
    };
}(jQuery));

/*
작성자 : KMH
작성일 : 2015-02-10
목적 : 텍스트박스에 숫자형 문자(전화번호, 사업자 번호 : '-' 입력가능) 만 입력 받는다.
기본 값:

사용 방법
    $(".selector").ucNumericStringText();
*/
(function ($) {
	$.fn.ucNumericStringText = function () {
		this.css("IME-MODE: disabled");
		this.keydown(function (e) {
			// 허용: backspace, delete, tab, escape, enter and - 부호.
			if ($.inArray(e.keyCode, [8, 46, 9, 27, 13, 189, 109]) !== -1 ||
				// 허용: Ctrl+A
                (e.keyCode == 65 && e.ctrlKey === true) ||
				// 허용: home, end, left, right, down, up
                (e.keyCode >= 35 && e.keyCode <= 40)) {
				// let it happen, don't do anything
				return;
			}
			// Ensure that it is a number and stop the keypress
			if ((e.shiftKey || (e.keyCode < 48 || e.keyCode > 57)) && (e.keyCode < 96 || e.keyCode > 105)) {
				e.preventDefault();
			}
		});
	};
}(jQuery));

/*
작성자 : 박현일
작성일 : 2014-12-09
목적 : 문자열을 바이트로 길이로 리턴.
기본 값:

사용 방법
    var aa = "aaa";
    aa.byte();
*/
String.prototype.byte = function () {
    var str = this;
    var length = 0;
    for (var i = 0; i < str.length; i++) {
        if (escape(str.charAt(i)).length >= 4)
            length += 2;
        else if (escape(str.charAt(i)) == "%A7")
            length += 2;
        else if (escape(str.charAt(i)) != "%0D")
            length++;
    }
    return length;
}

/*
작성자 : 이영진
작성일 : 2015-10-28
목적 : string format
사용예 :  
    "안녕하세요! {0}입니다.".format("홍길동");
*/
String.prototype.format = function () {
    var str = this;

    for (var i = 0; i < arguments.length; i++) {
        var regExp = new RegExp('\\{' + i + '\\}', 'gm');

        if (arguments[i] == null) {
            str = str.replace(regExp, '');
        } else {
            str = str.replace(regExp, arguments[i]);
        }
    }

    return str;
};

/*
작성자 : 신창호
작성일 : 2015-04-20
목적 : 날짜 포멧지정
기본 값:

사용 방법
    new Date().format("yyyy-MM-dd");
    new Date().format("yyyy년 MM월 dd일 a/p hh시 mm분 ss초");
*/
Date.prototype.format = function (f) {
    if (!this.valueOf()) return " ";

    var weekName = ["일요일", "월요일", "화요일", "수요일", "목요일", "금요일", "토요일"];
    var d = this;

    return f.replace(/(yyyy|yy|MM|dd|E|hh|mm|ss|a\/p)/gi, function ($1) {
        switch ($1) {
            case "yyyy": return d.getFullYear();
            case "yy": return (d.getFullYear() % 1000).zf(2);
            case "MM": return (d.getMonth() + 1).zf(2);
            case "dd": return d.getDate().zf(2);
            case "E": return weekName[d.getDay()];
            case "HH": return d.getHours().zf(2);
            case "hh": return ((h = d.getHours() % 12) ? h : 12).zf(2);
            case "mm": return d.getMinutes().zf(2);
            case "ss": return d.getSeconds().zf(2);
            case "a/p": return d.getHours() < 12 ? "오전" : "오후";
            default: return $1;
        }
    });
};
String.prototype.string = function (len) { var s = '', i = 0; while (i++ < len) { s += this; } return s; };
String.prototype.zf = function (len) { return "0".string(len - this.length) + this; };
Number.prototype.zf = function (len) { return this.toString().zf(len); };


/*
작성자 : 최대용
작성일 : 2014-12-15
목적 : 일정 소수자리수(nDecimal)에서 반올림하여 리턴 함수
기본 값:
    id:  
사용 방법
     myRound2(dData, nDecimal)
*/
function myRound2(dData, nDecimal) {
    var dValue;
    var i;

    dValue = parseFloat(dData);

    for (i = 1; i <= nDecimal; i++) {
        dValue = parseFloat(dValue) * 10;
    }
    //alert(dValue);


    dValue = Math.round(dValue);
    //alert(dValue);

    for (i = 1 ; i <= nDecimal; i++) {
        dValue = parseFloat(dValue) / 10;
        //alert(i + '//' + dValue);
    }

    return dValue;
}

/*
작성자 : 신창호
작성일 : 2015-01-06
목적 : 배열의 해당 index 부분을 삭제하는 함수
기본 값:
    arr : array
    rmIdx : 삭제하고자 하는 배열의 index
사용 방법
     removeArrayIndex(arr, 1)
*/
function removeArrayIndex(arr, rmIdx) {
    //인덱스 기본값(유효하지 않으면 0) 설정
    rmIdx = isNaN(rmIdx) ? 0 : rmIdx;

    //첫번째 인덱스 삭제시
    if (rmIdx == 0) {
        arr = arr.slice(rmIdx + 1, arr.length);
    }
    //마지막 인덱스 삭제시
    else if (rmIdx == arr.length - 1) {
        arr = arr.slice(-1 * arr.length, -1);
    }
    //중간 인덱스 삭제시
    else {
        var front = arr.slice(0, rmIdx);    //인덱스 앞부분 잘라오기
        var rear = arr.slice(rmIdx + 1, arr.length);    //인덱스 뒷부분 잘라오기
        arr = front.concat(rear);   //array를 하나로 통합
    }
    return arr;
}

/*
작성자 : 신창호
작성일 : 2015-01-13
목적 : 숫자 표현 함수 - 천단위 자리수 구분, 천단위 자리수 제거, input box에 콤마 추가하는 함수 추가
기본 값:
    setNumberFormat(number)
    removeNumberFormat(string)
    inputNumberFormat(inputObj)
사용 방법
     setNumberFormat(1000)
     removeNumberFormat("1,000")
     inputNumberFormat(txtO)
*/
//자리수 구분(,)
function setNumberFormat(num) {
    num = String(num);
    return num.replace(/(\d)(?=(?:\d{3})+(?!\d))/g, '$1,');
}

//자리수 제거
function removeNumberFormat(numTypeStr) {
    numTypeStr = String(numTypeStr);
    return parseInt(numTypeStr.replace(/[^\d]+/g, ''));
}

//input box에 자동으로 콤마추가하기
function inputNumberFormat(obj) {
    obj.value = setNumberFormat(removeNumberFormat(obj.value));
}

/*
작성자 : 박현일
작성일 : 2015-04-17
목적 : 셔틀박스의 기능 모듈
*/
function Shuttle() {
    this.downList = function (selector) {
        $.each($(selector).find(":selected").get().reverse(), function (idx, option) {
            $(option).next().after($(option));
        });
    }
    this.upList = function (selector) {
        $.each($(selector).find(":selected"), function (idx, option) {
            $(option).prev().before($(option));
        });
    }
    this.add = function (from, to) {
        var $options = $(from).find(":selected").filter(function (i, option) {
            return !$(to).find("option").is("[value='" + option.value + "']");
        }).clone();
        $(from).find("option").attr("selected", false);

        $(to).append($options);
    }
    this.del = function (selector) {
        $(selector).find(":selected").remove();
    }
    this.delAll = function (selector) {
        $(selector).find("option").remove();
    }
    this.noSelect = function (selector) {
        $(selector).find("option").attr("selected", false);
    }
}

/*
작성자 : 신창호
작성일 : 2015-03-24
목적 : grid 전체 선택 함수
사용예 :  
chkAll은 체크박스 오브젝트
$("#chkAll").change(function (e) {
    e.preventDefault();
    checkAllGridRows(this);
});
*/
function checkAllGridRows(checkboxO) {
    var $th = $(".ui-iggrid-rowselector-class");
    var $checkboxContainer = $(".ui-iggrid-rowselector-class > span[name=chk]");
    var $checkbox = $(".ui-iggrid-rowselector-class > span[name=chk] > span");
    if ($(checkboxO).prop("checked")) {
        $th.addClass("ui-iggrid-selectedcell ui-state-active");
        $checkboxContainer.attr("data-chk", "on");
        $checkbox.removeClass("ui-igcheckbox-normal-off");
        $checkbox.addClass("ui-igcheckbox-normal-on");
    }
    else {
        $th.removeClass("ui-iggrid-selectedcell ui-state-active");
        $checkboxContainer.attr("data-chk", "off");
        $checkbox.removeClass("ui-igcheckbox-normal-on");
        $checkbox.addClass("ui-igcheckbox-normal-off");
    }
}

/*
작성자 : 신창호
작성일 : 2015-04-20
목적 : 문자열을 파스칼 케이스로 변환
파라미터 : 
    _orgStr : [필수]원본문자열
    _spliter : 구분자, [기본값]_
사용예 :  
strToPascal("this is Test", " ");
->ThisIsTest
strToPascal("this_is_Test");
->ThisIsTest
*/
function strToPascal(_orgStr, _spliter) {
    _spliter = typeof (_spliter) == "undefined" ? "_" : _spliter;
    var strArr = _orgStr.split(_spliter);
    var tmpArr = [];
    $.each(strArr, function (idx, str) {
        str = str.charAt(0).toUpperCase() + str.substr(1, str.length - 1);
        tmpArr.push(str);
    });
    return tmpArr.join("");
}

/*
작성자 : 신창호
작성일 : 2015-04-20
목적 : 문자열을 카멜 케이스로 변환
파라미터 : 
    _orgStr : [필수]원본문자열
    _spliter : 구분자, [기본값]_
사용예 :  
strToCamel("this is Test", " ");
->thisIsTest
strToCamel("this_is_Test");
->thisIsTest
*/
function strToCamel(_orgStr, _spliter) {
    _spliter = typeof (_spliter) == "undefined" ? "_" : _spliter;
    var strArr = _orgStr.split(_spliter);
    var tmpArr = [];
    $.each(strArr, function (idx, str) {
        if (idx == 0)
            str = str.charAt(0).toLowerCase() + str.substr(1, str.length - 1);
        else
            str = str.charAt(0).toUpperCase() + str.substr(1, str.length - 1)
        tmpArr.push(str);
    });
    return tmpArr.join("");
}

/*
작성자 : 박현일
작성일 : 2015-09-21
목적 : 프로세스 바를 생성
샘플: ArWorkPermit/WorkPermit
*/

function renderProcess(target, currStep, activeStep, r, params, isGongmuDept, WorkState) {
    $(target).addClass("sub-menu");
    $.each(r, function (idx, row) {
        $li = $("<li class='none'><a href='#'>" + row.ProcessName + "</a><span></span></li>");
        // 2022-01-24 허지훈 추가 : 공무팀이 아닐 시 TBM 활동일지 탭 표시 안함
        if (!isGongmuDept && row.ProcessCode == "50") {
            return true;
        }
        if (row.ProcessCode == currStep) {
            $li.removeClass().addClass("on");
            $li.find("a").attr("href", "javascript:void(0)");
        }
        else if (row.ProcessCode <= activeStep) {
            $li.removeClass().addClass("on-none");
            $li.find("a").attr("href", row.ProcessUrl + params);
        }
        else {
            // 2022-01-24 허지훈 추가 : 승인완료 시 탭 활성화
            // row.ProcessCode == "50" -> TBM 활동일지
            // workStatus in ('50', '60') 승인완료, 작업완료
            if (row.ProcessCode == "50" && (WorkState == "50" || WorkState == "60")) {
                $li.removeClass().addClass("on-none");
                $li.find("a").attr("href", row.ProcessUrl + params);
            }
            else {
                $li.find("a").attr("href", "javascript:void(0)");
            }
        }

        $(target).append($li);
    });
}

function renderTab(target, currStep, activeStep, r, params) {
    $(target).addClass("sub-menu");
    $.each(r, function (idx, row) {
        $li = $("<li class='none'><a href='#'>" + row.ProcessName + "</a><span></span></li>");
        // 현재 activestep value 없으므로 그냥 메뉴 이동만 thko 24-04-22

        if (row.ProcessCode == currStep) {
            $li.removeClass().addClass("on");
            $li.find("a").attr("href", "javascript:void(0)");
        } else {
            $li.removeClass().addClass("on-none");
            $li.find("a").attr("href", row.ProcessUrl + params);
        }
        //else if (row.ProcessCode <= activeStep) {
        //    $li.removeClass().addClass("on-none");
        //    $li.find("a").attr("href", row.ProcessUrl + params);
        //}
        //else {
        //    $li.find("a").attr("href", "javascript:void(0)");
        //}

        $(target).append($li);
    });
}

// 가로 스크롤바
(function ($) {
    $.fn.hasHorizontalScrollBar = function () {
        return this.get(0) ? this.get(0).scrollWidth > this.innerWidth() : false;
    }
})(jQuery);

// 세로 스크롤바
(function ($) {
    $.fn.hasVerticalScrollBar = function () {
        return this.get(0) ? this.get(0).scrollHeight > this.innerHeight() : false;
    }
})(jQuery);

/*
작성자 : 박현일
작성일 : 2015-10-20
목적 : 에러 메시지를 가져온다.
사용법 :
    case 1: getErrMsg("작업전 점검/확인 사항을 가져오는 중")
        return "작업전 점검/확인 사항을 가져오는 중 오류가 발생했습니다. 시스템 관리자에게 문의 하세요."
    case 2: getErrMsg();
        return "처리시 예기치 않은 오류가 발생했습니다. 시스템 관리자에게 문의 하세요."
*/
function getErrMsg(userMsg) {
    if (typeof userMsg == "string")
        return userMsg + " 오류가 발생했습니다. 시스템 관리자에게 문의 하세요.";
    return "처리시 예기치 않은 오류가 발생했습니다. 시스템 관리자에게 문의 하세요.";
}

function showErrMsg(err) {
    if (typeof err == "string")
        Alert(getErrMsg(err));
    else if (typeof err == "number") {
        if (err == 100)
            Alert("처리시 예기치 않은 오류가 발생했습니다. 시스템 관리자에게 문의 하세요. 숫자");
        else
            Alert("처리시 예기치 않은 오류가 발생했습니다. 시스템 관리자에게 문의 하세요. 숫자형 기본");
    }
    else {
        Alert("처리시 예기치 않은 오류가 발생했습니다. 시스템 관리자에게 문의 하세요.");
    }
}

// null or empty 체크 phl 추가
function isNullOrEmpty(target) {
    if (target == undefined || target == null || target == "")
        return true;
    return false;
}

// null or undefined 이면 ""을 돌려 준다.
function getEmptyIfNullOrUndefined(target) {
    if (isNullOrEmpty(target))
        return "";
    return target;
}


//탭메뉴 설정
function setTabMenu(_menuName, _link, _hasSub) {
    _hasSub = typeof (_hasSub) == "undefined" ? false : _hasSub;
    var menuName = _menuName;
    var $tabMenuArea = $(".tab-menu-area");
    var $span = $("<span>");
    $tabMenuArea.append($span);
    var $anch = $("<a>");
    $anch.prop("href", _link);
    $anch.text(menuName);
    $span.addClass("tab-on");
    $span.append($anch);

    $(".subTitle-01 h1").text(_menuName);
}

//전화번호 형식 맞추기
function makePhoneNumFormat(phoneNum) {
    phoneNum = phoneNum.split("-").join("");
    var length = phoneNum.length;
    //02-000-0000
    if (length == 9) {
        phoneNum = phoneNum.substring(0, 2) + "-" + phoneNum.substring(2, 5) + "-" + phoneNum.substring(5, length);
    }
        //02-0000-0000, 000-000-0000
    else if (length == 10) {
        if (phoneNum.substring(0, 2) == "02") {
        }
        else {
            phoneNum = phoneNum.substring(0, 3) + "-" + phoneNum.substring(3, 6) + "-" + phoneNum.substring(6, length);
        }
    }
        //000-0000-0000
    else {
        phoneNum = phoneNum.substring(0, 3) + "-" + phoneNum.substring(3, 7) + "-" + phoneNum.substring(7, length);
    }
    return phoneNum;
}
/*
작성자 : lsh
작성일 : 2016-02-24
목적 : 기존 ucNumericTextDiv 에 align를 설정할 수 있도록 수정
기본 값:
사용 방법
    $(".selector").ucNumericTextDiv2();
*/
(function ($) {
    $.fn.ucNumericTextDiv = function (align) {
        //this.css("IME-MODE","disabled").css("text-align", "right");        
        if (isNullOrEmpty(align)) {
            if (!this.hasClass("number"))
                this.addClass("number");
        } else {
            this.css('IME-MODE', 'disabled');
            this.css('text-align', align);
        }

        this.keydown(function (e) {            
            // 허용: backspace, delete, tab, escape, enter and .
            if ($.inArray(e.keyCode, [46, 8, 9, 27, 13, 110, 190]) !== -1 ||
                // 허용: Ctrl+A
                (e.keyCode == 65 && e.ctrlKey === true) ||
                // 허용: 첫번째 - 부호
                (!isNaN(this.value.charAt(0)) && (e.keyCode == 189) || (e.keyCode == 109)) ||
                // 허용: home, end, left, right, down, up
                (e.keyCode >= 35 && e.keyCode <= 40)) {
                // let it happen, don't do anything
                return;
            }
            // Ensure that it is a number and stop the keypress
            if ((e.shiftKey || (e.keyCode < 48 || e.keyCode > 57)) && (e.keyCode < 96 || e.keyCode > 105)) {
                e.preventDefault();
            }
        });
        this.change(function (e) {
            if (this.value == "")
                this.value = "0";
            this.value = setNumberFormat(removeNumberFormat(this.value));
        });
    };
}(jQuery));

function clone(_json) {
    return JSON.parse(JSON.stringify(_json));
}

//2017.09.04. 김병수 추가.
function getFileName(_filePath, _spliter) {
    if (!_filePath)
        return _filePath;

    if (typeof (_spliter) == "undefined" || !_spliter)
        _spliter = "/";

    var fileArr = _filePath.split(_spliter);
    if (fileArr.length == 2 && fileArr[1] == "")
        return fileArr[0];
    return fileArr[fileArr.length-1];
}

// 2017.11.07 hsm 추가. SHE 시스템에 있는 util.js에서 ucMultiSelect 복사
/*
멀티 체크박스

<input type="text" value="10,30" id="multiselect" style="width:200px" />

$("#multiselect").ucMultiselect({
    dataSource: [
        { code: "10", name: "First checkbox" }
        , { code: "20", name: "Second checkbox" }
        , { code: "30", name: "Third checkbox" }
    ],
    valueKey: "code",
    textKey: "name",
    width: "200px",
    nullText: "-선택하세요-",
    maxHeight: "100px", // 옵션 기본값은 200
    allCheck : false,
    showFunc : function(){},
    hideFunc : function(){}
});
<div class='multiselect'>
    <div class='selectBox' onclick='showCheckboxes()'>
        <select>
            <option>Select an option</option>
        </select>
        <div class='overSelect'></div>
    </div>
    <div id='checkboxes'>
        <label for='one'><input type='checkbox' id='one' />First checkbox</label>
        <label for='two'><input type='checkbox' id='two' />Second checkbox </label>
        <label for='three'><input type='checkbox' id='three' />Third checkbox</label>
    </div>
</div>
*/
/* 2024.10.25. 크로버전 업데이트(ver130) 이후 멀티셀렉트 안되는 오류 수정.
 * 주요 변경사항과 개선사항은 다음과 같습니다:
1.	이벤트 바인딩 개선
	.click() 대신 .on('click', ...) 사용
	이벤트 버블링 방지를 위한 e.stopPropagation() 추가
2.	포커스/블러 처리 개선
	blur 이벤트 대신 document 클릭 이벤트로 변경
	외부 클릭 시 드롭다운 닫기 기능 추가
3.	값 처리 개선
	초기 값이 없을 때의 예외 처리
	값 변경 시 trigger('change') 추가하여 이벤트 발생
4.	오류 처리 개선
	콘솔에 자세한 에러 로깅 추가
	예외 발생 시 throw하여 상위로 전파
5.	성능 개선
	jQuery 셀렉터 캐싱
	불필요한 DOM 조작 최소화

(function ($) {
    $.fn.ucMultiselect = function (Json) {
        try {
            var id = this.attr("id");
            var arr = $(this).val().split(",");
            var arr2 = [];
            var width = isNullOrEmpty(Json.width) ? "200px" : Json.width;
            var maxHeight = isNullOrEmpty(Json.maxHeight) ? "200px" : Json.maxHeight;
            var allCheck = isNullOrEmpty(Json.allCheck) ? false : Json.allCheck;

            var showFunction = typeof (Json.showFunc) == 'function' ? Json.showFunc : function () { };
            var hideFunction = typeof (Json.hideFunc) == 'function' ? Json.hideFunc : function () { };

            var $main = $("<div>").addClass("yullin-multiselect-multiselect").width(width);
            var $div1 = $("<div>").addClass("yullin-multiselect-selectbox");
            var $div2 = $("<div style='max-height:200px;overflow-y:auto;'>").addClass("yullin-multiselect-checkboxes").width(width).attr("id", "ucmultiselect_checkboxes_" + id);

            if (!isNullOrEmpty(Json.maxHeight))
                $div2.css("max-height", maxHeight);

            if (allCheck) {
                var $checkbox = $("<input class='checkbox' id='ucmultiselect_" + id + "_all_check' type='checkbox' />");
                $checkbox.change(function () {
                    var checking = $(this).is(":checked");
                    $("#ucmultiselect_checkboxes_" + id).find("input:not(:first)").prop("checked", checking);
                    var len = $("#ucmultiselect_checkboxes_" + id).find("input:not(:first):checked").length;
                    var allCheckArr = [];
                    $.each($("#ucmultiselect_checkboxes_" + id).find("input:not(:first):checked"), function (index, checkbox) {
                        allCheckArr.push($(checkbox).attr("value"));
                    });
                    var optiontext = allCheckArr.length == 0 ? Json.nullText : allCheckArr.length + " 건 선택됨.";
                    $("#ucmultiselect_select_" + id + " option:first").text(optiontext);
                    $("#" + id).val(allCheckArr.join(","));
                });
                var $option = $("<label for='ucmultiselect_" + id + "_all_check'></label>").append($checkbox).append("전체선택");
                $div2.append($option);
            }

            $.each(Json.dataSource, function (index, row) {
                //체크박스 생성 및 이벤트 처리
                var $checkbox = $("<input class='checkbox' text='" + row[Json.textKey] + "' value='" + row[Json.valueKey] + "' type='checkbox' id='ucmultiselect_" + id + "_" + row[Json.valueKey] + "' />");
                $checkbox.change(function () {
                    var arr4 = [];

                    if (allCheck) {
                        $.each($(this).parent().parent().find("input:not(:first):checked"), function (index, checkbox) {
                            arr4.push($(checkbox).attr("value"));
                        });
                    }
                    else {
                        $.each($(this).parent().parent().find("input:checked"), function (index, checkbox) {
                            arr4.push($(checkbox).attr("value"));
                        });
                    }

                    var optiontext = arr4.length == 0 ? Json.nullText : arr4.length + " 건 선택됨.";
                    $("#ucmultiselect_select_" + id + " option:first").text(optiontext);
                    $("#" + id).val(arr4.join(","));
                });

                var $option = $("<label for='ucmultiselect_" + id + "_" + row[Json.valueKey] + "'></label>").append($checkbox).append(row[Json.textKey]);
                if ($.inArray(row[Json.valueKey], arr) > -1) {
                    $option.find("input").prop("checked", true);// 고민
                    arr2.push(row[Json.valueKey]);
                }
                $div2.append($option);
            });

            var optiontext = arr2.length == 0 ? Json.nullText : arr2.length + " 건 선택됨.";
            var $select = $("<select id='ucmultiselect_select_" + id + "'>").width(Json.width).append("<option>" + optiontext + "</option>");

            $select.click(function (e) {
                if ($("#ucmultiselect_checkboxes_" + id).is(":hidden")) {
                    $("#ucmultiselect_checkboxes_" + id).show().focus();
                }
                else {
                    $("#ucmultiselect_checkboxes_" + id).hide();
                }
            });

            $div3 = $("<div>").addClass("yullin-multiselect-overselect");

            $div1.append($select).append($div3);
            $main.append($div1);
            $main.append($div2);
            $("#" + id).attr("type", "hidden");
            $("#" + id).after($main);

            $("#ucmultiselect_checkboxes_" + id).blur(function (e) {
                if ($(this).has(document.activeElement).length == 0) {
                    $div2.hide();
                    hideFunction();
                }
                else {
                    $div2.focus();
                    showFunction();
                }
            });
        }
        catch (err) {
            alert(err);
        }
    };
}(jQuery));
*/

(function ($) {
    $.fn.ucMultiselect = function (Json) {
        try {
            var id = this.attr("id");
            var arr = $(this).val() ? $(this).val().split(",") : [];
            var arr2 = [];
            var width = isNullOrEmpty(Json.width) ? "200px" : Json.width;
            var maxHeight = isNullOrEmpty(Json.maxHeight) ? "200px" : Json.maxHeight;
            var allCheck = isNullOrEmpty(Json.allCheck) ? false : Json.allCheck;

            var showFunction = typeof (Json.showFunc) == 'function' ? Json.showFunc : function () { };
            var hideFunction = typeof (Json.hideFunc) == 'function' ? Json.hideFunc : function () { };

            var $main = $("<div>").addClass("yullin-multiselect-multiselect").width(width);
            var $div1 = $("<div>").addClass("yullin-multiselect-selectbox");
            var $div2 = $("<div>").addClass("yullin-multiselect-checkboxes").width(width).attr("id", "ucmultiselect_checkboxes_" + id);

            // 최대 높이 설정
            $div2.css({
                'max-height': maxHeight,
                'overflow-y': 'auto'
            });

            if (allCheck) {
                var $checkbox = $("<input>").addClass('checkbox')
                    .attr({
                        'id': 'ucmultiselect_' + id + '_all_check',
                        'type': 'checkbox'
                    });

                $checkbox.on('change', function () {
                    var checking = $(this).prop("checked");
                    $("#ucmultiselect_checkboxes_" + id).find("input:not(:first)").prop("checked", checking);

                    var allCheckArr = [];
                    $("#ucmultiselect_checkboxes_" + id).find("input:not(:first):checked").each(function () {
                        allCheckArr.push($(this).val());
                    });

                    var optiontext = allCheckArr.length == 0 ? Json.nullText : allCheckArr.length + " 건 선택됨.";
                    $("#ucmultiselect_select_" + id + " option:first").text(optiontext);
                    $("#" + id).val(allCheckArr.join(",")).trigger('change');
                });

                var $option = $("<label>")
                    .attr('for', 'ucmultiselect_' + id + '_all_check')
                    .append($checkbox)
                    .append("전체선택");

                $div2.append($option);
            }

            $.each(Json.dataSource, function (index, row) {
                var $checkbox = $("<input>").addClass('checkbox')
                    .attr({
                        'type': 'checkbox',
                        'id': 'ucmultiselect_' + id + '_' + row[Json.valueKey],
                        'value': row[Json.valueKey],
                        'data-text': row[Json.textKey]
                    });

                $checkbox.on('change', function () {
                    var arr4 = [];
                    var $checkboxes = allCheck ?
                        $(this).closest('.yullin-multiselect-checkboxes').find("input:not(:first):checked") :
                        $(this).closest('.yullin-multiselect-checkboxes').find("input:checked");

                    $checkboxes.each(function () {
                        arr4.push($(this).val());
                    });

                    var optiontext = arr4.length == 0 ? Json.nullText : arr4.length + " 건 선택됨.";
                    $("#ucmultiselect_select_" + id + " option:first").text(optiontext);
                    $("#" + id).val(arr4.join(",")).trigger('change');
                });

                var $option = $("<label>")
                    .attr('for', 'ucmultiselect_' + id + '_' + row[Json.valueKey])
                    .append($checkbox)
                    .append(row[Json.textKey]);

                if ($.inArray(row[Json.valueKey].toString(), arr) > -1) {
                    $checkbox.prop("checked", true);
                    arr2.push(row[Json.valueKey]);
                }

                $div2.append($option);
            });

            var optiontext = arr2.length == 0 ? Json.nullText : arr2.length + " 건 선택됨.";
            var $select = $("<select>")
                .attr('id', 'ucmultiselect_select_' + id)
                .width(width)
                .append($("<option>").text(optiontext));

            // 클릭 이벤트 개선
            $select.on('click', function (e) {
                e.stopPropagation();
                var $checkboxes = $("#ucmultiselect_checkboxes_" + id);
                if ($checkboxes.is(":hidden")) {
                    $(".yullin-multiselect-checkboxes").hide();
                    $checkboxes.show();
                    showFunction();
                } else {
                    $checkboxes.hide();
                    hideFunction();
                }
            });

            $div3 = $("<div>").addClass("yullin-multiselect-overselect");
            $div1.append($select).append($div3);
            $main.append($div1).append($div2);

            // 외부 클릭 처리
            $(document).on('click', function (e) {
                if (!$(e.target).closest('.yullin-multiselect-multiselect').length) {
                    $(".yullin-multiselect-checkboxes").hide();
                    hideFunction();
                }
            });

            // 기존 input을 hidden으로 변경
            this.attr("type", "hidden").after($main);

            // 초기 상태 설정
            $div2.hide();

            return this;
        } catch (err) {
            console.error("ucMultiselect Error:", err);
            throw err;
        }
    };
}(jQuery));


// 2017.11.22 hsm 추가. 휴대폰 정규식 체크
function cellNumberCheck(str) {
    // 휴대폰번호 정규식
    var regExp = /^01([0|1|6|7|8|9]?)-?([0-9]{3,4})-?([0-9]{4})$/;

    return regExp.test(str);
}

// 2017.11.22 hsm 추가. 이메일 정규식 체크
function emailCheck(str) {
    var regExp = /^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i;

    return regExp.test(str);
}
 
// 2018.07.27 마한울 휴대폰 유효성 체크 : 숫자, -, 제어키(백스페이스, tab, delete, 왼쪽 화살표, 오른쪽 화살표)만 등록되도록 처리
function onlyNumber(event) {
    event = event || window.event;
    var keyID = (event.which) ? event.which : event.keyCode;
    if ((keyID >= 48 && keyID <= 57) || (keyID >= 96 && keyID <= 105) || keyID == 189 || keyID == 8 || keyID == 9 || keyID == 46 || keyID == 37 || keyID == 39)
        return;
    else
        return false;
}

// 2018.07.27 마한울 휴대폰 유효성 체크 : shift 조합 문자를 체크하기 위해서 숫자와 - 를 제외한 문자는 지우도록 처리
function removeChar(event) {
    event = event || window.event;
    var keyID = (event.which) ? event.which : event.keyCode;
    if (keyID == 189 || keyID == 8 || keyID == 9 || keyID == 46 || keyID == 37 || keyID == 39)
        return;
    else
        event.target.value = event.target.value.replace(/[^0-9\-]/g, "");
}

//20230214 변진솔 number 유효성 체크 : 숫자, ., 제어키(백스페이스, tab, delete, 왼쪽 화살표, 오른쪽 화살표)만 등록되도록 처리
function onlyNumber2(event) {
    event = event || window.event;
    var keyID = (event.which) ? event.which : event.keyCode;
    if ((keyID >= 48 && keyID <= 57) || (keyID >= 96 && keyID <= 105) || keyID == 8 || keyID == 9 || keyID == 46 || keyID == 37 || keyID == 39 || keyID == 110 || keyID == 190)
        return;
    else
        return false;
}

//20230214 변진솔 number replace : 숫자, . 제외한 문자 모두 지우도록 처리
function removeChar2(num) {
    if (num == undefined)
        num = "undefined";
    return num.replace(/[^0-9\.]/g, "");
}

function comma(str) {
    str = String(str);
    return str.replace(/(\d)(?=(?:\d{3})+(?!\d))/g, '$1,');
}

function uncomma(str) {
    str = String(str);
    return str.replace(/[^\d]+/g, '');
}

//excel 다운로드할때 merge 컬럼 셋팅 
function _excelDown(grid, selBoxInfo) {
    var columns = grid.igGrid('option', 'columns').filter(function (row) {
        return !row.hidden;
    });

    var strCols = columns.reduce(function (pre, cur) {
        return pre + cur.key + ',';
    }, '');
    var arrCols = strCols.substr(0, strCols.length - 1).split(',');
    var data = grid.data('igGrid').dataSource._data;
    var RowData = [];



    $.each(data, function (i, row) {
        var tmp = {};
        $.each(arrCols, function (j, col) {
            var selTmp = selBoxInfo.filter(function (item) {
                return item.col == col;
            });

            if (selTmp.length) {
                var selTextObj = selTmp[0].selBox.filter(function (item) {
                    return item.Value == row[col];
                });
                if (selTextObj.length) {
                    tmp[col] = selTextObj[0].Text;
                } else {
                    tmp[col] = '';
                }
            } else {
                tmp[col] = row[col];
            }
        });
        RowData.push({
            RowData: tmp
            , ChildNode: {}
        });
    });

    var arrHeader = [];
    // 깊이 지정
    var setDeepLvl = function (header, deepLvl, posx, posy) {
        if (Array.isArray(header)) {
            var colspan = 0;
            $.each(header, function (i, row) {
                var cspan = setDeepLvl(row, deepLvl, ++posx, posy);
                colspan += cspan;
                if (row.group) {
                    posx += cspan - 1;
                }
                row.colspan = cspan;
                if (arrHeader[deepLvl - 1]) {
                    arrHeader[deepLvl - 1].push(row);
                } else {
                    arrHeader[deepLvl - 1] = [row];
                }
            });
            return colspan;
        } else {
            header.deepLvl = deepLvl;

            header.posx = posx;
            header.posy = posy;
            if (header.group) {
                header.group = header.group.filter(function (row) {
                    return !row.hidden;
                });
                return setDeepLvl(header.group, ++deepLvl, --posx, ++posy);
            } else {
                return 1;
            }
        }
    }

    var header = grid.igGridMultiColumnHeaders("getMultiColumnHeaders").filter(function (row) {
        return !row.hidden;
    });
    setDeepLvl(header, 1, 0, 1);

    var exportHeader = [];

    for (var i = 0; i < arrHeader.length; i++) {
        var tmp = [];
        for (var j = 0; j < arrHeader[i].length; j++) {
            var target = arrHeader[i][j];
            tmp.push({
                colspan: target.colspan ? target.colspan - 1 : 0
                , headerText: target.headerText
                , posx: target.posx
                , posy: target.posy
                , key: target.key
                , hidden: false
                , rowspan: target.rowspan ? target.rowspan - 1 : 0
            });
        }
        exportHeader.push(tmp);
    }
    var title = '엑셀 변환';
    runAjax('/ExcelDownload/ExportExcel', { excel: { Header: exportHeader, Rows: RowData }, title: $("li.end").text() }, true, 'post', function (result) {
        if (result.success) {
            var fileName = title ? title + ".xlsx" : result.fileName;
            window.location = '/ExcelDownload/DownloadExcel?excelFileName=' + fileName;
        }
    }, true);
}
