PageSourceSearch

https://busansinbo.or.kr/common/js/lib.js

js busansinbo.or.kr collected 2026-10-05 06:05:55 UTC 21,157 bytes, 588 lines download raw bytes

1/**
2 * yhdatabase javascript library
3 *
4 * @author ryeon
5 * @since 2022. 06. 24.
6 * @version 1.1.0
7 */
8
9var yhLib = (function () {
10	function removeParams(url) {
11		var startParamsIndex = url.indexOf('?');
12		return url.substring(0, startParamsIndex > -1 ? startParamsIndex : url.length);
13	}
14
15	function verifiedURL(url) {
16		return exist(yh.contextPath) ? (url.indexOf(yh.contextPath) == 0 ? url : yh.contextPath + url) : url;
17	}
18
19	function ajaxErrorContentFrom(html) {
20		var $html = $(html);
21		var $error = $html.filter('#ajaxErrorContent');
22		if ($error.length < 1) {
23			$error = $html.find('#ajaxErrorContent');
24		}
25
26		return $error.children();
27	}
28
29	var load = {
30		/**
31			jQuery.load의 wrapper 함수. 필요 인자 지정 시 $box 영역을 ajax 통신 결과로 대체하며, 접근 권한이 없거나 세션이 없는 경우 오류 내용을 노출함.
32
33			##### 사용 방법 #####
34			{
35				$box: (필수) 로딩 영역 엘리먼트 jquery 객체,
36				url: (필수) contents 로딩 URL.,
37				formId: (선택) payload 관리 form id. palyload 우선 순위 1,
38				$form: (선택) payload 관리 form. form id를 넘기는 대신 jquery 객체를 넘길 수도 있음. palyload 우선 순위 2,
39				params: (선택) URL payload palyload 우선 순위 3,
40				loadingArea: (선택) $box 내 로딩 마크 영역 선택자. 반드시 data-로 시작해야 하며, 미지정 시 기본값은 data-loading-area. 하나의 페이지 내 여러 개의 data-loading-area가 존재해 충돌이 나는 경우 사용 가능.,
41				contentsArea: (선택) $box 내 URL 호출 결과 대체 영역 선택자. 반드시 data-로 시작해야 하며, 미지정 시 기본값은 data-content-area.,
42				replaceContentsId: (선택) URL 호출 후 반환된 html 내 $box 영역에 노출할 요소의 id. 기본값은 aja
42xContent.
43				$replacement: (선택) URL 호출 대신 이미 존재하는 html 요소로 내용을 변경하고 싶은 경우 전달.
44			}
45		*/
46		content: function (args) {
47			var deferred = $.Deferred();
48			var $loading = yhLib.exist(args.loadingArea) ? args.$box.find("[" + args.loadingArea + "]") : args.$box.find("[data-loading-area]:first");
49			var $content = yhLib.exist(args.contentsArea) ? args.$box.find("[" + args.contentsArea + "]") : args.$box.find("[data-content-area]:first");
50			var replaceContentsId = yhLib.exist(args.replaceContentsId) ? args.replaceContentsId : "ajaxContent";
51			var $form = yhLib.exist(args.formId) ? $('#' + args.formId) : (yhLib.exist(args.$form) ? args.$form : null);
52			var params = yhLib.exist($form) ? $form.serializedJSON() : args.params;
53			var url = yhLib.exist($form) ? $form.attr('action') : args.url;
54			if (yhLib.exist(url)) {
55				url = verifiedURL(url);
56			}
57
58			args.preCallback instanceof Function ? args.preCallback() : null;
59
60			$content.hide().empty();
61			$loading.show();
62			if (yhLib.exist(args.$replacement)) { // 대체 html을 직접 전달.
63				$content.empty().append(args.$replacement.children());
64
65				$loading.yh_animate('fadeOut', 'fast').then(function () {
66					return $content.yh_animate('fadeIn', 'fast');
67				}).then(function () {
68					deferred.resolve();
69				});
70			} else {
71				$content.load(url + " #" + replaceContentsId + " > *", params, function (html, status) {
72					if (status == "error" || $content.is(':empty')) {
73						$content.append(ajaxErrorContentFrom(html));
74						$loading.yh_animate('fadeOut', 'fast').then(function () {
75							$content.fadeIn('fast');
76							deferred.reject();
77						});
78					} else {
79						$loading.yh_animate('fadeOut', 'fast').then(function () {
80							return $content.yh_animate('fadeIn', 'fast');
81						}).then(function () {
82							deferred.resolve();
83						});
84					}
85				});
86			}
87
88			return deferred.promise();
89		}
90	}
91
92	var file = {
93		download: function (atchFileIdEncrypted, fileSnEncrypted) {
94			$.ajax({
95				type: 'post',
96				url: verifiedURL('/common/file/download/log/saveProc.do'),
97				data: { atchFileId: atchFileIdEncrypted, fileSn: fileSnEncrypted, siteCode: yh.siteCodeFull },
98			});
99
100			window.open(verifiedURL('/common/file/download.do?atchFileId=' + atchFileIdEncrypted + '&fileSn=' + (exist(fileSnEncrypted) ? fileSnEncrypted : '')));
101			return false;
102		}, preview: function (arg0, arg1) {
103			var frm = document.getElementById("filePreviewForm");
104
105			frm.atchFileId.value = arg0;
106			frm.fileSn.value = arg1;
107
108			frm.submit();
109			return false;
110		}
111	}
112
113	var _promise = {
114		ajax: function (opt) { // opt는 기본 $.ajax 변수와 동일.
115			var deferred = $.Deferred();
116
117			var ajaxOptions = {
118				type: "post", dataType: "json", success: function (result) {
119					deferred.resolve(result);
120				}, error: function (e) {
121					console.log(e);
122					deferred.reject(e);
123					alert('서버와 통신 중 오류가 발생했습니다.');
124				}
125			}
126			$.extend(ajaxOptions, opt);
127			ajaxOptions.url = verifiedURL(ajaxOptions.url);
128
129			if (opt.data instanceof FormData) {
130				ajaxOptions.contentType = false;
131				ajaxOptions.processData = false;
132			}
133
134			$.ajax(ajaxOptions).fail(function (e) { deferred.reject(e); });
135
136			return deferred.promise();
137		}, get: function (opt) {
138			var deferred = $.Deferred();
139
140			$.get(verifiedURL(opt.url), function (html) {
141				deferred.resolve(html);
142			}).fail(function (e) {
143				deferred.reject(e);
144			});
145
146			return deferred.promise();
147		}
148	}
149
150	var inline = (function () {
151		var attrs = {
152			id: {
153				form: "data-req-form-id", // 통신에 이용할 form id. 없는 경우 임시 form 객체를 생성해 통신.
154				// 이 값이 있는 경우 req-form-id에 해당하는 form과 req-merge-form-id에 해당하는 form을 합쳐서 통신에 이용한다. 이때 통신 URL은 req-form-id를 이용한다.
155				// merge하고 싶지 않은 요소가 있다면 data-req-not-merge 속성 부여 시 merge하지 않는다.
156				// 이 값을 이용 시에는 data-req-merge-prefix를 지정할 수 있다. 미지정 시 기본값은 없다.
157				// data-req-merge-prefix값은, merge하려는 객체에 존재하는 엘리먼트의 명칭 앞의 prefix로 이용된다.
158				mergeForm: 'data-req-merge-form-id',
159				successForm: 'data-req-success-form-id' // ajax 처리 성공 후 post할 form id. 단, req-after가 선언되어 있다면 무시되며, success-msg는 함께 이용할 수 있다.
160			},
161			action: "data-req-action", // 통신 URL
162			msg: {
163				confirm: "data-req-confirm-msg", // 호출 전 확인 안내 문구
164				success: "data-req-success-msg", // 호출 후 성공 안내 문구
165				failed: "data-req-failed-msg" // 호출 후 실패 안내 문구
166			},
167			url: {
168				success: 'data-req-success-url' // 성공 후 이동 화면 url
169			},
170			before: "data-req-before", // ajax 호출 전처리. form 데이터 복사, alert 등 처리 가능.
171			after: "data-req-after", // ajax 호출 후처리. 이 값이 있는 경우 success message, url 등 다른 옵션은 무시된다.
172			target: "data-req-target" // post 시 form tag target
173		}
174
175		var temporaryRequestFormName = "temporaryRequestForm";
176
177		/* ########## private ########## */
178
179		function paramsOf(thiz) {
180			return $.map(thiz.attributes, function (e) {
181				var converted = {};
182				converted.key = e.name;
183				converted.value = e.value;
184				return converted;
185			}).filter(function (e) {
186				return e.key.match(/^data-req-p-.+$/ig) != null;
187			}).map(function (e) {
188				e.key = e.key.replace(/data-req-p-/ig, "");
189				return e;
190				// return e.key.replace(/-[a-zA-Z]{1}/, function(matched) { return matched.substr(1, 2).toUpperCase() });
191			});
192		}
193
194		function getParamsOf(thiz) {
195			return $.map(thiz.attributes, function (e) {
196				var converted = {};
197				converted.key = e.name;
198				converted.value = e.value;
199				return converted;
200			}).filter(function (e) {
201				return e.key.match(/^data-req-get-p-.+$/ig) != null;
202			}).map(function (e) {
203				e.key = e.key.replace(/data-req-get-p-/ig, "");
204				return e;
205				// return e.key.replace(/-[a-zA-Z]{1}/, function(matched) { return matched.substr(1, 2).toUpperCase() });
206			});
207		}
208
209		function prepareFrom(el) {
210			$("form[name=" + temporaryRequestFormName + "]").remove();
211
212			var $this = exist(el) ? $(el) : $(this);
213			var params = paramsOf($this[0]);
214			var formId = $this.attr(attrs.id.form);
215			var $form = $("#" + formId);
216			var action = $form.length > 0 ? $form.attr('action') : $this.attr(attrs.action);
217			var mergeFormId = $this.attr(attrs.id.mergeForm);
218
219			var getParams = getParamsOf($this[0]);
220			if (getParams.length > 0) {
221				// 현재 action에 기재되어 있는 인자 정보. (cache 방지용)
222				var currentQueryString = action.indexOf('?') > -1 ? action.substring(action.indexOf('?') + 1, action.length) : null;
223				var currentQuerySet = yhLib.exist(currentQueryString)
224					? currentQueryString.split('&').map(function (e) {
225						return {
226							key: e.substring(e, e.indexOf('=')),
227							value: e.substring(e.indexOf('=') + 1, e.length)
228						}
229					}) : [];
230				var currentQueryKeyList = currentQuerySet.map(function (e) { return e.key })
231
232				// 중복 인자 제거.
233				var duplicatedKeys = getParams.map(function (e) {
234					return e.key.camelcase();
235				}).filter(function (key) {
236					return currentQueryKeyList.indexOf(key) > -1;
237				})
238				if (yhLib.exist(duplicatedKeys)) {
239					for (var i = 0; i < duplicatedKeys.length; i++) {
240						var querySets = currentQuerySet.filter(function (e) { return e.key == duplicatedKeys[i]; })
241						for (var j = 0; j < querySets.length; j++) {
242							var queryString = querySets[j].key + '=' + querySets[j].value;
243							action = action.replace(queryString, '');
244						}
245					}
246				}
247
248				// 신규 인자 추가.
249				var queryString = getParams.map(function (e) {
250					return e.key.camelcase() + '=' + e.value;
251				}).join('&');
252				action += ((action.indexOf('?') > -1 ? '&' : '?') + queryString);
253			}
254
255			if ($form.length < 1) {
256				$form = $("<form id='" + temporaryRequestFormName + "' name='" + temporaryRequestFormName + "' method='post'>");
257				$form.appendTo("body");
258			}
259
260			exist($this.attr(attrs.target)) ? $form.attr("target", $this.attr(attrs.target)) : null;
261			$form.attr("action", action);
262
263			if (exist(mergeFormId)) {
264				var $mergeForm = $('#' + mergeFormId);
265				var $mergeElems = [];
266
267				var $mergeInputs = $mergeForm.clone().find('input[type=hidden], input[type=text]').not('[data-req-not-merge]').hide();
268				var $mergeEtcs = $mergeForm.find('select, [type=checkbox]:checked, [type=radio]:checked').not('[data-req-not-merge]').map(function (_, e) {
269					return $('<input type="hidden" name="' + $(e).attr('name') + '" value="' + $(e).val() + '">');
270				});
271
272				$mergeElems = $mergeElems.concat($mergeInputs.get());
273				$mergeElems = $mergeElems.concat($mergeEtcs.get());
274
275				var prefix = $(el).attr('data-req-merge-prefix');
276				if ($mergeElems.length > 0) {
277					$mergeElems.forEach(function (e) {
278						$(e).attr('data-merged', 'y');
279
280						var name = $(e).attr('name');
281						$(e).attr('name', (exist(prefix) ? (prefix + '_') : '') + name);
282					});
283				}
284
285				$form.find('[data-merged=y]').remove();
286				$form.append($mergeElems);
287			}
288
289			Object.keys(params).forEach(function (i) {
290				var keyValue = params[i];
291				var $target = $form.find('[name="' + keyValue.key.camelcase() + '"]');
292				if ($target.length < 1) {
293					$target = $("<input type='hidden' name='" + keyValue.key.camelcase() + "' />");
294					$target.appendTo($form);
295				}
296				$target.val(keyValue.value);
297			});
298
299			return $form;
300		}
301
302		function ajax(el) {
303			var deferred = $.Deferred();
304
305			var $this = exist(el) ? $(el) : $(this);
306			var before = $this.attr(attrs.before); // ajax 전처리 함수
307
308			if (!exist($this.attr(attrs.msg.confirm)) || confirm($this.attr(attrs.msg.confirm))) {
309				var before = exist(before) && window[before] instanceof Function ? window[before]($this) : true;
310				if (before) {
311					var $form = prepareFrom(el);
312					var data = $form.serializedJSON();
313					var after = $this.attr(attrs.after);
314					var successFormId = $this.attr(attrs.id.successForm);
315
316					yhLib.promise.ajax({
317						url: verifiedURL($form.attr("action")), data: data
318					}).then(function (result) {
319						if (exist(after) && window[after] instanceof Function) {
320							window[after](result);
321						} else {
322							if (result.success) {
323								yhLib.exist($this.attr(attrs.msg.success)) ? alert($this.attr(attrs.msg.success)) : null;
324
325								if (yhLib.exist(successFormId)) {
326									$('#' + successFormId)[0].submit();
327								} else {
328									var successURL = $this.attr(attrs.url.success);
329									yhLib.exist(successURL) ? location.href = verifiedURL(successURL) : null;
330									deferred.resolve(result);
331								}
332							} else {
333								var msg = yhLib.exist($this.attr(attrs.msg.failed))
334									? $this.attr(attrs.msg.failed)
335									: (yhLib.exist(result.error)
336										? result.error
337										: (yhLib.exist(result.errors) ? result.errors[0] : null)
338									);
339								yhLib.exist(msg) ? alert(msg) : null;
340							}
341						}
342					})
343
344					$form.remove();
345				}
346			}
347
348			return deferred.promise();
349		}
350
351		function post(el) {
352			prepareFrom(el)[0].submit();
353		}
354
355		function get(el) {
356			var $form = prepareFrom(el);
357			$form.attr('method', 'get');
358			$form.submit();
359		}
360
361		/**
362		 * 새 창 열림.
363		 *
364		 * data-req-action: (form-id 보다 우선 순위 낮음)
365		 * data-req-name: (선택) 새 창 title. 기본값: 새 창 열림.
366		 * data-req-width: (선택) 새 창 너비. 기본값: 500px.
367		 * data-req-height: (선택) 새 창 높이. 기본값: 450px.
368		 */
369		function open(el) {
370			var url = $(el).attr('data-req-action');
371			var windowName = $(el).attr('data-req-name');
372			var width = $(el).attr('data-req-width');
373			var height = $(el).attr('data-req-height');
374
375			window.open(
376				url,
377				(yhLib.exist(windowName) ? windowName : '새 창 열림'),
378				"width=" + (yhLib.exist(width) ? width : '500') +
379				", height=" + (yhLib.exist(height) ? height : '450') +
380				", scrollbars=yes, resizable=yes"
381			);
382		}
383
384		function failCallback(e) {
385			console.log(e);
386			alert("통신 중 오류가 발생했습니다.");
387		}
388
389		return {
390			ajax: ajax, get: get, post: post, open: open, failCallback: failCallback, paramsOf: paramsOf, prepareFrom: prepareFrom
391		}
392	})();
393
394	function execute(funcStr) {
395		exist(funcStr) ? window[funcStr]() : null;
396	}
397
398	function exist(obj) {
399		return obj != undefined && obj != null
400			&& (obj.constructor.name != "String" || obj.trim().length > 0)
401			&& (!(obj instanceof Array) || obj.length > 0);
402	}
403
404	function _eval(funcStr) {
405		return funcStr != undefined && funcStr != null && funcStr.length > 0 ? (new Function("return " + funcStr))() : null;
406	}
407
408	function turnOnAjaxLoadingBox() {
409		var $loadingBox = ajaxLoadingBox();
410
411		$(document).ajaxStart(function () { $loadingBox.fadeIn('fast'); });
412		$(document).ajaxStop(function () { $loadingBox.fadeOut('fast'); });
413
414		function ajaxLoadingBox() {
415			var $box = $('#ajaxLoadingBox');
416			if ($box.length > 0) {
417				return $box;
418			} else {
419				$('body').append(''
420					+ '<div id="ajaxLoadingBox" class="ajax-loading" style="display: none;">'
421					+ '    <img src="' + yh.contextPath + '/sys/img/login/ico_load_modal.gif" alt="요청 내용 처리 중...">'
422					+ '</div>'
423				);
424				return $('#ajaxLoadingBox');
425			}
426		}
427	}
428
429	function turnOffAjaxLoadingBox() {
430		$('#ajaxLoadingBox').fadeOut('fast');
431		$(document).unbind('ajaxStart');
432		$(document).unbind('ajaxStop');
433	}
434
435	return {
436		removeParams: removeParams, verifiedURL: verifiedURL, ajaxErrorContentFrom: ajaxErrorContentFrom,
437		file: file, inline: inline, req: inline, exist: exist, eval: _eval, promise: _promise, load: load,
438		turnOnAjaxLoadingBox: turnOnAjaxLoadingBox, turnOffAjaxLoadingBox: turnOffAjaxLoadingBox,
439		execute: execute
440	}
441})();
442
443String.prototype.camelcase = function() {
444	// test[0].idx -> test_0___idx
445	// test[0].idx-abc -> test_0___idx-abc
446	// [] = __
447	// . = __
448	var value = this;
449
450	var listIndexMatches = value.match(/_[\d]_/g);
451	if (listIndexMatches !== null) {
452		listIndexMatches.forEach(function(matched) {
453			value = value.replace(new RegExp(matched, 'g'), '[' + matched.replace(/_/g, '') + ']');
454		});
455	}
456
457	value = value.replace(/__/g, '.');
458
459	return value.toLowerCase().replace(/-+(.)/g, function(_, chr) {
460		return chr.toUpperCase();
461	});
462};
463
464
465/** 공통 페이징 함수 */
466function goPage(page) {
467	var formId;
468	try {
469		formId = yh.formId ? yh.formId : "list";
470	} catch (e) {
471		formId = "list";
472	}
473
474	var frm = document.getElementById(formId);
475	frm.page.value = page;
476	frm.submit();
477}
478
479function goListLimit() {
480	var formId;
481	try {
482		formId = yh.formId ? yh.formId : "list";
483	} catch (e) {
484		formId = "list";
485	}
486
487	var frm = document.getElementById(formId);
488	 // 선택된 값 가져오기
489    var selectedValue = document.getElementById("countType").value;
490	frm.listLimit.value = selectedValue;
491	frm.page.value = 1;
492	frm.searchType3.value = "0";
493	frm.submit();
494}
495
496$.fn.serializedJSON = function () {
497	var params = $(this).serializeArray();
498	var keys = params.map(function (e) { return e.name });
499	var values = params.map(function (e) { return e.value });
500
501	var rtn = {};
502	keys.forEach(function (e, i) {
503		rtn[e] = values[i];
504	});
505
506	return rtn;
507}
508
509$.fn.yh_animate = function (funcName, speed) {
510	var deferred = $.Deferred();
511	var $this = $(this);
512	$this[funcName](yhLib.exist(speed) ? speed : 'normal', function () {
513		return deferred.resolve($this);
514	});
515
516	return deferred.promise();
517}
518
519$.fn.simpleAjaxForm = function (callback, opt) {
520	$(this).each(function () {
521		var $form = $(this);
522		var options = {
523			url: yhLib.verifiedURL($form.attr('action')), type: 'post', dataType: 'json', resetForm: false,
524			beforeSubmit: function () {
525				var result = $form.find('[data-v-target=y]').validate().alert();
526				result ? yhLib.turnOnAjaxLoadingBox() : null;
527				return result;
528			}, success: function (result, _, _, form) {
529				yhLib.exist(callback) && callback instanceof Function ? callback(result, form) : null;
530			}, fail: function (e) {
531				console.log(e);
532				alert('서버와 통신 중 오류가 발생했습니다.');
533			}, error: function (e) {
534				console.log(e);
535				alert('서버와 통신 중 오류가 발생했습니다.');
536			}, complete: yhLib.turnOffAjaxLoadingBox
537		};
538
539		yhLib.exist(opt) ? $.extend(options, opt) : null;
540
541		$form.ajaxForm(options);
542	});
543}
544
545/**
546 * YN값을 받으면서 on-off 디자인의 checkbox를 제공하는 필드의 동작 지원 함수.
547 * YN값을 받는 실제 필드를 hidden으로 선언 후 data-onoff-type="y" 속성 부여,
548 * YN값을 받는 실제 필드의 이름 + OnOff를 id로 하는 checkbox 별도 선언해 이용
549 *
550 * 예) <form:hidden path="test" data-onoff-type="y" />
551 * <input type="checkbox" id="testOnOff" value="Y">
552 * <label for="testOnOff" class="chk-onoff">test</label>
553 */
554$.fn.useOnOffHandler = function () {
555	$(this).get().forEach(function (real) {
556		var $real = $(real);
557		var onOffElementId = yhLib.exist($real.attr('data-onoff-id')) ? $real.attr('data-onoff-id') : $real.attr('name') + 'OnOff';
558		if (yhLib.exist(onOffElementId)) {
559			var $onOff = $('#' + onOffElementId);
560			$onOff.unbind().change(function () {
561				$real.val($(this).is(':checked') ? 'Y' : 'N').trigger('change');
562			});
563
564			$real.syncOnOffHandlerStatus(); // real의 현재 선택 값을 onOff handler 요소에 적용. real == 'Y'라면 onOff는 checked될 것이고, 아니라면 반대가 된다.
565		}
566	});
567}
568
569/**
570 * YN값을 관리하는 실제 필드와 on-off 디자인의 checkbox 요소간 값 동기화 함수.
571 * 실제 값을 관리하는 필드의 YN 값에 따라 on-off 디자인 checkbox의 상태를 변화시킨다.
572 * 기본적으로 외부 호출은 useOnOffHandler를 사용하는 것으로 충분하나(onOff 이벤트 바인딩과 실제 요소와의 값 동기화 지원),
573 * 특별한 경우 실제 필드의 값만이 바뀐 경우 on-off checkbox를 동기화하기 위해 이용할 수 있다.
574 * 그 역, 즉 onoff 상태를 실제 필드로 전이하려는 경우는 onoff 요소에 change 이벤트를 일으키면 된다.
575 *
576 * @param editable true: 수정 가능, false: 수정 불가. false 할당 시 onOff 요소는 disabled 상태가 된다.
577 */
578$.fn.syncOnOffHandlerStatus = function (editable) {
579	editable = yhLib.exist(editable) ? editable : true;
580	$(this).get().forEach(function (real) {
581		var $real = $(real);
582		var onOffElementId = yhLib.exist($real.attr('data-onoff-id')) ? $real.attr('data-onoff-id') : $real.attr('name') + 'OnOff';
583		if (yhLib.exist(onOffElementId)) {
584			var $onOff = $('#' + onOffElementId);
585			$onOff.prop('checked', $real.val() == 'Y').trigger('change').prop('disabled', !editable);
586		}
587	});
588}

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.