PageSourceSearch

https://www.dealpang.com/data/skin/front/fresh/js/gd_common.js?ts=1784784794

js dealpang.com collected 2026-09-24 13:09:04 UTC 74,734 bytes, 1,953 lines download raw bytes

1/**
2 * This is commercial software, only users who have purchased a valid license
3 * and accept to the terms of the License Agreement can install and use this
4 * program.
5 *
6 * Do not edit or add to this file if you wish to upgrade Godomall5 to newer
7 * versions in the future.
8 *
9 * 공용 스크립트 및 프로토타입 정의
10 *
11 * @copyright ⓒ 2016, NHN godo: Corp.
12 * @link http://www.godo.co.kr
13 */
14
15
16/**
17 * 자바스크립트 Trim함수
18 *
19 * @deprecated 자바스크립트 기본 함수 혹은 $.trim() 사용
20 * @return string 좌우 공백 제거한 문자열
21 */
22//String.prototype.trim = function () {
23//    return this.replace(/^\s+|\s+$/, '');
24//};
25
26/**
27 * 자바스크립트 number_format 함수
28 *
29 * @deprecated numeral로 대체
30 * @return string 문자열을 세자리 단위로 쉼표 찍기
31 */
32//String.prototype.number_format = function()
33//{
34//    return this.replace(/(\d)(?=(?:\d{3})+(?!\d))/g, '$1,');
35//};
36
37// 멀티상점 변수 기본처리
38if (typeof gdCurrencyDecimalFormat === 'undefined') {
39    gdCurrencyDecimal = 0;
40    gdCurrencyDecimalFormat = 0;
41}
42
43// IE9에서 console 객체가 없어 console 객체가 없는 경우 log로 사용하도록 처리
44if (!window.console) console = {
45    log: function () {
46    }
47};
48
49// IE8 이하에서 Array.indexOf 지원하지 않는 경우에 대한 대응
50if (typeof Array.prototype.indexOf !== 'function') {
51    Array.prototype.indexOf = function (ele) {
52        return $.inArray(ele, this);
53    };
54}
55
56// IE8 이하에서 String.trim 지원하지 않는 경우에 대한 대응
57if (typeof String.prototype.trim !== 'function') {
58    String.prototype.trim = function(){
59        return $.trim(this);
60    };
61}
62
63// @qnibus bugfix. toFixed 사용시 무조건 반올림 처리하는 부분으로 인해 고도몰5의 정책과 맞지 않아서 toFixed 대신 사용해야 함
64if (typeof Number.prototype.toRealFixed !== 'function') {
65    Number.prototype.toRealFixed = function (digits, format) {
66        if (typeof digits === 'undefined') {
67            digits = gdCurrencyDecimal;
68        }
69        if (typeof format === 'undefined') {
70            format = gdCurrencyDecimalFormat;
71        }
72
73        _value = this.valueOf();
74        if(/[9]{9}/g.test(_value)) _value = _value.toFixed(9);
75        return numeral(Math.floor( _value * Math.pow(10, digits)) / Math.pow(10, digits)).format('0,' + format);
76    };
77}
78
79/**
80 * 스트링 치환 메소드
81 * @returns {String}
82 */
83String.prototype.format = function () {
84    var formatted = this;
85    for (var i = 0; i < arguments.length; i++) {
86        formatted = formatted.replace("{" + i + "}", arguments[i]);
87    }
88    return formatted;
89};
90
91/**
92 * DOM 로드
93 */
94$(document).ready(handleImageError);
95$(window).on('load', handleImageError);
96$(document).ajaxStart(handleImageError);
97$(document).ajaxComplete(handleImageError);
98$(document).ready(function () {
99    function getCookie(cookieName) {
100        let cookie = {};
101        document.cookie.split(';').forEach(function(el) {
102            let [key,value] = el.split('=');
103            cookie[key.trim()] = value;
104        })
105        return cookie[cookieName];
106    }
107
108    $("a").each(function (index) {
109
110        var href = $(this).attr('href');
111        if (!href) return false;
112        var shopTypeCookie = getCookie('shopTypeCookie');
113
114        if (shopTypeCookie == undefined) shopTypeCookie = 1;
115
116        if (href.indexOf('javascript:') == -1 && href.indexOf('#') == -1) {
117            if (href.indexOf('?') == -1) href = href + '?shopTypeCookie=' + shopTypeCookie;
118            else href = href + '&shopTypeCookie=' + shopTypeCookie;
119        }
120
121        //$(this).attr('href', href);
122    });
123
124
125
126
127    // IE 9 이하 placeholder 처리
128    if (gd_is_ie() < 10) {
129        $("input, textarea").placeholder();
130
131        $('form').submit(function(e){
132            $(this).find("input, textarea").each(function(){
133                var _name = this.name;
134                var _placeholder = this.getAttribute('placeholder');
135
136                if (_name && _placeholder) {
137                    var _target = document.getElementsByName(_name)[0];
138                    if (_target.value == _placeholder) {
139                        _target.value = '';
140                    }
141                }
142            });
143        });
144    }
145
146	// jQuery Validator 기본값 설정
147    $.validator.setDefaults({
148        onfocusout: false,
149        onclick: false,
150        onkeyup: false,
151        errorPlacement: function (error, element) {
152            // do nothing
153        },
154        invalidHandler: function (form, validator) {
155            var errors = validator.numberOfInvalids();
156            if (errors) {
157                alert(validator.errorList[0].message);
158                validator.errorList[0].element.focus();
159            }
160        },
161        submitHandler: function (form) {
162            form.submit();
163        }
164    });
165
166    // jQuery Validator 기본 메시지 설정
167    jQuery.extend(jQuery.validator.messages, {
168        required: __("필수항목 입니다."),
169        remote: __("이 필드를 수정해주세요."),
170        email: __("이메일을 정확하게 입력해주세요."),
171        url: __("유효하지 않은 URL이 입력되었습니다."),
172        date: __("날짜형식이 맞지 않습니다."),
173        dateISO: __("유효한 ISO 타입의 날짜로 다시 입력해주세요."),
174        number: __("숫자만 입력하실 수 있습니다."),
175        digits: __("숫자만 입력하실 수 있습니다."),
176        creditcard: __("유효한 신용카드 번호로 다시 입력해주세요."),
177        equalTo: __("동일한 값을 입력해주세요."),
178        accept: "Please enter a value with a valid extension.",
179        maxlength: jQuery.validator.format(__("최대 %i 이하 입력해 주세요.", "{0}")),
180        minlength: jQuery.validator.format(__("최소 %i 이상 입력해 주세요.", "{0}")),
181        rangelength: jQuery.validator.format(__("%1$i자에서 %2$i까지 입력가능합니다.", ["{0}", "{1}"])),
182        range: jQuery.validator.format(__("%1$i와 %2$i사이의 숫자를 입력해주세요.", ["{0}", "{1}"])),
183        max: jQuery.validator.format(__("최대 %i 이상 입력하실 수 없습니다.", "{0}")),
184        min: jQuery.validator.format(__("최소 %i 이하 입력하실 수 없습니다.", "{0}"))
185    });
186
187    //검색어
188    $("#frmSearchTop").validate({
189        submitHandler: function (form) {
190            var keyword = $('#frmSearchTop input[name="keyword"]').val();
191            if(keyword.length > 2) {
192                //var regKeyword = /^[a-zA-Z0-9~!?@#$%^&*():;{}<>\-_=+\[\]\|\\\"\'\,\.\/\`\\]$/;
193                var regNonAlpha = /[0-9\{\}\[\]\/?.,;:|\)*~`!^\-_+<>@\#$%&\\\=\(\'\" ]*$/;
194                if(!regNonAlpha.test(keyword)) {
195
196
197                    var regKeyword = /^[a-zA-Z0-9\{\}\[\]\/?.,;:|\)*~`!^\-_+<>@\#$%&\\\=\(\'\" ]*$/;
198
199                    if (regKeyword.test(keyword)) {
200                        var params = {keyword: keyword, mode: 'convertKeyword'};
201                        $.ajax({
202                            url: '../goods/goods_ps.php',
203                            type: "get",
204                            cache: false,
205                            async: false,
206                            data: params,
207                            success: function (data) {
208                                if (data.ack == 'y') {
209                                    $('#frmSearchTop input[name="keyword"]').val(data.converted);
210                                }
211                            },
212                            error: function (e) {
213
214                            }
215                        });
216                    }
217                }
218            }
219            if ($("#frmSearchTop input[name='adUrl']").val() && $("#frmSearchTop input[name='keyword']").val() == '') document.location.href = $("#frmSearchTop input[name='adUrl']").val();
220            else form.submit();
221        },
222        rules: {
223            keyword: {
224                required: function () {
225
226                    if ($("#frmSearchTop input[name='adUrl']").val()) {
227                        return false;
228                    }
229                    else {
230                        return true;
231                    }
232                }
233            }
234        },
235        messages: {
236            keyword: {
237                required: __('검색어를 입력하세요.')
238            }
239        }
240    });
241
242    function setDefultKeyword() {
243        $('.js_recent_area dt').html('최근 검색어');
244        $('.js_recent_area dt').addClass('active');
245        $('.js_recent_area .list_frame').addClass('active');
246        $('.js_recent_area').parents().find('.related_types').hide();
247        $('.js_recent_area').parents().find('.recent_keywords').show();
248        if ($('.recent_keywords').find('li').length === 0 ) {
249            var addEmptyHtml = '';
250            addEmptyHtml += '<li class="empty_txt">최근 검색어가 없습니다.</li>';
251            $('.recent_keywords').append(addEmptyHtml)
252        }
253    }
254
255    function setJsKeyword(json) {
256        $('.js_recent_area dt').html('추천 검색어');
257        $('.js_recent_area dt').removeClass('active');
258        $('.js_recent_area .list_frame').removeClass('active');
259
260        if($('.js_recent_list li').length ) {
261            $('.js_recent_list').empty();
262        }
263
264        var addHtml ='';
265        $.each(json.relatedKeyword, function(i, v) {
266
267            var resultKeyword = v.ep == 0 ? v.keywordKo:v.keywordEn;
268
269            addHtml += '<li class="related_keyword point_txt">';
270            //addHtml += '<a href="../goods/goods_search.php?keyword='+ encodeURI(v.keywordKo+' '+v.keywordEn) +'">';
271            addHtml += '<a href="../goods/goods_search.php?keyword='+ encodeURI(v.keywordKo) +'">';
272            addHtml += resultKeyword.replace(json.origin, '<strong>'+json.origin+'</strong>');
273            addHtml += '</a>';
274            addHtml += '</li>';
275        });
276        $('.js_recent_list ').append(addHtml);
277        // $('.js_recent_area').parents().find('.search_cont').show();
278        $('.js_recent_area').parents().find('.recent_keywords').hide();
279        $('.js_recent_area').parents().find('.related_types').show();
280    }
281
282    $('#frmSearchTop input[name="keyword"]').on('keyup', function(e) {
283        if (e.keyCode === 13) {
284            //event.preventDefault();
285            $('#frmSearchTop').submit();
286        }
287        var regKeyword = /^[a-zA-Z0-9\{\}\[\]\/?.,;:|\)*~`!^\-_+<>@\#$%&\\\=\(\'\" ]*$/;
288        var regKo = /([^가-힣\x20])/;
289
290        var  related = false;
291        // 영숫자특수문자가 이거나 자모음이 아닌 경우
292        if(!regKeyword.test($(this).val())) {
293            if(!regKo.test($(this).val())) {
294                related = true;
295            }
296        }
297        if($(this).val().length && related === true) {
298            var params = {keyword: $(this).val(), mode: 'relatedKeyword'};
299            $.ajax({
300                url: '../goods/goods_ps.php',
301                type: "get",
302                cache: false,
303                async: true,
304                data: params,
305                success: function (data) {
306                    if (data.ack == 'y') {
307                        setJsKeyword(data);
308                    }
309                },
310                error: function (e) {
311
312                }
313            });
314        } else {
315            setDefultKeyword();
316        }
317
318    });
319
320
321
322    /**
323     //검색어
324     $(".header_search_sub .frmSearchTop").validate({
325        submitHandler: function (form) {
326
327            var keyword = $('#frmSearchTop input[name="keyword"]').val();
328            if(keyword.length > 2) {
329
330                //var regKeyword = /^[a-zA-Z0-9~!?@#$%^&*():;{}<>\-_=+\[\]\|\\\"\'\,\.\/\`\\]$/;
331                var regKeyword = /^[a-zA-Z0-9\{\}\[\]\/?.,;:|\)*~`!^\-_+<>@\#$%&\\\=\(\'\" ]*$/;
332                if(regKeyword.test(keyword)) {
333                    var params = {keyword: keyword, mode: 'convertKeyword'};
334                    $.ajax({
335                        url:'../goods/goods_ps.php',
336                        type: "get",
337                        cache: false,
338                        async: false,
339                        data: params,
340                        success: function(data) {
341                            if(data.ack == 'y') {
342                                $('#frmSearchTop input[name="keyword"]').val(data.converted+' '+keyword);
343                            }
344                        },
345                        error: function(e) {
346
347                        }
348                    });
349                }
350            }
351            if ($(".header_search_sub .frmSearchTop input[name='adUrl']").val() && $(".header_search_sub .frmSearchTop input[name='keyword']").val() == '') document.location.href = $(".header_search_sub .frmSearchTop input[name='adUrl']").val();
352            else form.submit();
353        },
354        rules: {
355            keyword: {
356                required: function () {
357
358                    if ($(".header_search_sub .frmSearchTop input[name='adUrl']").val()) {
359                        return false;
360                    }
361                    else {
362                        return true;
363                    }
364                }
365            }
366        },
367        messages: {
368            keyword: {
369                required: __('검색어를 입력하세요.')
370            }
371        }
372    });
373     **/
374
375
376
377    // 최근 검색어 삭제
378    $('.btn_top_search_del').click(function(e){
379        e.stopPropagation();
380        $self = $(this);
381        $.post('../goods/goods_ps.php', {
382            'mode': 'delete_recent_keyword',
383            'keyword': $(this).data('recent-keyword')
384        }, function (data, status) {
385            // 값이 없는 경우 성공
386            if (status == 'success' && data == '') {
387                if ($self.closest('ul').find('li').length == 1) {
388                    $self.closest('li').remove();
389                    $('.btn_top_search_all_del').remove();
390                    $('.js_recent_area').append('<dd>' + __('최근 검색어가 없습니다.') + '</dd>');
391                } else {
392                    $self.closest('li').remove();
393                }
394            } else {
395                console.log('request fail. ajax status (' + status + ')');
396            }
397        });
398    });
399
400    // 최근 검색어 전체 삭제
401    $('.btn_top_search_all_del').click(function(e){
402        $.post('../goods/goods_ps.php', {
403            'mode': 'delete_recent_all_keyword'
404        }, function (data, status) {
405            // 값이 없는 경우 성공
406            if (status == 'success' && data == '') {
407                // UXUI 변경 전 PC 적용 화면
408                // $('.js_recent_list').find('li').remove()
409                // $('.btn_top_search_all_del').remove();
410                // $('.js_recent_area').append('<dd>' + __('최근 검색어가 없습니다.') + '</dd>');
411
412                // UXUI 변경 후 PC 적용 화면
413                $('.js_recent_list_custom').find('li').remove()
414                $('.btn_top_search_all_del').remove();
415                $('.js_recent_area .list_frame .js_recent_list_custom').append('<li class="empty_txt">' + __('최근 검색어가 없습니다.') + '</li>');
416                
417            } else {
418            }
419        });
420    });
421
422    // Ajax 에러 및 처리 기본값 설정
423    $.ajaxSetup({
424        beforeSend: function (xhr, settings) {
425            xhr.url = settings.url;
426            xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'));
427        },
428        complete: function () {
429            gd_trigger_checkbox_ui();
430            gd_select_remodeling();
431            gd_checkbox_all();
432
433            //이미지 로딩 향상 사용 시 호출.
434            if ($.isFunction($.fn.lazyload) === true) {
435                setTimeout(function() {
436                    $("img.gd_image_lazy").lazyload({threshold:200});
437                }, 1);
438            }
439        },
440        error: function (xhr, textStatus, error) {
441            if (xhr.status == '404' && error == 'Not Found') {
442                console.log('[404 Not Found]\nThe requested URL was not found.');
443            }
444            else if (xhr.status == '500' && error == 'Internal Server Error' && xhr.responseText != '') {
445                console.log(xhr.responseText);
446            }
447            gd_close_layer();
448        }
449    });
450
451    $(document).on('click', '.btn_alert_login', function (e) {
452        var target = $(this).attr('id');
453        e.preventDefault();
454        alert(__('로그인하셔야 본 서비스를 이용하실 수 있습니다.'));
455        document.location.href = target == undefined ?  "../member/login.php" : "../member/login.php?id=" + target;
456        return false;
457    });
458
459    // 미확인 입금자 팝업
460    $('#ghostDepositorBanner').click(function () {
461        var url = '/service/popup_ghost_depositor.php';
462        var win = gd_popup({
463            url: url
464            , target: 'ghostDepositorPopup'
465            , width: 630
466            , height: 560
467            , resizable: 'no'
468            , scrollbars: 'no'
469        });
470        win.focus();
471        return win;
472    });
473
474    if ($('.btn_prev').length > 0) {
475        $('.btn_prev').click(function (e) {
476            e.preventDefault();
477            history.go(-1);
478        });
479    }
480
481    // 복사 기능
482    // https://github.com/zeroclipboard/zeroclipboard/blob/master/docs/api/ZeroClipboard.md
483    if ($('.gd_clipboard').length) {
484        if (navigator.userAgent.match(/MSIE 8/) !== null) {
485            $('.gd_clipboard').each(function () {
486                $(this).click(function () {
487                    alert(__("주소를 드래그 해서 복사해주세요"));
488                    return false;
489                });
490            });
491        } else {
492            var clipboard = new Clipboard('.gd_clipboard');
493            clipboard.on('success', function (e) {
494                var title = $(e.trigger).attr('title') == undefined ? '' : $(e.trigger).attr('title');
495                if (title === "") {
496                    alert('정보를 클립보드에 복사했습니다.\nCtrl+V를 이용해서 사용하세요.');
497                    e.clearSelection();
498                } else {
499                    alert('[' + title + '] ' + __('정보를 클립보드에 복사했습니다.\nCtrl+V를 이용해서 사용하세요.'));
500                    e.clearSelection();
501                }
502            });
503            clipboard.on('error', function (e) {
504                console.error('Action:', e.action);
505                console.error('Trigger:', e.trigger);
506            });
507        }
508    }
509});
510
511// @qnibus bugfix. toFixed 사용시 무조건 반올림 처리하는 부분으로 인해 고도몰5의 정책과 맞지 않아서 toFixed 대신 사용해야 함
512if (typeof Number.prototype.toRealFixed !== 'function') {
513    Number.prototype.toRealFixed = function (digits, format) {
514        if (typeof digits === 'undefined') {
515            digits = gdCurrencyDecimal;
516        }
517        if (typeof format === 'undefined') {
518            format = gdCurrencyDecimalFormat;
519        }
520
521        return numeral(Math.floor(this.valueOf() * Math.pow(10, digits)) / Math.pow(10, digits)).format('0,' + format);
522    };
523}
524
525/**
526 * 기준화폐 환율변환
527 *
528 * @param price 금액
529 * @param isFormat 포맷여부
530 * @returns {*}
531 */
532function gd_money_format(price, isFormat) {
533    var convertPrice = fx.convert(price).toRealFixed();
534    if (typeof isFormat !== 'undefined') {
535        if (isFormat) {
536            return numeral().unformat(convertPrice);
537        }
538    }
539
540    return convertPrice;
541}
542
543/**
544 * 추가화폐 환율변환
545 *
546 * @param price 금액
547 * @param isFormat 포맷여부
548 * @returns {*}
549 */
550function gd_add_money_format(price, isFormat) {
551    var convertPrice = fx.convert(price, {to: gdCurrencyAddCode}).toRealFixed(gdCurrencyAddDecimal, gdCurrencyAddDecimalFormat);
552    if (typeof isFormat !== 'undefined') {
553        if (isFormat) {
554            return numeral().unformat(convertPrice);
555        }
556    }
557
558    return convertPrice;
559}
560
561/**
562 * 윈도우팝업 호출
563 * @param array options 창정보
564 * @return object Window 개체
565 */
566function gd_popup(options) {
567    if (!options.width) options.width = 500;
568    if (!options.height) options.height = 415;
569    var status = new Array();
570    $.each(options, function (i, v) {
571        if ($.inArray(i, ['url', 'target']) == '-1') {
572            status.push(i + '=' + v);
573        }
574    });
575    var status = status.join(',');
576    var win = window.open(options.url, options.target, status);
577    return win;
578}
579
580/**
581 * 통신판매사업자 상세조회창
582 * @param {string} businessNo 사업자 번호
583 * @return
584 */
585function gd_popup_bizInfo(businessNo) {
586    var url = 'http://www.ftc.go.kr/info/bizinfo/communicationViewPopup.jsp?wrkr_no=' + businessNo;
587    var win = gd_popup({
588        url: url
589        , target: 'communicationViewPopup'
590        , width: 750
591        , height: 700
592        , resizable: 'no'
593        , scrollbars: 'no'
594    });
595    win.focus();
596    return win;
597}
598/**
599 * 쿠키 생성
600 */
601function createCookie(name, value, days) {
602    var expires;
603    if (days) {
604        var date = new Date();
605        date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
606        expires = "; expires=" + date.toGMTString();
607    } else {
608        expires = "";
609    }
610    document.cookie = name + "=" + value  + "; path=/; expires=" + expires + ";";
611}
612/**
613 * 팝업창 Cookie 컨트롤
614 * @param string name 팝업창 이름 (코드_창종류)
615 * @param object elemnt elemnt
616 * @return
617 */
618function gd_popup_cookie(name, elemnt) {
619    if (elemnt.checked === true) {
620        createCookie(name,'true',1);
621        var popupKind = name.split('_');
622        if (popupKind[1] == 'window') {
623            setTimeout('self.close()');
624        } else {
625            setTimeout("$('#" + name + "').hide()");
626        }
627    } else {
628       createCookie(name, null);
629    }
630    return;
631}
632
633/**
634 * 메일 도메인 선택
635 */
636function gd_select_email_domain(name,select) {
637    if (typeof select === 'undefined') {
638        select = 'emailDomain';
639    }
640    var $email = $(':text[name=' + name + ']');
641    var $emailDomain = $('select[id='+select+']');
642    $emailDomain.on('change', function (e) {
643        var emailValue = $email.val();
644        var indexOf = emailValue.indexOf('@');
645        if (indexOf == -1) {
646            if ($emailDomain.val() === 'self') {
647                $email.val(emailValue + '@');
648            } else {
649                $email.val(emailValue + '@' + $emailDomain.val());
650            }
651            $email.trigger('focusout');
652        } else {
653            if ($emailDomain.val() === 'self') {
654                $email.val(emailValue.substring(0, indexOf + 1));
655                $email.focus();
656            } else {
657                $email.val(emailValue.substring(0, indexOf + 1) + $emailDomain.val());
658                $email.trigger('focusout');
659            }
660        }
661    });
662}
663
664/**
665 * 도로명 주소 찾기 (팝업)
666 *
667 * @author artherot
668 * @param {string} zoneCodeID zonecode input ID
669 * @param {string} addrID address input ID
670 * @param {string} zipCodeID zipcode input ID
671 */
672function gd_postcode_search(zoneCodeID, addrID, zipCodeID) {
673    var win = gd_popup({
674        url: '../share/postcode_search.php?zoneCodeID=' + zoneCodeID + '&addrID=' + addrID + '&zipCodeID=' + zipCodeID,
675        target: 'postcode',
676        width: 500,
677        height: 450,
678        resizable: 'yes',
679        scrollbars: 'yes'
680    });
681    win.focus();
682    return win;
683}
684
685/**
686 * 비회원 개인정보 수집항목 동의 링크
687 */
688function gd_redirect_collection_agree() {
689    window.open('/service/private.php');
690}
691
692/**
693 * 파일 업로드 객체
694 */
695var gdAjaxUpload = {
696    upload : function(data) {
697        var formData = new FormData();
698        for (var k in data.params){
699            if (data.params.hasOwnProperty(k)) {
700                formData.append(k, data.params[k]);
701            }
702        }
703        if(data.onbeforeunload){
704            window.onbeforeunload = data.onbeforeunload;
705            data.formObj.on("submit", function () {
706                window.onbeforeunload = null;
707            });
708        }
709
710        if(data.formObj.find('[name=uploadType][value=ajax]').length < 1) {
711            data.formObj.append('<input type="hidden"  name="uploadType" value="ajax" >');
712        }
713        let index = data.thisObj.closest('form').find('input:file').index(data.thisObj);
714
715        // 파일이 존재했다가 파일이 선택되지 않은 경우 처리 중단
716        if (!data.thisObj[0].files || !data.thisObj[0].files[0]) {
717            // 기존 업로드 정보 제거
718            $("input[name='uploadFileNm[" + index + "]']").remove();
719            $("input[name='saveFileNm[" + index + "]']").remove();
720            return;
721        }
722
723        let maxSize = data.thisObj.data('upload-max-size');
724        let uploadFile = data.thisObj[0].files[0];
725        let fileSize = uploadFile.size;
726
727        if (maxSize !== undefined && maxSize !== null && fileSize > maxSize) {
728            alert(`파일 1개당 최대 업로드 용량은 ${Math.floor(maxSize / (1024 * 1024))}MByte(s)입니다.`);
729            $('label[for=attach' + (index + 1) + '] .file_text').val('');
730            let uploadFileInput = $('input[name="upfiles[]"]').eq(index);
731            uploadFileInput.wrap('<form>').closest('form')[0].reset();
732            uploadFileInput.unwrap();
733            // 기존 업로드 정보 제거
734            $("input[name='uploadFileNm[" + index + "]']").remove();
735            $("input[name='saveFileNm[" + index + "]']").remove();
736            return;
737        }
738
739        formData.append('uploadFile', data.thisObj[0].files[0]);
740
741        $.ajax({
742            url: data.actionUrl,
743            type: 'POST',
744            data: formData,
745            async: false,
746            cache: false,
747            contentType: false,
748            processData: false,
749            dataType: 'json',
750            success: function (returnData) {
751                returnData['index'] = index;
752                if(returnData.result == 'ok') {
753                    if ($('input[name="uploadFileNm[' + index + ']"]').length == 0) {
754                        data.formObj.append("<input type='hidden' name='uploadFileNm[" + index + "]' value='" + returnData.uploadFileNm + "'>");
755                        data.formObj.append("<input type='hidden' name='saveFileNm[" + index + "]' value='" + returnData.saveFileNm + "'>");
756                        // 한 페이지에서 다중 업로드르 위해 식별용 inputNm 같이 추가 (place_register)
757                        if(returnData.inputNm) {
758                            data.formObj.append("<input type='hidden' name='inputNm[" + index + "]' value='" + returnData.inputNm + "'>");
759                        }
760                    }
761                    else {
762                        $("input[name='uploadFileNm[" + index + "]']").val(returnData.uploadFileNm);
763                        $("input[name='saveFileNm[" + index + "]']").val(returnData.saveFileNm);
764                        // 한 페이지에서 다중 업로드르 위해 식별용 inputNm 같이 추가 (place_register)
765                        if(returnData.inputNm) {
766                            $("input[name='inputNm[" + index + "]']").val(returnData.inputNm);
767                        }
768                    }
769                    if(typeof data.successAfter == 'function') {
770                        data.successAfter(returnData);
771                    }
772                }
773                else if(returnData.result == 'cancel'){
774                    if ($("input[name='uploadFileNm[" + index + "]']").length > 0) {
775                        $('label[for=attach' + (index + 1) + '] .file_text').val('');  //파일시스템 텍스트 빈값 처리
776                        $("input[name='uploadFileNm[" + index + "]']").remove();
777                        $("input[name='saveFileNm[" + index + "]']").remove();
778                        // 한 페이지에서 다중 업로드르 위해 식별용 inputNm 같이 추가 (place_register)
779                        if(returnData.inputNm) {
780                            $("input[name='inputNm[" + index + "]']").remove();
781                        }
782                    }
783                }
784                else {
785                    gdAjaxUpload.isSuccess = false;
786                    $('label[for=attach' + (index + 1) + '] .file_text').val('');  //파일시스템 텍스트 빈값 처리
787                    // 기존 업로드 정보 제거
788                    $("input[name='uploadFileNm[" + index + "]']").remove();
789                    $("input[name='saveFileNm[" + index + "]']").remove();
790                    alert(returnData.errorMsg);
791                    if(typeof data.failAfter == 'function') {
792                        data.failAfter(returnData);
793                    }
794                }
795            },
796            error: function () {
797                alert(__('업로드에 실패하였습니다.'));
798                $('label[for=attach' + (index + 1) + '] .file_text').val('');
799                let uploadFileInput = $('input[name="upfiles[]"]').eq(index);
800                uploadFileInput.wrap('<form>').closest('form')[0].reset();
801                uploadFileInput.unwrap();
802                // 기존 업로드 정보 제거
803                $("input[name='uploadFileNm[" + index + "]']").remove();
804                $("input[name='saveFileNm[" + index + "]']").remove();
805            }
806        });
807    }
808};
809
810/**
811 * 프레임 리사이즈
812 */
813/* iframe(mypage 등)으로 board 목록이 실릴 때, onload 1회 측정(resize_frame/gd_resize_frame) 이후에도
814   댓글/답글 폼 토글, ALTCHA 위젯 지연 렌더, 댓글 등록/삭제 등으로 내용 높이가 바뀌면
815   부모 iframe 높이를 다시 맞춘다. body 높이가 실제로 변했을 때만 호출해 재측정 루프를 방지. */
816(function () {
817    let parentResize;
818    try {
819        if (window.parent === window) {
820            return; // 최상위 문서 → 대상 아님
821        }
822        parentResize = window.parent.gd_resize_frame || window.parent.resize_frame;
823    } catch (e) {
824        return; // cross-origin 부모 → 접근 불가, 대상 아님
825    }
826    if (typeof parentResize !== 'function' || typeof window.ResizeObserver === 'undefined') {
827        return;
828    }
829    const startObserve = function () {
830        const frameEl = window.frameElement
831            || (window.name ? window.parent.document.getElementsByName(window.name)[0] : null);
832        if (!frameEl || !document.body) {
833            return;
834        }
835        let timer = null;
836        let lastHeight = -1;
837        const observer = new ResizeObserver(function () {
838            if (timer) {
839                clearTimeout(timer);
840            }
841            timer = setTimeout(function () {
842                const height = document.body.clientHeight;
843                if (height === lastHeight) {
844                    return; // 실제 콘텐츠 높이 변화 없음 → 재측정 루프 방지
845                }
846                lastHeight = height;
847                parentResize.call(window.parent, frameEl);
848            }, 100);
849        });
850        observer.observe(document.body);
851    };
852    if (document.body) {
853        startObserve();
854    } else {
855        document.addEventListener('DOMContentLoaded', startObserve);
856    }
857})();
858
859function gd_resize_frame(obj) {
860    var iframeHeight = (obj).contentWindow.document.body.clientHeight;
861    (obj).height = iframeHeight + 80;
862}
863
864/**
865 * 회원다운로드 쿠폰 링크 다운 받기
866 *
867 * @param couponNo
868 */
869function couponLinkDown(couponNo) {
870    var params = {
871        mode: "couponDownLink",
872        couponCode: couponNo
873    };
874    $.ajax({
875        method: "POST",
876        async: false,
877        cache: false,
878        url: "/mypage/coupon_link_down.php",
879        data: params,
880        success: function (data) {
881            result = JSON.parse(data);
882            alert(result['msg']);
883            if (result['code'] == '0') {
884                document.location.href = "/member/login.php";
885            }
886        },
887        error: function (data) {
888            alert(result['msg']);
889        }
890    });
891}
892
893/**
894 * PG 관련 영수증 보기
895 *
896 * @author artherot
897 * @param string modeStr 카드, 현금영수증 종류 (card, cash)
898 * @param string orderNo 주문 번호
899 */
900function gd_pg_receipt_view(modeStr, orderNo) {
901    // 사이즈를 미리 설정 - 자동으로 창이 커지지 않아 미리 설정함
902    var preWidth = 430;
903    var preHeight = 700;
904
905    // 미리 팝업창을 띄우기
906    var prePopupData = {
907        'url': 'about:blank',
908        'target': 'show_receipt',
909        'width': preWidth,
910        'height': preHeight
911    };
912    var show_receipt = gd_popup(prePopupData);
913
914    // 각 PG별 영수증 팝업창
915    $.post('../share/show_receipt.php', {
916        mode: modeStr,
917        orderNo: orderNo
918    }, function (data) {
919        var infoData = data;
920        if (typeof infoData['error'] == 'undefined') {
921            gd_popup(infoData);
922        }
923        else {
924            alert(infoData['error']);
925            show_receipt.close();
926        }
927    }, 'json');
928}
929
930/*** IE 버전 체크 ***/
931function gd_is_ie () {
932    var nav = navigator.userAgent.toLowerCase();
933    if (nav.indexOf('msie') != -1) {
934        return parseInt(nav.split('msie')[1]);
935    } else {
936        return false;
937    }
938}
939
940/**
941 * 쿼리스트링값 찾기
942 * @param query
943 * @param variable
944 * @returns {string}
945 */
946function gd_get_query_variable(query, variable) {
947    var vars = query.split('&');
948    for (var i = 0; i < vars.length; i++) {
949        var pair = vars[i].split('=');
950        if (decodeURIComponent(pair[0]) == variable) {
951            return decodeURIComponent(pair[1]);
952        }
953    }
954    console.log('Query variable %s not found', variable);
955}
956
957/**
958 * 동적 스크립트 바인딩 (스크립트 로딩 후 메서드 실행되도록 처리)
959 *
960 * @author Jong-tae Ahn
961 * @param number
962 * @param places
963 * @param symbol
964 * @param thousand
965 * @param decimal
966 * @returns {string}
967 */
968function add_script(url, callback) {
969    var done = false; // 스크립트 로딩 여부
970    var head = document.getElementsByTagName("head")[0] || document.documentElement;
971    var script = document.createElement("script");
972
973    //script.charset = 'UTF-8';
974    script.src = url;
975    script.onload = script.onreadystatechange = function () {
976        if (!done && (!this.readyState || this.readyState === "loaded" || this.readyState === "complete")) {
977            done = true;
978            callback();
979
980            // IE에서 메모리 누수 방지를 위한 처리
981            script.onload = script.onreadystatechange = null;
982            if (head && script.parentNode) {
983                head.removeChild(script);
984            }
985        }
986    };
987
988    // Use insertBefore instead of appendChild  to circumvent an IE6 bug.
989    // This arises when a base node is used (#2709 and #4378).
990    head.insertBefore(script, head.firstChild);
991}
992
993
994
995
996/*** 스토리지 지원 여부 ***/
997function supports_html5_storage() {
998    try {
999        return 'localStorage' in window && window['localStorage'] !== null;
1000    } catch (e) {
1001        return false;
1002    }
1003}
1004
1005/*** 세션 스토리지 저장 ***/
1006function saveSession(control_key, control_value) {
1007    if (!supports_html5_storage()) {
1008        createCookie(control_key, control_value, 7);
1009    } else {
1010        sessionStorage[control_key] = control_value;
1011    }
1012};
1013
1014/*** 세션 스토리지 로드 ***/
1015function loadSession(control_key) {
1016    var control_value;
1017    if (!supports_html5_storage()) {
1018        control_value = readCookie(control_key);
1019    } else {
1020        control_value = sessionStorage[control_key];
1021    }
1022    return control_value;
1023};
1024
1025/*** 로컬 스토리지 저장 ***/
1026function saveVal(control_key, control_value) {
1027    if (!supports_html5_storage()) {
1028        createCookie(control_key, control_value, 7);
1029    } else {
1030        localStorage.setItem(control_key, control_value);
1031    }
1032};
1033
1034/*** 로컬 스토리지 로드 ***/
1035function loadVal(control_key) {
1036    var control_value;
1037    if (!supports_html5_storage()) {
1038        control_value = readCookie(control_key);
1039    } else {
1040        control_value = localStorage.getItem(control_key);
1041    }
1042    return control_value;
1043};
1044
1045//로딩바
1046var dealLoadingBar = {
1047    init: function () {
1048        var loadingTemplete = '<div id="main_loading" style="width:100%;height:100vh;background: rgba(0,0,0,0.5);"><img style="width:30px;"src="https://majorworld.hgodo.com/dealpang/loading.gif"" /></div>';
1049        $("body").append(loadingTemplete);
1050    },
1051    show: function () {
1052        if ($("#main_loading").length != 1) {
1053            this.init();
1054        }
1055    },
1056    hide: function () {
1057        $("#main_loading").remove();
1058    }
1059};
1060
1061// godo format
1062function convertToISO(string) {
1063    let parts = string.split(" ");
1064    let dateParts = parts[0].split("-");
1065
1066    return dateParts[0] + "/" + dateParts[1] + "/" + dateParts[2] + " " + parts[1];
1067}
1068function mwdDefaultFormatDate1(str) {
1069    const parts = str.split(' ')[0].split('-');
1070    const month = parseInt(parts[1], 10);
1071    const day = parseInt(parts[2], 10);
1072
1073    return month + "월 " + day + "일";
1074}
1075// new date 객체 치환
1076function mwdDefaultFormatDate2(a) {
1077    var year = a.getFullYear();
1078    var month = (a.getMonth() + 1).toString();
1079    var day = a.getDate().toString();
1080    month = month.length === 1 ? '0' + month : month;
1081    day = day.length === 1 ? '0' + day : day;
1082    return year + '-' + month + '-' + day;
1083}
1084function mwdDefaultFormatDate3(a) {
1085    return a.split(' ')[0]
1086}
1087
1088function jsonType(a){
1089    let string = JSON.parse(JSON.stringify(a))
1090    return string
1091}
1092function goLogInPage(){
1093    return window.location.href="../member/login.php"
1094}
1095function goSignPage(){
1096    return window.location.href="../member/join_method.php"
1097}
1098
1099function swiperClickCenter(obj){
1100    var slides = obj.parent().children();
1101    slides.removeClass('on');
1102    if(!slides.last().hasClass('swiperClickCenterLastIndex') ){
1103        slides.last().addClass('swiperClickCenterLastIndex')
1104    };
1105    obj.addClass('on');
1106    var snbwrap = $('.mySwiper .swiper-wrapper');
1107    var targetPos = obj.position();
1108    var box = $('.mySwiper');
1109    var boxHarf = box.width()/2;
1110    var pos;
1111    var listWidth=0;
1112    snbwrap.find('.swiper-slide').each(function(){ listWidth += $(this).outerWidth(); });
1113    var selectTargetPos = targetPos.left + obj.outerWidth()/2;
1114    if (selectTargetPos <= boxHarf ) {
1115        pos = 0;
1116    }else if ((listWidth - selectTargetPos) <= boxHarf) {
1117        pos = listWidth-box.width();
1118    } else {
1119        pos = selectTargetPos - boxHarf;
1120    }
1121
1122    if (obj.hasClass('swiperClickCenterLastIndex')){
1123        setTimeout(function(){snbwrap.css({
1124            "transform": "translate3d("+ ((pos+($('.swiperClickCenterLastIndex').width()/2))*-1)+"px, 0, 0)",
1125            "transition-duration": "250ms"
1126        })}, 100);
1127    } else{
1128        setTimeout(function(){snbwrap.css({
1129            "transform": "translate3d("+ (pos*-1) +"px, 0, 0)",
1130            "transition-duration": "250ms"
1131        })}, 100);
1132    }
1133};
1134
1135function numberWithCommas(x) {
1136    return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
1137}
1138function mwdCountTimerFunc(a,b,d){
1139    let endDateCountValue = convertToISO(a);
1140    let startDateCountValue = convertToISO(b);
1141    let containerId = d
1142
1143    // count down timer start
1144    let countDownDate = new Date(endDateCountValue).getTime();
1145    countTimer(containerId, countDownDate);
1146    let countDownFunction = setInterval(function() {
1147        countTimer(containerId, countDownDate);
1148    }, 1000);
1149    // count down timer end
1150
1151    function countTimer(obj, time){
1152        let box = obj.toString()
1153        let cnt = time
1154        let now = new Date().getTime();
1155        let distance = cnt - now;
1156        let days = Math.floor(distance / (1000 * 60 * 60 * 24));
1157        let hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
1158        let minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
1159        let seconds = Math.floor((distance % (1000 * 60)) / 1000);
1160        let Days = document.querySelector(box + " .Count #days")
1161        let Hours = document.querySelector(box + " .Count #hours")
1162        let Minutes = document.querySelector(box + " .Count #minutes")
1163        let Seconds = document.querySelector(box + " .Count #seconds")
1164
1165        Days.innerText = days;
1166        Hours.innerText = hours;
1167        Minutes.innerText = minutes;
1168        Seconds.innerText = seconds;
1169
1170        if ( days == '0' ){
1171            document.querySelector(box+ ' .Count .days').style.display='none'
1172
1173        }
1174        if (distance < 0) {
1175            clearInterval(countDownFunction);
1176            // event end point message~
1177            document.querySelector(box+ ' .Count').innerHTML = "<b style='color:#0b3b4d;font-size:45px;font-weight: 800;'>이벤트가 종료되었습니다.</b>";
1178        }
1179    }
1180
1181    let eventDate = document.querySelector(containerId + ' .mwd_first_come_event_days');
1182    if ( eventDate != null){
1183        let endDate = new Date(endDateCountValue);
1184        let startDate = new Date(startDateCountValue);
1185        let differenceInTime = endDate.getTime() - startDate.getTime();
1186        let differenceInDays = differenceInTime / (1000 * 3600 * 24);
1187        countEndDate(eventDate , differenceInDays);
1188    }
1189
1190    function countEndDate (obj, day){
1191        let endDate = obj;
1192        let differenceInDays = day
1193        endDate.textContent = differenceInDays.toFixed(0);
1194    }
1195}
1196
1197
1198//출석체크 공용 start
1199
1200const attendCalendar = (a, b, c, d, e, f, g, h, i, j) => {
1201    var $result = true
1202    const attendData = a;
1203    const arrStamp = b;
1204    let currentDate = c;
1205    let checkData = d;
1206    const checkSno = e;
1207    const mileageCum = f;
1208    const uploadPath = g;
1209    const mode = h;
1210    let wrap = document.querySelector('#'+i);
1211    const checkLogStatus = j
1212    if (checkData == undefined || checkData == null ) checkData = {"attendanceCount":"0"}
1213    let userCurrentDt = new Date();
1214    let startDt = jsonType(attendData.startDt)
1215    let endDt = jsonType(attendData.endDt)
1216    let checkLog1 = '';
1217
1218    if(checkLogStatus){
1219        checkLog1 ='<div class="userAttendBox"><p>나의 출석 현황 <span>'+ jsonType(checkData.attendanceCount)+'일</span></p><p>현재 적립금 <span>'+ numberWithCommas(jsonType(mileageCum))+' <s style="color:#606060; text-decoration:unset">M</s></span></p></div>'
1220
1221    } else{
1222        checkLog1 = '<div class="userAttendBox" style="display: none;"><p style="cursor: pointer;" onclick="goLogInPage();">로그인 후 참여 가능합니다.</p></div>'
1223    }
1224
1225    wrap.insertAdjacentHTML('beforeend',
1226        '<div class="attend_event_date">출석체크 이벤트 기간 '+mwdDefaultFormatDate1(startDt)+' ~ '+mwdDefaultFormatDate1(endDt)+'</div>'+checkLog1)
1227
1228    const attendCalendar = document.createElement('div')
1229    attendCalendar.id='attend_calendar'
1230
1231    attendCalendar.insertAdjacentHTML('beforeend',''
1232        +'<div class="c_h"><p onclick="mwd_attendance_prevMonth();" class="prev_month"><svg width="9" height="14" viewBox="0 0 9 14" fill="none" xmlns="http://www.w3.org/2000/svg">'
1233        +'<path d="M7.53846 12.3333L1.53201 7.66836C0.822663 7.11743 0.822663 6.21592 1.53201 5.66499L7.53846 1" stroke="#2D2D2D" stroke-width="2" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>'
1234        +'</svg></p><p class="currentDate">'
1235        + jsonType(currentDate)
1236        +'</p><p onclick="mwd_attendance_nextMonth();" class="next_month"><svg width="9" height="14" viewBox="0 0 9 14" fill="none" xmlns="http://www.w3.org/2000/svg">'
1237        +'<path d="M1.46154 1.66667L7.46799 6.33164C8.17734 6.88257 8.17734 7.78408 7.46799 8.33501L1.46154 13" stroke="#2D2D2D" stroke-width="2" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>'
1238        +'</svg></p></div><div class="attend_calendar_days"></div>'
1239        +'<form id="formStamp" name="formStamp" method="post" action="../event/attendance_ps.php">'
1240        +'<input type="hidden" id="sno" name="sno" value="'
1241        + jsonType(attendData.sno)
1242        +'"/>'
1243        +'<input type="hidden" id="checkSno" name="checkSno" value="'
1244        + jsonType(checkSno)
1245        +'"/>'
1246        +'<input type="hidden" id="currentDate" name="currentDate" value="'
1247        + jsonType(currentDate)
1248        +'"/>'
1249        +'<input type="hidden" id="mode" name="mode" value="'
1250        + jsonType(mode)
1251        +'"/>'
1252        +'<input type="hidden" id="startDt" name="startDt" value="'
1253        + jsonType(attendData.startDt)
1254        +'"/>'
1255        +'<input type="hidden" id="endDt" name="endDt" value="'
1256        + jsonType(attendData.endDt)
1257        +'"/>'
1258        +'<button type="button" id="attendanceCheck" onclick="mwd_attendance_check('+checkLogStatus+');"  class="btn_attend_check">출석체크</button>'
1259        +'</form>');
1260
1261    wrap.appendChild(attendCalendar);
1262
1263    let calendarBox = document.querySelector('.attend_calendar_days');
1264
1265
1266
1267    calendarBox.insertAdjacentHTML('beforeend','<p class="wekk">일</p><p class="wekk">월</p><p class="wekk">화</p><p class="wekk">수</p><p class="wekk">목</p><p class="wekk">금</p><p class="wekk">토</p>')
1268
1269    for (let key in arrStamp) {
1270        if (arrStamp.hasOwnProperty(key)) {
1271            let dayValue = arrStamp[key].day;
1272            let classValue = arrStamp[key].class;
1273            let dateValue = arrStamp[key].date;
1274
1275            let e = document.createElement('p');
1276            e.className = 'day ' + classValue;
1277            e.textContent = dayValue;
1278            e.dataset.date = dateValue;
1279
1280            calendarBox.appendChild(e);
1281            document.querySelectorAll('.attend').forEach(x=>x.textContent='출석');
1282        }
1283    }
1284
1285    if(new Date(mwdDefaultFormatDate3(endDt)) <= new Date(mwdDefaultFormatDate2(userCurrentDt))){
1286        let btn = document.querySelector('.btn_attend_check');
1287        btn.textContent='출석체크 이벤트 종료';
1288        btn.style.opacity='0.5';
1289    };
1290}
1291
1292
1293const mwd_attendance_prevMonth = () => {
1294    return window.location.href = window.location.origin + window.location.pathname +'?sno=' + new URLSearchParams(window.location.search).get('sno') + '&currentDate=' + document.querySelector('#currentDate').value + '&move=prev';
1295}
1296const mwd_attendance_nextMonth = () => {
1297    return window.location.href = window.location.origin + window.location.pathname +'?sno=' + new URLSearchParams(window.location.search).get('sno') + '&currentDate=' + document.querySelector('#currentDate').value + '&move=next';
1298}
1299
1300
1301const mwd_attendance_check = (bool) => {
1302    if(bool){
1303        var params = $('#formStamp').serializeArray();
1304        $.post('../event/attendance_ps.php', params, function (data) {
1305            if (data.code === undefined && data.message === undefined) {
1306                alert(data);
1307                return window.location.reload();
1308            } else {
1309                alert(data.message);
1310                return window.location.reload();
1311            }
1312        })
1313    } else{
1314        alert('로그인 후 참여 가능합니다.')
1315        return window.location.href="../member/login.php";
1316    }
1317};
1318
1319
1320//출석체크 공용 end
1321
1322function getScrollbarWidth() {
1323    let outer = document.createElement("div");
1324    outer.style.visibility = "hidden";
1325    outer.style.width = "100px";
1326    document.body.appendChild(outer);
1327
1328    let widthNoScroll = outer.offsetWidth;
1329
1330    outer.style.overflow = "scroll";
1331    let inner = document.createElement("div");
1332    inner.style.width = "100%";
1333    outer.appendChild(inner);
1334
1335    let widthWithScroll = inner.offsetWidth;
1336    outer.parentNode.removeChild(outer);
1337
1338    return widthNoScroll - widthWithScroll;
1339}
1340function maskWrap(){
1341    let maskWrap = document.createElement('div');
1342    maskWrap.className='maskWrap'
1343    maskWrap.style.width='100%'
1344    maskWrap.style.height='100%'
1345    maskWrap.style.position='fixed'
1346    maskWrap.style.top='0'
1347    maskWrap.style.left='0'
1348    maskWrap.style.zIndex='101'
1349    maskWrap.style.background='rgba(0,0,0,0.7)'
1350    document.body.appendChild(maskWrap);
1351}
1352
1353function openPopupOverflow() {
1354    maskWrap()
1355    let scrollbarWidth = getScrollbarWidth();
1356    let wrap = document.getElementById('wrap');
1357
1358    document.body.style.overflowY = 'hidden';
1359    document.body.style.paddingRight = scrollbarWidth + 'px';
1360}
1361
1362function closePopupOverflow() {
1363    mask = document.querySelector('.maskWrap')
1364    if ( mask == null || mask == undefined){
1365    } else{
1366        mask.remove();
1367    }
1368    document.body.style.overflowY = '';
1369    document.body.style.paddingRight = '0px';
1370}
1371function showSnsLyaer(){
1372    $("#lySns").show();
1373    $('.wrapper').addClass('mwd_opacity')
1374}
1375function snsLayerHide(){
1376    $("#lySns").hide();
1377    $('.wrapper').removeClass('mwd_opacity')
1378    if ($coupon && $coupon!==undefined && $coupon!==null){
1379        shareCloseCouponAlert().then(
1380            (r) =>{
1381                if ($couponResult == 'ok'){
1382                    $couponMsg = $couponMsg.replace(/\\n/g, '\n');
1383                    alert($couponMsg);
1384                }
1385            }
1386        );
1387    }
1388}
1389async function shareCloseCouponAlert(){
1390    return Promise.resolve()
1391}
1392function mwd_is_login(){
1393    /*{? gd_is_login() === true}*/
1394    return true
1395    /*{ : }*/
1396    return false
1397    /*{ / }*/
1398
1399}
1400
1401
1402function handleImageError() {
1403    let nonImg = "https://dealpang.hgodo.com/data/skin/img_error.svg";
1404    document.querySelectorAll('img').forEach((ele) => {
1405        ele.onerror = function() {
1406            this.src  =  "https://dealpang.hgodo.com/data/skin/img_error.svg";
1407            this.onerror = null;
1408        };
1409
1410        if (ele.complete && ele.naturalWidth == 0 ){
1411            ele.onerror();
1412        }
1413    });
1414
1415}
1416
1417function mwdImageAreaMove(){
1418    // area 스크롤 이동 펑션 상품리스트 맨위로 올라가기
1419    let areaMoveId = $('.goods_list.wrap_check_div').eq(0).attr('id');
1420    let eleId = '#'+areaMoveId.toString();
1421    window.location.href = eleId
1422    setTimeout(function(){
1423        var currentScroll = $(window).scrollTop();
1424        $('html, body').animate({
1425            scrollTop: currentScroll - 80
1426        }, 80);
1427    },200)
1428}
1429
1430
1431/***
1432 * 미사용중으로 확인 (2026.04.21)
1433 * 이미지형식의 레이어 open/close 함수
1434 * @param targetName : string 레이어로 오픈 할 앨리먼트 클래스/아이디
1435 * @param status : string {
1436 *     open : targetName 대상 이미지 오픈
1437 *     close : targetName 대상 이미지 닫기
1438 * }
1439 */
1440function mwdImgAreaClick (targetName, status){
1441    let img = document.querySelector(targetName);
1442    if ( status.includes('close')){
1443        closePopupOverflow();
1444        img.style.display='none';
1445    } else {
1446        img.style.cssText = "" +
1447            "position:fixed; display:block; top:50%; left:50%; transform:translate(-50%,-50%); z-index:1001;";
1448        openPopupOverflow();
1449    }
1450};
1451
1452/**
1453 * 미사용중으로 확인 (2026.04.21)
1454 * 개발자 도구 감지 함수
1455 * 기존 window.devToolsIsOpen 대신 debugger 사용
1456 * 원하는 위치에서 setInterval(mwdPreventInspect, 1000) 선언
1457 */
1458function mwdPreventInspect(){
1459    const start = new Date();
1460    debugger;
1461    const end = new Date();
1462    if (end - start > 100) {
1463        alert('개발자도구를 종료해주세요.\n 확인 후 새로고침 됩니다.');
1464        return location.reload();
1465    }
1466};
1467
1468/**
1469 * 미사용중으로 확인 (2026.04.21)
1470 * @param className : string  대상 클래스명
1471 * @param cloneNum : number 복사할 갯수
1472 * @param useConsole : boolean | null 복사 후 콘솔 사용 여부
1473 */
1474function mwdCloningElement(className, cloneNum,useConsole = null) {
1475    let targetEle = document.querySelector('.' + className);
1476    if (!targetEle) {
1477        return;
1478    }
1479    let cloneEle = targetEle.children;
1480    let maxCount = cloneEle.length;
1481    for (let i = 0; i < cloneNum; i++) {
1482        for (let j = 0; j < maxCount; j++) {
1483            targetEle.appendChild(cloneEle[j].cloneNode(true));
1484        }
1485    }
1486    useConsole && console.log('총 '+targetEle.children.length+'개')
1487};
1488
1489
1490const mwdGetHolidayArr = async () => {
1491    try {
1492        const result = await $.post('../share/calendar_ps.php', {
1493            mode: 'get_holiday',
1494            start: '2023-11',
1495            end: '2025-12'
1496        });
1497        return result.data;
1498    } catch (error) {
1499        const result ={
1500            a:"[2023-01-01]"
1501        }
1502        return result.a;
1503    }
1504};
1505
1506function mwdCommonPopup(evdt,type,txtString,imgSrc = null,link= null, confirmTxt = null, cancelTxt = null){
1507    type=type.toString()
1508    openPopupOverflow()
1509    $('body').append('<div class="mwd_pop_mask"><div class="mwd_pop_ly"></div></div>')
1510    const hidePopupBtn1 = '<p class="mwd_event_calendar_pop_close" onclick="mwdCommonPopupClose();"><?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->\n' +
1511        '<svg width="25px" height="25px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">\n' +
1512        '<path d="M12 22C17.5 22 22 17.5 22 12C22 6.5 17.5 2 12 2C6.5 2 2 6.5 2 12C2 17.5 6.5 22 12 22Z" stroke="#292D32" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>\n' +
1513        '<path d="M9.16998 14.83L14.83 9.17004" stroke="#292D32" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>\n' +
1514        '<path d="M14.83 14.83L9.16998 9.17004" stroke="#292D32" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>\n' +
1515        '</svg></p></div>'
1516    const confirmHidePopupBtn = '<div class="confirmBlock"><p class="set_res" style="width:50%;" onClick="goLogInPage();">로그인</p><p class="set_res" style="width:50%;" onClick="goSignPage();">회원가입하러 가기</p></div>'
1517    const linkClass = link === null ? "display_none" : "move_link";
1518    let popALert = document.querySelector('.mwd_pop_ly');
1519    const getConfirmTxt = confirmTxt !== null ? confirmTxt : '확인';
1520    const getCancelTxt = cancelTxt !== null ? cancelTxt : '취소';
1521    popALert.innerHTML='';
1522    if(!evdt){
1523        evdt = ''
1524    }
1525    if (type === 'allAccount'){
1526        // 참여자 구분 : 회원 전체
1527        if(txtString){
1528            popALert.innerHTML += '<div class="textBlock textBlock2" style="position:relative;"><p>'+txtString+'</p>' + hidePopupBtn1;
1529        }else{
1530            popALert.innerHTML += '<div class="textBlock textBlock2" style="position:relative;"><p>딜팡 회원에게만 제공하고 있습니다.<br>로그인 후 참여해주세요 :)</p>' + hidePopupBtn1;
1531        }
1532    } else if ( type === 'new' ){
1533        // 참여자 구분 : 신규 회원
1534        popALert.innerHTML += '<div class="textBlock textBlock2" style="position:relative;"><p>'+txtString+'<br>'+evdt+'일 이후 딜팡에<br>가입하신 신규 회원에게만<br>제공하고 있습니다.<br><br>로그인 후 참여해주세요 :)</p>' + hidePopupBtn1;
1535    } else  if ( type === 'kakaoNew' ){
1536        // 참여자 구분 : 카카오 신규가입
1537        popALert.innerHTML += '<div class="textBlock textBlock2" style="position:relative;"><p>'+txtString+'<br>'+evdt+'일 이후 딜팡에<br>가입하신 카카오 신규 회원에게만<br>제공하고 있습니다.<br><br>로그인 후 참여해주세요 :)</p>' + hidePopupBtn1;
1538    } else if ( type === 'roulette' ){
1539        // 룰렛전용
1540        if (evdt === '') {
1541            popALert.innerHTML += '<div class="textBlock textBlock2 roulette_pop_ly" style="position:relative;"><p style="padding:50px 0;">'+txtString+'</p><div class="confirmBlock"><p class="set_res cancel" style="width:50%;" onClick="mwdCommonPopupClose();">취소</p><p class="set_res success" style="width:50%;" onClick="goLogInPage();">확인</p></div>'
1542        } else if (evdt === 1) {
1543            popALert.innerHTML += '<div class="textBlock textBlock2 roulette_pop_ly" style="position:relative;"><p style="padding:10px 0;">'+txtString+'</p><div class="confirmBlock"><p class="set_res success" style="width:50%;" onClick="mwdCommonPopupClose();">확인</p></div>'
1544        } else if (evdt === 2) {
1545            popALert.innerHTML += '<div class="textBlock textBlock2 roulette_pop_ly" style="position:relative;"><p style="padding:10px 0;">'+txtString+'</p><div class="confirmBlock"><p class="set_res success" style="width:50%;" onClick="mwdCommonPopupClose();">확인</p></div>'
1546        }
1547    }  else if (type === 'custom') {
1548        // 안내문구 커스텀
1549        if (txtString != '') {
1550            popALert.innerHTML += '<div class="textBlock textBlock2 custom_pop_ly" style="position:relative;">' +
1551                '<p>'+txtString+'</p>' +
1552                '<div class="confirmBlock flex flex_jc_c flex_ai_c">' +
1553                '<p class="set_res cancel flex flex_jc_c flex_ai_c" onClick="mwdCommonPopupClose();">'+getCancelTxt+'</p>' +
1554                '<p class="set_res success flex flex_jc_c flex_ai_c" onClick="goLogInPage();">'+getConfirmTxt+'</p>' +
1555                '</div>' +
1556                '</div>'
1557        } else {
1558            console.log('안내문구 필수값이 누락되었습니다. 확인해주세요.');
1559            return false;
1560        }
1561    } else if ( type === 'image_popup') {
1562        // 이미지파일 팝업
1563        popALert.innerHTML += '<div class="img_box_pop_ly">' +
1564            '<div class="close_btn" onClick="mwdCommonPopupClose();"></div>' +
1565            '<img src="'+imgSrc+'" alt=""/>' +
1566            '<a class="'+linkClass+'" href="'+link+'" ></a>'+
1567            '</div>';
1568    } else if ( type === 'share_success') {
1569        // 공유하기 성공 후 레이어
1570        popALert.innerHTML += '<div class="textBlock textBlock2 roulette_pop_ly" style="position:relative;"><p class="success_title">공유성공🎉</p><p style="padding:10px 0;">'+txtString+'</p><div class="confirmBlock"><p class="set_res success" style="width:50%;" onClick="mwdCommonPopupClose();">확인</p></div>'
1571    }
1572    if (!['roulette','custom'].includes(type)) popALert.innerHTML += confirmHidePopupBtn;
1573    document.querySelector('.mwd_pop_mask').style.display="flex";
1574    return true;
1575
1576}
1577
1578function mwdCommonPopupClose(){
1579    closePopupOverflow()
1580    document.querySelector('.mwd_pop_mask').style.display='none';
1581    return true;
1582}
1583
1584/**
1585 * @date 2024-07-25 14:52:41 각 스킨템플릿에 중복된 항목을 통합
1586 * @param {string} params
1587 * @param {Object} cartInfo
1588 * @param {bool} returnFl
1589 * @return {bool|void}
1590 */
1591function gd_goods_option_view_result(params, cartInfo, returnFl ) {
1592    params += "&mode=cartIn";
1593    let returnVal = false;
1594    $.ajax({
1595        method: "POST",
1596        cache: false,
1597        async: false,
1598        url: "../order/cart_ps.php",
1599        data: params,
1600        success: function (data) {
1601             if(returnFl === true) {
1602                 returnVal = data.ack === 'y' ? true : false;
1603                 //return returnVal;
1604            } else {
1605                 if(cartInfo.moveCartPageFl == 'y' || (cartInfo.moveCartPageFl == 'n' && cartInfo.moveCartPageDeviceFl == 'mobile')) {
1606                     gd_close_layer();
1607                     location.href = "../order/cart.php";
1608                 } else {
1609                     $("#optionViewLayer").addClass('dn');
1610                     $("#addCartLayer").removeClass('dn');
1611                     $('#layerDim').removeClass('dn');
1612                     $("#addCartLayer").find('> div').center();
1613                 }
1614             }
1615        },
1616        error: function (data) {
1617            alert(data.message);
1618        }
1619    });
1620    if(returnFl === true) {
1621        return returnVal;
1622    }
1623}
1624
1625// WRITER : KKT
1626// JAVASCRIPT MONEY FORMMATING
1627const scriptMoneyForm = (money) => {
1628    return Math.ceil(money).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
1629};
1630
1631// COMMON INTERSECTION OBSERVER
1632function gdCreateObserver(callback,options ={}) {
1633    const defaultOptions = {
1634        root:null,
1635        rootMargin:'0px',
1636        threshold:0.1,
1637        ...options,
1638    };
1639
1640    return new IntersectionObserver((entries,observer) => {
1641        entries.forEach(entry => {
1642            callback(entry, observer, entry.isIntersecting);
1643        });
1644    }, defaultOptions);
1645};
1646function gdObserverElements(selectObserverElements, callback, options ={}) {
1647    const observer = gdCreateObserver(callback,options);
1648
1649    let elements = [];
1650
1651    if (typeof selectObserverElements === 'string') {
1652        elements = document.querySelectorAll(selectObserverElements);
1653    } else if (NodeList.prototype.isPrototypeOf(selectObserverElements) || Array.isArray(selectObserverElements)) {
1654        elements = selectObserverElements;
1655    } else if (selectObserverElements instanceof Element) {
1656        elements = [selectObserverElements];
1657    }
1658
1659    elements.forEach(el => observer.observe(el));
1660
1661    return observer;
1662};
1663
1664// LIKE BUTTON CLICK EFFECT
1665const onhandleClickAddWishEffect = (event, getThis, sno, groupSno, autoMoves, status) => {
1666    if (!status) {
1667        var minOrderCnt = 1;
1668        if (getThis.data('min-order-cnt')) {
1669            minOrderCnt = parseInt(getThis.data('min-order-cnt'));
1670            if (minOrderCnt > 1) {
1671                alert(__('최소 %s개 이상 구매가능합니다', minOrderCnt));
1672            }
1673        }
1674/*
1675        LEGACY 상태에서는 data-goods-no와 data-optionfl 값을 가지고 있기 떄문에 정상적으로 작동하나
1676        커스텀을 통한 설정에서는 해당 값을 undefined로 받아오는 문제로 인해 조건문을 통하여 event 객체의
1677        data-goods-no 와 data-optionfl 값을 사용함
1678*/
1679        if (getThis.data('goods-no') === undefined) {
1680            let getGoodsNo = event.currentTarget.getAttribute('data-goods-no');
1681            $('#frmWishTemplateView input[name=\'cartMode\']').val(getGoodsNo);
1682        } else {
1683            $('#frmWishTemplateView input[name=\'cartMode\']').val(getThis.data('goods-no'));
1684        }
1685        if (getThis.data('optionfl') === undefined) {
1686            let getOptionFl = event.currentTarget.getAttribute('data-optionfl');
1687            $('#frmWishTemplateView input[name=\'optionFl\']').val(getOptionFl);
1688        } else {
1689            $('#frmWishTemplateView input[name=\'optionFl\']').val(getThis.data('optionfl'));
1690        }
1691        $('#frmWishTemplateView input[name=\'mode\']').val('wishIn');
1692
1693        var params = $('#frmWishTemplateView').serialize();
1694        $.ajax({
1695            method: "POST",
1696            cache: false,
1697            url: '../mypage/wish_list_ps.php',
1698            data: params,
1699            success: function (data) {
1700                if (!_.isUndefined(data.error) && data.error == 1) {
1701                    alert(data.message);
1702                    return false;
1703                }
1704                if (autoMoves) {
1705                    location.href = "../mypage/wish_list.php";
1706                    return false;
1707                }
1708                $("#addWishLayer").removeClass('dn');
1709                $('#layerDim').removeClass('dn');
1710                $("#addWishLayer").find('> div').center();
1711/*
1712                찜기능 작동 시 즉각적으로 사용자에게 아이콘의 색상이 채워지는 모습을 보여주기 위해 JavaScript를
1713                활용하여 svg 색상 변경.
1714                화면 re-rendering 이후 채워진 색상으로 변경됨 (즉각적인 re-rendering 방지)
1715*/
1716                if (!event.currentTarget.classList.contains('enable')) {
1717                    event.currentTarget.classList.add('enable');
1718                    event.currentTarget.querySelector('svg').setAttribute('fill','#EC2525');
1719                    event.currentTarget.querySelector('svg > path').setAttribute('stroke','#EC2525');
1720                }
1721            },
1722            error: function (data) {
1723                alert(data.message);
1724            }
1725        });
1726
1727        return false;
1728    } else {
1729        $("#deleteWishLayer").removeClass('dn');
1730        $('#layerDim').removeClass('dn');
1731        $("#deleteWishLayer").find('> div').center();
1732    }
1733};
1734
1735// CUSTOM LAYER CLOSE EVENT
1736const closeThisLayer = (e) => {
1737    e.closest('.active').classList.remove('active');
1738};
1739
1740// CUSTOM LAYER REMOVE EVENT
1741const removeThisLayer = (e,targetName) => {
1742    e.closest(targetName).remove(targetName);
1743};
1744
1745// GET TIMER
1746const timerMap = {};
1747const makeTimeCounter = (getEndDateTime, type = null, targetName = null) => {
1748    if (timerMap[targetName]) {
1749        clearInterval(timerMap[targetName]);
1750    }
1751    let _vDate = new Date(getEndDateTime);
1752    let _second = 1000;
1753    let _minute = _second * 60;
1754    let _hour = _minute * 60;
1755    let _day = _hour * 24;
1756    let timer;
1757    let label = '주간';
1758
1759    function showRemaining(){
1760        let now = new Date();
1761        let distDt = _vDate - now;
1762
1763        if (distDt < 0) {
1764            if (document.getElementById(targetName)) {
1765                document.getElementById(targetName).textContent = '해당 이벤트가 종료 되었습니다!';
1766            }
1767            return;
1768        }
1769
1770        let days = Math.floor(distDt / _day);
1771        let hours = String(Math.floor((distDt % _day) / _hour)).padStart(2, "0");
1772        let minutes = String(Math.floor((distDt % _hour) / _minute)).padStart(2, "0");
1773        let seconds = String(Math.floor((distDt % _minute) / _second)).padStart(2, "0");
1774        let milliseconds = String(Math.floor((distDt % _second) / 10)).padStart(2, "0");
1775
1776        let timerHtml = '';
1777
1778        switch (type) {
1779            case 'timesale':
1780                timerHtml += '<span class="font_weight_ch">' + days + '일 </span>';
1781                timerHtml += '<span>' + hours + ':';
1782                timerHtml += minutes + ':';
1783                timerHtml += seconds + '</span>';
1784                timerHtml += '<span class="milliseconds_box" style="min-width: 46px;">:' + milliseconds + '</span> 남음';
1785
1786                $("." + targetName).html(timerHtml);
1787                break
1788            case 'weeksale':
1789                timerHtml += '<span>' + label + '특가 ' + days + '일 ' + hours + ':';
1790                timerHtml += minutes + ':';
1791                timerHtml += seconds + ':';
1792                timerHtml += milliseconds + '</span><span class="font_weight_ch"></span>'
1793                $("#" + targetName).html(timerHtml);
1794                break
1795            case 'maintimesale':
1796                if (days >= 1) {
1797                    {
1798                        timerHtml += '<span class="font_weight_ch" style="font-size: 23px; color:var(--point-color);">' + days + '일&nbsp;</span>';
1799                        timerHtml += hours + ':';
1800                        timerHtml += minutes + ':';
1801                        timerHtml += seconds;
1802                        if (window.location.pathname.includes('event_sale')) {
1803                            timerHtml += '<span class="milliseconds_box" style="min-width: 46px;">:' + milliseconds + '</span> 남음';
1804                        }
1805                    }
1806                } else {
1807                    timerHtml += hours + ':';
1808                    timerHtml += minutes + ':';
1809                    timerHtml += seconds;
1810                    if (window.location.pathname.includes('event_sale')) {
1811                        timerHtml += '<span class="milliseconds_box" style="min-width: 46px;">:' + milliseconds + '</span> 남음';
1812                    }
1813                }
1814                $("." + targetName).html(timerHtml);
1815                break
1816            case 'eventsale' :
1817                if (days >= 1) {
1818                    {
1819                        timerHtml += '<span class="font_weight_ch">' + days + '일 </span>';
1820                        timerHtml += hours + ':';
1821                        timerHtml += minutes + ':';
1822                        timerHtml += seconds + '  남음';
1823                    }
1824                } else {
1825                    timerHtml += hours + ':';
1826                    timerHtml += minutes + ':';
1827                    timerHtml += seconds + '  남음';
1828                }
1829                $("." + targetName).html(timerHtml);
1830                break
1831            case 'onlytimer' :
1832                timerHtml += '<span class="houres">' + hours + '</span>:';
1833                timerHtml += '<span class="minutes">' + minutes + '</span>:';
1834                timerHtml += '<span class="seconds">' + seconds + '</span>:';
1835                timerHtml += '<span class="milliseconds">' + milliseconds + '</span>'
1836                $("." + targetName).html(timerHtml);
1837                break
1838        }
1839    };
1840
1841    if (['timesale','eventsale','onlytimer'].includes(type)) {
1842        let now = new Date();
1843        let endDate = getEndDateTime.substring(0, 10);
1844        let date_arr = endDate.split("-");
1845
1846        let year = now.getFullYear();   // 연도
1847        let month = now.getMonth() + 1;   // 월
1848        let day = now.getDate();        // 일
1849
1850        let stDate = new Date(date_arr[0], date_arr[1], date_arr[2]);
1851        let nedDate = new Date(year, month, day);
1852
1853        let btMs = nedDate.getTime() - stDate.getTime();
1854        let btDay = btMs / (1000 * 60 * 60 * 24);
1855
1856        if (btDay < 1) {
1857            showRemaining();
1858            timerMap[targetName] = setInterval(showRemaining, 10);
1859        } else {
1860            showRemaining();
1861        }
1862    } else if (type ==='weeksale') {
1863        let now = new Date();
1864        timerMap[targetName] = setInterval(showRemaining, 10);
1865    } else if (type === 'maintimesale') {
1866        let now = new Date();
1867        let endDate = getEndDateTime.substring(0, 10);
1868        let date_arr = endDate.split("-");
1869
1870        let year = now.getFullYear();   // 연도
1871        let month = now.getMonth() + 1;   // 월
1872        let day = now.getDate();        // 일
1873
1874        let stDate = new Date(date_arr[0], date_arr[1], date_arr[2]);
1875        let nedDate = new Date(year, month, day);
1876
1877        let btMs = nedDate.getTime() - stDate.getTime();
1878        let btDay = btMs / (1000 * 60 * 60 * 24);
1879        if (btDay < 1) {
1880            showRemaining();
1881            timerMap[targetName] = setInterval(showRemaining, window.location.pathname.includes('event_sale') ? 10 : 1000);
1882        } else {
1883            timerMap[targetName] = setInterval(showRemaining, window.location.pathname.includes('event_sale') ? 10 : 1000);
1884        }
1885    } else if (type === null) {
1886        timerMap[targetName] = setInterval(showRemaining, 1000);
1887    }
1888};
1889
1890// 할부 첫달 계산
1891const getCalcFirstMonth = (goodsPrice,getMonth) => {
1892    let price;
1893    let month;
1894    if (typeof goodsPrice === "string") {
1895     price = Number(goodsPrice);
1896    }
1897    if (typeof getMonth === "string") {
1898        month = Number(getMonth)
1899    }
1900    const principalPayment = Math.floor(price / month);
1901    const interestPayment = (price * (5 / 100)) / month;
1902    return scriptMoneyForm(principalPayment + interestPayment);
1903}
1904
1905// 첫구매 상품구매 버튼 이벤트
1906const firstBuyProductBtnEvent = (userType) => {
1907    console.log(userType);
1908    if (userType === "HAS_PRICE_STRING") {
1909        alert("'첫 구매 회원'만 구매 가능합니다.\n 비회원인 경우 회원가입 후 이용해주세요");
1910        window.location.href = "../member/login.php";
1911    } else if (userType === "FIRST_SALE_LIMITED") {
1912        alert("해당 상품은 '첫구매 회원'만 구매 가능합니다.")
1913    } else if (userType === "MIN_ORDER_PRICE_LIMITED") {
1914        alert("상품을 장바구니에 담으시고, 함께 구매할 상품 (5만원 이상)과 같이 주문해주세요.")
1915    }
1916}
1917
1918// 숫자 슬롯머신 효과
1919// function RollingCount(className, number, type) {
1920//     const speed = 100
1921//     const delay = 300
1922//     const el = document.querySelector(className);
1923//     const num = number.replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ",").split('')
1924//     num.forEach((item,i)=>{
1925//         const classId = item ==','? `num-idx-`+i+`-point` : `num-idx-`+i+`-`+item;
1926//         const text = item;
1927//         const slideStyle = 'transition: margin .3s';
1928//         const test = type == 'slide' ? slideStyle : ''
1929//         el.innerHTML += '<span class="num ' + classId +'" data-text="'+text+'">'+
1930//             '<span  style="'+test+'" class="num-list">0 1 2 3 4 5 6 7 8 9 ,</span>'+
1931//             '</span>'
1932//
1933//         setTimeout(()=>{
1934//             numAnimate('.'+classId)
1935//         }, delay*i)
1936//     })
1937//
1938//     function numAnimate(unit){
1939//         const el = document.querySelector(className).querySelector(unit)
1940//         const numList = el.querySelector('.num-list');
1941//         const dataText = el.getAttribute('data-text')
1942//         const pos = dataText == ',' ? 10 : dataText
1943//         let n = 0;
1944//         const numInterval = setInterval(()=>{
1945//             numList.style.marginTop= '-'+n*30+'px'
1946//             if (n >= 10) {
1947//                 clearInterval(numInterval)
1948//                 numList.style.marginTop= '-'+pos*30+'px'
1949//             }
1950//             n++
1951//         },speed)
1952//     }
1953// }

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.