PageSourceSearch

https://fassto.ai/fss/js/login.js

js fassto.ai collected 2026-10-01 16:41:38 UTC 24,070 bytes, 732 lines download raw bytes

1var LoginUser = {};
2
3var str = $.cookie('loginResult');
4if (str !== undefined && str !== null && str !== "") {
5  var loginResult = JSON.parse(str);
6  if (loginResult != undefined && loginResult != null) {
7    // FSS 계정으로 SNS 로그인 시도 시 실패 관련 toast 호출
8    if (loginResult.fssUserCheck == 'Y') {
9      NoticePopup.toast({
10        message: "FSS 계정은 사용 할 수 없습니다.",
11        timeout: 3000
12      });
13    }
14  }
15  $.cookie('loginResult', null, {path: "/"});
16}
17
18// 플러그인만들기
19(function ($) {
20  $.fn.loginForm = function () {
21    this.each(function (index) {
22      var login = new LoginForm(this);
23    })
24    return this;
25  }
26})(jQuery)
27
28var promotion = "";
29
30function loginFormInit(selector) {
31  $(selector).loginForm();
32  promotion = $("[data-join-promotion]").attr("data-join-promotion");
33}
34
35function getParameterByName(name) {
36  name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
37  var regexS = "[\\?&]" + name + "=([^&#]*)";
38  var regex = new RegExp(regexS);
39  var results = regex.exec(window.location.href);
40  if (results == null) {
41    return "";
42  } else {
43    return decodeURIComponent(results[1].replace(/\+/g, " "));
44  }
45}
46
47LoginForm.prototype = new Form();
48
49function LoginForm(selector) {
50  Form.call(this);
51
52  this.$selector = null;
53
54  this._init(selector);
55  this._initEvent();
56}
57
58LoginForm.prototype._init = function (selector) {
59  this.$selector = $(selector);
60
61  this.$form = this.$selector.find("[data-login-form='loginForm']");
62
63  this.$loginId = this.$selector.find("input[name=loginId]");
64  this.$password = this.$selector.find("input[name=password]");
65  this.$btnLogin = this.$selector.find("[data-login-btn='login']");
66  //this.$saveId = this.$selector.find("input[name='saveLoginId']");
67  this.$saveId = this.$selector.find("[data-save-btn='email']");
68  this.$btnNaverLogin = this.$selector.find("[data-sns-login-btn='naver']");
69  this.$btnKakaoLogin = this.$selector.find("[data-sns-login-btn='kakao']");
70  this.$btnGoogleLogin = this.$selector.find("[data-sns-login-btn='google']");
71  this.$btnAppleLogin = this.$selector.find("[data-sns-login-btn='apple']");
72}
73
74LoginForm.prototype._initEvent = function () {
75  var objThis = this;
76
77  function doLogin() {
78    objThis.$form.trigger("submit");
79  }
80
81  objThis.$loginId.keypress(function (e) {
82    if (e.which != '13') {
83      return;
84    }
85
86    e.preventDefault();
87    doLogin();
88  });
89
90  objThis.$password.keypress(function (e) {
91    if (e.which != '13') {
92      return;
93    }
94
95    e.preventDefault();
96    doLogin();
97  });
98
99  objThis.$btnLogin.click(function (e) {
100    e.preventDefault();
101
102    doLogin();
103  });
104
105  // ajax 처리하기 위해서 submit을 막음
106  objThis.$form.on("submit", function (e) {
107    e.preventDefault();
108
109    var meObj = $(this);
110
111    objThis._inputElmentTrim();
112
113    objThis._clearIsInvalid();
114
115    if (objThis.$saveId.is(":checked")) {
116      var encryptVal = Aes.Ctr.encrypt(objThis.$loginId.val(),
117          $(location).attr('host'), 256);
118      $.cookie("_fss", encryptVal, {path: "/", expires: 365});
119    } else {
120      $.cookie('_fss', null, {path: "/"});
121    }
122
123    if (meObj[0].checkValidity()) {
124      let data = objThis.$form.serialize();
125      const oAuthURL = getParameterByName('oAuthURL');
126      const oAuthType = getParameterByName('oAuthType');
127      const originURL = getParameterByName('originURL');
128
129      if (oAuthURL || oAuthType) {
130        data += window.location.search.replace('?',
131            '&');
132      }
133      data += '&originURL=' + originURL;
134
135      showLoadingPopup();
136      $.ajax({
137        url: "/api/v1/auth/login", // 이메일 로그인
138        data: data,
139        method: 'POST',
140        dataType: "json",
141        crossDomain: true,
142        success: function (response) {
143          const result = {
144            redisKey: response.fasstoSelfCertCode,
145            didTemporayPwLogin: false
146          };
147
148          if (isFasstoSelfApp.any()) {
149            if (isFasstoSelfApp.Android()) {
150              hideLoadingPopup();
151              window.FASSTO_SELF_BRIDGE.sendRedisKey(JSON.stringify(result));
152              return false;
153            } else if (isFasstoSelfApp.iOS()) {
154              hideLoadingPopup();
155              window.webkit.messageHandlers.sendRedisKey.postMessage(
156                  JSON.stringify(result));
157              return false;
158            }
159          } else {
160            // 메인 배너 내 표준요금 소개서 받기 버튼 클릭 시 브릿지 페이지 flow 미적용을 위한 session item get
161            const loginMethod = sessionStorage.getItem('loginMethod');
162
163            hideLoadingPopup();
164            if (null !== response && response.pswdChgYn === 'N') {
165              hideLogin();
166
167              result.didTemporayPwLogin = true;
168
169              if (isFasstoSelfApp.Android()) {
170                window.FASSTO_SELF_BRIDGE.sendRedisKey(JSON.stringify(result));
171                return false;
172              } else if (isFasstoSelfApp.iOS()) {
173                window.webkit.messageHandlers.sendRedisKey.postMessage(
174                    JSON.stringify(result));
175                return false;
176              } else {
177                showsetUpPasswordPopup(response.loginId);
178              }
179            } else {
180              NoticePopup.toast("로그인 되었습니다.");
181
182              $('body').trigger('login', [response]);
183              hideLogin();
184
185              const returnUrl = response.returnUrl;
186              const currentUrl = location.href;
187              const redirectSiteName = response.redirectSiteName;
188              const redirectPageName = response.redirectPageName;
189
190              const prevURL = document.referrer;
191              const para = prevURL.split("/");
192              const lastPara = para[para.length - 1];
193
194              // 파스토셀프(fasstoSelf) 로그인 시 파스토셀프로 이동
195              if (redirectSiteName === 'FASSTO_SELF') {
196                window.location.href = decodeURIComponent(returnUrl);
197              } else if (redirectSiteName === 'MOCAR') {
198                reqMocarRedirect(returnUrl, response.userId);
199              } else if (redirectSiteName === 'FMS') {
200                if (localStorage.SUB_NEWSLETTER && lastPara === 'join') {
201                  location.href = '/content/page/newsletter';
202                } else if (loginMethod === 'globalFulfillmentGuide') {
203                  window.location.href = attachNaverSearchParam(
204                      '/content/page/globalFulfillment');
205                } else {
206                  window.location.href = attachNaverSearchParam('/');
207                }
208              } else if (loginMethod === 'standardPriceGuide') {
209                // window.location.href = attachNaverSearchParam('/main-new?standardPriceYn=Y');
210                window.location.href = attachNaverSearchParam(
211                    returnUrl + '?standardPriceYn=Y');
212              } else if (loginMethod === 'fmsLogin') {
213                reqSSO();
214              } else if (loginMethod === 'globalFulfillmentGuide') {
215                window.location.href = attachNaverSearchParam(
216                    '/content/page/globalFulfillment');
217              } else if (redirectPageName === 'serviceRefuse') {
218                // 서비스 심사 거절 상태의 경우, 서비스 이용 보류페이지로 이동
219                window.location.href = attachNaverSearchParam(
220                    '/view/service-apply');
221              } else {
222                if (returnUrl === '/view/service-join'
223                    || returnUrl === '/view/service-ready'
224                    || returnUrl === '/view/service-joindone'
225                    || returnUrl === '/view/service-readydone'
226                ) {
227                  if (!localStorage.SUB_NEWSLETTER
228                      && lastPara !== 'join'
229                      && currentUrl.indexOf('/view/service-apply') < 0
230                      && loginMethod === null
231                  ) {
232                    window.location.href = attachNaverSearchParam(returnUrl);
233                  } else if (returnUrl === '/view/service-join'
234                      && loginMethod === 'serviceApplyBtn'
235                  ) {
236                    // [IT-14989] 신청 유형 팝업에서 해외를 선택했던 경우 해외 전용 화면으로 진입.
237                    // 같은 탭에서 재로그인 시 이전 클릭 상태가 남아 브릿지를 건너뛰고 직행하지 않도록 사용한 값은 제거
238                    var applyOverseasYn = sessionStorage.getItem('applyOverseasYn');
239                    sessionStorage.removeItem('loginMethod');
240                    window.location.href = attachNaverSearchParam(
241                        '/view/service-apply'
242                        + (applyOverseasYn === 'Y' ? '?overseas=Y' : ''));
243                  } else if (localStorage.SUB_NEWSLETTER && lastPara
244                      === 'join') {
245                    window.location.href = attachNaverSearchParam(
246                        '/content/page/newsletter');
247                  } else if (-1 < currentUrl.indexOf('/view/service-apply')) {// 서비스 신청 전 단계 > GNB > 서비스 신청하기 버튼 클릭 > 로그인 > 브릿지 페이지 미노출
248                    // [IT-15051] 해외 유형을 선택하고 해외 신청 화면에서 로그인한 경우
249                    // 브릿지로 보내 유형을 다시 묻지 않고 해외 신청 화면을 유지한다
250                    if (-1 < currentUrl.indexOf('overseas=Y')
251                        && sessionStorage.getItem('applyOverseasYn') === 'Y') {
252                      window.location.href = attachNaverSearchParam(
253                          '/view/service-apply?overseas=Y');
254                    } else {
255                      reqSSO();
256                    }
257                  } else {
258                  }
259                } else if (-1 < currentUrl.indexOf("/view/service-apply")) {
260                  window.location.href = attachNaverSearchParam(
261                      '/view/service-apply');
262                } else if (undefined === returnUrl
263                    || null === returnUrl
264                    || returnUrl.trim() === ""
265                ) {
266                  window.location.href = attachNaverSearchParam('/');
267                } else if (returnUrl == 'self') {
268                  window.location.reload();
269                } else {
270                  window.location.href = attachNaverSearchParam(returnUrl);
271                }
272              }
273              $("[data-show-is-login='true']").show();
274            }
275            // 메인 배너 내 표준요금 소개서 받기 버튼 클릭 시 브릿지 페이지 flow 미적용을 위한 session item remove
276            // if (null !== sessionStorage.getItem('loginMethod')) {
277            //   sessionStorage.removeItem('loginMethod');
278            // }
279          }
280        },
281        error: function (jqXHR, textStatus, errorThrown) {
282          hideLoadingPopup();
283          var responseJSON = jqXHR.responseJSON;
284          if (responseJSON != null && responseJSON.errorMessage !== undefined
285              && responseJSON.errorMessage != null && responseJSON.errorMessage
286              != "") {
287            NoticePopup.toast({
288              message: responseJSON.errorMessage,
289              location: 'red_toastAlert',
290              yesCallback: function () {
291                setTimeout(function () {
292                  objThis.$password.focus();
293                }, 0);
294              }
295            });
296          } else {
297            NoticePopup.alert("서버에 접속할 수 없습니다.");
298          }
299        }
300      });
301    } else {
302      objThis._focusToInvalid();
303    }
304    return false;
305  })
306
307  // 파셀앱측에 SDK 사용하라고 알림.
308  function handleFasstoSelfAppSDKEvent(snsType) {
309    const data = {
310      snsType,
311      status: 'loginViaSns',
312    }
313
314    if (isFasstoSelfApp.Android()) {
315      window.FASSTO_SELF_BRIDGE.sendLoginSns(JSON.stringify(data));
316      return false;
317    } else if (isFasstoSelfApp.iOS()) {
318      window.webkit.messageHandlers.sendLoginSns.postMessage(
319          JSON.stringify(data));
320      return false;
321    }
322    return false;
323  }
324
325  function gotoSnsLoginUrl(snsType, promotion) {
326    var promotionCode = getParameterByName('promotion');
327    if (promotion == undefined) {
328      promotion = promotionCode;
329    }
330
331    showLoadingPopup();
332    let returnUrl = $("#loginDialog").attr("data-login-return-url");
333    const oAuthType = getParameterByName('oAuthType');
334    const originURL = getParameterByName('originURL');
335
336    if (returnUrl == "self") {
337      returnUrl = originURL ?? window.location.pathname;
338      if (window.location.search != undefined && window.location.search != null
339          && window.location.search != "") {
340        returnUrl += attachNaverSearchParam(window.location.search);
341      }
342      if (window.location.hash != undefined && window.location.hash != null
343          && window.location.hash != "") {
344        returnUrl += attachNaverSearchParam(window.location.hash);
345      }
346    } else {
347      returnUrl = attachNaverSearchParam(window.location.href);
348    }
349
350    returnUrl = (window.location.pathname == '/view/login') ? '' : returnUrl;
351
352    if (originURL != null && originURL !== '') {
353      returnUrl = originURL;
354    }
355
356    if (window.location.search && oAuthType === 'mocar') {
357      returnUrl = (window.location.pathname + window.location.search);
358    }
359
360    $.ajax({
361      url: "/sns/" + snsType + "/loginUrl",
362      data: {
363        returnUrl: returnUrl,
364        promotion: promotion
365      },
366      method: 'GET',
367      dataType: "json",
368      crossDomain: true,
369      cache: false,
370      success: function (response) {
371        hideLoadingPopup();
372        const apiURL = response.apiURL;
373
374        if (apiURL !== undefined && apiURL != null && apiURL != "") {
375          window.location.href = apiURL;
376        }
377      },
378      error: function (jqXHR, textStatus, errorThrown) {
379        hideLoadingPopup();
380        var responseJSON = jqXHR.responseJSON;
381
382        if (responseJSON != null && responseJSON.errorMessage !== undefined
383            && responseJSON.errorMessage != null && responseJSON.errorMessage
384            != "") {
385          NoticePopup.toast(responseJSON.errorMessage);
386        } else {
387          NoticePopup.alert("서버에 접속할 수 없습니다.");
388        }
389      }
390    });
391  }
392
393  if (promotion == undefined || promotion == null) {
394    promotion = "";
395  }
396
397  objThis.$btnNaverLogin.click(function () {
398    if (isFasstoSelfApp.any()) {
399      handleFasstoSelfAppSDKEvent("naver");
400      return;
401    }
402    gotoSnsLoginUrl("naver");
403  })
404
405  objThis.$btnKakaoLogin.click(function () {
406    if (isFasstoSelfApp.any()) {
407      handleFasstoSelfAppSDKEvent("kakao");
408      return;
409    }
410    gotoSnsLoginUrl("kakao");
411  })
412
413  objThis.$btnGoogleLogin.click(function () {
414    if (isFasstoSelfApp.any()) {
415      handleFasstoSelfAppSDKEvent("google");
416      return;
417    }
418    gotoSnsLoginUrl("google");
419  })
420
421  objThis.$btnAppleLogin.click(function () {
422    if (isFasstoSelfApp.any()) {
423      handleFasstoSelfAppSDKEvent("apple");
424      return;
425    }
426    gotoSnsLoginUrl("apple");
427  })
428
429  $('body').on("beforeShow", objThis.$selector, function () {
430    objThis._clearIsInvalid();
431    objThis.$loginId.val("");
432    objThis.$password.val("");
433
434    // layout의 labelText 원복을 위한 작업
435    objThis.$loginId.trigger("blur");
436    objThis.$password.trigger("blur");
437
438    // 아이디 저장(쿠키) 체크
439    var cookieVal = $.cookie("_fss");
440    if (cookieVal != undefined && cookieVal != "null" && cookieVal != "") {
441      var decryptVal = Aes.Ctr.decrypt(cookieVal, $(location).attr('host'),
442          256);
443      objThis.$saveId.prop("checked", true);
444      objThis.$loginId.val(decryptVal);
445    }
446  })
447
448  $('body').on("afterShow", objThis.$selector, function () {
449    // 로그인창 켤때 포커스 옵션
450    // objThis.$loginId.focus();
451  })
452
453  $("body").on("login", function (e, loginUser) {
454    objThis.setLoginUser(loginUser);
455
456    $("[data-show-is-login='false']").hide();
457    $("[data-show-is-login='true']").show();
458  });
459
460  $("body").on("logout", function () {
461    objThis.setLoginUser({});
462
463    $("[data-show-is-login='true']").hide();
464    $("[data-show-is-login='false']").show();
465
466    $("[data-hide-is-login='false']").hide();
467  });
468
469  objThis.$selector.on("click", ".btnPasswdFind", function (e) {
470    e.preventDefault();
471    const sendEventTarget = e.target.id;
472
473    if (isFasstoSelfApp.Android()) {
474      window.FASSTO_SELF_BRIDGE.sendEventTarget(sendEventTarget);
475      return false;
476    } else if (isFasstoSelfApp.iOS()) {
477      window.webkit.messageHandlers.sendEventTarget.postMessage(
478          sendEventTarget);
479      return false;
480    } else {
481      $("#loginDialog").hide();
482
483      var dialogObj = NoticePopup.dialog("#passwdFind");
484      var dialogId = dialogObj.attr("id");
485
486      passwdFindDialogFormInit("#" + dialogId);
487
488      NoticePopup.dialogShow(dialogObj);
489    }
490  });
491}
492
493LoginForm.prototype.setLoginUser = function (loginUser) {
494  LoginUser = loginUser;
495
496  $("[data-login-user]").each(function () {
497    var meObj = $(this);
498    var name = meObj.attr("data-login-user");
499    var value = LoginUser[name];
500    if (value === undefined || value == null) {
501      value = "";
502    }
503    meObj.text(value);
504  });
505}
506
507function hideLogin() {
508  $("#loginDialog").hide();
509  $('html').removeClass('overflow-hidden');
510}
511
512function showLogin(returnUrl) {
513  if ($('.btnNavClose').length > 0) {
514    $('.btnNavClose').click();
515  }
516  $("#loginDialog").attr("data-login-return-url", returnUrl);
517  $("#loginDialog").trigger("beforeShow");
518  $("#loginDialog").show();
519  $('html').addClass('overflow-hidden');
520  $("#loginDialog").trigger("afterShow");
521}
522
523// 이용약관 변경 팝업 - 2020-01-06 시작
524function serviceTermsNew(returnUrl) {
525  $("#serviceTermsNewDialog").show();
526  $('html').addClass('overflow-hidden');
527}
528
529// 이용약관 변경 팝업 - 2020-05-01 시작
530function serviceTermsNew200501(returnUrl) {
531  $("#serviceTermsNewDialog-200501").show();
532  // $('html').addClass('overflow-hidden');
533}
534
535// 프로모션 - 사방넷 쿠폰 발급 팝업 확인 전용
536function sabangnet(returnUrl) {
537  //$("#loginDialog").attr("data-login-return-url", returnUrl);
538  //$("#loginDialog").trigger("beforeShow");
539  $("#sabangnetDialog").show();
540  $('html').addClass('overflow-hidden');
541  //$("#loginDialog").trigger("afterShow");
542}
543
544// 프로모션 - 고도몰 팝업 확인 전용
545function godo(returnUrl) {
546  $("#godoTestDialog").show();
547  $('html').addClass('overflow-hidden');
548}
549
550//프로모션 - 아임웹 팝업 확인 전용
551function imweb(returnUrl) {
552  $("#imwebTestDialog").show();
553  $('html').addClass('overflow-hidden');
554}
555
556//프로모션 - 아임웹 서비스 중지
557function imwebTerminate(returnUrl) {
558  $("#imwebTerminateDialog").show();
559  $('html').addClass('overflow-hidden');
560}
561
562// FSS 토큰 발행 테스트 전용
563function getToken(returnUrl) {
564  $("#tokenTestDialog").show();
565  $('html').addClass('overflow-hidden');
566}
567
568// 프로모션 - 2019 회원가입 환영 팝업 - 2019-12-11 주석 처리
569/*function join2019(returnUrl) {
570	$("#join2019Dialog").show();
571	$('html').addClass('overflow-hidden');
572}*/
573
574function isLoggedIn() {
575  var userId = $("[data-login-user='userId']").text().trim();
576  return (userId !== undefined && userId != null && userId != "");
577}
578
579function logout() {
580  showLoadingPopup();
581  $.ajax({
582    url: "/api/v1/auth/logout",
583    data: "",
584    method: 'POST',
585    dataType: "json",
586    crossDomain: true,
587    success: function (response) {
588      hideLoadingPopup();
589      $('body').trigger('logout');
590      /*NoticePopup.toast({
591        message: "로그아웃에 성공하였습니다.",
592        callback: function() {
593          window.location.href = "/";
594        }
595      });*/
596      window.location.href = "/";
597    },
598    error: function (jqXHR, textStatus, errorThrown) {
599      hideLoadingPopup();
600      var responseJSON = jqXHR.responseJSON;
601      if (responseJSON != null && responseJSON.errorMessage !== undefined
602          && responseJSON.errorMessage != null && responseJSON.errorMessage
603          != "") {
604        NoticePopup.toast(responseJSON.errorMessage);
605      } else {
606        NoticePopup.alert("서버에 접속할 수 없습니다.");
607      }
608    }
609  });
610}
611
612$(function () {
613  loginFormInit("#loginDialog");
614});
615
616function showPW() {
617  $('.pwShowBtn').on('click', function () {
618    const pwInput = $(this).siblings('input[name="password"]');
619
620    pwInput.toggleClass('active');
621
622    if (pwInput.hasClass('active')) {
623      $(this).removeClass('closed').addClass('open');
624      pwInput.attr('type', 'text');
625    } else {
626      $(this).removeClass('open').addClass('closed');
627      pwInput.attr('type', 'password');
628    }
629  })
630};
631
632function randomBg() {
633  const Pics = ['https://cdn.fassto.ai/resources/img-hp/login_bg01.jpg',
634    'https://cdn.fassto.ai/resources/img-hp/login_bg02.jpg',
635    'https://cdn.fassto.ai/resources/img-hp/login_bg03.jpg',
636    'https://cdn.fassto.ai/resources/img-hp/login_bg04.jpg',
637    'https://cdn.fassto.ai/resources/img-hp/login_bg05.jpg'];
638  const imgBox = document.querySelector(".random-bg");
639
640  imgBox.style.backgroundImage = 'url(' + Pics[Math.floor(
641      Math.random() * Pics.length)] + ')';
642};
643
644function checkValidate(loginSubmitBtn) {
645  // 토스트 팝업
646  $(loginSubmitBtn).click(function () {
647    if ($('.form-control').hasClass('is-invalid')) {
648      $('.login-submitBtn').addClass('invalid');
649    }
650
651    switch (loginSubmitBtn) {
652      case '.login-submitBtn' :
653        if ($('#loginId_loginForm').val() === '') {
654          NoticePopup.toast(
655              {location: 'red_toastAlert', message: '아이디를 입력해주세요.'});
656          return;
657        }
658        if ($('#password_loginForm').val() === '') {
659          NoticePopup.toast(
660              {location: 'red_toastAlert', message: '비밀번호를 입력해주세요.'});
661          return;
662        }
663        if ($('#loginId_loginForm').val().indexOf('@') === -1) {
664          NoticePopup.toast({
665            location: 'red_toastAlert',
666            message: '가입하지 않은 계정이거나 틀린 비밀번호입니다.'
667          });
668          return;
669        }
670
671      case '#btnLogin_loginRequiredForm' :
672        if ($('#loginId_loginRequiredForm').val() === '') {
673          NoticePopup.toast(
674              {location: 'red_toastAlert', message: '아이디를 입력해주세요.'});
675          return;
676        }
677        if ($('#password_loginRequiredForm').val() === '') {
678          NoticePopup.toast(
679              {location: 'red_toastAlert', message: '비밀번호를 입력해주세요.'});
680          return;
681        }
682
683      default:
684        if ($('#loginId_loginRequiredForm').val().indexOf('@') === -1) {
685          NoticePopup.toast({
686            location: 'red_toastAlert',
687            message: '가입하지 않은 계정이거나 틀린 비밀번호입니다.'
688          });
689          return;
690        }
691    }
692  })
693
694  // 키 입력시 is-invalid 초기화
695  $('.form-control').keydown(function () {
696    if ($(this).hasClass('is-invalid')) {
697      $('.login-submitBtn').removeClass('invalid');
698      $(this).removeClass('is-invalid');
699    }
700  })
701}
702
703function reqMocarRedirect(url, userId, snsType) {
704  $.ajax({
705    url: "/api/v1/auth/mocar/token",
706    method: "POST",
707    data: {
708      userId: userId
709    },
710    dataType: "json",
711    crossDomain: true,
712    success: function (response) {
713      if (snsType) {
714        // sns 로그인 시
715        window.location.replace(
716            url += "?fasstoOAuthToken=" + response.accessToken);
717      } else {
718        // 파스토 로그인 시
719        window.location.href = (url += "?fasstoOAuthToken="
720            + response.accessToken);
721      }
722    },
723    error: function (jqXHR) {
724      const responseJSON = jqXHR.responseJSON;
725      if (responseJSON != null && !responseJSON.errorMessage) {
726        NoticePopup.alert(responseJSON.errorMessage);
727      } else {
728        NoticePopup.alert("서버에 접속할 수 없습니다.");
729      }
730    }
731  })
732}

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.