PageSourceSearch

https://www.kusuri-aoki.co.jp/wordpress/wp-content/plugins/izuruto…/assets/js/confirm.js?ver=1.0.0

js kusuri-aoki.co.jp collected 2026-10-02 11:13:41 UTC 6,236 bytes, 226 lines download raw bytes

1/**
2 * Contact Form 7 add confirm — front-end controller.
3 *
4 * 流れ:
5 *   step1: 確認ボタン(type=submit)→ CF7 が REST 送信(サーバ側フル検証・メールはスキップ)
6 *          → 応答 status "cscf7_confirmed" → このスクリプトが確認表示へ切替
7 *   step2: 送信ボタン → CF7 の通常送信 → "mail_sent" → 入力表示へ復帰
8 *
9 * CF7 6.x の仕様に依存している点:
10 *   - wpcf7submit / wpcf7mailsent はフォーム要素から bubbles:true で dispatch される
11 *   - 応答 status が未知の値でもフォームの data-status が custom-* になるだけで壊れない
12 *   - FormData はフォーム要素から構築される(disabled は載らない・readonly は載る)
13 */
14(() => {
15	'use strict';
16
17	const HIDE = 'wpcf7c-force-hide';
18
19	const setup = ( form ) => {
20		if ( form.cscf7 ) {
21			return;
22		}
23
24		if ( ! form.querySelector( '.wpcf7c-btn-confirm' ) ) {
25			return;
26		}
27
28		let marker = form.querySelector( 'input[name="_cscf7"]' );
29
30		if ( ! marker ) {
31			marker = document.createElement( 'input' );
32			marker.type = 'hidden';
33			marker.name = '_cscf7';
34			form.appendChild( marker );
35		}
36
37		form.cscf7 = { step: 1, marker };
38
39		// 通常の送信ボタンは確認ステップ(step2)の要素として扱う。
40		form.querySelectorAll( '.wpcf7-submit' ).forEach( ( el ) => {
41			if ( ! el.classList.contains( 'wpcf7c-btn-confirm' ) ) {
42				el.classList.add( 'wpcf7c-elm-step2' );
43			}
44		} );
45
46		form.addEventListener( 'click', ( e ) => {
47			const back = e.target.closest( '.wpcf7c-btn-back' );
48
49			if ( back && ! back.disabled ) {
50				e.preventDefault();
51				toStep1( form, true );
52			}
53		} );
54
55		show( form, 1 );
56	};
57
58	const show = ( form, step ) => {
59		form.querySelectorAll( '.wpcf7c-elm-step1' ).forEach( ( el ) => {
60			el.classList.toggle( HIDE, 1 !== step );
61		} );
62
63		form.querySelectorAll( '.wpcf7c-elm-step2' ).forEach( ( el ) => {
64			el.classList.toggle( HIDE, 2 !== step );
65		} );
66
67		form.classList.toggle( 'wpcf7c-confirming', 2 === step );
68		form.cscf7.step = step;
69		form.cscf7.marker.value = 'step' + step;
70	};
71
72	const addClone = ( el, name, value ) => {
73		const clone = document.createElement( 'input' );
74		clone.type = 'hidden';
75		clone.name = name;
76		clone.value = value;
77		clone.className = 'wpcf7c-conf-hidden';
78		el.after( clone );
79	};
80
81	/**
82	 * 入力を確認表示(編集不可)へ。
83	 * disabled にした要素は FormData に載らないため、選択値を hidden で複製して
84	 * step2 の本送信に同じ値が渡るようにする。元に戻すための状態は
85	 * data-cscf7-locked に記録する(元から readonly/disabled の要素は触らない)。
86	 */
87	const lock = ( form ) => {
88		form.querySelectorAll( 'input, textarea, select' ).forEach( ( el ) => {
89			const tag = el.tagName.toLowerCase();
90			const type = ( el.getAttribute( 'type' ) || 'text' ).toLowerCase();
91
92			if ( 'input' === tag
93				&& [ 'submit', 'button', 'hidden', 'image', 'reset' ].includes( type ) ) {
94				return;
95			}
96
97			if ( el.dataset.cscf7Locked ) {
98				return;
99			}
100
101			if ( 'textarea' === tag ) {
102				if ( ! el.readOnly ) {
103					el.dataset.cscf7Locked = 'readonly';
104					el.readOnly = true;
105				}
106				el.classList.add( 'wpcf7c-conf' );
107			} else if ( 'select' === tag ) {
108				if ( ! el.disabled ) {
109					el.dataset.cscf7Locked = 'disabled';
110					Array.from( el.selectedOptions ).forEach( ( opt ) => {
111						addClone( el, el.name, opt.value );
112					} );
113					el.disabled = true;
114				}
115				el.classList.add( 'wpcf7c-conf' );
116			} else if ( 'radio' === type || 'checkbox' === type ) {
117				if ( ! el.disabled ) {
118					el.dataset.cscf7Locked = 'disabled';
119					if ( el.checked ) {
120						addClone( el, el.name, el.value );
121					}
122					el.disabled = true;
123				}
124				el.classList.add( 'wpcf7c-conf' );
125			} else if ( 'file' === type ) {
126				el.dataset.cscf7Locked = 'file';
127				el.classList.add( HIDE );
128
129				const stand = document.createElement( 'input' );
130				stand.type = 'text';
131				stand.readOnly = true;
132				stand.disabled = true;
133				stand.className = 'wpcf7c-conf wpcf7c-conf-hidden';
134				stand.value = Array.from( el.files || [] )
135					.map( ( f ) => f.name )
136					.join( ', ' );
137				el.after( stand );
138			} else {
139				if ( ! el.readOnly ) {
140					el.dataset.cscf7Locked = 'readonly';
141					el.readOnly = true;
142				}
143				el.classList.add( 'wpcf7c-conf' );
144			}
145		} );
146	};
147
148	const unlock = ( form ) => {
149		form.querySelectorAll( '.wpcf7c-conf-hidden' ).forEach( ( el ) => {
150			el.remove();
151		} );
152
153		form.querySelectorAll( '[data-cscf7-locked]' ).forEach( ( el ) => {
154			const mode = el.dataset.cscf7Locked;
155			delete el.dataset.cscf7Locked;
156
157			el.classList.remove( 'wpcf7c-conf' );
158
159			if ( 'readonly' === mode ) {
160				el.readOnly = false;
161			} else if ( 'disabled' === mode ) {
162				el.disabled = false;
163			} else if ( 'file' === mode ) {
164				el.classList.remove( HIDE );
165			}
166		} );
167
168		// 元から readonly/disabled で locked が付かなかった要素の表示クラスを掃除。
169		form.querySelectorAll( '.wpcf7c-conf' ).forEach( ( el ) => {
170			el.classList.remove( 'wpcf7c-conf' );
171		} );
172	};
173
174	const toStep2 = ( form ) => {
175		lock( form );
176		show( form, 2 );
177		scrollToForm( form );
178	};
179
180	const toStep1 = ( form, scroll ) => {
181		unlock( form );
182		show( form, 1 );
183
184		if ( scroll ) {
185			scrollToForm( form );
186		}
187	};
188
189	const scrollToForm = ( form ) => {
190		const anchor = form.querySelector( '.wpcf7c-anchor' ) || form;
191		anchor.scrollIntoView( { behavior: 'smooth', block: 'start' } );
192	};
193
194	document.addEventListener( 'wpcf7submit', ( e ) => {
195		const form = e.target;
196
197		if ( ! form || ! form.cscf7 ) {
198			return;
199		}
200
201		if ( e.detail && 'cscf7_confirmed' === e.detail.status ) {
202			toStep2( form );
203		}
204	} );
205
206	document.addEventListener( 'wpcf7mailsent', ( e ) => {
207		const form = e.target;
208
209		if ( ! form || ! form.cscf7 ) {
210			return;
211		}
212
213		// CF7 本体がこの後 form.reset() する。表示だけ入力ステップへ戻す。
214		toStep1( form, false );
215	} );
216
217	const init = () => {
218		document.querySelectorAll( '.wpcf7 > form' ).forEach( setup );
219	};
220
221	if ( 'loading' === document.readyState ) {
222		document.addEventListener( 'DOMContentLoaded', init );
223	} else {
224		init();
225	}
226})();

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.