PageSourceSearch

https://www.cau.ac.kr/js/comm_fr.js

js cau.ac.kr collected 2026-10-01 10:14:35 UTC 68,698 bytes, 2,367 lines download raw bytes

1/**
2 * comm.js 업무를 제외한 시스템 공통 javascript.
3 *
4 */
5
6// null체크용. util.js와의 의존성을 제거하기 위해 만든 내부 함수.
7var __fn_comm_nvl = function(objValue, defValue) {
8	return (objValue == null || objValue == undefined) ? defValue : objValue;
9};
10
11/**
12 * 해당 폼의 내용들을 JSON 형태로 반환합니다. classDivider 를 주지 않으면, 다음과 같은 형식의 JSON 객체가 반환됩니다.
13 * 이 경우 disabled 된 요소는 제외됩니다. classDivider 를 주면, 폼 내부에서 classDivider 선택자를 검사하여,
14 * 검사 결과 각각의 내부의 폼 요소들의 값들을 담은 JSON 객체들의 배열이 반환됩니다. 이 경우는 disabled 된 요소가 포함됩니다.
15 *
16 * @param selector :
17 *            폼 선택자 (ex: #frm), classDivider 사용 시 궂이 form 요소를 사용할 필요는 없으나, 선택
18 *            결과가 고유하도록 사용하는 것을 권장, classDivider 사용 안할 시 반드시 form 요소 사용
19 * @param classDivider :
20 *            폼 내부 단위 구분용 선택자 (ex: .FORM_BLOCK_ELEMENT)
21 */
22function fn_comm_jsonFromForm(selector, classDivider) {
23	if (classDivider) { // 다건(동적으로)인 경우 (form은 하나)
24		var resultList = [];
25		var $_unitDiv = null;
26		if (selector == classDivider)
27			$_unitDiv = $(selector); // 폼 선택자와 단위 구분 선택자가 같은 경우에 적용 (disabled
28										// 된 요소를 포함시키기 위해 일부러 이렇게 호출한 경우)
29		else
30			$_unitDiv = $(selector).find(classDivider);
31		$_unitDiv.each(function() {
32			var newObj = {};
33			$(this).find("input, select, textarea").each(function() { // 폼 요소
34																		// 검사
35				var element = this;
36				if ($(this).is("[type='checkbox']")) { // 체크박스의 경우 (값이 다수일 수 있음
37														// !)
38					if ($(this).is(':checked')) { // 체크되어 있으면
39						if (newObj[element.name])
40							newObj[element.name].push(this.value); // 배열이 만들어져
41																	// 있으면 --> 값
42																	// 추가
43						else
44							newObj[element.name] = [ this.value ]; // 배열이 만들어져
45																	// 있지 않으면
46																	// --> 배열
47																	// 만들고 값 삽입
48					} else if (!newObj[element.name])
49						newObj[element.name] = []; // 체크되지 않았지만 배열이 만들어져 있지 않으면
50													// --> 빈 배열 생성
51				} else if ($(this).is("[type='radio']")) { // 라디오 버튼의 경우
52					if ($(this).is(':checked'))
53						newObj[element.name] = this.value; // 선택되어 있으면 --> 값 삽입
54					else if (!newObj[element.name])
55						newObj[element.name] = null; // 선택되지 않았지만 값이 만들어져 있지
56														// 않으면 --> null 삽입
57														// (undefined 방지)
58				} else if ($(this).is("select")) { // 콤보박스 / 리스트의 경우
59					if ($(this).is("[size]")) { // size 속성이 있으면 --> 다건 선택 가능
60						$(this).find('option').each(function() { // option
61																	// 요소들 찾음
62							if (this.is(':selected')) { // 선택되어 있으면
63								if (newObj[element.name])
64									newObj[element.name].push(this.value);
65								else
66									newObj[element.name] = [ this.value ];
67							} else if (!newObj[element.name])
68								newObj[element.name] = [];
69						});
70
71					} else
72						newObj[element.name] = this.value; // 다건 선택 안해도 되므로 값
73															// 삽입
74				} else
75					newObj[element.name] = this.value; // 그 외의 폼 요소 --> 값 삽입
76			});
77			resultList.push(newObj);
78		});
79		return resultList;
80	} else { // 단건일 경우
81		var nextObjArr = $(selector).serializeArray();
82		var nextObj = {};
83
84		// 배열 형태를 JSON 형태로 변환
85		for (var idx = 0; idx < nextObjArr.length; idx++) {
86			if (nextObj[nextObjArr[idx].name]) {
87				if ($.isArray(nextObj[nextObjArr[idx].name])) {
88					nextObj[nextObjArr[idx].name].push(nextObjArr[idx].value);
89				} else {
90					var beforeObj = nextObj[nextObjArr[idx].name];
91					nextObj[nextObjArr[idx].name] = [];
92					nextObj[nextObjArr[idx].name].push(beforeObj);
93					nextObj[nextObjArr[idx].name].push(nextObjArr[idx].value);
94				}
95			} else
96				nextObj[nextObjArr[idx].name] = nextObjArr[idx].value;
97		}
98		return nextObj;
99	}
100}
101
102$.fn.fn_comm_serializeObject = function() {
103	var obj = {};
104	var arr = this.serializeArray();
105	$.each(arr, function() {
106		if (obj[this.name] !== undefined) {
107			if (!$.isArray(obj[this.name])) {
108				obj[this.name] = [ obj[this.name] ];
109			}
110			obj[this.name].push(this.value);
111		} else {
112			obj[this.name] = this.value;
113		}
114	});
115	return obj;
116};
117
118var __ajax_count__ = 0;
119
120var fn_comm_showProgressbar = function() {
121	if (__ajax_count__ == 0) {
122		if ($("#div_comm_progressbarDialog").length == 0) {
123			$("body")
124					.append(
125							"<div id='div_comm_progressbarDialog' style='display:none;'><div id='div_comm_progressbar'></div></div>");
126			if (typeof $("#div_comm_progressbar").progressbar == 'function')
127				$("#div_comm_progressbar").progressbar({
128					value : false
129				});
130		}
131		if (typeof $("#div_comm_progressbarDialog").dialog == 'function')
132			$("#div_comm_progressbarDialog").dialog({
133				modal : true,
134				title : "잠시만 기다리세요",
135				height : 100
136			});
137	}
138	++__ajax_count__;
139};
140
141var fn_comm_hideProgressbar = function() {
142	--__ajax_count__;
143	if (__ajax_count__ <= 0
144			&& typeof $("#div_comm_progressbarDialog").dialog == 'function') {
145		$("#div_comm_progressbarDialog").dialog("close");
146		__ajax_count__ = 0;
147	}
148};
149
150/**
151 * ajax 공통함수. jQuery의 argument는 ajax 함수와 같음.
152 *
153 * @param {}
154 *            url
155 * @param {}
156 *            options success, error 콜백 함수를 가로채서 처리함. parentIdForSetByName 옵션을
157 *            설정하면 success일 경우 parentIdForSetByName 값으로 노드를 찾은 후 자식 노드의 name값이
158 *            json data 값과 일치하면 값을 설정함. input 요소의 경우 val()함수를 호출하고 나머지는 text()
159 *            함수 호출함. 파일 업로드 사용시 options에 ajaxFormName 추가 (예 : ajaxFormName :
160 *            "frm")
161 */
162var fn_comm_ajax = function(url, options) {
163	// If url is an object, simulate pre-1.5 signature
164	if (typeof url === "object") {
165		options = url;
166		url = undefined;
167	}
168
169	if (!options) {
170		$.ajax(url);
171		return;
172	}
173
174	if (!options.dataType) {
175		options.dataType = "json";
176	}
177
178	// 검색조건 저장
179	var pageId = options.pageId;
180	if ((pageId != null && typeof (pageId) != 'undefined')
181			&& options.data != null && typeof (options.data) != 'undefined') {
182		// pageId 가 'auto' 이면 svcName 사용 (sub_template, popup_template 상단에 정의됨)
183		if (pageId == 'auto') {
184			if (svcName == null || typeof (svcName) == 'undefined') {
185				throw "svcName 을 가져오지 못했습니다. pageId 를 수동으로 지정해야 합니다.";
186			}
187			pageId = svcName;
188		}
189		fn_util_setCookie('PAGE_' + pageId, JSON
190				.stringify(fn_util_jsonFromGet(options.data)), null, '/');
191	}
192
193	if (options.success) {
194		options._success = options.success;
195	}
196	options.success = this.fn_comm_ajaxSuccess;
197
198	if (options.error) {
199		options._error = options.error;
200	}
201	options.error = this.fn_comm_ajaxError;
202
203	options.beforeSend = function(jqXHR, settings) {
204		jqXHR._success = settings._success;
205		jqXHR._error = settings._error;
206
207		if (settings.parentIdForSetByName) {
208			jqXHR.parentIdForSetByName = settings.parentIdForSetByName;
209		}
210	};
211
212	if(options.progressBar == null || typeof (options.progressBar) == 'undefined'){
213		options.progressBar = true;
214	}
215	if(options.progressBar){
216		fn_comm_showProgressbar();
217	}
218
219	options.complete = function() {
220		//$('.view_func .zoom').destroy(easyView);
221		$('.view_func .zoom').removeData('easyView');
222		$('.view_func .zoom').easyView({
223			container: 'article',
224			increaseSelector: '.btn_zoomIn',
225			decreaseSelector: '.btn_zoomOut',
226			normalSelector: '.btn_zoomReset'
227		});
228	};
229
230	// 09.11 starworld
231	options.type = "POST";
232
233	if (options.ajaxFormName) {
234		if ($.isPlainObject(options.data) || options.date == null) {
235			options.type = "POST";
236			$("#" + options.ajaxFormName)
237					.attr("enctype", "multipart/form-data");
238			$("#" + options.ajaxFormName).attr("action", url);
239			$("#" + options.ajaxFormName).ajaxForm(options);
240			$("#" + options.ajaxFormName).submit();
241		} else {
242			throw "options.data형식은 json형식이여야 합니다.";
243		}
244
245	} else {
246		return $.ajax(url, options);
247	}
248
249};
250
251var fn_comm_ajaxSuccess = function(data, textStatus, jqXHR) {
252	if (jqXHR.parentIdForSetByName) {
253		fn_comm_setValue(jqXHR.parentIdForSetByName, data.data);
254	}
255
256	fn_comm_hideProgressbar();
257	if (jqXHR._success) {
258		jqXHR._success.apply(this, [ data.data, textStatus, jqXHR ]);
259	}
260};
261
262this.fn_comm_ajaxError = function(jqXHR, textStatus, errorThrown) {
263	fn_comm_hideProgressbar();
264
265	var errmsg = "시스템에 오류가 발생했습니다.\n[오류메세지]\n" + textStatus + "\n"
266			+ errorThrown + "\n" + jqXHR.responseText;
267	if (jqXHR._error) {
268		jqXHR._error.apply(this, [ jqXHR, textStatus, errorThrown ]);
269		return;
270	}
271
272	var jsonStr = jqXHR.responseText;
273	var jsonObj = null;
274	try {
275		jsonObj = $.parseJSON(jsonStr);
276	} catch (e) {
277		//alert(errmsg);
278		return;
279	}
280	errmsg = jsonObj.alertmsg;
281	if (errmsg != undefined) {
282		alert(errmsg);
283		return;
284	}
285	errmsg = jsonObj.errmsg;
286	errmsg = errmsg.replace("java.lang.RuntimeException: ", "");
287	if (svcMode == "LOCAL") {
288		alert(errmsg);
289	} else {
290		location.href = contextPath + "/code500.jsp?comm_error_DOMAIN_CD="
291				+ encodeURIComponent(domainCd) + "&errmsg="
292				+ encodeURIComponent(errmsg);
293	}
294};
295
296var fn_comm_processScalarAjax = function(url, options) {
297	// If url is an object, simulate pre-1.5 signature
298	if (typeof url === "object") {
299		options = url;
300		url = undefined;
301	}
302
303	if (!options) {
304		options = {
305			url : url,
306			async : false,
307			dataType : "text"
308		};
309	} else {
310		options.async = false;
311		options.dataType = "text";
312	}
313
314	if (options.success) {
315		options._success = options.success;
316	}
317	options.success = this.fn_comm_processScalarAjaxSuccess;
318	if (options.error) {
319		options._error = options.error;
320	}
321	options.error = this.fn_comm_ajaxError;
322	options.beforeSend = function(jqXHR, settings) {
323		jqXHR._success = settings._success;
324		jqXHR._error = settings._error;
325	};
326
327	var returnData = null;
328	options.complete = function(jqXHR, textStatus) {
329		returnData = jqXHR.returnData;
330	};
331
332	if(options.progressBar == null || typeof (options.progressBar) == 'undefined'){
333		options.progressBar = true;
334	}
335
336	if(options.progressBar){
337		fn_comm_showProgressbar();
338	}
339
340	$.ajax(url, options);
341	return returnData;
342};
343
344var fn_comm_processScalarAjaxSuccess = function(data, textStatus, jqXHR) {
345	fn_comm_hideProgressbar();
346	if (data != undefined || data != null)
347		data = data.replace(/\"/g, "");
348	jqXHR.returnData = data;
349	if (jqXHR._success) {
350		jqXHR._success.apply(this, [ data, textStatus, jqXHR ]);
351	}
352};
353
354/**
355 * input element 및 기타 element에 값 대입. select 태그의 multiple 경우는 고려 안함;;
356 *
357 * @param {}
358 *            $_parent
359 * @param {}
360 *            jsonObj
361 */
362var fn_comm_setValue = function(parentIdForSetByName, jsonObj) {
363	$(parentIdForSetByName).fn_comm_setValue(jsonObj);
364};
365
366/**
367 * input element 및 기타 element에 값 대입. select 태그의 multiple 경우는 고려 안함;;
368 *
369 * @param {}
370 *            $_parent
371 * @param {}
372 *            jsonObj
373 */
374$.fn.fn_comm_setValue = function(jsonObj) {
375	return this.each(function(index, element) {
376		var $_parent = $(element);
377		for ( var elementName in jsonObj) {
378			if("CONTENTS" == elementName) continue;
379			var $_element = $_parent.find("[name='" + elementName + "']");
380			if ($_element.length == 0)
381				continue;
382			var value = jsonObj[elementName];
383			value = __fn_comm_nvl(value, "");
384
385			if ($.isArray(value)) { // 배열인 경우
386				// 체크박스, 라디오의 경우
387				$_element.filter(":checkbox,:radio").val(value);
388
389				// 그 외의 경우
390				if (value.length == 0) {
391					// input 요소 -> .val()로 대입
392					$_element.filter(":input:not(:checkbox,:radio)").val("");
393					// text 요소 -> .text()로 대입
394					$_element.filter(":not(:input)").html("");
395				} else {
396					// input 요소 -> .val()로 대입
397					$_element.filter(":input:not(:checkbox,:radio)").val(
398							value[0]);
399					// text 요소 -> .text()로 대입
400					$_element.filter(":not(:input)").html(
401							fn_util_htmlEncode(value[0]));
402				}
403			} else { // 배열이 아닌 경우
404				// input:checkbox,radio 요소 -> .val([])로 대입
405				$_element.filter(":checkbox,:radio").val([ value ]);
406				// input 요소 -> .val()로 대입
407				$_element.filter(":input:not(:checkbox,:radio)").val(value);
408				// text 요소 -> .text()로 대입
409				$_element.filter(":not(:input)")
410						.html(fn_util_htmlEncode(value));
411			}
412		}
413	});
414};
415/**
416 * 쿠키로부터 저장된 검색조건들을 받아 폼에 적용합니다.
417 *
418 * pageId 를 지정하지 않으면 서비스 이름을 사용합니다.
419 */
420var prevPageId;
421$.fn.fn_comm_setFromCookie = function(pageId) {
422	if(prevPageId != pageId){
423		prevPageId = pageId;
424		return;
425	}
426	// 페이지 ID를 지정하지 않은 경우 --> svcName 사용 (sub_template, popup_template 상단에 정의되어
427	// 있음)
428	if (pageId == null && (svcName != null && typeof (svcName) != 'undefined'))
429		pageId = svcName;
430
431	var cookieJSON = fn_util_getCookie('PAGE_' + pageId);
432	if (cookieJSON == null || typeof (cookieJSON) == 'undefined'
433			|| fn_util_isEmpty(cookieJSON))
434		return;
435	var jsonObj = JSON.parse(cookieJSON);
436	$(this).fn_comm_setValue(jsonObj);
437};
438
439/**
440 * list에 값 대입. jquery template 사용. id값은 #을 붙여서 사용 바람. paginationId 값이 있으면 페이징
441 * 결과라 생각하고 data.list를 기준으로 출력함. (paging처리 리스트인데 페이지 번호를 사용 안할리는 없잖아...?)
442 *
443 * @param {}
444 *            parentId. 보통... tbody. table, ul, ol 등등 부모 selector값
445 * @param {}
446 *            data
447 * @param ...
448 */
449var fn_comm_setList = function(parentId, data, dataTemplateId,
450		noDataTemplateId, rowCountId, paginationId, cb) {
451	$(parentId).fn_comm_setList(data, dataTemplateId, noDataTemplateId,
452			rowCountId, paginationId, cb);
453};
454
455$.fn.fn_comm_setList = function(data, dataTemplateId, noDataTemplateId,
456		rowCountId, paginationId) {
457	var isPaging = !fn_comm_isNull(paginationId);
458	var list = null;
459	if (isPaging) {
460		if (typeof data.list == "undefined") {
461			list = data;
462		} else {
463			list = data.list;
464		}
465	} else {
466		list = data;
467	}
468	this.empty();
469	if (list == null || list.length == 0) {
470		if (rowCountId) {
471			$(rowCountId).text(0);
472		}
473		if (noDataTemplateId) {
474			$(noDataTemplateId).tmpl({}).appendTo(this);
475		}
476		if (isPaging) {
477			$(paginationId).html("");
478		}
479		return;
480	}
481
482	if (rowCountId) {
483		var cnt = 0;
484		if (isPaging) {
485//			var cntVal = String(list[0]["__CNT__"]);
486			var cntVal = String(data.totalRecordCount);
487			if (!fn_util_isEmpty(cntVal))
488				cnt = Number(cntVal);
489		} else {
490			cnt = list.length;
491		}
492		cnt = fn_util_makeComma(cnt);
493		$(rowCountId).text(cnt);
494	}
495	for (var idx = 0; idx < list.length; idx++) {
496		var dataObj = list[idx];
497		if (isPaging) {
498			dataObj.rownum = dataObj["__RNUM__"];
499		} else {
500			dataObj.rownum = (idx + 1);
501		}
502	}
503	$(dataTemplateId).tmpl(list).appendTo(this);
504	if (isPaging) {
505		var paging_url = "/bvs/pagingF.do";
506		if(paginationId=="#p_moreF"){
507			paging_url = "/bvs/moreF.do";
508		}else if(paginationId=="#p_pagingFH"){
509			paging_url = "/bvs/pagingFH.do";
510		}
511		$.ajax({
512            url: paging_url,
513            data : {
514                currentPageNo : data.currentPageNo,
515                totalRecordCount : data.totalRecordCount,
516                recordCountPerPage : data.recordCountPerPage,
517                paginationJsFunction : data.jsFunction
518            },
519            type : "POST",
520            success : function(data) {
521            	$(paginationId).html(data);
522            }
523        });
524	}
525	if (typeof applyDotdotdot == 'function') {
526		applyDotdotdot();
527	}
528
529};
530
531var fn_comm_moreList = function(parentId, data, dataTemplateId,
532		noDataTemplateId, rowCountId, paginationId, cb) {
533	$(parentId).fn_comm_moreList(data, dataTemplateId, noDataTemplateId,
534			rowCountId, paginationId, cb);
535};
536
537$.fn.fn_comm_moreList = function(data, dataTemplateId, noDataTemplateId,
538		rowCountId, paginationId) {
539	var isPaging = !fn_comm_isNull(paginationId);
540	var list = null;
541	if (isPaging) {
542		if (typeof data.list == "undefined") {
543			list = data;
544		} else {
545			list = data.list;
546		}
547	} else {
548		list = data;
549	}
550	//this.empty();
551	if (list == null || list.length == 0) {
552		if (rowCountId) {
553			$(rowCountId).text(0);
554		}
555		if (noDataTemplateId) {
556			$(noDataTemplateId).tmpl({}).appendTo(this);
557		}
558		if (isPaging) {
559			$(paginationId).html("");
560		}
561		return;
562	}
563
564	if (rowCountId) {
565		var cnt = 0;
566		if (isPaging) {
567//			var cntVal = String(list[0]["__CNT__"]);
568			var cntVal = String(data.totalRecordCount);
569			if (!fn_util_isEmpty(cntVal))
570				cnt = Number(cntVal);
571		} else {
572			cnt = list.length;
573		}
574		cnt = fn_util_makeComma(cnt);
575		$(rowCountId).text(cnt);
576	}
577	for (var idx = 0; idx < list.length; idx++) {
578		var dataObj = list[idx];
579		if (isPaging) {
580			dataObj.rownum = dataObj["__RNUM__"];
581		} else {
582			dataObj.rownum = (idx + 1);
583		}
584	}
585	$(dataTemplateId).tmpl(list).appendTo(this);
586	if (isPaging) {
587
588		$.ajax({
589            url: paginationId=='#p_moreF'?"/bvs/moreF.do":"/bvs/pagingF.do",
590            data : {
591                currentPageNo : data.currentPageNo,
592                totalRecordCount : data.totalRecordCount,
593                recordCountPerPage : data.recordCountPerPage,
594                paginationJsFunction : data.jsFunction
595            },
596            type : "POST",
597            success : function(data) {
598            	$(paginationId).html(data);
599            }
600        });
601	}
602	if (typeof applyDotdotdot == 'function') {
603		applyDotdotdot();
604	}
605
606};
607
608/*
609 * table merge 출처 :
610 * http://willifirulais.blogspot.kr/2007/07/jquery-table-column-break.html 등등..
611 * 상위행 기준으로 merge. 하위행은 삭제됨.
612 */
613$.fn.rowspan = function(colIdx, stdColIdx) {
614	stdColIdx = __fn_comm_nvl(stdColIdx, colIdx);
615	return this.each(function() {
616		var that = null;
617		var stdThat = null;
618		$('tr', this).each(
619				function(row) {
620					var $_td = $('>:eq(' + colIdx + ')', this).filter(
621							':visible');
622					var $_stdTd = $('>:eq(' + stdColIdx + ')', this).filter(
623							':visible');
624					$_td.each(function(col) {
625						var stdThis = $_stdTd.filter(':eq(' + col + ')')[0]; // stdThis=td:stdColIdx
626						if ($(stdThis).html() == $(stdThat).html()) { // this=td:colIdx
627							var rowspan = $(stdThat).attr('rowspan') || 1;
628							rowspan = Number(rowspan) + 1;
629							$(stdThat).attr('rowspan', rowspan); // do your
630																	// action
631																	// for the
632																	// colspan
633																	// cell here
634							$(that).attr('rowspan', rowspan); // do your
635																// action for
636																// the colspan
637																// cell here
638							$(this).hide(); // .remove(); // do your action for
639											// the old cell here
640							$(stdThis).hide(); // .remove(); // do your action
641												// for the old cell here
642						} else {
643							that = this;
644							stdThat = stdThis;
645						}
646						that = (that == null) ? this : that; // set the that
647																// if not
648																// already set
649						stdThat = (stdThat == null) ? stdThis[0] : stdThat; // set
650																			// the
651																			// that
652																			// if
653																			// not
654																			// already
655																			// set
656					});
657				});
658	});
659};
660
661$.fn.rowspanByAttr = function(colIdx, stdAttr) {
662	return this.each(function() {
663		var that = null;
664		var td = null;
665		var rowCnt = $('tr', this).length;
666		for (var idx = 0; idx < rowCnt; idx++) {
667			td = $('tr:eq(' + idx + ')>:eq(' + colIdx + ')', this);
668			if (td.attr(stdAttr) != null) {
669				if (td.attr(stdAttr) == $(that).attr(stdAttr)) {
670					var rowspan = $(that).attr('rowspan') || 1;
671					rowspan = Number(rowspan) + 1;
672					$(that).attr('rowspan', rowspan); // do your action for
673														// the colspan cell here
674					td.hide(); // .remove(); // do your action for the old cell
675								// here
676				} else {
677					that = td;
678				}
679				that = (that == null) ? td : that; // set the that if not
680													// already set
681			}
682		}
683	});
684};
685
686$.fn.colspan = function(rowIdx) {
687	return this.each(function() {
688		var that = null;
689		$('tr:eq(' + rowIdx + ')', this).each(function(row) {
690			$(this).find('td,th').filter(':visible').each(function(col) {
691				if ($(this).html() == $(that).html()) {
692					var colspan = $(that).attr('colspan') || 1;
693					colspan = Number(colspan) + 1;
694					$(that).attr("colspan", colspan);
695					$(this).hide(); // .remove();
696				} else {
697					that = this;
698				}
699				that = (that == null) ? this : that; // set the that if not
700														// already set
701			});
702		});
703	});
704};
705/* table merge */
706
707/* table sum */
708$.fn.sum = function(colIdx, expr, cls, total) {
709	var sumValue = 0;
710	this.each(function() {
711		$('tr', this).each(function(row) {
712			$('td:eq(' + colIdx + ')', this).each(function(col) {
713				var val = 0;
714				if (cls == null) {
715					val = new Number($(this).text()); // parseInt($(this).text());
716				} else {
717					val = new Number($(this).find(cls).text()); // parseInt($(this).text());
718				}
719
720				if (isNaN(val))
721					val = 0;
722				sumValue += val;
723			});
724		});
725	});
726	if (expr) {
727		$(expr).text(sumValue);
728	}
729	return sumValue;
730};
731/* table sum */
732/* table avg */
733$.fn.avg = function(colIdx, expr, dcmPoint) {
734	var sumValue = 0;
735	var avgValue = 0;
736	var rowCnt = $('tr', this).length - 1;
737	this.each(function() {
738		$('tr', this).each(
739				function(row) {
740					$('td:eq(' + colIdx + ')', this).filter(':visible').each(
741							function(col) {
742								var val = new Number($(this).text().replace(
743										/%/gi, '')); // parseInt($(this).text());
744								if (isNaN(val))
745									val = 0;
746								sumValue += val;
747							});
748				});
749	});
750	avgValue = new Number(new Number(sumValue / rowCnt).toFixed(dcmPoint));
751
752	if (expr) {
753		$(expr).text(avgValue + '%');
754	}
755	return avgValue;
756};
757/* table avg */
758
759
760
761/**
762 * jQuery mask를 이용하여 시간입력 포맷 등록.
763 *
764 * @param settings
765 */
766$.fn.fn_comm_maskTime = function(settings) {
767	this.mask("99:99", settings);
768	this.blur(function(eventObject) {
769		var $_this = $(this);
770		var timeReg = /^(([0-1][0-9])|(2[0-3])):[0-5][0-9]$/;
771		if (!timeReg.test($_this.val())) {
772			$_this.val("");
773		}
774	});
775};
776
777$.fn.fn_comm_maskInteger = function(mask) {
778	$(this).css("text-align", "right");
779	if (!fn_comm_isNull(mask)) {
780		$(this).mask(mask);
781	}
782	$(this).blur(function(eventObject) {
783		var $_this = $(this);
784		var numReg = /[^0-9|^\-]/g;
785		if (numReg.test($_this.val())) {
786			$_this.val("");
787		}
788	});
789};
790
791$.fn.fn_comm_maskNumber = function(mask) {
792	$(this).css("text-align", "right");
793	if (!fn_comm_isNull(mask)) {
794		$(this).mask(mask);
795	}
796	$(this).blur(function(eventObject) {
797		var $_this = $(this);
798		if (isNaN(Number($_this.val()))) {
799			$_this.val("");
800		}
801	});
802};
803
804/* input 요소 생성 */
805$.fn.fn_comm_makeSelect = function(options) {
806	var arr = options.data; // 필수
807	var url = options.url; // arr이 널일경우 필수
808	var jsonName = options.jsonName; // 필수
809	var jsonValue = options.jsonValue; // 필수
810	var defaultText = options.defaultText;
811
812	if (fn_comm_isNull(arr) && !fn_comm_isNull(options.url)) {
813		fn_comm_ajax({
814			url : url,
815			async : false,
816			dataType : "json",
817			success : function(arrayData, textStatus, jqXHR) {
818				arr = arrayData;
819			}
820		});
821	}
822
823	this.each(function(elementInJQueryIndex, element) {
824		var $_element = $(element);
825		if (element.tagName != "SELECT") {
826			return;
827		}
828		if (defaultText != null && defaultText != undefined)
829			$_element.append('<option value="">' + defaultText + '</option>');
830		for (var idx = 0; idx < arr.length; idx++) {
831			var data = arr[idx];
832			$(
833					'<option value="' + data[jsonName] + '">' + data[jsonValue]
834							+ '</option>').appendTo($_element).data("data",
835					data);
836		}
837	});
838	if (options.callbackFunc) {
839		options.callbackFunc.apply(this, [ arr ]);
840	}
841	return this;
842};
843
844$.fn.fn_comm_makeCheckbox = function(options) {
845	var arr = options.data; // 필수
846	var url = options.url; // arr이 널일경우 필수
847	var jsonName = options.jsonName; // 필수
848	var jsonValue = options.jsonValue; // 필수
849	var elementName = __fn_comm_nvl(options.elementName, "");
850	var prefix = __fn_comm_nvl(options.prefix, ""); // <span class="inputbox">
851	var suffix = __fn_comm_nvl(options.suffix, ""); // </span>
852
853	if (fn_comm_isNull(arr) && !fn_comm_isNull(options.url)) {
854		fn_comm_ajax({
855			url : url,
856			async : false,
857			dataType : "json",
858			success : function(arrayData, textStatus, jqXHR) {
859				arr = arrayData;
860			}
861		});
862	}
863
864	this.each(function(elementInJQueryIndex, element) {
865		var $_element = $(element);
866		for (var idx = 0; idx < arr.length; idx++) {
867			var data = arr[idx];
868			var $input = $(
869					'<input type="checkbox" id="' + elementName
870							+ data[jsonName] + '" name="' + elementName
871							+ '" value="' + data[jsonName] + '"/>').data(
872					"data", data);
873			var $label = $(
874					'<label for="' + elementName + data[jsonName] + '">'
875							+ data[jsonValue] + '</label>' + suffix).appendTo(
876					$_element).data("data", data);
877			$label.insertBefore(prefix);
878			$label.prepend($input);
879		}
880	});
881	if (options.callbackFunc) {
882		options.callbackFunc.apply(this, [ arr ]);
883	}
884	return this;
885};
886
887$.fn.fn_comm_makeRadio = function(options) {
888	var arr = options.data; // 필수
889	var url = options.url; // arr이 널일경우 필수
890	var jsonName = options.jsonName; // 필수
891	var jsonValue = options.jsonValue; // 필수
892	var elementName = __fn_comm_nvl(options.elementName, "");
893	var defaultText = options.defaultText;
894	var prefix = __fn_comm_nvl(options.prefix, ""); // <span class="inputbox">
895	var suffix = __fn_comm_nvl(options.suffix, ""); // </span>
896
897	if (fn_comm_isNull(arr) && !fn_comm_isNull(options.url)) {
898		fn_comm_ajax({
899			url : url,
900			async : false,
901			dataType : "json",
902			success : function(arrayData, textStatus, jqXHR) {
903				arr = arrayData;
904			}
905		});
906	}
907
908	this.each(function(elementInJQueryIndex, element) {
909		var $_element = $(element);
910		if (defaultText != null && defaultText != undefined) {
911			$_element.append(prefix + '<label for="' + elementName
912					+ '_all"><input type="radio" id="' + elementName
913					+ '_all" name="' + elementName
914					+ '" value="" checked="checked" />' + defaultText
915					+ '</label>' + suffix);
916		}
917		for (var idx = 0; idx < arr.length; idx++) {
918			var data = arr[idx];
919			var $input = $(
920					'<input type="radio" id="' + elementName + data[jsonName]
921							+ '" name="' + elementName + '" value="'
922							+ data[jsonName] + '"/>').data("data", data);
923			var $label = $(
924					'<label for="' + elementName + data[jsonName] + '">'
925							+ data[jsonValue] + '</label>' + suffix).appendTo(
926					$_element).data("data", data);
927			$label.insertBefore(prefix);
928			$label.prepend($input);
929		}
930	});
931	if (options.callbackFunc) {
932		options.callbackFunc.apply(this, [ arr ]);
933	}
934	return this;
935};
936/* input 요소 생성 */
937
938/* validation */
939/**
940 * 유효성 체크.
941 *
942 * required="required" minlength="X" maxlength="X" 등등 form 요소에 attribute 설정해야함
943 *
944 * @param options
945 *            유효성체크 설정.
946 *
947 * <pre>
948 * var validationOptions = {
949 * 	messages : {
950 * 		LC_NM : &quot;자격증명을 입력하세요&quot; //json name: form 요소 id 또는 name, json value: 유효성 오류메세지
951 * 	},
952 * 	invalidCallbacks : {
953 * 		LC_NM : function() { //json name: form 요소 id 또는 name, json value: 유효성 오류 발생시 실행할 함수
954 * 			fn_P01();
955 * 		}
956 * 	}
957 * };
958 * $(&quot;#form&quot;).fn_comm_validate(validationOptions);
959 * </pre>
960 *
961 */
962$.fn.fn_comm_validate = function(options) {
963	var messages = (options && options.messages) ? options.messages : {};
964	var invalidCallbacks = (options && options.invalidCallbacks) ? options.invalidCallbacks
965			: {};
966	var isValid = true;
967	this.each(function(elementInJQueryIndex1, element1) { // form loop
968		if (!isValid) // 한개만 체크
969			return;
970
971		var $_input = $(element1).find(":input");
972
973		var alertInvalidMessage = function($_input2, msg, defaultMsg,
974				invalidCallbacks) {
975			var idOrName = $_input2.attr("id") || $_input2.attr("name");
976			if (idOrName != undefined && msg[idOrName] != undefined) { // id가
977																		// 있고
978																		// id에
979																		// 대한
980																		// 메시지가
981																		// 있을경우
982				alert(msg[idOrName]);
983				$_input2.focus();
984			} else {
985				alert(defaultMsg);
986				$_input2.focus();
987			}
988			if (invalidCallbacks[idOrName]) {
989				invalidCallbacks[idOrName].apply(this, [ $_input2 ]);
990			}
991		};
992		// required
993		$_input.filter("[required]").each(
994				function(elementInJQuery2, element2) { // input loop
995					if (!isValid) // 한개만 체크
996						return;
997					var $_input2 = $(element2);
998					var val = $_input2.val();
999					if (val == null || val == undefined || val == "") { // not
1000																		// null
1001																		// 체크.
1002																		// trim
1003																		// 할까
1004																		// 말까?
1005						alertInvalidMessage($_input2, messages,
1006								"필수 입력 항목을 확인하세요.", invalidCallbacks);
1007						isValid = false;
1008					}
1009				}); // input loop
1010
1011		// minlength
1012		$_input.filter(":text[minlength],textarea[minlength]").each(
1013				function(elementInJQuery2, element2) { // input loop
1014					if (!isValid) // 한개만 체크
1015						return;
1016					var $_input2 = $(element2);
1017					var val = $_input2.val();
1018					var minlength = parseInt($_input2.attr("minlength"), 10);
1019					if (val == null || val == undefined
1020							|| fn_util_getByteLength(val) < minlength) { // length
1021																			// 체크.
1022						alertInvalidMessage($_input2, messages, minlength
1023								+ "자 이상 입력하세요.", invalidCallbacks);
1024						isValid = false;
1025					}
1026				}); // input loop
1027
1028		// maxlength
1029		$_input.filter(":text[maxlength],textarea[maxlength]").each(
1030				function(elementInJQuery2, element2) { // input loop
1031					if (!isValid) // 한개만 체크
1032						return;
1033					var $_input2 = $(element2);
1034					var val = $_input2.val();
1035					var maxlength = parseInt($_input2.attr("maxlength"), 10);
1036					if (val == null || val == undefined
1037							|| fn_util_getByteLength(val) > maxlength) { // length
1038																			// 체크.
1039						alertInvalidMessage($_input2, messages, maxlength
1040								+ "자를 넘을 수 없습니다.", invalidCallbacks);
1041						isValid = false;
1042					}
1043				}); // input loop
1044	}); // form loop
1045	return isValid;
1046};
1047/* validation */
1048
1049/*******************************************************************************
1050 * 기능 FUNCTION
1051 ******************************************************************************/
1052// 받아온 변수가 null, undefined, '' 일 경우 true 를 리턴.
1053var fn_comm_isNull = function(p_value) {
1054	if (p_value == '' || p_value == null || p_value == undefined) {
1055		return true;
1056	} else {
1057		return false;
1058	}
1059};
1060
1061// 해당값이 null undefined 라면 '' 리턴
1062var fn_comm_rtnBlank = function(p_value) {
1063
1064	if (p_value == null || p_value == 'null' || p_value == undefined
1065			|| p_value == 'undefined') {
1066		return '';
1067	} else {
1068		return p_value + '';
1069	}
1070};
1071
1072$.fn.fn_engnum_mixCheck = function(minLength, maxLength) {
1073	var str = $(this).val();
1074	var chk_num = str.search(/[0-9]/g);
1075	var chk_eng = str.search(/[a-z]/ig);
1076	if(str.length>minLength&&str.length<maxLength){
1077		if(chk_num < 0 || chk_eng < 0){
1078		  return false;
1079		}
1080	}else{
1081		return false;
1082	}
1083	return true;
1084}
1085
1086$.fn.fn_engnum_Check = function(minLength, maxLength) {
1087	var str = $(this).val();
1088	if(str.length>minLength&&str.length<maxLength){
1089		for( var i = 0; i <= str.length -1 ; i++ ){
1090			if('a' <= str.charAt(i) && str.charAt(i) <= 'z' || str.charAt(i) >= '0' && str.charAt(i) <= '9'){
1091			}else{
1092				return false;
1093			}
1094		}
1095	}else{
1096		return false;
1097	}
1098	return true;
1099}
1100
1101function fn_emaill_Check(str){
1102	var regEmail = /([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/;
1103	if( !str ){
1104	    return false;
1105	}else{
1106	    if(!regEmail.test(str)) {
1107	        return false;
1108	    }
1109	}
1110	return true;
1111}
1112
1113function fn_jumin_Check(str){
1114	var Jumin = str;
1115	var sum = 0;
1116	if(Jumin.match(/\d{2}[0-1]\d{1}[0-3]\d{1}\d{7}/)){
1117		if(Jumin.substr(6, 1) >= 5 && Jumin.substr(6, 1) <= 8){
1118			//외국인
1119			if(Number(Jumin.substr(7, 2)) % 2 != 0){
1120				return false;
1121			}
1122			for(var i = 0; i < 12; i++){
1123				sum += Number(Jumin.substr(i, 1)) * ((i % 8) + 2);
1124			}
1125			if((((11 - (sum % 11)) % 10 + 2) % 10) == Number(Jumin.substr(12, 1))){
1126				return true;
1127			}else{
1128				return false;
1129			}
1130		}else{
1131			//내국인
1132			for(var i = 0; i < 12; i++){
1133				sum += Number(Jumin.substr(i, 1)) * ((i % 8) + 2);
1134			}
1135			if(((11 - (sum % 11)) % 10) == Number(Jumin.substr(12, 1))){
1136				return true;
1137			}else{
1138				return false;
1139			}
1140		}
1141	}else{
1142		return false;
1143	}
1144}
1145
1146/**
1147 * 입력 키 체크하여 입력 제한
1148 *
1149 * @param obj :
1150 *            input박스 객체
1151 * @param type :
1152 *            num(정수), dnum(실수), eng(영문), engnum(영문+숫자)
1153 * @param decimalLength :
1154 *            실수 소수점자리수 fn_comm_keyCheck(document.getElementById('text'),
1155 *            'dnum', 3); //실수로서 3째자리까지만 입력 가능
1156 */
1157var fn_comm_keyCheck = function(obj, type, decimalLength) {
1158	return $(obj).fn_comm_keyCheck(type, decimalLength);
1159};
1160
1161
1162/**
1163 * $(".text").fn_comm_keyCheck('dnum', 3); //실수로서 3째자리까지만 입력 가능
1164 */
1165$.fn.fn_comm_keyCheck = function(type, decimalLength) {
1166	var $this = $(this);
1167	var rtn = undefined;
1168	$this.each(function(idx, obj) {
1169		var $obj = $(obj);
1170		if (type == undefined)
1171			type = 'num';
1172		var pattern = '';
1173		if (type == 'num')
1174			pattern = /[^0-9]/; // 숫자
1175		if (type == 'dnum')
1176			pattern = /[^0-9.]/; // 소수점 + 숫자
1177		if (type == 'eng')
1178			pattern = /[ㄱ-힣]/; // 영문
1179		if (type == 'engnum')
1180			pattern = /[ㄱ-힣][^0-9]/; // 영문 + 숫자
1181
1182
1183		var value = $obj.val();
1184
1185		if (type == 'dnum') {
1186			if (value == '.')
1187				$obj.val('');
1188			var split = value.split('.');
1189			if (split.length > 2)
1190				$obj.val(value.substr(0, value.length - 1));
1191			if (split[1] != null && split[1].length > decimalLength)
1192				$obj.val(value.substr(0, value.length - 1));
1193		}
1194		if (pattern.test(value)) {
1195			if (type == 'num')
1196				$obj.val(value.replace(/[^0-9]/g, '')); // 숫자
1197			if (type == 'dnum')
1198				$obj.val(value.replace(/[^0-9.]/g, '')); // 소수점 + 숫자
1199			if (type == 'eng')
1200				$obj.val(value.replace(/[ㄱ-힣]/g, '')); // 영문
1201			if (type == 'engnum')
1202				$obj.val(value.replace(/[ㄱ-힣][^0-9]/g, '')); // 영문 + 숫자
1203
1204			$obj.focus();
1205			rtn = false;
1206		}
1207	});
1208	return rtn;
1209};
1210
1211/**
1212 *
1213 * $(".text").fn_comm_attachKeyCheckEventHandler('dnum', 3);
1214 */
1215$.fn.fn_comm_attachKeyCheckEventHandler = function(type, decimalLength) {
1216	$(this).on("keyup", function(evt) {
1217		return $(this).fn_comm_keyCheck();
1218	});
1219};
1220
1221/*******************************************************************************
1222 * Log 공통
1223 ******************************************************************************/
1224var logger = {
1225	log : function(msg) {
1226		try {
1227			console.log(msg);
1228		} catch (e) {
1229		}
1230	},
1231
1232	ajaxResp : function(msg, data) {
1233		try {
1234			console.log(msg);
1235		} catch (e) {
1236		}
1237		try {
1238			console.dir(data);
1239		} catch (e) {
1240		}
1241	}
1242};
1243
1244/*******************************************************************************
1245 * UI 처리관련 FUNCTION
1246 ******************************************************************************/
1247// 파라메터 가져오기
1248var fn_comm_getParameter = function() {
1249
1250	var returnParam = new Object();
1251
1252	var url = document.location.href;
1253
1254	if (url.indexOf("?") > 0) {
1255
1256		var paramUrl = decodeURIComponent(url.substring(url.indexOf("?") + 1,
1257				url.length));
1258
1259		var paramArr = paramUrl.split("&");
1260
1261		$.each(paramArr, function(index, value) {
1262
1263			var key = value.split("=")[0];
1264			// var keyValue = decodeURIComponent(value.split("=")[1]); // 흠..
1265			// 암호화?? ㅋㅋ
1266			var keyValue = value.split("=")[1];
1267
1268			if ((key.indexOf("FC_") == 0) && ($("#" + key).length == 0)) {
1269
1270				$($("form")[0]).append(
1271						"<input type='hidden' name='" + key + "' id='" + key
1272								+ "' value='" + keyValue + "' />");
1273			}
1274
1275			returnParam[key] = keyValue;
1276		});
1277	}
1278
1279	return returnParam;
1280};
1281
1282// 검색조건 자동입력
1283var fn_comm_setSearchOpt = function(detailData) {
1284
1285	logger.ajaxResp("detailData", detailData);
1286
1287	var prefix = "";
1288	var count = -1;
1289
1290	$
1291			.each(
1292					detailData,
1293					function(key, value) {
1294
1295						logger
1296								.log("#"
1297										+ prefix
1298										+ key
1299										+ " = "
1300										+ $("#" + prefix + key).is(
1301												"input[type=radio]"));
1302						if ($("#" + prefix + key).length > 0) {
1303
1304							if ($("input[name*=" + key + "]").is(
1305									"input[type=checkbox]") == true
1306									|| $("input[name*=" + key + "]").is(
1307											"input[type=radio]") == true) {
1308
1309								if ($("input[name*=" + key + "]").is(
1310										"input[type=checkbox]") == true) {
1311									logger.log("checkebox - 처리방안 필요함...  ㅋㅋ");
1312									$("#" + prefix + key).attr("checked", true);
1313								} else if ($("input[name*=" + key + "]").is(
1314										"input[type=radio]") == true) {
1315
1316									$("#" + prefix + key + value).attr(
1317											"checked", true);
1318
1319								}
1320							} else {
1321								if ($("#" + prefix + key).is("input") == true) {
1322
1323									$("#" + prefix + key).val(value);
1324
1325								} else if ($("#" + prefix + key).is("select") == true) {
1326
1327									$("#" + prefix + key).val(value);
1328								} else if ($("#" + prefix + key).is("textarea") == true) {
1329
1330									$("#" + prefix + key).val(value);
1331								}
1332							}
1333
1334							count++;
1335						}
1336					});
1337
1338	return count;
1339};
1340
1341// 목록으로 이동
1342var fn_comm_goBackList = function(url) {
1343
1344	var searchOpt = new Object();
1345	var searchOptObj = $('input[name^="FC_"]');
1346
1347	$.each(searchOptObj, function(idx, obj) {
1348
1349		var id = $(obj).attr('id');
1350		var value = $(obj).val();
1351
1352		searchOpt[id] = value;
1353	});
1354
1355	var pageInfo = {
1356		"url" : url,
1357		"param" : searchOpt
1358
1359	};
1360
1361	fn_comm_movePage(pageInfo);
1362};
1363
1364// 페이지 이동
1365var fn_comm_movePage = function(pageInfo) {
1366
1367	var url = pageInfo["url"];
1368
1369	if ($.trim(url).length == 0) {
1370		alert("url을 확인하세요");
1371		return;
1372	}
1373
1374	var param = pageInfo["param"] == undefined ? new Object()
1375			: pageInfo["param"];
1376	var strParam = "";
1377
1378	$.each(param, function(key, value) {
1379		strParam += "&" + key + "=" + fn_comm_rtnBlank(value);
1380	});
1381
1382	var searchOpt = pageInfo["searchOpt"] == undefined ? ""
1383			: pageInfo["searchOpt"];
1384
1385	if ((typeof searchOpt) == "string") {
1386
1387		if ($.trim(searchOpt).length > 0) {
1388			strParam += "&" + searchOpt;
1389		}
1390	} else {
1391		$.each(searchOpt, function(key, value) {
1392			strParam += "&" + key + "=" + fn_comm_rtnBlank(value);
1393		});
1394	}
1395
1396	// url = url.indexOf("?") > 0 ? url + encodeURIComponent(strParam) : url +
1397	// "?" + encodeURIComponent(strParam.substring(1, strParam.length));
1398	url = url.indexOf("?") > 0 ? url + strParam : url + "?"
1399			+ strParam.substring(1, strParam.length);
1400
1401	document.location.href = url;
1402
1403};
1404
1405/*----------------------------------------------------------------
1406 /기능 : 날짜를 요일로 반환한다.
1407 /인수 : day : 일자 (yyyyMMdd)   opt: 1-한자(月) 2-한글(월) 3-한글(월요일) 4-코드(e)
1408 /리턴 : 요일반환
1409 ----------------------------------------------------------------*/
1410var fn_comm_getDayToWeek = function(p_day, p_opt) {
1411	var v_week;
1412
1413	v_week = fn_comm_dateToDayofWeek(p_day);
1414
1415	if (p_opt == 1) {
1416		switch (v_week) {
1417		case 0:
1418			return "日";
1419			break;
1420		case 1:
1421			return "月";
1422			break;
1423		case 2:
1424			return "火";
1425			break;
1426		case 3:
1427			return "æ°´";
1428			break;
1429		case 4:
1430			return "木";
1431			break;
1432		case 5:
1433			return "金";
1434			break;
1435		case 6:
1436			return "土";
1437			break;
1438		}
1439	} else if (p_opt == 2) {
1440		switch (v_week) {
1441		case 0:
1442			return "일";
1443			break;
1444		case 1:
1445			return "월";
1446			break;
1447		case 2:
1448			return "화";
1449			break;
1450		case 3:
1451			return "수";
1452			break;
1453		case 4:
1454			return "목";
1455			break;
1456		case 5:
1457			return "금";
1458			break;
1459		case 6:
1460			return "토";
1461			break;
1462		}
1463	} else if (p_opt == 3) {
1464		switch (v_week) {
1465		case 0:
1466			return "일요일";
1467			break;
1468		case 1:
1469			return "월요일";
1470			break;
1471		case 2:
1472			return "화요일";
1473			break;
1474		case 3:
1475			return "수요일";
1476			break;
1477		case 4:
1478			return "목요일";
1479			break;
1480		case 5:
1481			return "금요일";
1482			break;
1483		case 6:
1484			return "토요일";
1485			break;
1486		}
1487	} else if (p_opt == 4) {
1488		switch (v_week) {
1489		case 0:
1490			return "g";
1491			break;
1492		case 1:
1493			return "a";
1494			break;
1495		case 2:
1496			return "b";
1497			break;
1498		case 3:
1499			return "c";
1500			break;
1501		case 4:
1502			return "d";
1503			break;
1504		case 5:
1505			return "e";
1506			break;
1507		case 6:
1508			return "f";
1509			break;
1510		}
1511	}
1512};
1513
1514/* ============================================================================ */
1515/*
1516 * 메소드 명 : fn_comm_dateToDayofWeek( p_date ) /* 내용 설명 : 날짜를 받아서 요일로 변환 /* 인자 :
1517 * yyyyMMdd /* RETURN 값 : int
1518 * /*============================================================================
1519 */
1520var fn_comm_dateToDayofWeek = function(p_date) {
1521	if (p_date.length < 0)
1522		return "";
1523
1524	var v_year = p_date.substr(0, 4);
1525	var v_month = p_date.substr(4, 2);
1526	var v_day = p_date.substr(6, 2);
1527
1528	var m = parseInt(v_month, 10) - 1;
1529	var d = parseInt(v_day, 10);
1530
1531	var end = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
1532	if ((v_year % 4 == 0 && v_year % 100 != 0) || v_year % 400 == 0) {
1533		end[1] = 29;
1534	}
1535
1536	if (d < 1 || d > end[m]) {
1537		return -1;
1538	}
1539
1540	var newDate = new Date(v_year, m, v_day);
1541
1542	return parseInt(String(newDate.getDay()));
1543};
1544
1545/**
1546 * 페이징 생성을 위한 정보들의 전달 역할과 함께 페이징 관련 계산을 수행하는 클래스 형식의 함수입니다.
1547 *
1548 */
1549var PaginationInfo = function() {
1550
1551	/**
1552	 * Required Fields - 이 필드들은 페이징 계산을 위해 반드시 입력되어야 하는 필드 값들이다.
1553	 *
1554	 * currentPageNo : 현재 페이지 번호 recordCountPerPage : 한 페이지당 게시되는 게시물 건 수
1555	 * pageSize : 페이지 리스트에 게시되는 페이지 건수, totalRecordCount : 전체 게시물 건 수.
1556	 */
1557
1558	this.currentPageNo = 0;
1559	this.recordCountPerPage = 0;
1560	this.pageSize = 0;
1561	this.totalRecordCount = 0;
1562
1563	this.getRecordCountPerPage = function() {
1564		return this.recordCountPerPage;
1565	};
1566
1567	this.setRecordCountPerPage = function(recordCountPerPage) {
1568		this.recordCountPerPage = recordCountPerPage;
1569	};
1570
1571	this.getPageSize = function() {
1572		return this.pageSize;
1573	};
1574
1575	this.setPageSize = function(pageSize) {
1576		this.pageSize = pageSize;
1577	};
1578
1579	this.getCurrentPageNo = function() {
1580		return this.currentPageNo;
1581	};
1582
1583	this.setCurrentPageNo = function(currentPageNo) {
1584		this.currentPageNo = currentPageNo;
1585	};
1586
1587	this.setTotalRecordCount = function(totalRecordCount) {
1588		this.totalRecordCount = totalRecordCount;
1589	};
1590
1591	this.getTotalRecordCount = function() {
1592		return this.totalRecordCount;
1593	};
1594
1595	/**
1596	 * Not Required Fields - 이 필드들은 Required Fields 값을 바탕으로 계산해서 정해지는 필드 값이다.
1597	 *
1598	 * totalPageCount: 페이지 개수 firstPageNoOnPageList : 페이지 리스트의 첫 페이지 번호
1599	 * lastPageNoOnPageList : 페이지 리스트의 마지막 페이지 번호 firstRecordIndex : 페이징 SQL의
1600	 * 조건절에 사용되는 시작 rownum. lastRecordIndex : 페이징 SQL의 조건절에 사용되는 마지막 rownum.
1601	 */
1602
1603	this.totalPageCount = 0;
1604	this.firstPageNoOnPageList = 0;
1605	this.lastPageNoOnPageList = 0;
1606	this.firstRecordIndex = 0;
1607	this.lastRecordIndex = 0;
1608
1609	this.getTotalPageCount = function() {
1610		this.totalPageCount = Math.floor((this.getTotalRecordCount() - 1)
1611				/ this.getRecordCountPerPage()) + 1;
1612		return this.totalPageCount;
1613	};
1614
1615	this.getFirstPageNo = function() {
1616		return 1;
1617	};
1618
1619	this.getLastPageNo = function() {
1620		return this.getTotalPageCount();
1621	};
1622
1623	this.getFirstPageNoOnPageList = function() {
1624		this.firstPageNoOnPageList = Math.floor((this.getCurrentPageNo() - 1)
1625				/ this.getPageSize())
1626				* this.getPageSize() + 1;
1627		return this.firstPageNoOnPageList;
1628	};
1629
1630	this.getLastPageNoOnPageList = function() {
1631		this.lastPageNoOnPageList = this.getFirstPageNoOnPageList()
1632				+ this.getPageSize() - 1;
1633		if (this.lastPageNoOnPageList > this.getTotalPageCount()) {
1634			this.lastPageNoOnPageList = this.getTotalPageCount();
1635		}
1636		return this.lastPageNoOnPageList;
1637	};
1638
1639	this.getFirstRecordIndex = function() {
1640		this.firstRecordIndex = (this.getCurrentPageNo() - 1)
1641				* this.getRecordCountPerPage();
1642		return this.firstRecordIndex;
1643	};
1644
1645	this.getLastRecordIndex = function() {
1646		this.lastRecordIndex = this.getCurrentPageNo()
1647				* this.getRecordCountPerPage();
1648		return this.lastRecordIndex;
1649	};
1650};
1651
1652/**
1653 * 페이징 컴포넌트 HTML 소스를 만드는 역할을 하는 클래스 형식의 함수입니다.
1654 *
1655 */
1656var ImagePaginationRenderer = function(resourcesPath) {
1657	/*
1658	 * super.firstPageLabel = "<ul><a href=\"#\" onclick=\"{0}({1}); return
1659	 * false;\">[처음]</a>&#160;"; super.previousPageLabel = "<a href=\"#\"
1660	 * onclick=\"{0}({1}); return false;\">[이전]</a>&#160;";
1661	 * super.currentPageLabel = "<strong>{0}</strong>&#160;";
1662	 * super.otherPageLabel = "<a href=\"#\" onclick=\"{0}({1}); return
1663	 * false;\">{2}</a>&#160;"; super.nextPageLabel = "<a href=\"#\"
1664	 * onclick=\"{0}({1}); return false;\">[다음]</a>&#160;"; super.lastPageLabel = "<a
1665	 * href=\"#\" onclick=\"{0}({1}); return false;\">[마지막]</a>&#160;";
1666	 *
1667	 * <ul> <li class="pre_end"><a href="javascript:;">맨 처음페이지로 가기</a></li>
1668	 * <li class="btn_pre"><a href="javascript:;">이전 페이지</a></li> <li><a
1669	 * href="javascript:;">1</a></li> <li><a href="javascript:;">2</a></li>
1670	 * <li><a href="javascript:;">3</a></li> <li class="on"><a
1671	 * href="javascript:;">4</a></li> <li><a href="javascript:;">5</a></li>
1672	 * <li><a href="javascript:;">6</a></li> <li><a href="javascript:;">7</a></li>
1673	 * <li><a href="javascript:;">8</a></li> <li><a href="javascript:;">9</a></li>
1674	 * <li><a href="javascript:;">10</a></li> <li class="btn_next"><a
1675	 * href="javascript:;">다음페이지로 가기</a></li> <li class="next_end"><a
1676	 * href="javascript:;">마지막 페이지로 가기</a></li> </ul>
1677	 */
1678
1679	var firstPageLabel = "<a href='javascript:;' class='paging_first' onclick=\"{0}({1});\"><img src='"
1680			+ resourcesPath + "/images/board/paging_first.png' alt='맨앞' /></a>";
1681	var previousPageLabel = "<a href='#' class='paging_prev' onclick=\"{0}({1});\"><img src='"
1682			+ resourcesPath + "/images/board/paging_prev.png' alt='이전' /></a>";
1683	var currentPageLabel = "<a href=\'javascript:;\' class='on'>{0}</a>";
1684	var otherPageLabel = "<a href=\'javascript:;\' onclick=\"{0}({1});\">{2}</a>";
1685	var nextPageLabel = "<a href='javascript:;' class='paging_next' onclick=\"{0}({1});\"><img src='"
1686			+ resourcesPath + "/images/board/paging_next.png' alt='다음' /></a>";
1687	var lastPageLabel = "<a href='javascript:;' class='paging_last' onclick=\"{0}({1});\"><img src='"
1688			+ resourcesPath + "/images/board/paging_last.png' alt='맨뒤' /></a>";
1689
1690	var MessageFormat = {
1691		format : function(str, replacements) {
1692			return str.replace(/\{(\d+)\}/g, function(match, p) {
1693				return replacements[p];
1694			});
1695		}
1696	};
1697	var StringBuffer = function() {
1698		this.result = "";
1699		this.append = function(str) {
1700			this.result += str;
1701			return this;
1702		};
1703		this.toString = function() {
1704			return this.result;
1705		};
1706	};
1707
1708	var Integer = {
1709		parseInt : function(str) {
1710			return parseInt(str, 10);
1711		},
1712		toString : function(i) {
1713			return i + "";
1714		}
1715	};
1716
1717	this.renderPagination = function(paginationInfo, jsFunction) {
1718		var strBuff = new StringBuffer();
1719
1720		var firstPageNo = paginationInfo.getFirstPageNo();
1721		var firstPageNoOnPageList = paginationInfo.getFirstPageNoOnPageList();
1722		var totalPageCount = paginationInfo.getTotalPageCount();
1723		var pageSize = paginationInfo.getPageSize();
1724		var lastPageNoOnPageList = paginationInfo.getLastPageNoOnPageList();
1725		var currentPageNo = paginationInfo.getCurrentPageNo();
1726		var lastPageNo = paginationInfo.getLastPageNo();
1727
1728		if (totalPageCount > pageSize) {
1729			if (firstPageNoOnPageList > pageSize) {
1730				strBuff.append(MessageFormat.format(firstPageLabel, [
1731						jsFunction, Integer.toString(firstPageNo) ]));
1732				strBuff.append(MessageFormat.format(previousPageLabel,
1733						[ jsFunction,
1734								Integer.toString(firstPageNoOnPageList - 1) ]));
1735			} else {
1736				strBuff.append(MessageFormat.format(firstPageLabel, [
1737						jsFunction, Integer.toString(firstPageNo) ]));
1738				strBuff.append(MessageFormat.format(previousPageLabel, [
1739						jsFunction, Integer.toString(firstPageNo) ]));
1740			}
1741		}
1742		strBuff.append("<span>");
1743		for (var i = firstPageNoOnPageList; i <= lastPageNoOnPageList; i++) {
1744			if (i == currentPageNo) {
1745				strBuff.append(MessageFormat.format(currentPageLabel, [ Integer
1746						.toString(i) ]));
1747			} else {
1748				strBuff
1749						.append(MessageFormat.format(otherPageLabel, [
1750								jsFunction, Integer.toString(i),
1751								Integer.toString(i) ]));
1752			}
1753		}
1754		strBuff.append("</span>");
1755		if (totalPageCount > pageSize) {
1756			if (lastPageNoOnPageList < totalPageCount) {
1757				strBuff.append(MessageFormat.format(nextPageLabel, [
1758						jsFunction,
1759						Integer.toString(firstPageNoOnPageList + pageSize) ]));
1760				strBuff.append(MessageFormat.format(lastPageLabel, [
1761						jsFunction, Integer.toString(lastPageNo) ]));
1762			} else {
1763				strBuff.append(MessageFormat.format(nextPageLabel, [
1764						jsFunction, Integer.toString(lastPageNo) ]));
1765				strBuff.append(MessageFormat.format(lastPageLabel, [
1766						jsFunction, Integer.toString(lastPageNo) ]));
1767			}
1768		}
1769		return strBuff.toString();
1770	};
1771};
1772
1773/**
1774 * 데이터 배열을 받아 페이징 컴포넌트 구성 HTML 소스를 반환합니다.
1775 *
1776 * pageSize 기본값은 10 입니다. paginationJsFunction 기본값은 linkPage 입니다.
1777 *
1778 * @param data :
1779 *            기존 데이터 배열
1780 * @param currentPageNo :
1781 *            현재 페이지 번호
1782 * @param recordCountPerPage :
1783 *            페이지 하나에 표시할 최대 데이터 수
1784 * @param pageSize :
1785 *            화면에 표시할 페이지 링크 수
1786 * @param paginationJsFunction :
1787 *            페이지 링크 클릭 시 호출할 메소드 이름
1788 * @param totalCnt :
1789 *            전체 데이터 갯수, 명시하지 않으면 data 배열 원소 갯수로 지정됨
1790 * @returns 페이징 정보가 붙은 객체
1791 */
1792function fn_getPagingTag(data, currentPageNo, recordCountPerPage, pageSize,
1793		paginationJsFunction, totalCnt) {
1794	if (typeof (pageSize) == 'undefined' || pageSize == null) {
1795		pageSize = 10;
1796	}
1797	if (typeof (paginationJsFunction) == 'undefined'
1798			|| paginationJsFunction == null) {
1799		paginationJsFunction = 'linkPage';
1800	}
1801	var paginationInfo = new PaginationInfo();
1802	paginationInfo.setCurrentPageNo(Math.floor(Number(currentPageNo)));
1803	if (totalCnt)
1804		paginationInfo.setTotalRecordCount(totalCnt);
1805	else
1806		paginationInfo.setTotalRecordCount(data.length);
1807	paginationInfo
1808			.setRecordCountPerPage(Math.floor(Number(recordCountPerPage)));
1809	paginationInfo.setPageSize(Math.floor(Number(pageSize)));
1810
1811	var paginationRenderer = new ImagePaginationRenderer(resourcesPath);
1812	return paginationRenderer.renderPagination(paginationInfo,
1813			paginationJsFunction);
1814}
1815
1816/**
1817 * 데이터 배열을 페이징 정보가 붙은 객체로 만들어 반환합니다. fn_comm_setList 메소드에 사용이 가능합니다.
1818 *
1819 * pageSize 기본값은 10 입니다. paginationJsFunction 기본값은 linkPage 입니다.
1820 *
1821 * totalCnt 매개변수가 명시된 경우, data 에 페이지 내 데이터만 들어왔다고 가정함 --> 데이터 필터링 없음, 행 번호 자체 계산
1822 * totalCnt 매개변수가 명시되지 않은 경우, data 에 전체 데이터가 모두 들어왔다고 가정함 --> 데이터 필터링 있음
1823 *
1824 * @param data :
1825 *            기존 데이터 배열
1826 * @param currentPageNo :
1827 *            현재 페이지 번호
1828 * @param recordCountPerPage :
1829 *            페이지 하나에 표시할 최대 데이터 수
1830 * @param pageSize :
1831 *            화면에 표시할 페이지 링크 수
1832 * @param paginationJsFunction :
1833 *            페이지 링크 클릭 시 호출할 메소드 이름
1834 * @param totalCnt :
1835 *            데이터 총 갯수 (입력하지 않는 경우 data 배열 원소 갯수로 지정됨)
1836 * @returns 페이징 정보가 붙은 객체
1837 */
1838function fn_attachPaging(data, currentPageNo, recordCountPerPage, pageSize,
1839		paginationJsFunction, totalCnt) {
1840	if (typeof (pageSize) == 'undefined' || pageSize == null)
1841		pageSize = 10;
1842	if (typeof (paginationJsFunction) == 'undefined'
1843			|| paginationJsFunction == null) {
1844		paginationJsFunction = 'linkPage';
1845	}
1846
1847	var curPageNo = Math.floor(Number(currentPageNo));
1848	var recCountPerPage = Math.floor(Number(recordCountPerPage));
1849	var pgSize = Math.floor(Number(pageSize));
1850
1851	var result = {};
1852	var pagedData = [];
1853
1854	var rnum = 0; // 순방향 행번호
1855	var dnum = data.length + 1; // 역방향 행번호
1856	var cnt = data.length; // 총 갯수
1857
1858	if (totalCnt) { // 총 갯수가 명시된 경우, data에 페이징된 데이터만 들어온 경우이므로, 데이터를 필터링하지 않는 대신
1859					// 행 번호를 계산해 주어야 함
1860		cnt = Number(totalCnt);
1861		rnum = (curPageNo - 1) * recCountPerPage;
1862		dnum = cnt;
1863		for (var idx = 0; idx < data.length; idx++) {
1864			rnum = idx + 1;
1865			dnum--;
1866			var row = data[idx];
1867			row["__CNT__"] = cnt;
1868			row["__RNUM__"] = dnum;
1869			row["__RNUM1__"] = rnum;
1870			pagedData.push(row);
1871		}
1872		result.list = pagedData;
1873		result.pagination = fn_getPagingTag(data, curPageNo, recCountPerPage,
1874				pgSize, paginationJsFunction, cnt);
1875	} else { // 총 갯수가 명시되지 않은 경우, data에 페이징 되지 않은 전체 데이터가 들어온 경우이므로 행 번호는 그냥
1876				// 매기면 되지만 데이터를 필터링해야 함
1877		for (var idx = 0; idx < data.length; idx++) {
1878			rnum = idx + 1;
1879			dnum--;
1880			var row = data[idx];
1881			row["__CNT__"] = cnt;
1882			row["__RNUM__"] = dnum;
1883			row["__RNUM1__"] = rnum;
1884			if (idx >= (curPageNo - 1) * recCountPerPage
1885					&& idx < curPageNo * recCountPerPage) {
1886				pagedData.push(row);
1887			}
1888		}
1889		result.list = pagedData;
1890		result.pagination = fn_getPagingTag(data, curPageNo, recCountPerPage,
1891				pgSize, paginationJsFunction);
1892	}
1893
1894	return result;
1895}
1896
1897/**
1898 * 해당 선택자에 페이징 컴포넌트를 배치합니다.
1899 *
1900 * 예 : $('#paging').paging(2, data.length, 20, 10, 'linkPage');
1901 *
1902 * pageSize 기본값은 10 입니다. paginationJsFunction 기본값은 linkPage 입니다.
1903 */
1904$.fn.paging = function(currentPageNo, totalRecordCount, recordCountPerPage,
1905		pageSize, paginationJsFunction) {
1906	if (typeof (pageSize) == 'undefined' || pageSize == null)
1907		pageSize = 10;
1908	if (typeof (paginationJsFunction) == 'undefined'
1909			|| paginationJsFunction == null) {
1910		paginationJsFunction = 'linkPage';
1911	}
1912	var paginationInfo = new PaginationInfo();
1913	paginationInfo.setCurrentPageNo(currentPageNo);
1914	paginationInfo.setTotalRecordCount(totalRecordCount);
1915	paginationInfo.setRecordCountPerPage(recordCountPerPage);
1916	paginationInfo.setPageSize(pageSize);
1917
1918	var paginationRenderer = new ImagePaginationRenderer();
1919	var result = paginationRenderer.renderPagination(paginationInfo,
1920			paginationJsFunction);
1921	return this.each(function() {
1922		this.html(result);
1923	});
1924};
1925
1926function __changeHeaderCheckbox__() {
1927	var $_headerCheckbox = $(this);
1928	var $_table = $_headerCheckbox.parentsUntil("table", ":last").parent();
1929	var columnIdx = $_headerCheckbox.data("__columnIdx__");
1930	$_table
1931			.find(
1932					"tr:not(:eq(0)) :nth-child(" + (columnIdx + 1)
1933							+ ") :checkbox").prop("checked",
1934					$_headerCheckbox.prop("checked"));
1935}
1936
1937/**
1938 * 테이블의 헤더에 체크박스 전체선택 이벤트 추가
1939 */
1940$.fn.bindHeaderCheckboxEvent = function(columnIdx) {
1941	return this.each(function() {
1942		var $_this = $(this);
1943		if ($_this[0].tagName != "TABLE") {
1944			return;
1945		}
1946
1947		var $_headerCheckbox = $_this.find("tr:eq(0) :eq(" + columnIdx
1948				+ ") :checkbox");
1949		$_headerCheckbox.data("__columnIdx__", columnIdx);
1950		$_headerCheckbox.off("change", __changeHeaderCheckbox__).on("change",
1951				__changeHeaderCheckbox__);
1952		var $_bodyCheckbox = $_this.find("tr:not(:eq(0)) :nth-child("
1953				+ (columnIdx + 1) + ") :checkbox");
1954		$_bodyCheckbox.on("change", function() {
1955			if ($(this).prop("checked")) {
1956				$_headerCheckbox.prop("checked", $_bodyCheckbox
1957						.filter(":checked").length == $_bodyCheckbox.length);
1958			} else {
1959				$_headerCheckbox.prop("checked", false);
1960			}
1961		});
1962	});
1963};
1964
1965$.fn.fn_comm_scrollFocus = function(nDuration, nMargin) {
1966	nDuration = nDuration | 400;
1967	nMargin = nMargin | 0;
1968	var $_this = $(this);
1969	var pt = $_this.position().top;
1970	$('html, body').animate({
1971		scrollTop : pt - nMargin
1972	}, {
1973		duration : nDuration,
1974		complete : function() {
1975			$_this.focus();
1976		}
1977	});
1978};
1979
1980function paginationRend(data, paginationId) {
1981	var pagination = fn_comm_processScalarAjax({
1982		url : contextPath + "/CM_CM03_CON/CM_CM03_R01.do",
1983		data : {
1984			currentPageNo : data.currentPageNo,
1985			totalRecordCount : data.totalRecordCount,
1986			recordCountPerPage : data.recordCountPerPage,
1987			templateCd : templateCd,
1988			templatePath : templatePath,
1989			paginationJsFunction : data.jsFunction,
1990			styleName : data.styleName
1991		}
1992	});
1993	$(paginationId).html(pagination);
1994}
1995
1996/**
1997 * 태그를 없앰. 20171008 by hdy
1998 *
1999 * @param str
2000 * @returns
2001 */
2002function stripTags(str) {
2003	if (str)
2004		return str.replace(/(<([^>]+)>)/gi, "");
2005}
2006
2007function BBSList(MENU_SN) {
2008	var link = "";
2009	link = "/ko/cms/CM_BB01_CON/CM_BB01_L01.do?MENU_SN=" + MENU_SN;
2010	location.href = link;
2011}
2012
2013/**
2014 * MENU_SN 과 BBS_SN 으로 해당 뷰 페이지로 이동
2015 */
2016function BBSView(MENU_SN, BBS_SN) {
2017
2018	var link = "";
2019	switch (MENU_SN) {
2020	case 1884: // 사진일기
2021		// 해당 게시물이 몇페이지에 있는지 알아야 함.
2022		// 뷰 페이지로 이동 후 뷰 페이지 내 에서 몇 페이지인지 알아낸 후 linkPage(페이지번호) 을 수행 후 화면에 해당
2023		// 게시물을 표시하는 처리가 필요함.
2024		link = "/ko/cms/CM_BB01_CON/CM_BB01_L01.do?MENU_SN=" + MENU_SN
2025				+ "&BBS_SN=" + BBS_SN + "&ATCH_SN=1";
2026		break;
2027	case 1885: // 동영상갤러리
2028	case 1886: // 인터뷰,칼럼
2029	case 1889: // 공지사항
2030	case 1888: // 보도자료
2031	case 1887: // 정책자료
2032	case 1894: // 토론의장
2033	case 1891: // 모범사례
2034	case 1890: // 가장 많은 질문
2035		link = "/ko/cms/CM_BB01_CON/CM_BB01_V01.do?MENU_SN=" + MENU_SN
2036				+ "&BBS_SN=" + BBS_SN;
2037		break;
2038	}
2039	location.href = link;
2040}
2041
2042/**
2043 * 해시태그를 이용해서 파라미터를 받고자 할 때 사용
2044 */
2045function hashParams(cb) {
2046	var hashArr = location.hash.substring(1).split("&");
2047	var hashParams = new Array;
2048	for ( var i in hashArr) {
2049		var tmp = hashArr[i].split("=");
2050		var key = tmp[0];
2051		var val = tmp[1]
2052		hashParams[key] = decodeURIComponent(val);
2053	}
2054	// 콜백처리
2055	if (typeof cb == 'function') {
2056		cb(hashParams);
2057	}
2058	return hashParams;
2059}
2060
2061function hashProcess() {
2062	var hParams = hashParams();
2063
2064	// 통합검색 처리
2065	if (typeof hParams != 'undefined' && typeof hParams.keyword != 'undefined'
2066			&& hParams.keyword != '') {
2067		document.frm_search.keyword.value = hParams.keyword;
2068		applySearch(hParams);
2069		applyMenu(hParams);
2070	}
2071}
2072function nl2br(str, is_xhtml) {
2073	var breakTag = (is_xhtml || typeof is_xhtml === 'undefined') ? '<br />'
2074			: '<br>';
2075	return (str + '').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + breakTag
2076			+ '$2');
2077}
2078
2079/**
2080 * 타임스탬프를 지정된 포멧으로 출력한다.
2081 *
2082 * @param timestamp
2083 * @param format
2084 * @returns {String}
2085 */
2086function timestampFormat(timestamp, format) {
2087	var date = new Date(timestamp);
2088
2089	var year = date.getFullYear();
2090	var month = date.getMonth() + 1;
2091	var day = date.getDate();
2092	var hour = date.getHours();
2093	var minute = date.getMinutes();
2094	var second = date.getSeconds();
2095
2096	var result = "";
2097
2098	if (typeof format == 'undefined') {
2099		format = "%Y-%M-%D: %H:%I:%S";
2100	}
2101	result = format.replace(/\%Y/gi, year).replace(/\%M/gi, zeroFill(month, 2))
2102			.replace(/\%D/gi, zeroFill(day, 2)).replace(/\%H/gi,
2103					zeroFill(hour, 2)).replace(/\%I/gi, zeroFill(minute, 2))
2104			.replace(/\%S/gi, zeroFill(second, 2));
2105	return result;
2106}
2107
2108/**
2109 * 수(number) 를 지정된 숫자 (width) 만큼 0 으로 채움.
2110 *
2111 * @param number
2112 * @param width
2113 * @returns
2114 */
2115function zeroFill(number, width) {
2116	width -= number.toString().length;
2117	if (width > 0) {
2118		return new Array(width + (/\./.test(number) ? 2 : 1)).join('0')
2119				+ number;
2120	}
2121	return number + ""; // always return a string
2122}
2123
2124/**
2125 * 날짜 차이 계산해서 반환함.
2126 *
2127 * @param diff_day
2128 * @param day
2129 * @returns {String}
2130 */
2131function date_diff(diff_day, day) {
2132	if (typeof day == 'undefined') {
2133		day = new Date();
2134	} else {
2135		day = new Date(day);
2136	}
2137	var d = (new Date(Date.parse(day) + diff_day * 1000 * 60 * 60 * 24));
2138	var ret = d.getFullYear() + '-' + zeroFill(d.getMonth() + 1, 2) + '-'
2139			+ zeroFill(d.getDate(), 2);
2140	return ret;
2141}
2142
2143/*
2144 * Password Validator 0.1 비밀번호 검증 (c) 2007 Steven Levithan MIT License
2145 */
2146
2147function validatePassword(pw, options) {
2148	// default options (allows any password)
2149	var o = {
2150		lower : 0,
2151		upper : 0,
2152		alpha : 0, /* lower + upper */
2153		numeric : 0,
2154		special : 0,
2155		length : [ 0, Infinity ],
2156		custom : [ /* regexes and/or functions */],
2157		badWords : [],
2158		badSequenceLength : 0,
2159		noQwertySequences : false,
2160		noSequential : false
2161	};
2162
2163	for ( var property in options)
2164		o[property] = options[property];
2165
2166	var re = {
2167		lower : /[a-z]/g,
2168		upper : /[A-Z]/g,
2169		alpha : /[A-Z]/gi,
2170		numeric : /[0-9]/g,
2171		special : /[\W_]/g
2172	}, rule, i;
2173
2174	// enforce min/max length
2175	if (pw.length < o.length[0] || pw.length > o.length[1])
2176		return false;
2177
2178	// enforce lower/upper/alpha/numeric/special rules
2179	for (rule in re) {
2180		if ((pw.match(re[rule]) || []).length < o[rule])
2181			return false;
2182	}
2183
2184	// enforce word ban (case insensitive)
2185	for (i = 0; i < o.badWords.length; i++) {
2186		if (pw.toLowerCase().indexOf(o.badWords[i].toLowerCase()) > -1)
2187			return false;
2188	}
2189
2190	// enforce the no sequential, identical characters rule
2191	if (o.noSequential && /([\S\s])\1/.test(pw))
2192		return false;
2193
2194	// enforce alphanumeric/qwerty sequence ban rules
2195	if (o.badSequenceLength) {
2196		var lower = "abcdefghijklmnopqrstuvwxyz", upper = lower.toUpperCase(), numbers = "0123456789", qwerty = "qwertyuiopasdfghjklzxcvbnm", start = o.badSequenceLength - 1, seq = "_"
2197				+ pw.slice(0, start);
2198		for (i = start; i < pw.length; i++) {
2199			seq = seq.slice(1) + pw.charAt(i);
2200			if (lower.indexOf(seq) > -1 || upper.indexOf(seq) > -1
2201					|| numbers.indexOf(seq) > -1
2202					|| (o.noQwertySequences && qwerty.indexOf(seq) > -1)) {
2203				return false;
2204			}
2205		}
2206	}
2207
2208	// enforce custom regex/function rules
2209	for (i = 0; i < o.custom.length; i++) {
2210		rule = o.custom[i];
2211		if (rule instanceof RegExp) {
2212			if (!rule.test(pw))
2213				return false;
2214		} else if (rule instanceof Function) {
2215			if (!rule(pw))
2216				return false;
2217		}
2218	}
2219
2220	// great success!
2221	return true;
2222}
2223
2224function checkPassword (str) {
2225	var password = str;
2226	var passed = validatePassword(password, {
2227	 length:   [9, Infinity],
2228	 lower:    1,
2229	 upper:    1,
2230	 numeric:  1,
2231	 special:  1,
2232	 badWords: ["password", "steven", "levithan"],
2233	 badSequenceLength: 4
2234	});
2235	console.log (passed);
2236	return passed;
2237}
2238
2239function form_val_chk($frm) {
2240    var ok = true;
2241    $.each($frm.find('input, select, textarea'), function() {
2242        if ($(this).hasClass('req')) {
2243            switch ($(this).prop('tagName').toLowerCase()) {
2244            case 'select':
2245                if ($(this).find('option:selected').length < 1 || $(this).find('option:selected').val() == '') {
2246                    ok = false;
2247                    alert($(this).attr('title') ? $(this).attr('title') : '모든 항목을 선택해주세요.');
2248                    $(this).focus();
2249                    return false;
2250                }
2251                break;
2252            case 'textarea':
2253                if ($(this).val().replace(/ /g,'') == '') {
2254                    ok = false;
2255                    alert($(this).attr('title') ? $(this).attr('title') : '모든 항목을 입력해주세요.');
2256                    $(this).focus();
2257                    return false;
2258                }
2259                break;
2260            default:
2261                if ($(this).attr('type').toLowerCase() == 'radio' || $(this).attr('type').toLowerCase() == 'checkbox') {
2262                    if ($(this).attr('name').indexOf('[') > 0) obj_name_cond = 'input[name*="'+$(this).attr('name').substr(0, $(this).attr('name').indexOf('['))+'["]:checked';
2263                    else obj_name_cond = 'input[name="'+$(this).attr('name')+'"]:checked';
2264                    if ($frm.find(obj_name_cond).length < 1) {
2265                        ok = false;
2266                        alert($(this).attr('title') ? $(this).attr('title') : '모든 항목을 선택해주세요.');
2267                        return false;
2268                    }
2269                }
2270                else if ($(this).val().replace(/ /g,'') == '') {
2271                    ok = false;
2272                    alert($(this).attr('title') ? $(this).attr('title') : '모든 항목을 입력해주세요.');
2273                    if ($(this).attr('type').toLowerCase() != 'hidden') $(this).focus();
2274                    return false;
2275                }
2276                break;
2277            }
2278        }
2279        if ($(this).data('pattern') && $(this).val().replace(/ /g,'') != '') {
2280            if (!pattern_check($(this).data('pattern'), $(this).val())) {
2281                $(this).focus();
2282                ok = false;
2283                return false;
2284            }
2285        }
2286        if ($(this).data('minlen') && $(this).val().replace(/ /g,'') != '') {
2287            if ($(this).val().length < $(this).data('minlen')) {
2288                alert($(this).data('minlen')+'자 이상 입력해주세요.');
2289                $(this).focus();
2290                ok = false;
2291                return false;
2292            }
2293        }
2294    });
2295    if ($frm.find('.date_range').length > 0) {
2296        $.each($frm.find('.date_range'), function() {
2297            if ($(this).find('input.calendar:eq(0)').val() != '' && $(this).find('input.calendar:eq(1)').val() && $(this).find('input.calendar:eq(0)').val() > $(this).find('input.calendar:eq(1)').val()) {
2298                alert('시작일은 종료일보다 클 수 없습니다.');
2299                $(this).find('input.calendar:eq(0)').focus();
2300                ok = false;
2301                return false;
2302            }
2303        });
2304    }
2305    if (ok && $('input.agreeY').length > 0 && !$('input.agreeY').prop('checked')) {
2306        alert($('input.agreeY').attr('title')+'해주셔야 등록이 가능합니다.');
2307        ok = false;
2308    }
2309    return ok;
2310}
2311
2312function getFileExtIcon(name){
2313
2314	var ext = ".bmp .doc .gif .hwp .jpg .mp4 .pdf .png .ppt .swf .txt .xls .zip";
2315    var _fileLen = name.length;
2316    var _lastDot = name.lastIndexOf('.');
2317    var _fileExt = name.substring(_lastDot+1, _fileLen).toLowerCase();
2318
2319    if(ext.indexOf(_fileExt) == -1) _fileExt = 'etc';
2320
2321	return _fileExt;
2322}
2323
2324$.fn.rowspan = function(colIdx, isStats) {
2325    return this.each(function(){
2326        var that;
2327        $('tr', this).each(function(row) {
2328            $('td',this).eq(colIdx).filter(':visible').each(function(col) {
2329
2330                if ($(this).html() == $(that).html() && (!isStats || isStats && $(this).prev().html() == $(that).prev().html() ) ) {
2331                    rowspan = $(that).attr("rowspan") || 1;
2332                    rowspan = Number(rowspan)+1;
2333
2334                    $(that).attr("rowspan",rowspan);
2335
2336                    $(this).hide();
2337
2338                } else {
2339                    that = this;
2340                }
2341
2342                that = (that == null) ? this : that;
2343            });
2344        });
2345    });
2346};
2347
2348function fn_email_Check(str){
2349	var regEmail = /([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/;
2350	if( !str ){
2351	    return false;
2352	}else{
2353	    if(!regEmail.test(str)) {
2354	        return false;
2355	    }
2356	}
2357	return true;
2358}
2359$(document).ready(function () {
2360	$('.view_func .zoom').removeData('easyView');
2361	$('.view_func .zoom').easyView({
2362		container: 'article',
2363		increaseSelector: '.btn_zoomIn',
2364		decreaseSelector: '.btn_zoomOut',
2365		normalSelector: '.btn_zoomReset'
2366	});
2367})

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.