PageSourceSearch

https://www.kaobeautybrands.com/content/dam/sites/kanebo/www-kaobeautybrands-com/js/dialog_modal.js

js kaobeautybrands.com collected 2026-10-01 04:21:54 UTC 6,144 bytes, 201 lines download raw bytes

1(function() {
2  // =================================================== Main Routine
3  document.addEventListener('DOMContentLoaded', function() {
4    // モーダルダイアログ初期化
5    initModal();
6  });
7
8  // =================================================== Sub Routines
9  InitModal.prototype = {
10    settings: {
11      selectorSrcYouTubeIframe: '.contentYT'
12    },
13    env: {
14      breakpoint: 1023,
15      elemScreenContext: document.querySelector('#wrapper'),
16      seriesTrigger: [].slice.call(document.querySelectorAll('.g-TileLinkTextUnit'))
17    },
18
19    init: function() {
20      const scopeInstance = this;
21
22      scopeInstance.env.seriesTrigger.forEach(function(trigger) {
23
24        // if(!trigger.getAttribute('data-id-content')) {
25        //   console.log('data-id-content' + ' does not exist');
26        //   return;
27        // }
28
29        const targetDialog = document.getElementById(trigger.getAttribute('data-id-content'));
30
31        if(!targetDialog) {
32          return;
33        };
34
35        trigger.addEventListener('click', _initiateModalDialog);
36
37        function _initiateModalDialog(ev) {
38          ev.preventDefault();
39
40          let modalBg = document.createElement('div');
41          scopeInstance.open(modalBg, targetDialog);
42        }
43      });
44    },
45
46    open: function(modalBg, targetDialog) {
47      const scopeInstance = this;
48
49      modalBg.classList.add('l-modalDialog');
50      this.env.elemScreenContext.appendChild(modalBg);
51
52      kbbIndividual.interaction.lockScreen();
53
54      modalBg.classList.add('show');
55
56      const waitBeforeVisiblization = 350;
57      setTimeout(function() {
58        scopeInstance.showContent(modalBg, targetDialog);
59      }, waitBeforeVisiblization);
60
61      modalBg.addEventListener('click', function(ev) {
62        // コンテンツ部はモーダル解除検知対象外
63        if(ev.target.closest('.c-modal-content')) { return; }
64
65        scopeInstance.close(modalBg);
66      });
67    },
68
69    showContent: function(modalBg, targetDialog) {
70      const scopeInstance = this;
71
72      const htmlBodyDialog = targetDialog.outerHTML;
73      modalBg.innerHTML = htmlBodyDialog;
74
75      const bodyDialog = modalBg.querySelector('.c-modal-content .scrollContainer');
76      const waitBeforeVisiblization = 100;
77
78      setTimeout(function() {
79        bodyDialog.addEventListener('transitionend', _showDialog);
80
81        bodyDialog.classList.add('showInitial');
82      }, waitBeforeVisiblization);
83
84      function _showDialog(ev) {
85        ev.stopPropagation();
86
87        if(bodyDialog.classList.contains('showInitial')) {
88          bodyDialog.classList.add('showTransition');
89        }
90
91        scopeInstance.addBtClose(modalBg);
92
93        // タブキーフォーカス「メニュー範囲内でサイクル」に設定。アニメーション終了後に先頭にフォーカス
94        kbbIndividual.interaction.rangeTabFocus(
95          [].slice.call(modalBg.querySelectorAll('a')), // サイクル対象要素群
96          {
97            elemAnimationEnd: bodyDialog // アニメーション終了判定に利用する要素
98          }
99        );
100
101        // 画像後追いロード
102        scopeInstance.loadImgSrc(bodyDialog);
103
104        bodyDialog.removeEventListener('transitionend', _showDialog);
105      }
106    },
107
108    loadImgSrc: function(elemContainer) {
109      const seriesImg = [].slice.call(elemContainer.querySelectorAll('[data-src]'));
110      seriesImg.forEach(function(img) {
111        img.addEventListener('load', function(ev) {
112          const container = img.closest('.containerHoldLoad');
113          if(!container) { return; }
114          container.classList.add('loadCompleted');
115        });
116      });
117
118      seriesImg.forEach(function(img) {
119        kbbIndividual.interaction.unholdImgSrc(img);
120      })
121    },
122
123    addBtClose: function(modalBg) {
124      const scopeInstance = this;
125
126      // 閉じるリンク
127      const btClose = document.createElement('a');
128      btClose.classList.add('triggerClose');
129      btClose.setAttribute('href', 'javascript:void(0);');
130      btClose.innerHTML = 'Close';
131
132      const bodyDialog = modalBg.querySelector('.c-modal-content .contentBody');
133      bodyDialog.prepend(btClose);
134      btClose.classList.add('show')
135
136      btClose.addEventListener('transitionend', function(ev) {
137        ev.stopPropagation();
138      });
139      btClose.addEventListener('click', function(ev) {
140        ev.stopPropagation();
141        scopeInstance.close(modalBg);
142      });
143    },
144
145    close: function(modalBg) {
146      const scopeInstance = this;
147
148      const bodyDialog = modalBg.querySelector('.c-modal-content .scrollC
148ontainer');
149      bodyDialog.addEventListener('transitionend', _hideDialog);
150      const btClose = modalBg.querySelector('.triggerClose');
151      btClose.classList.remove('show');
152
153      modalBg.addEventListener('transitionend', function(ev) {
154        if(!modalBg) { return; }
155
156        ev.stopPropagation();
157        bodyDialog.removeEventListener('transitionend', _hideDialog);
158        scopeInstance.env.elemScreenContext.removeChild(modalBg);
159        modalBg = undefined;
160        kbbIndividual.interaction.unlockScreen();
161      });
162
163      bodyDialog.classList.remove('showTransition');
164
165      function _hideDialog(ev) {
166        ev.stopPropagation();
167
168        if(bodyDialog.classList.contains('showInitial')) {
169          bodyDialog.classList.remove('showInitial');
170          return;
171        }
172
173        modalBg.classList.remove('show');
174      }
175    }
176  }
177
178  // InitModal コンストラクタ
179  function InitModal(options) {
180    const scopeInstance = this;
181
182    scopeInstance.construct = function(options) {
183      scopeInstance.env.elemScreenContext = 
184        options.elemScreenContext
185          ? options.elemScreenContext
186          : document.querySelector('#wrapper');
187      ;
188
189      scopeInstance.env.seriesTrigger =
190        options.seriesTrigger
191          ? options.seriesTrigger
192          : [].slice.call(document.querySelectorAll('.g-TileLinkTextUnit'))
193      ;
194    }
195
196    scopeInstance.construct(options ? options : {});
197  }
198
199  // InitModal インスタンス呼び出し
200  function initModal() { return(new InitModal().init()); }
201})();

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.