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,'&') 70 .replace(/</g,'<') 71 .replace(/>/g,'>') 72 .replace(/"/g,'"') 73 .replace(/'/g,''') ; 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.