PageSourceSearch

https://dna-am.co.jp/wp-content/themes/dna_am_new/assets/js/form.js?ver=1791079725

js dna-am.co.jp collected 2026-10-04 02:09:19 UTC 19,948 bytes, 554 lines download raw bytes

1// =============
2// お問い合わせフォーム動的処理
3// =============
4
5// フォームの初期化
6const setInitOption = (selectElement) => {
7    const options = [
8        { textContent: "選択してください", value: "選択してください" },
9        { textContent: "指定しない", value: "指定しない" },
10    ];
11    options.forEach((optionInfo) => {
12        const option = document.createElement("option");
13        option.textContent = optionInfo.textContent;
14        option.value = optionInfo.value;
15        selectElement.appendChild(option);
16    });
17};
18
19// Contactフォーム都道府県絞り込み機能
20const input_data = {
21    area: "",
22    pref: "",
23    clinic: "",
24    month01: "",
25    day01: "",
26    date01: "",
27    client: "",
28    email: "",
29    tel: "",
30    content: "",
31    privacy: false,
32};
33
34const getElement = (id, selector) => {
35    const root = document.getElementById(id);
36    return root ? root.querySelector(selector) : null;
37};
38
39// TOPお問い合わせ(CF7): 送信ボタンは input または button
40const getTopSubmitControl = () => {
41    const wrap = document.getElementById("submit_button");
42    if (!wrap) return null;
43    return wrap.querySelector('input[type="submit"], button[type="submit"]');
44};
45
46// 要素の取得(#tel がラベル側と重複していても、先頭の .form_item_input#tel は電話番号行)
47const areaSelect = getElement("area_select", "select");
48const prefSelect = getElement("prefecture_select", "select");
49const clinicSelect = getElement("clinic_select", "select");
50const client = getElement("client", "input");
51const email = getElement("email", "input");
52const tel = getElement("tel", "input");
53const content = getElement("content", "textarea");
54const privacy = getElement("privacycheck", 'input[type="checkbox"]') || getElement("privacycheck", "input");
55const form = getElement("mw_wp_form_mw-wp-form-6156", "form");
56const submitButton = getTopSubmitControl();
57const getDateSelect = (id, index) => {
58    const wrapper = document.getElementById(id);
59    if (!wrapper) return null;
60    const selects = wrapper.querySelectorAll("select");
61    return selects[index] || null;
62};
63// ご希望の日時01: 従来どおり #date01 内の select* month01 / day01(2つ)でも、
64// [date* date01] の input[type=date] でもどちらでも動くように分岐する
65const date01Wrapper = document.getElementById("date01");
66const date01NativeInput = date01Wrapper
67    ? date01Wrapper.querySelector('input[type="date"]')
68    : null;
69const usesNativeDate01 = !!date01NativeInput;
70const month01 = usesNativeDate01 ? null : getDateSelect("date01", 0);
71const day01 = usesNativeDate01 ? null : getDateSelect("date01", 1);
72const validation_msg = document.getElementById("validation_msg");
73
74const validation_check = (input_data) => {
75    const requiredFields = ["area", "pref", "client", "email", "tel"];
76
77    const isFieldEmpty = (field) =>
78        input_data[field] === "" || input_data[field] === "選択してください";
79
80    const dateIncomplete = usesNativeDate01
81        ? !input_data["date01"] || String(input_data["date01"]).trim() === ""
82        : isFieldEmpty("month01") || isFieldEmpty("day01");
83
84    const isInvalid =
85        requiredFields.some((field) => isFieldEmpty(field)) ||
86        dateIncomplete ||
87        input_data["privacy"] === false;
88
89    if (!submitButton || !validation_msg) {
90        return;
91    }
92
93    if (isInvalid) {
94        submitButton.classList.remove("enable");
95        submitButton.setAttribute("disabled", true);
96        validation_msg.innerHTML = `
97    <p>
98      【ご確認ください】<br />
99      <span class="validation_star">*</span>項目の入力が完了していないため送信できません。
100    </p>
101  `;
102    } else {
103        submitButton.classList.add("enable");
104        submitButton.removeAttribute("disabled");
105        validation_msg.innerHTML = "";
106    }
107};
108
109// DOMの現在値を input_data に反映(CF7描画後・ブラウザ自動入力・日付[type=date]対応)
110const syncTopFormStateFromDom = () => {
111    if (!document.getElementById("submit_button")) {
112        return;
113    }
114    if (areaSelect) input_data.area = areaSelect.value || "";
115    if (prefSelect) {
116        input_data.pref = translate_enjp(prefSelect.value || "");
117    }
118    if (clinicSelect) input_data.clinic = clinicSelect.value || "";
119    if (client) input_data.client = client.value || "";
120    if (email) input_data.email = email.value || "";
121    if (tel) input_data.tel = tel.value || "";
122    if (content) input_data.content = content.value || "";
123    if (privacy) input_data.privacy = !!privacy.checked;
124    if (month01) input_data.month01 = month01.value || "";
125    if (day01) input_data.day01 = day01.value || "";
126    if (date01NativeInput) input_data.date01 = date01NativeInput.value || "";
127    validation_check(input_data);
128};
129
130if (submitButton) {
131    submitButton.setAttribute("disabled", true);
132}
133
134if (document.readyState === "loading") {
135    document.addEventListener("DOMContentLoaded", syncTopFormStateFromDom);
136} else {
137    syncTopFormStateFromDom();
138}
139// CF7 の DOM 生成が遅れる場合の再同期
140setTimeout(syncTopFormStateFromDom, 0);
141setTimeout(syncTopFormStateFromDom, 300);
142
143// input hiddenのvalue更新(都道府県)
144let inputValuePref = {};
145const updateInputValuePref = (area_pref) => {
146    inputValuePref = {
147        ...inputValuePref,
148        "__children[prefecture][]": JSON.stringify(
149            area_pref.reduce((acc, val) => {
150                acc[val] = val;
151                return acc;
152            }, {})
153        ),
154    };
155
156    const inputElement = document.querySelector("input[name='__children[prefecture][]']");
157    if (inputElement) {
158        inputElement.value = JSON.stringify(inputValuePref["__children[prefecture][]"]);
159    }
160};
161
162// input hiddenのvalue更新(クリニック)
163let inputValueHospital = {};
164const updateInputValueHospital = (area_pref) => {
165    inputValueHospital = {
166        ...inputValueHospital,
167        "__children[hospital][]": JSON.stringify(
168            area_pref.reduce((acc, val) => {
169                acc[val] = val;
170                return acc;
171            }, {})
172        ),
173    };
174
175    const inputElement = document.querySelector("input[name='__children[hospital][]']");
176    if (inputElement) {
177        inputElement.value = JSON.stringify(inputValueHospital["__children[hospital][]"]);
178    }
179};
180
181const translate_enjp = (name) => {
182    if (name === "" || name === null || name === undefined || name === "選択してください") {
183        return "";
184    }
185    const translations = {
186        "北海道・東北": "hokkaido-tohoku",
187        関東: "kanto",
188        中部: "chubu",
189        "近畿・関西": "kinki-kansai",
190        "中国・四国": "chugoku-shikoku",
191        "九州・沖縄": "kyusyu-okinawa",
192        北海道: "hokkaido",
193        青森: "aomori",
194        岩手: "iwate",
195        宮城: "miyagi",
196        秋田: "akita",
197        山形: "yamagata",
198        福島: "fukushima",
199        茨城: "ibaraki",
200        栃木: "tochigi",
201        群馬: "gunma",
202        埼玉: "saitama",
203        千葉: "chiba",
204        東京: "tokyo",
205        神奈川: "kanagawa",
206        新潟: "niigata",
207        富山: "toyama",
208        石川: "ishikawa",
209        福井: "fukui",
210        山梨: "yamanashi",
211        長野: "nagano",
212        岐阜: "gifu",
213        静岡: "shizuoka",
214        愛知: "aichi",
215        三重: "mie",
216        滋賀: "shiga",
217        京都: "kyoto",
218        大阪: "osaka",
219        兵庫: "hyogo",
220        奈良: "nara",
221        和歌山: "wakayama",
222        鳥取: "tottori",
223        å³¶æ ¹: "shimane",
224        岡山: "okayama",
225        広島: "hiroshima",
226        山口: "yamaguchi",
227        徳島: "tokushima",
228        香川: "kagawa",
229        愛媛: "ehime",
230        高知: "kochi",
231        福岡: "fukuoka",
232        佐賀: "saga",
233        長崎: "nagasaki",
234        熊本: "kumamoto",
235        大分: "oita",
236        宮崎: "miyazaki",
237        鹿児島: "kagoshima",
238        沖縄: "okinawa",
239    };
240
241    // 日本語から英語への変換
242    if (translations[name]) {
243        return translations[name];
244    }
245
246    // 英語から日本語への変換
247    const reverseTranslations = Object.fromEntries(
248        Object.entries(translations).map(([jp, en]) => [en, jp])
249    );
250
251    if (reverseTranslations[name]) {
252        return reverseTranslations[name];
253    }
254
255    // 一致しない場合
256    return "unknown";
257};
258
259if (areaSelect && prefSelect) {
260    areaSelect.addEventListener("change", (e) => {
261        e.preventDefault();
262        input_data["area"] = e.target.value;
263        validation_check(input_data);
264
265        // 初期化処理
266        prefSelect.innerHTML = "";
267        setInitOption(prefSelect);
268        if (clinicSelect) {
269            clinicSelect.innerHTML = "";
270            setInitOption(clinicSelect);
271        } else {
272            input_data["clinic"] = "";
273            updateInputValueHospital([]);
274        }
275        let area_pref = [];
276
277        // pref_clinic_openが定義されているか確認
278        if (typeof pref_clinic_open === 'undefined' || !Array.isArray(pref_clinic_open)) {
279            return;
280        }
281
282        // pref_listが定義されているか確認
283        if (typeof pref_list === 'undefined') {
284            return;
285        }
286
287        // フォームに常に表示する都道府県(本番で非公開の医院がある都道府県)
288        const alwaysShowPrefs = ['miyagi', 'fukushima', 'gunma', 'toyama', 'kyoto', 'saga', 'nagasaki', 'kumamoto', 'miyazaki'];
289
290        // クリニックがある都道府県のみ追加
291        switch (e.target.value) {
292            case "北海道・東北":
293            case "関東":
294            case "中部":
295            case "近畿・関西":
296            case "中国・四国":
297            case "九州・沖縄":
298                const areaKey = translate_enjp(e.target.value);
299                const selectedArea = pref_list[areaKey];
300                
301                if (selectedArea && Array.isArray(selectedArea)) {
302                    selectedArea.forEach((el) => {
303                        // pref_clinic_openに含まれているか、常に表示する都道府県リストに含まれている場合は追加
304                        if (pref_clinic_open.includes(el) || alwaysShowPrefs.includes(el)) {
305                            area_pref.push(el);
306                        }
307                    });
308                }
309                break;
310        }
311
312        // option value
313        area_pref.forEach((val) => {
314            const option = document.createElement("option");
315            option.textContent = translate_enjp(val);
316            option.value = translate_enjp(val);
317            prefSelect.appendChild(option);
318        });
319
320        updateInputValuePref(area_pref);
321    });
322}
323
324// 都道府県セレクトボックスをトリガーにクリニックセレクトボックスを非同期更新
325if (prefSelect) {
326    prefSelect.addEventListener("change", (e) => {
327        e.preventDefault();
328        input_data["pref"] = translate_enjp(e.target.value);
329        validation_check(input_data);
330
331        // クリニックセレクトがない場合はここで終了
332        if (!clinicSelect) {
333            input_data["clinic"] = "";
334            updateInputValueHospital([]);
335            return;
336        }
337
338        // partner_postsが定義されているか確認
339        if (typeof partner_posts === 'undefined' || !Array.isArray(partner_posts)) {
340            return;
341        }
342
343        let clinicArr = [];
344        partner_posts.forEach((post) => {
345            // 都道府県が一致するか確認(英語コードで比較)
346            if (post.prefecture == input_data["pref"]) {
347                clinicArr.push(post.title);
348            }
349        });
350
351        // 初期化
352        // 「選択してください」、「指定しない」をセット
353        clinicSelect.innerHTML = "";
354        setInitOption(clinicSelect);
355
356        // 仮名順にソート
357        clinicArr.sort(function (a, b) {
358            return a.localeCompare(b, "ja");
359        });
360
361        clinicArr.forEach((val) => {
362            const option = document.createElement("option");
363            option.textContent = val;
364            option.value = val;
365            clinicSelect.appendChild(option);
366        });
367
368        updateInputValueHospital(clinicArr);
369    });
370}
371
372const addChangeListener = (element, property) => {
373    if (!element) return;
374
375    element.addEventListener("change", (e) => {
376        e.preventDefault();
377        input_data[property] = element.type === "checkbox" ? e.target.checked : e.target.value;
378        validation_check(input_data);
379    });
380};
381
382addChangeListener(clinicSelect, "clinic");
383addChangeListener(month01, "month01");
384addChangeListener(day01, "day01");
385if (date01NativeInput) {
386    ["change", "input"].forEach((evt) => {
387        date01NativeInput.addEventListener(evt, (e) => {
388            input_data["date01"] = e.target.value || "";
389            validation_check(input_data);
390        });
391    });
392}
393addChangeListener(client, "client");
394addChangeListener(email, "email");
395addChangeListener(tel, "tel");
396addChangeListener(content, "content");
397addChangeListener(privacy, "privacy");
398
399// URLパラメータからフォームを自動選択する機能
400(function() {
401    function initAutoFill() {
402        
403        // URLSearchParamsのサポート確認
404        if (typeof URLSearchParams === 'undefined') {
405            return;
406        }
407        
408        // URLパラメータを取得(クエリ文字列とハッシュフラグメントの両方をチェック)
409        let urlParams = new URLSearchParams(window.location.search);
410        let area = urlParams.get('area');
411        let prefecture = urlParams.get('prefecture');
412        let clinic = urlParams.get('clinic');
413        
414        // ハッシュフラグメント内にパラメータがある場合もチェック
415        if ((!area && !prefecture && !clinic) && window.location.hash.includes('?')) {
416            const hashParams = new URLSearchParams(window.location.hash.split('?')[1]);
417            area = area || hashParams.get('area');
418            prefecture = prefecture || hashParams.get('prefecture');
419            clinic = clinic || hashParams.get('clinic');
420        }
421        
422        
423        if (!area && !prefecture && !clinic) {
424            return;
425        }
426        
427        function getFormElements() {
428            try {
429                const areaSelect = document.getElementById('area_select');
430                const prefSelect = document.getElementById('prefecture_select');
431                const clinicSelect = document.getElementById('clinic_select');
432                
433                // 要素が存在するかチェック
434                if (!areaSelect || !prefSelect) {
435                    return { areaSelect: null, prefSelect: null, clinicSelect: null };
436                }
437                
438                return {
439                    areaSelect: areaSelect,
440                    prefSelect: prefSelect,
441                    clinicSelect: clinicSelect
442                };
443            } catch (e) {
444                return { areaSelect: null, prefSelect: null, clinicSelect: null };
445            }
446        }
447        
448        let attempts = 0;
449        const maxAttempts = 50;
450        
451        function tryAutoFill() {
452            attempts++;
453            const { areaSelect, prefSelect, clinicSelect } = getFormElements();
454            
455            if (areaSelect && prefSelect) {
456                performAutoFill(areaSelect, prefSelect, clinicSelect, area, prefecture, clinic);
457            } else if (attempts < maxAttempts) {
458                setTimeout(tryAutoFill, 300);
459            }
460        }
461        
462        function performAutoFill(areaSelect, prefSelect, clinicSelect, area, prefecture, clinic) {
463            if (area && areaSelect) {
464                const selectElement = areaSelect.querySelector('select');
465                if (selectElement) {
466                    for (let option of selectElement.options) {
467                        if (option.textContent.includes(area)) {
468                            option.selected = true;
469                            selectElement.dispatchEvent(new Event('change'));
470                            
471                            setTimeout(function() {
472                                if (prefecture && prefSelect) {
473                                    const prefSelectElement = prefSelect.querySelector('select');
474                                    if (prefSelectElement) {
475                                        for (let option of prefSelectElement.options) {
476                                            if (option.textContent.includes(prefecture)) {
477                                                option.selected = true;
478                                                prefSelectElement.dispatchEvent(new Event('change'));
479                                                
480                                                if (clinic && clinicSelect) {
481                                                    setTimeout(function() {
482                                                        const clinicSelectElement = clinicSelect.querySelector('select');
483                                                        if (clinicSelectElement) {
484                                                            for (let option of clinicSelectElement.options) {
485                                                                if (option.textContent.includes(clinic)) {
486                                                                    option.selected = true;
487                                                                    break;
488                                                                }
489                                                            }
490                                                        }
491                                                    }, 200);
492                                                }
493                                                break;
494                                            }
495                                        }
496                                    }
497                                }
498                            }, 250);
499                            break;
500                        }
501                    }
502                }
503            }
504        }
505        
506        tryAutoFill();
507    }
508    
509    // 既存のJavaScriptエラーを回避するために遅延実行
510    setTimeout(function() {
511        initAutoFill();
512    }, 2000);
513    
514    // 複数のイベントで実行を試行
515    document.addEventListener('DOMContentLoaded', function() {
516        setTimeout(initAutoFill, 1000);
517    });
518    
519    window.addEventListener('load', function() {
520        setTimeout(initAutoFill, 500);
521    });
522})();
523
524// TOPのCF7フォーム: 日付入力欄のどこを押してもカレンダーを開く
525(function () {
526    const el = document.getElementById("mw_wp_form_mw-wp-form-6156");
527    const formRoot =
528        el && el.tagName === "FORM" ? el : el ? el.querySelector("form") : null;
529    if (!formRoot) return;
530
531    const dateInputs = formRoot.querySelectorAll('input[type="date"]');
532    if (!dateInputs.length) return;
533
534    const openDatePicker = (input) => {
535        if (!input || input.disabled || input.readOnly) return;
536
537        // Chrome系は showPicker が使える
538        if (typeof input.showPicker === "function") {
539            try {
540                input.showPicker();
541                return;
542            } catch (e) {
543                // showPicker 非対応ブラウザ向けに focus へフォールバック
544            }
545        }
546
547        input.focus();
548    };
549
550    dateInputs.forEach((input) => {
551        input.addEventListener("click", () => openDatePicker(input));
552        input.addEventListener("touchstart", () => openDatePicker(input), { passive: true });
553    });
554})();

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.