PageSourceSearch

https://www.theforestakan.com/files/js/dmo_main.js

js theforestakan.com collected 2026-10-04 11:17:29 UTC 28,685 bytes, 654 lines download raw bytes

1
2/* =================================================== */
3// slideUp, slideDown, slideToggle関数を定義
4/* =================================================== */
5// slideUp定義
6const slideUp = (el, duration = 300) => {
7    el.style.height = el.offsetHeight + "px";
8    el.offsetHeight;
9    el.style.transitionProperty = "height, margin, padding";
10    el.style.transitionDuration = duration + "ms";
11    el.style.transitionTimingFunction = "ease";
12    el.style.overflow = "hidden";
13    el.style.height = 0;
14    el.style.paddingTop = 0;
15    el.style.paddingBottom = 0;
16    el.style.marginTop = 0;
17    el.style.marginBottom = 0;
18    setTimeout(() => {
19        el.style.display = "none";
20        el.style.removeProperty("height");
21        el.style.removeProperty("padding-top");
22        el.style.removeProperty("padding-bottom");
23        el.style.removeProperty("margin-top");
24        el.style.removeProperty("margin-bottom");
25        el.style.removeProperty("overflow");
26        el.style.removeProperty("transition-duration");
27        el.style.removeProperty("transition-property");
28        el.style.removeProperty("transition-timing-function");
29        el.classList.remove("is-open");
30    }, duration);
31};
32
33// slideDown定義
34const slideDown = (el, duration = 300) => {
35    el.classList.add("is-open");
36    el.style.removeProperty("display");
37    let display = window.getComputedStyle(el).display;
38    if (display === "none") {
39        display = "block";
40    }
41    el.style.display = display;
42    let height = el.offsetHeight;
43    el.style.overflow = "hidden";
44    el.style.height = 0;
45    el.style.paddingTop = 0;
46    el.style.paddingBottom = 0;
47    el.style.marginTop = 0;
48    el.style.marginBottom = 0;
49    el.offsetHeight;
50    el.style.transitionProperty = "height, margin, padding";
51    el.style.transitionDuration = duration + "ms";
52    el.style.transitionTimingFunction = "ease";
53    el.style.height = height + "px";
54    el.style.removeProperty("padding-top");
55    el.style.removeProperty("padding-bottom");
56    el.style.removeProperty("margin-top");
57    el.style.removeProperty("margin-bottom");
58    setTimeout(() => {
59        el.style.removeProperty("height");
60        el.style.removeProperty("overflow");
61        el.style.removeProperty("transition-duration");
62        el.style.removeProperty("transition-property");
63        el.style.removeProperty("transition-timing-function");
64    }, duration);
65};
66
67// slideToggle定義
68const slideToggle = (el, duration = 300) => {
69    if (window.getComputedStyle(el).display === "none") {
70        return slideDown(el, duration);
71    } else {
72        return slideUp(el, duration);
73    }
74};
75
76/* =================================================== */
77// アコーディオン
78/* =================================================== */
79function set_accordion_events(accordion) {
80    const accordion_items = accordion.querySelectorAll(".js-dmo-accordion-item");
81    if (accordion_items) {
82        accordion_items.forEach((accordion_item) => {
83            const target_accordion_item_id = accordion_item.dataset.accordion_id;
84            accordion_item.querySelector(".js-dmo-accordion-heading").addEventListener("click", (e) => {
85                accordion_items.forEach((accordion_item) => {
86                    if (accordion_item.dataset.accordion_id === target_accordion_item_id) {
87                        accordion_item.querySelector(".modal-heading").classList.toggle("is-active");
88                        slideToggle(accordion_item.querySelector(".js-dmo-accordion-body"));
89                    }
90                })
91            });
92        });
93    }
94}
95
96
97const MAX_NUMBER_OF_PEOPLE = 9; // 最大人数
98
99/**
100 * roomCount: 部屋数
101 * peoplePerRoom: 1部屋あたりの人数
102 * maxCapacity: 最大人数
103 */
104function assignPeopleToRooms(roomCount, peoplePerRoom, maxCapacity) {
105    const rooms = [];
106    for (let i = 0; i < roomCount; i++) {
107        rooms.push(0);
108    }
109
110    // 最大人数を超えないようにする
111    let totalPeople = roomCount * peoplePerRoom;
112    if (maxCapacity < totalPeople) {
113        totalPeople = maxCapacity;
114    }
115
116    // 各部屋に割り当てる
117    for (let i = 0; i < totalPeople; i++) {
118        rooms[i % roomCount]++;
119    }
120
121    return rooms;
122}
123
124/**
125 * モーダルオープン
126 */
127function modal_open() {
128    const widget = this.closest(".js-dmo-widget");
129    if (widget === null) {
130        return
131    }
132    const target_id = widget.dataset.widget_id ?? "";
133    const modal = widget.querySelector(`[data-modal_id="${target_id}"]`);
134    if (modal) {
135        modal.style.display = 'block';
136        modal.animate([{opacity: '0'}, {opacity: '1'}], {duration: 300, fill: "forwards"});
137    }
138}
139
140/**
141 * モーダルクローズ
142 */
143function modal_close() {
144    const widget = this.closest(".js-dmo-widget");
145    if (widget === null) {
146        return
147    }
148    const target_id = widget.dataset.widget_id ?? "";
149    const modal = widget.querySelector(`[data-modal_id="${target_id}"]`);
150    if (modal) {
151        modal.style.display = 'none';
152        modal.animate([{opacity: '1'}, {opacity: '0'}], {duration: 300, fill: "forwards"});
153    }
154}
155
156/**
157 * 子供の年齢変更時
158 */
159function change_children_age() {
160    const js_detail = this.closest(".js-dmo-detail");
161    if (js_detail) {
162        if (Number(this.value) <= 5) {
163            js_detail.querySelector(".js-dmo-children-required-option").classList.add("d-n");
164            js_detail.querySelector(".js-dmo-children-option").classList.remove("d-n");
165        } else {
166            js_detail.querySelector(".js-dmo-children-required-option").classList.remove("d-n");
167            js_detail.querySelector(".js-dmo-children-option").classList.add("d-n");
168        }
169    }
170}
171
172/**
173 * 子供の内訳(○人目)の項目を設定
174 */
175function set_children_detail(widget_id, accordion_id) {
176    const accordion = document.querySelector(`[data-widget_id="${widget_id}"] [data-accordion_id="${accordion_id}"]`);
177    if (accordion) {
178        // 一度中身を空にする
179        const clone = accordion.querySelector(".js-dmo-details").cloneNode(false);
180        accordion.querySelector(".js-dmo-details").parentNode.replaceChild(clone, accordion.querySelector(".js-dmo-details"));
181        const js_children = accordion.querySelector(".js-dmo-children");
182        const template_children_detail = document.getElementById("template-accordion-children-detail");
183        for (let i = 1; i <= parseInt(js_children.value); i++) {
184            const clone_element = template_children_detail.content.cloneNode(true);
185            clone_element.querySelector(".js-dmo-count").innerText = i.toString();
186            const js_age = clone_element.querySelector("select[name='js-dmo-age']");
187            js_age.addEventListener("change", change_children_age);
188            accordion.querySelector(".js-dmo-details").appendChild(clone_element);
189        }
190    }
191}
192
193/**
194 * 大人の人数変更時
195 */
196function change_adult_count() {
197    const accordion = this.closest(".js-dmo-accordion-item");
198    if (accordion) {
199        const js_adult = accordion.querySelector(".js-dmo-adult");
200        const js_children = accordion.querySelector(".js-dmo-children");
201        // 大人と子供の合計人数が6人になるように調整する
202        if (parseInt(js_adult.value) + parseInt(js_children.value) > 9) {
203            // 子供の人数を調整する
204            js_children.value = (9 - parseInt(js_adult.value));
205            const accordion_id = accordion.dataset.accordion_id;
206            const widget_id = accordion.closest(".js-dmo-widget").dataset.widget_id;
207            set_children_detail(widget_id, accordion_id);
208        }
209    }
210}
211
212/**
213 * 子供の人数変更時
214 */
215function change_children_count() {
216    const accordion = this.closest(".js-dmo-accordion-item");
217    if (accordion) {
218        // 一度中身を空にする
219        const clone = accordion.querySelector(".js-dmo-details").cloneNode(false);
220        accordion.querySelector(".js-dmo-details").parentNode.replaceChild(clone, accordion.querySelector(".js-dmo-details"));
221
222        const js_adult = accordion.querySelector(".js-dmo-adult");
223        const js_children = accordion.querySelector(".js-dmo-children");
224        const accordion_id = accordion.dataset.accordion_id;
225        const widget_id = accordion.closest(".js-dmo-widget").dataset.widget_id;
226        set_children_detail(widget_id, accordion_id);
227        // 大人と子供の合計人数が6人になるように調整する
228        if (parseInt(js_adult.value) + parseInt(js_children.value) > 9) {
229            // 大人の人数を調整する
230            js_adult.value = (9 - parseInt(js_children.value));
231        }
232    }
233}
234
235/**
236 * 人数内訳のテキスト設定
237 */
238function set_count_detail() {
239    const widget = this.closest(".js-dmo-widget");
240    if (widget === null) {
241        return;
242    }
243    const target_id = widget.dataset.widget_id ?? "";
244    const modal = widget.querySelector(`[data-modal_id="${target_id}"]`);
245    if (modal === null) {
246        return;
247    }
248    const accordion_items = modal.querySelectorAll(".js-dmo-accordion-item");
249    if (accordion_items) {
250        let adult_count = 0;
251        let children_count = 0;
252        const room_details = [];
253        accordion_items.forEach((accordion_item) => {
254            const js_adult = accordion_item.querySelector(".js-dmo-adult");
255            const js_children = accordion_item.querySelector(".js-dmo-children");
256            if (js_adult && js_children) {
257                const children_details = [];
258                const adult_num = Number(js_adult.value);
259                const children_num = Number(js_children.value);
260                adult_count += adult_num;
261                children_count += children_num;
262                if (children_count > 0) {
263                    const children_detail = accordion_item.querySelectorAll(".js-dmo-detail");
264                    children_detail.forEach((detail) => {
265                        const age = detail.querySelector("select[name='js-dmo-age']").value;
266                        const params = {
267                            age: age,
268                            meal: true,
269                            futon: true,
270                        };
271                        // 5歳以下の場合は食事と布団の有無を選択できる
272                        if (age <= 5) {
273                            const meal_futon = detail.querySelector("input[name='meal_futon']").checked;
274                            params.meal = meal_futon;
275                            params.futon = meal_futon;
276                        }
277                        children_details.push(params);
278                    });
279                }
280                room_details.push({
281                    adult: adult_num,
282                    child: children_details,
283                });
284            }
285        });
286
287        // 合計人数をチェック
288        if ((adult_count + children_count) > MAX_NUMBER_OF_PEOPLE) {
289            alert(`予約可能な人数の上限を超えています。${MAX_NUMBER_OF_PEOPLE}名以下でお申し込みください。`);
290            return;
291        }
292
293        widget.querySelector(`input[name="room-detail"]`).value = JSON.stringify(room_details);
294        const js_modal_label_area = widget.querySelector(`.js-dmo-modal-open`);
295        if (js_modal_label_area) {
296            js_modal_label_area.querySelector(".count-all").innerText = `${adult_count + children_count}`;
297            js_modal_label_area.querySelector(".count-adult").innerText = `${adult_count}`;
298            js_modal_label_area.querySelector(".count-children").innerText = `${children_count}`;
299        }
300    }
301    modal.style.display = 'none';
302    modal.animate([{opacity: '1'}, {opacity: '0'}], {duration: 300, fill: "forwards"});
303}
304
305// 部屋数変更時
306function change_room_count() {
307    const widget = this.closest(".js-dmo-widget");
308    if (widget === null) {
309        return;
310    }
311    const room_count = widget.querySelector("select[name='room-count']");
312    const modal = widget.querySelector(".js-dmo-modal");
313    if (room_count && modal) {
314        // アコーディオンを一度削除
315        const accordion = widget.querySelector(`.js-dmo-accordion`);
316        const clone = accordion.cloneNode(false);
317        accordion.parentNode.replaceChild(clone, accordion);
318        // 部屋数分、アコーディオンを追加
319        const template_accordion_item = document.getElementById("template-accordion-item");
320        const room_detail = [];
321        let count_all = 0;
322
323        const assignRooms = assignPeopleToRooms(room_count.value, DMO_DEFAULT_ONE_ROOM_NUMBER_OF_PEOPLE, MAX_NUMBER_OF_PEOPLE);
324        for (let i = 1; i <= assignRooms.length; i++) {
325            const peopleNum = assignRooms[i - 1];
326            const accordion_item_clone = template_accordion_item.content.cloneNode(true);
327            const js_accordion_item = accordion_item_clone.querySelector(".js-dmo-accordion-item");
328            js_accordion_item.dataset.accordion_id = i;
329            const modal_heading = accordion_item_clone.querySelector(".modal-heading");
330            modal_heading.innerText = `お部屋${i}`;
331            const js_accordion_body = js_accordion_item.querySelector(".js-dmo-accordion-body");
332            if (i === 1) {
333                // 1部屋目のアコーディオンをオープンにする
334                js_accordion_body.classList.add("is-open");
335                modal_heading.classList.add("is-active");
336            }
337            // 大人の人数
338            const js_adult = js_accordion_body.querySelector(".js-dmo-adult");
339            js_adult.value = peopleNum;
340            js_adult.addEventListener("change", change_adult_count);
341            // 子供の人数
342            const js_children = js_accordion_body.querySelector(".js-dmo-children");
343            js_children.addEventListener("change", change_children_count);
344            widget.querySelector(".js-dmo-accordion").appendChild(accordion_item_clone);
345            room_detail.push({adult: peopleNum, child: []});
346            count_all += peopleNum;
347            if (count_all > MAX_NUMBER_OF_PEOPLE) {
348                count_all = MAX_NUMBER_OF_PEOPLE;
349            }
350        }
351
352        set_accordion_events(widget.querySelector(".js-dmo-accordion"));
353        // 人数の詳細
354        widget.querySelector("input[name='room-detail']").value = JSON.stringify(room_detail);
355        widget.querySelector('.count-all').innerText = `${count_all}`;
356        widget.querySelector('.count-adult').innerText = `${count_all}`;
357        widget.querySelector('.count-children').innerText = "0";
358    }
359}
360
361/**
362 * カレンダーの設定
363 */
364function setFlatpickr(element, minDate, maxDate, defaultDate) {
365    const options = {
366        locale: "ja",
367        minDate: minDate,
368        maxDate: maxDate,
369        defaultDate: defaultDate,
370        altInput: true,
371        altFormat: "Y/m/d",
372        dateFormat: "Y-m-d",
373        disableMobile: true,
374        onChange: function(selectedDates, dateStr, instance) {
375            const widget = instance.element.closest(".js-dmo-widget");
376            if (widget) {
377                changeTravelDate(widget);
378            }
379        },
380        appendTo: document.querySelector('.js-dmo-widget'), // NOTE:カレンダーモーダルをウィジェット内に表示する
381    };
382    if (maxDate) {
383        options.enable = [{from: minDate, to: maxDate}];
384    }
385    flatpickr(element, options);
386}
387
388/**
389 * 旅行期間が正しいかチェックする
390 */
391function isValidateTravelTerm(departure, arrival) {
392    const departureDate = dayjs(departure);
393    const arrivalDate = dayjs(arrival);
394    if (!departureDate.isValid() || !arrivalDate.isValid()) {
395        return false;
396    }
397
398    const travelDays = arrivalDate.diff(departureDate, "day") + 1; // 旅行日数(日間)
399    const maxTravelDays = (DMO_MAX_TRAVEL_DAYS > 1) ? DMO_MAX_TRAVEL_DAYS : 14; // 最大旅行日数(デフォルトは14日間)
400    if (travelDays < 2 || maxTravelDays < travelDays) {
401        // 2日未満または最大旅行日数を超えている
402        return false;
403    }
404    return true;
405}
406
407/**
408 * 出発日をもとに、正しい出発日と帰着日を取得する
409 */
410function getValidTravelTerm(departure = null) {
411    const now = new Date();
412    const departureAfterDays = (5 <= DMO_DEPARTURE_DATE_DAYS) ? DMO_DEPARTURE_DATE_DAYS : 5; // 出発日(○日後に出発)
413    const maxTravelDays = (DMO_MAX_TRAVEL_DAYS > 1) ? DMO_MAX_TRAVEL_DAYS : 14; // 最大旅行日数(デフォルトは14日間)
414    const travelDays = (DMO_DEFAULT_NUMBER_OF_STAYS > 0) ? DMO_DEFAULT_NUMBER_OF_STAYS : 1; // 旅行日数(拍数)
415
416    // 出発日のデータ
417    let departureDefaultDate = dayjs(now).add(departureAfterDays, "day"); // 出発日
418    if (dayjs(departure).isValid()) {
419        departureDefaultDate = dayjs(departure);
420    }
421    const departureData = {
422        minDate: dayjs(now).add(5, "day").format("YYYY-MM-DD"),
423        defaultDate: departureDefaultDate.format("YYYY-MM-DD"),
424        maxDate: null,
425    }
426
427    // 帰着日のデータ
428    const arrivalDefaultDate = dayjs(departureDefaultDate).add(1, "day"); // 帰着日(出発日の1日後)
429    const arrivalData = {
430        minDate: arrivalDefaultDate.format("YYYY-MM-DD"),
431        defaultDate: dayjs(departureDefaultDate).add(travelDays, "day").format("YYYY-MM-DD"),
432        maxDate: dayjs(departureDefaultDate).add(maxTravelDays - 1, "day").format("YYYY-MM-DD"),
433    }
434
435    return {
436        departure: departureData,
437        arrival: arrivalData
438    }
439}
440
441/**
442 * 出発日と帰着日の変更時
443 */
444function changeTravelDate(widget) {
445    // ウィジェットの`出発日`と`帰着日`を取得
446    const departureElement = widget.querySelector("input[class^='date-picker'][name='departure']");
447    const arrivalElement = widget.querySelector("input[class^='date-picker'][name='arrival']");
448    if (departureElement && arrivalElement) {
449        const departureDate = dayjs(departureElement.value).format("YYYY-MM-DD");
450        const arrivalDate = dayjs(arrivalElement.value).format("YYYY-MM-DD");
451        // 旅行日数をチェック
452        const travelTerm = getValidTravelTerm(departureDate);
453        if (isValidateTravelTerm(departureDate, arrivalDate)) {
454            // 帰着日のみ再設定(選択可能な日)
455            setFlatpickr(arrivalElement, travelTerm.arrival.minDate, travelTerm.arrival.maxDate, arrivalDate);
456        } else {
457            // 出発日と帰着日を再設定
458            setFlatpickr(departureElement, travelTerm.departure.minDate, null, travelTerm.departure.defaultDate);
459            setFlatpickr(arrivalElement, travelTerm.arrival.minDate, travelTerm.arrival.maxDate, travelTerm.arrival.defaultDate);
460        }
461    }
462}
463
464/**
465 * 検索
466 */
467function search() {
468    const widget = this.closest(".js-dmo-widget");
469    if (widget === null) {
470        return
471    }
472    const departure_airport = widget.querySelector("select[name='departure-airport']").value;
473    const departure_date = widget.querySelector("input[type='hidden'][name='departure']").value;
474    const arrival_date = widget.querySelector("input[type='hidden'][name='arrival']").value;
475    const room_count = widget.querySelector("select[name='room-count']").value;
476    const room_detail = widget.querySelector("input[type='hidden'][name='room-detail']").value;
477    const search_params = {
478        c_airport_from: "OKA",
479        from: departure_airport,
480        to: DMO_DEFAULT_ARRIVAL_AIRPORT_VALUE,
481        start: departure_date,
482        end: arrival_date,
483        checkin: departure_date,
484        checkout: arrival_date,
485        days: 1,
486        rooms: room_count,
487        roomDetail: JSON.parse(room_detail),
488    };
489    const url_params = new URLSearchParams();
490    url_params.append("params", JSON.stringify(search_params));
491
492    const url = DMO_PLAN_URL + "?" + url_params.toString();
493    // console.debug({
494    //     "search_param": JSON.parse(url_params.getAll("params").toString()),
495    //     "url": url,
496    // });
497    window.open(url);
498}
499
500/**
501 * ウィジェットの設定
502 */
503function widget_setting() {
504    const widgets = document.querySelectorAll(".js-dmo-widget");
505    if (widgets.length > 0) {
506        const template_widget = document.getElementById("template-widget");
507        const template_modal = document.getElementById("template-modal");
508        widgets.forEach((widget, index) => {
509            const widget_id = index + 1;
510            widget.dataset.widget_id = widget_id;
511            const template_widget_clone = template_widget.content.cloneNode(true);
512            const search_button = template_widget_clone.querySelector("input[type='button'][name='search-button']");
513            search_button.addEventListener("click", search);
514
515            // 出発空港の項目設定
516            const departure_airport = template_widget_clone.querySelector("select[name='departure-airport']");
517            if (departure_airport) {
518                if (DMO_AIRPORTGROUP) {
519                    const airport_select_document = document.createDocumentFragment();
520                    let is_default_value = false; // 同じ空港がある場合に最初の項目を選択状態にするため
521                    DMO_AIRPORTGROUP.forEach((data) => {
522                        const optgroup = document.createElement("optgroup");
523                        optgroup.setAttribute("label", data.group_name);
524                        Object.keys(data.airport_list).forEach((air_code) => {
525                            const option = document.createElement("option");
526                            option.setAttribute("value", air_code);
527                            option.innerHTML = data.airport_list[air_code];
528                            if (!is_default_value && air_code === DMO_DEFAULT_DEPARTURE_AIRPORT_VALUE) {
529                                option.setAttribute("selected", "true");
530                                is_default_value = true;
531                            }
532                            optgroup.appendChild(option);
533                        })
534                        airport_select_document.appendChild(optgroup);
535                    })
536                    departure_airport.appendChild(airport_select_document);
537                }
538            }
539
540            // 出発日の設定
541            let departureDate = dayjs(); // 出発日
542            const departureDatePicker = template_widget_clone.querySelector("input[class='date-picker'][name='departure']");
543            if (departureDatePicker) {
544                const date = dayjs();
545                const minDate = dayjs(date).add(5, "day").format("YYYY-MM-DD"); // min: 5日後から選択可能
546                const minDays = (DMO_DEPARTURE_DATE_DAYS >= 5) ? DMO_DEPARTURE_DATE_DAYS : 5;
547                departureDate = dayjs(date).add(minDays, "day");
548                const defaultDate = departureDate.format("YYYY-MM-DD");
549                setFlatpickr(departureDatePicker, minDate, null, defaultDate);
550            }
551
552            // 帰着日の設定
553            const arrivalDatePicker = template_widget_clone.querySelector("input[class='date-picker'][name='arrival']");
554            if (arrivalDatePicker) {
555                const arrivalMinDate = dayjs(departureDate).add(1, "day"); // min: 出発日の翌日
556                let maxTravelDays = (DMO_MAX_TRAVEL_DAYS > 1) ? DMO_MAX_TRAVEL_DAYS : 14; // 最大旅行日数(デフォルトは14日間)
557                maxTravelDays -= 2; // 出発日と到着日を除く
558                const arrivalMaxDate = dayjs(arrivalMinDate).add(maxTravelDays, "day").format("YYYY-MM-DD"); // max: 出発日と帰着日を含めた日数
559                let numberOfStays = (DMO_DEFAULT_NUMBER_OF_STAYS > 0) ? DMO_DEFAULT_NUMBER_OF_STAYS : 1;
560                if (maxTravelDays <= DMO_DEFAULT_NUMBER_OF_STAYS) {
561                    numberOfStays = maxTravelDays - 1;
562                }
563                const arrivalValueDate = dayjs(departureDate).add(numberOfStays, "day").format("YYYY-MM-DD");
564                setFlatpickr(arrivalDatePicker, arrivalMinDate.format("YYYY-MM-DD"), arrivalMaxDate, arrivalValueDate);
565            }
566
567            // 人数の設定
568            const room_detail = template_widget_clone.querySelector("input[type='hidden'][name='room-detail']");
569            if (room_detail) {
570                room_detail.value = JSON.stringify([{"adult": DMO_DEFAULT_ONE_ROOM_NUMBER_OF_PEOPLE, "child": []}]); // 大人2人・子供0人
571                // テキスト部分の設定
572                template_widget_clone.querySelector(".count-all").innerText = DMO_DEFAULT_ONE_ROOM_NUMBER_OF_PEOPLE;
573                template_widget_clone.querySelector(".count-adult").innerText = DMO_DEFAULT_ONE_ROOM_NUMBER_OF_PEOPLE;
574            }
575
576            // モーダルオープンの設定
577            const js_modal_open = template_widget_clone.querySelector(".js-dmo-modal-open");
578            if (js_modal_open) {
579                js_modal_open.addEventListener("click", modal_open);
580            }
581
582            // モーダルクローズの設定
583            const template_modal_clone = template_modal.content.cloneNode(true);
584            const modal = template_modal_clone.querySelector(".js-dmo-modal");
585            if (modal) {
586                modal.dataset.modal_id = widget_id;
587                const js_modal_close = modal.querySelectorAll(".js-dmo-modal-close");
588                if (js_modal_close) {
589                    js_modal_close.forEach((js_modal) => {
590                        js_modal.addEventListener("click", modal_close);
591                    })
592                }
593                const js_modal_fix = modal.querySelector(".js-dmo-modal-fix");
594                if (js_modal_fix) {
595                    js_modal_fix.addEventListener("click", set_count_detail);
596                }
597            }
598
599            // モーダル内のアコーディオン組み立て
600            const accordion = template_modal_clone.querySelector(".js-dmo-accordion");
601            const template_accordion_item = document.getElementById("template-accordion-item");
602
603            // 部屋数の設定
604            const room_count = template_widget_clone.querySelector("select[name='room-count']");
605            if (room_count) {
606                room_count.addEventListener("change", change_room_count);
607            }
608
609            const room_num = room_count?.value ?? 1;
610            for (let i = 1; i <= room_num; i++) {
611                // 部屋数分
612                const accordion_item_clone = template_accordion_item.content.cloneNode(true);
613                const js_accordion_item = accordion_item_clone.querySelector(".js-dmo-accordion-item");
614                if (js_accordion_item) {
615                    js_accordion_item.dataset.accordion_id = i;
616                    const modal_heading = accordion_item_clone.querySelector(".modal-heading");
617                    if (modal_heading) {
618                        modal_heading.innerText = `お部屋${i}`;
619                    }
620                    const js_accordion_body = js_accordion_item.querySelector(".js-dmo-accordion-body");
621                    if (js_accordion_body) {
622                        if (i === 1) {
623                            // 1部屋目のアコーディオンをオープンにする
624                            js_accordion_body.classList.add("is-open");
625                            modal_heading.classList.add("is-active");
626                        }
627                        // 大人の人数
628                        const js_adult = js_accordion_body.querySelector(".js-dmo-adult");
629                        if (js_adult.querySelector(`option[value='${DMO_DEFAULT_ONE_ROOM_NUMBER_OF_PEOPLE}']`) !== null) {
630                            js_adult.value = DMO_DEFAULT_ONE_ROOM_NUMBER_OF_PEOPLE;
631                        } else {
632                            js_adult.value = "2"; // デフォルト値
633                        }
634
635                        if (js_adult) {
636                            js_adult.addEventListener("change", change_adult_count);
637                        }
638                        // 子供の人数
639                        const js_children = js_accordion_body.querySelector(".js-dmo-children");
640                        if (js_children) {
641                            js_children.addEventListener("change", change_children_count);
642                        }
643                    }
644                }
645                accordion.appendChild(accordion_item_clone);
646            }
647            set_accordion_events(accordion);
648
649            widget.appendChild(template_widget_clone);
650            widget.appendChild(template_modal_clone);
651        });
652    }
653}
654widget_setting();

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.