PageSourceSearch

https://bizforce-neo.com/wp-content/themes/cocoon-child-master/assets/jp-company-finder2.js

js bizforce-neo.com collected 2026-10-04 20:35:14 UTC 9,750 bytes, 282 lines download raw bytes

1/* jp-station-finder.allinone.js
2 * 都道府県 → 路線 → 駅 → 遷移(WordPress等)の一括版。
3 * ・#pref-list2 に既存の <dl><dd>…</dd></dl> があればそれを使用(上書きしない)
4 * ・無ければ API から都道府県を取得し、地域別の <dl> を生成
5 * ・路線/駅は HeartRails Express API を使用
6 * ・駅クリック時の遷移は buildStationURL() を必要に応じて編集
7 */
8
9(function(){
10	'use strict' ;
11
12	;// ===== 設定 =====
13	const API = {
14		//prefectures: 'https://geoapi.heartrails.com/api/json?method=getPrefectures',
15		lines: 'https://express.heartrails.com/api/json?method=getLines',
16		stations: 'https://express.heartrails.com/api/json?method=getStations'
17	} ;
18
19	// 遷移先URLの組み立て;;
20	let buildStationURL = ({stationName, lineName, prefecture})=>{
21		const base = '/media/company/' ;
22		// 「駅」は送らない(検索キーは駅なし)
23		const station = String(stationName || '').replace(/駅$/u, '') ;
24		const params = new URLSearchParams() ;
25		if(prefecture) params.set('pref', prefecture) ;
26		if(lineName) params.set('line', lineName) ;
27		if(station) params.set('station', station) ;
28		const qs = params.toString() ;
29		return `${base}?${qs}` ;
30	} ;
31
32	;// ===== 要素 =====
33	const els = {
34		prefList: document.querySelector('#pref-list2'),
35		lineList: document.querySelector('#line-list'),
36		stationList: document.querySelector('#station-list'),
37		prefSelected: document.querySelector('#pref-selected'),
38		lineSelected: document.querySelector('#line-selected')
39	} ;
40
41	;// ===== 状態 =====
42	const state = {
43		selectedPref: '',
44		selectedLine: ''
45	} ;
46
47	;// ===== 地域グループ(DL生成用) =====
48	const REGION_GROUPS = {
49		'北海道・東北': ['北海道','青森県','岩手県','宮城県','秋田県','山形県','福島県'],
50		'関東': ['茨城県','栃木県','群馬県','埼玉県','千葉県','東京都','神奈川県'],
51		'甲信越': ['新潟県','山梨県','長野県'],
52		'北陸': ['富山県','石川県','福井県'],
53		'東海': ['岐阜県','静岡県','愛知県','三重県'],
54		'関西': ['滋賀県','京都府','大阪府','兵庫県','奈良県','和歌山県'],
55		'中国': ['鳥取県','島根県','岡山県','広島県','山口県'],
56		'四国': ['徳島県','香川県','愛媛県','高知県'],
57		'九州・沖縄': ['福岡県','佐賀県','長崎県','熊本県','大分県','宮崎県','鹿児島県','沖縄県']
58	} ;
59
60	;// ===== 共通 =====
61	async function fetchJSON(url){
62		const res = await fetch(url, {cache: 'no-store'}) ;
63		if(!res.ok) throw new Error('Network error ' + res.status) ;
64		return res.json() ;
65	}
66
67	function escapeHTML(s){
68		return String(s)
69			.replace(/&/g,'&amp;')
70			.replace(/</g,'&lt;')
71			.replace(/>/g,'&gt;')
72			.replace(/"/g,'&quot;')
73			.replace(/'/g,'&#39;') ;
74	}
75
76	;// ===== API =====
77	async function loadPrefectures(){
78		const data = await fetchJSON(API.prefectures) ;
79		const list = Array.isArray(data?.response?.prefecture) ? data.response.prefecture : [] ;
80		return list ;
81	}
82
83	async function loadLines(prefName){
84		const data = await fetchJSON(`${API.lines}&prefecture=${encodeURIComponent(prefName)}`) ;
85		const list = Array.isArray(data?.response?.line) ? data.response.line : [] ;
86		return list ;
87	}
88
89	async function loadStations(lineName, prefName){
90		const data = await fetchJSON(`${API.stations}&line=${encodeURIComponent(lineName)}&prefecture=${encodeURIComponent(prefName)}`) ;
91		const list = Array.isArray(data?.response?.station) ? data.response.station : [] ;
92		return list ;
93	}
94
95	;// ===== 県DL描画(API時のみ使用) =====
96	function renderPrefDLFromAPI(prefList){
97		if(!els.prefList) return ;
98		els.prefList.innerHTML = '' ;
99		const ok = new Set(prefList) ;
100		for(const [region, prefs] of Object.entries(REGION_GROUPS)){
101			const shown = prefs.filter(p=>ok.has(p)) ;
102			if(shown.length===0) continue ;
103			const dl = document.createElement('dl') ;
104			const dt = document.createElement('dt') ;
105			dt.textContent = region ;
106			dl.appendChild(dt) ;
107			shown.forEach(name=>{
108				const dd = document.createElement('dd') ;
109				dd.textContent = name ;
110				dl.appendChild(dd) ;
111			}) ;
112			els.prefList.appendChild(dl) ;
113		}
114	}
115
116	;// ===== 路線/駅の描画 =====
117	function renderLineList(lines){
118		if(!els.lineList) return ;
119		const target = els.lineList.querySelector('.ov') || els.lineList;
120		target.innerHTML = ''; // 以前のリストをクリア
121		const ul = document.createElement('ul');
122		lines.forEach(name=>{
123			const li = document.createElement('li');
124			li.innerHTML = `<button type="button" data-value="${escapeHTML(name)}">${escapeHTML(name)}</button>`;
125			ul.appendChild(li);
126		});
127		target.appendChild(ul);
128	}
129
130	function renderStationList(stations){
131		if(!els.stationList) return ;
132		const target = els.stationList.querySelector('.ov') || els.stationList;
133		target.innerHTML = '';
134		const ul = document.createElement('ul');
135		stations.forEach(st=>{
136			const li = document.createElement('li');
137			li.innerHTML = `<button type="button" data-station="${escapeHTML(st.name)}" data-line="${escapeHTML(st.line)}" data-pref="${escapeHTML(st.prefecture)}">${escapeHTML(st.name)}</button>`;
138			ul.appendChild(li);
139		});
140		target.appendChild(ul);
141	}
142
143	;// ===== 選択処理 =====
144	async function selectPref(pref){
145		state.selectedPref = pref ;
146		if(els.prefSelected) els.prefSelected.textContent = pref ;
147		if(els.lineSelected) els.lineSelected.textContent = '' ;
148		state.selectedLine = '' ;
149		const lineTarget = els.lineList?.querySelector('.ov') || els.lineList ;
150		if(lineTarget) lineTarget.textContent = '読み込み中…' ;
151		const stTarget = els.stationList?.querySelector('.ov') || els.stationList ;
152		if(stTarget) stTarget.textContent = '' ;
153		const lines = await loadLines(pref) ;
154		renderLineList(lines) ;
155	}
156
157	async function selectLine(line){
158		state.selectedLine = line ;
159		if(els.lineSelected) els.lineSelected.textContent = line ;
160		const stTarget = els.stationList?.querySelector('.ov') || els.stationList ;
161		if(stTarget) stTarget.textContent = '読み込み中…' ;
162		const stations = await loadStations(line, state.selectedPref) ;
163		renderStationList(stations) ;
164	}
165
166	function navigateToStation(btn){
167		const stationName = btn.getAttribute('data-station') ;
168		const lineName = btn.getAttribute('data-line') ;
169		const prefecture = btn.getAttribute('data-pref') ;
170		const url = buildStationURL({stationName, lineName, prefecture}) ;
171		window.location.href = url ;
172	}
173
174	;// ===== 既存DLの活用 =====
175	function enhanceExistingPrefHTML(){
176		if(!els.prefList) return false ;
177		const hasDL = !!els.prefList.querySelector('dl') ;
178		if(!hasDL) return false ;
179		els.prefList.addEventListener('click', e=>{
180			const dd = e.target.closest('dd') ;
181			if(!dd) return ;
182			selectPref(dd.textContent.trim()) ;
183		}) ;
184		return true ;
185	}
186
187	;// ===== 初期化 =====
188	document.addEventListener('DOMContentLoaded', async ()=>{
189		if(!els.prefList){ console.warn('#pref-list2 が見つかりません') ; return ; }
190
191		// 1) 既存DLがあればそれを使う(APIで上書きしない)
192		const usingExisting = enhanceExistingPrefHTML() ;
193
194		// 2) 無ければAPIから県一覧を取得してDL生成
195		if(!usingExisting){
196			els.prefList.textContent = '読み込み中…' ;
197			try{
198				const prefList = await loadPrefectures() ;
199				renderPrefDLFromAPI(prefList) ;
200			}catch(err){
201				console.error(err) ;
202				els.prefList.textContent = '都道府県の取得に失敗しました。' ;
203			}
204			// API生成DLにもクリックを付与
205			enhanceExistingPrefHTML() ;
206		}
207
208		// 路線クリック
209		if(els.lineList){
210			els.lineList.addEventListener('click', e=>{
211				const btn = e.target.closest('button[data-value]') ;
212				if(!btn) return ;
213				selectLine(btn.getAttribute('data-value')) ;
214			}) ;
215		}
216
217		// 駅クリック
218		if(els.stationList){
219			els.stationList.addEventListener('click', e=>{
220				const btn = e.target.closest('button[data-station]') ;
221				if(!btn) return ;
222				navigateToStation(btn) ;
223			}) ;
224		}
225	}) ;
226})() ;
227
228// UI
229$(function(){
230	const $step1 = $('#search3 .step1');
231	const $step2 = $('#search3 .step2');
232	const $step3 = $('#search3 .step3');
233	$('#search3 dl dd').on('click', function(){
234		$step1.slideUp(500, 'swing');
235		checkAndSlideDown();
236	});
237	const observer = new MutationObserver(function(){
238		checkAndSlideDown();
239	});
240	observer.observe($step2[0], { childList: true, subtree: true });
241	function checkAndSlideDown(){
242		const dlCount = $step2.find('ul').length;
243		if(dlCount >= 1 && !$step2.is(':visible')){
244			$step2.slideDown(500, 'swing');
245		}
246	}
247	
248	$step2.on('click', 'button', function(e){
249		e.preventDefault() ;
250		console.log('ad') ;
251		$step2.stop(true, true).slideUp(500, 'swing') ;
252		if(typeof checkAndSlideDown2==='function') checkAndSlideDown2() ;
253	}) ;
254	const observer2 = new MutationObserver(function(){
255		checkAndSlideDown2();
256	});
257	observer2.observe($step3[0], { childList: true, subtree: true });
258	function checkAndSlideDown2(){
259		const dlCount2 = $step3.find('ul').length;
260		if(dlCount2 >= 1 && !$step3.is(':visible')){
261			$step3.slideDown(500, 'swing');
262		}
263	}
264
265	$('#search3 .step2 .back').on('click', function(){
266		$('#search3 .step1').slideDown(500, 'swing');
267		$('#search3 .step2').slideUp(500, 'swing', function(){
268			$('#search3 .step2 ul').remove();
269		});
270	});
271	$('#search3 .step3 .back').on('click', function(){
272		$('#search3 .step2').slideDown(500, 'swing');
273		$('#search3 .step3').slideUp(500, 'swing', function(){
274			$('#search3 .step3 ul').remove();
275		});
276	});
277	$('#search3 dl dd, #search3 .step2 .back').click(function() {
278		var speed = 500;
279		var position = $('#search3').offset().top - 70 - 60 - 20;
280		$('body,html').animate({scrollTop:position}, 500, 'swing');
281	});
282});

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.