PageSourceSearch

https://www.nitori-net.tw/js/webchat-embed.js

js nitori-net.tw collected 2026-10-05 07:48:14 UTC 4,195 bytes, 111 lines download raw bytes

1/**
2 * 客服機器人嵌入腳本
3 *
4 * 原始來源:https://chatbot.nitori-net.tw/wise/script/webchat-embed.js
5 * 下載日期:2026-05-06
6 *
7 * 修改記錄:
8 * [安全性] resizeFrontEndIframe、injectToEndOfBody、toggleFrontEndIframe
9 *          原本為隱式全域變數(implicit global),已加上 var 宣告限制在 IIFE 作用域內,
10 *          避免污染 window 物件,防止與專案其他程式碼發生命名衝突。
11 * [安全性] $this = $(this) 原本為隱式全域變數,已改為 var $this = $(this)。
12 * [修正] 將 $this.click() 直接綁定改為 $(document).on() event delegation,
13 *        避免 React re-render 替換 DOM 元素後 click handler 失效導致按鈕無反應。
14 * [修正] injectToEndOfBody 加入防重複注入判斷,避免多次呼叫產生多個 wrapper。
15 * [修正] resizeFrontEndIframe 中 max-width 數值由 '100' 修正為 '100%'。
16 * [效能] 關閉聊天視窗時不再清除 iframe src,改為僅隱藏 wrapper;
17 *        首次開啟仍為懶載入,第二次起開啟為瞬間顯示。
18 */
19(function ($) {
20  var webchatUrl;
21  var triggerSelector;
22
23  var resizeFrontEndIframe = function () {
24    if ($('.front-end-iframe-wrapper').css('display') == 'block') {
25      if ($(window).width() <= 480) {
26        $('.front-end-iframe-wrapper').css('max-height', '90%');
27        $('.front-end-iframe-wrapper').css('max-width', '100%');
28        $('.front-end-iframe-wrapper').css('height', '100%');
29        $('.front-end-iframe-wrapper').css('width', '100%');
30        $('.front-end-iframe-wrapper').css('bottom', 0);
31        $('.front-end-iframe-wrapper').css('right', 0);
32        $('.btn-close-front-end-iframe').css('top', 5);
33        $('.btn-close-front-end-iframe').css('right', 5);
34      } else {
35        $('.front-end-iframe-wrapper').css('height', '90%');
36        $('.front-end-iframe-wrapper').css('bottom', 10);
37        $('.front-end-iframe-wrapper').css('right', 50);
38      }
39    }
40  };
41
42  var injectToEndOfBody = function () {
43    if ($('#front-end-iframe-wrapper').length > 0) {
44      return;
45    }
46    $('body').append(
47      $(
48        '<div id="front-end-iframe-wrapper" class="front-end-iframe-wrapper"><div class="btn-close-front-end-iframe fas fa-times fa-lg"></div><iframe name="front-end-iframe" src="about:blank" width="400" height="600" frameborder="0" scrolling="auto" class="front-end-iframe"></iframe></div>',
49      ),
50    );
51  };
52
53  var toggleFrontEndIframe = function () {
54    if ($('.front-end-iframe-wrapper').css('display') == 'block') {
55      $('.front-end-iframe-wrapper').css('display', 'none');
56      $('.btn-close-front-end-iframe').css('display', 'none');
57    } else {
58      if ($('.front-end-iframe-wrapper iframe').attr('src') === 'about:blank') {
59        $('.front-end-iframe-wrapper iframe').attr('src', webchatUrl);
60      }
61      $('.front-end-iframe-wrapper').css('display', 'block');
62      $('.btn-close-front-end-iframe').css('display', 'block');
63      resizeFrontEndIframe();
64    }
65  };
66
67  $(document).on('click', '.btn-close-front-end-iframe', toggleFrontEndIframe);
68
69  $.fn.bindWebchat = function (url) {
70    webchatUrl = url;
71
72    this.each(function () {
73      triggerSelector = this.id ? '#' + this.id : null;
74
75      injectToEndOfBody();
76
77      $(window).on('resize', resizeFrontEndIframe);
78    });
79
80    if (triggerSelector) {
81      $(document)
82        .off('click.webchat')
83        .on('click.webchat', triggerSelector, toggleFrontEndIframe);
84    }
85  };
86
87  /**
88   * 公開 API:window.NitoriChatbot
89   * 提供外部程式碼(React 元件、任何 JS)開關客服機器人。
90   *
91   * 用法:
92   *   window.NitoriChatbot.open()    // 強制開啟
93   *   window.NitoriChatbot.close()   // 強制關閉
94   *   window.NitoriChatbot.toggle()  // 切換開/關
95   */
96  window.NitoriChatbot = {
97    open: function () {
98      if ($('.front-end-iframe-wrapper').css('display') !== 'block') {
99        toggleFrontEndIframe();
100      }
101    },
102    close: function () {
103      if ($('.front-end-iframe-wrapper').css('display') === 'block') {
104        toggleFrontEndIframe();
105      }
106    },
107    toggle: function () {
108      toggleFrontEndIframe();
109    },
110  };
111})(jQuery);

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.