PageSourceSearch

https://arukumachikyoto.jp/js/map_search_input.js?_=tl6mep

js arukumachikyoto.jp collected 2026-10-02 06:36:29 UTC 15,302 bytes, 452 lines download raw bytes

1/* ============================================================================
2   地図から調べる(map.php) — 入力/マーカー操作
3   ----------------------------------------------------------------------------
4   ベクトル地図(MapLibre GL JS / jnrm.maplibre.js)版。
5   ・地図上クリック or 住所/駅名/ランドマークから出発地・目的地マーカーを配置
6   ・MapLibre は lng/lat を直接扱うため、旧 ol.proj.fromLonLat/toLonLat は不要
7   ・ジオコーダ(geocoder.js)・近傍駅(common系)・日時セレクト・検索URL生成は流用
8   ============================================================================ */
9var CITYBUS_SEARCH_MODE = false;
10
11var distanceMatrixService = new JNRM.OsmMatrix();
12var walkingVelocity = 1.0;
13var OSM = null;
14var startMarker = null, endMarker = null;
15var startPlaced = false, endPlaced = false;   // マーカーが地図に配置済みか
16var kyotoBounds = {   /* 配置可否の粗判定。京都府全域をカバー(実サービス範囲判定は checkKyotoCity=京都府) */
17  minLng: 134.7,
18  minLat: 34.6,
19  maxLng: 136.1,
20  maxLat: 35.85
21};
22var geocoder = new JNRGEO.Geocoder();
23
24var fn = '', tn = '', fs = '', ts = '', wt = '';  // 検索条件
25var originMode = true;  // true:出発地設定中, false:到着地設定中
26
27if (lang == 'en') {
28  var MARKER_DEPARTURE = './img/en/map/marker_departure.png';
29  var MARKER_ARRIVAL = './img/en/map/marker_arrival.png';
30  var BUTTON_SEARCH = './img/en/buttons/btn_search_map.png';
31  var BUTTON_SEARCH_GRAY = './img/en/buttons/btn_search_map_gray.png';
32  var TEXT_DEPARTURE = 'Departure';
33  var TEXT_ARRIVAL = 'Arrival';
34  var ADDR_KYOTO_CITY = '京都市'; //'Kyoto';
35  var ADDR_KYOTO_PREF = '京都府'; //'Kyoto Prefecture';
36  var ADDR_JAPAN = '日本'; //'Japan';
37  var MESSAGE_TITLE = 'Input Error';
38  var MESSAGE1 = 'Please accurately enter point of departure and arrival. See <a href="./static.php?page=guide&lang=en#setting_area">this page</a> for available departure and destination setting coverage."';
39  var MESSAGE2 = 'Point of departure or arrival not entered.';
40  var MESSAGE3 = 'Please accurately enter point of departure.';
41  var MESSAGE4 = 'Please accurately enter point of arrival.';
42}
43else {
44  var MARKER_DEPARTURE = './img/ja/map/marker_departure.png';
45  var MARKER_ARRIVAL = './img/ja/map/marker_arrival.png';
46  var BUTTON_SEARCH = './img/ja/buttons/btn_search_map.png';
47  var BUTTON_SEARCH_GRAY = './img/ja/buttons/btn_search_map_gray.png';
48  var TEXT_DEPARTURE = '出発地';
49  var TEXT_ARRIVAL = '目的地';
50  var ADDR_KYOTO_CITY = '京都市';
51  var ADDR_KYOTO_PREF = '京都府';
52  var ADDR_JAPAN = '日本';
53  var MESSAGE_TITLE = '入力エラー';
54  var MESSAGE1 = '出発地・目的地を正しく入力してください。本システムで出発地・目的値として設定可能な範囲は<a href="./static.php?page=guide&lang=ja#setting_area">こちら</a>をご覧ください。';
55  var MESSAGE2 = '出発地と目的地を設定して下さい。';
56  var MESSAGE3 = '出発地を正しく入力して下さい。';
57  var MESSAGE4 = '目的地を正しく入力してください。';
58}
59
60// 出発地/目的地マーカー(画像ピン・ドラッグ可)を生成する
61function makePin(isDeparture) {
62  var img = document.createElement('img');
63  img.src = isDeparture ? MARKER_DEPARTURE : MARKER_ARRIVAL;
64  img.className = 'jnrm-pin';
65  img.alt = isDeparture ? TEXT_DEPARTURE : TEXT_ARRIVAL;
66  img.draggable = false;
67  var m = new maplibregl.Marker({ element: img, anchor: 'bottom', draggable: true });
68  return m;
69}
70
71$(function() {
72  // 地図生成(MapLibre ベクトル)
73  // ★初期ズーム★ 既定(14)ではなく 12 で開く。ベクタタイルはソースの maxzoom が 14 で、
74  // z14 タイルには建物形状が全部入っている(1枚 652KB のうち building が 520KB)。
75  // 画面いっぱいに 9 枚取ると 4.5MB になり、初期表示が目に見えて遅い。
76  // z12 なら同じ 9 枚でも 851KB で済む。
77  OSM = new JNRM.OpenStreetMap("map", { zoom: 12 });
78
79  // マーカー(出発地/目的地)生成。配置されるまで地図には追加しない
80  startMarker = makePin(true);
81  endMarker = makePin(false);
82
83  // ドラッグ移動したら駅/バス停/スポット名指定を無効化(座標優先)
84  startMarker.on('dragend', function() { fn = ''; });
85  endMarker.on('dragend', function() { tn = ''; });
86
87  // 地図クリックでマーカーを配置(出発地→目的地の順)
88  OSM.map.on('click', function(evt) {
89    var ll = [evt.lngLat.lng, evt.lngLat.lat];
90    if (!startPlaced) {
91      startMarker.setLngLat(ll).addTo(OSM.map);
92      startPlaced = true;
93      fn = '';
94      toggleOd();
95    } else if (!endPlaced) {
96      endMarker.setLngLat(ll).addTo(OSM.map);
97      endPlaced = true;
98      tn = '';
99      toggleOd();
100    }
101  });
102
103  search_btn();
104
105  // サジェストを有効にする
106  $('#text4').catcomplete({
107    source: function(request, response) { response(make_od_list(request.term)); },
108    search: function(event, ui) { $('text4_selected_type').val(''); },
109    select: function(event, ui) { $('text4_selected_type').val(ui.item.category); }
110  });
111
112  // 事業者のツールチップ
113  $(document).tooltip({
114    position: {
115      my: "left+5 center",
116      at: "right center"
117    }
118  });
119
120  // 日時選択の選択項目を生成
121  SetupDateSelect('#month', '#day', '#date_sav');
122  SetupHourSelect('#hour', '#hour_sav');
123  SetupMinuteSelect('#minute', '#minute_sav');
124
125  // 現在時刻設定
126  $('#set_currtime').click(function() {
127    $('#date_sav, #hour_sav, #minute_sav').val('');
128    SetupDateSelect('#month', '#day', '#date_sav');
129    SetupHourSelect('#hour', '#hour_sav');
130    SetupMinuteSelect('#minute', '#minute_sav');
131  });
132
133  // パラメタで指定された検索条件をセットする
134  var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
135  var args = new Array();
136  for (var i = 0; i < hashes.length; i++) {
137    hash = hashes[i].split('=');
138    args[hash[0]] = decodeURIComponent(hash[1]);
139  }
140
141  if (args['fn'] && args['fn'] != '') {
142    setPosition(args['fn']);
143  } else if (args['fl']){
144    var latlng = args['fl'].split(',');
145    var lat = parseFloat(latlng[0]);
146    var lng = parseFloat(latlng[1]);
147    startMarker.setLngLat([lng, lat]).addTo(OSM.map);
148    startPlaced = true;
149    fn = '';
150  }
151  if (args['tn'] && args['tn'] != '') {
152    setPosition(args['tn']);
153  } else if (args['tl']){
154    var latlng = args['tl'].split(',');
155    var lat = parseFloat(latlng[0]);
156    var lng = parseFloat(latlng[1]);
157    endMarker.setLngLat([lng, lat]).addTo(OSM.map);
158    endPlaced = true;
159    tn = '';
160  }
161  if (args['dt']) {
162    days = args['dt'].split('/');
163    $('#month').val(days[0] + "_" + days[1]);
164    $('#day').val(days[2]);
165  }
166  if (args['tm']) {
167    times = args['tm'].split(':');
168    $('#hour').val(times[0]);
169    $('#minute').val(times[1]);
170  }
171  if (args['tt']) {
172    switch (args['tt']) {
173    case 'd':
174      $('#date1').prop('checked', 'checked');
175      break;
176    case 'a':
177      $('#date2').prop('checked', 'checked');
178      break;
179    case 'f':
180      $('#date3').prop('checked', 'checked');
181      break;
182    case 'l':
183      $('#date4').prop('checked', 'checked');
184      break;
185    }
186  }
187  // タブ内や非表示状態から表示された場合に備えてサイズ再計算
188  OSM.map.on('load', function() { OSM.map.resize(); search_btn(); });
189});
190
191// リセットボタンが押された時
192function markerReset() {
193  startMarker.remove();
194  endMarker.remove();
195  startPlaced = false;
196  endPlaced = false;
197  originMode = false;
198  toggleOd();
199}
200
201// 検索ボタンの gray-out
202function search_btn() {
203  if (startPlaced && endPlaced) {
204    $('#btn_search').attr('src', BUTTON_SEARCH);
205  } else {
206    $('#btn_search').attr('src', BUTTON_SEARCH_GRAY);
207  }
208}
209
210function setPosition(position_name) {
211  if (position_name == '') {
212    ShowMessage(MESSAGE1, MESSAGE_TITLE);
213    return;
214  }
215
216  // 「嵐山」の例外処理
217  if (position_name == ARASHIYAMA_NAME) {
218    var arashiyama_landmark = LandmarkData.data[ARASHIYAMA_LANDMARK_CODE];
219    if (arashiyama_landmark != null) {
220      setMarker([arashiyama_landmark.lng, arashiyama_landmark.lat], position_name);
221      return;
222    }
223  }
224
225  // 駅・バス停名
226  var ss = Master.stationselect[position_name];
227  if (ss !== undefined) {
228    var lat = 0.0, lng = 0.0, count = 0;
229    for (var i = 0; i < ss.stationnames.length; i++) {
230      var sn = ss.stationnames[i].stationname;
231      var sinfo = Master.station[sn];
232      if (sinfo !== undefined) {
233        lat -= -sinfo.lat;
234        lng -= -sinfo.lng;
235        count++;
236      }
237    }
238    if (count > 0) {
239      setMarker([lng / count, lat / count], position_name);
240      return;
241    }
242  }
243
244  // ランドマーク名
245  for (var code in LandmarkData.data) {
246    var lm = LandmarkData.data[code];
247    if (lm.name == position_name && lm.lat > 0 && lm.lng > 0) {
248      setMarker([lm.lng, lm.lat], position_name);
249      return;
250    }
251  }
252
253  // 住所
254  geocoder.geocode({
255    'address': position_name,
256  },
257  function(results, status) {
258    if (status == JNRGEO.Status.OK) {
259      var lng = parseFloat(results.longitude);
260      var lat = parseFloat(results.latitude);
261      if (kyotoBounds.minLat <= lat && lat <= kyotoBounds.maxLat
262        && kyotoBounds.minLng <= lng && lng <= kyotoBounds.maxLng) {
263        setMarker([lng, lat], position_name);
264        return;
265      }
266    }
267    ShowMessage(MESSAGE1, MESSAGE_TITLE);
268  });
269}
270
271function toggleOd() {
272  if (originMode) {
273    $('#od_label').text(TEXT_ARRIVAL).addClass('arr_label').removeClass('dep_label');
274  } else {
275    $('#od_label').text(TEXT_DEPARTURE).addClass('dep_label').removeClass('arr_label');
276  }
277  $('#text4').val('').change();
278  originMode = !originMode;
279  search_btn();
280}
281
282// lngLat = [lng, lat]
283function setMarker(lngLat, name) {
284  if (originMode) {
285    fn = name;
286    startMarker.setLngLat(lngLat).addTo(OSM.map);
287    startPlaced = true;
288  } else {
289    tn = name;
290    endMarker.setLngLat(lngLat).addTo(OSM.map);
291    endPlaced = true;
292  }
293  OSM.map.easeTo({ center: lngLat });
294  toggleOd();
295}
296
297// 緯度経度が京都市内かを判定する。lonLat = [lng, lat]
298function checkKyotoCity(lonLat, callback) {
299  var address = '';
300
301  geocoder.revGeocode({
302    'latitude': lonLat[1],
303    'longitude': lonLat[0]
304  },
305  function(results, status) {
306    if (status == JNRGEO.Status.OK ) {
307      var pref = results.Address.pref;
308      var city = results.Address.city;
309      var section = results.Address.section;
310      var banchi = results.Address.banchi;
311      var registry = results.Address.registry;
312      if (pref == ADDR_KYOTO_PREF){   /* 京都府内ならOK(旧: 京都市内限定 city.indexOf(京都市)==0 を府全域へ緩和) */
313        address = city
314                + (section ? " " + section  : "")
315                + (banchi  ? " " + banchi   : "")
316                + (registry? "-" + registry : "");
317        callback(address);
318        return;
319      }
320    }
321
322    ShowMessage(MESSAGE1, MESSAGE_TITLE);
323  });
324}
325
326function get_near_stations(name, lonLat, callback) {
327  var kiyomizudera_landmark = null;
328  if (LandmarkData.data[KIYOMIZUDERA_LANDMARK_CODE] !== undefined) {
329    kiyomizudera_landmark = LandmarkData.data[KIYOMIZUDERA_LANDMARK_CODE];
330  }
331  var ginkakuji_landmark = null;
332  if (LandmarkData.data[GINKAKUJI_LANDMARK_CODE] !== undefined) {
333    ginkakuji_landmark = LandmarkData.data[GINKAKUJI_LANDMARK_CODE];
334  }
335
336  if (name == ARASHIYAMA_NAME) {
337    callback(ARASHIYAMA_NEAR_STATIONS, '');
338    return;
339  } else if (kiyomizudera_landmark != null && name == kiyomizudera_landmark.name) {
340    var loc = kiyomizudera_landmark.lat + ',' + kiyomizudera_landmark.lng;
341    callback(KIYOMIZUDERA_NEAR_STATIONS, loc);
342    return;
343  } else if (ginkakuji_landmark != null && name == ginkakuji_landmark.name) {
344    var loc = ginkakuji_landmark.lat + ',' + ginkakuji_landmark.lng;
345    callback(GINKAKUJI_NEAR_STATIONS, loc);
346    return;
347  }
348
349  var ranking = [];
350  for (var i = 0; i < Master.coefficient['SEARCH_NEAR_SPOTS_NUMBER']; i++) {
351    ranking[i] = {len:0, name: ''};
352  }
353
354  search_near_stations(lonLat, '', 'S', ranking, function(near_stations) {
355    var loc = lonLat[1] + ',' + lonLat[0];
356    callback(near_stations, loc);
357  });
358}
359
360function search_submit() {
361  if (!startPlaced || !endPlaced) {
362    ShowMessage(MESSAGE2, MESSAGE_TITLE);
363    return;
364  }
365
366  var lonLat = startMarker.getLngLat().toArray();  // [lng, lat]
367  checkKyotoCity(lonLat, function(address) {
368    if (fn == '') {
369      fn = address;
370    }
371    search_submit2();
372  });
373}
374
375function search_submit2() {
376  var lonLat = endMarker.getLngLat().toArray();
377  checkKyotoCity(lonLat, function(address) {
378    if (tn == '') {
379      tn = address;
380    }
381    search_submit3();
382  });
383}
384
385function search_submit3() {
386  var lonLat = startMarker.getLngLat().toArray();
387  get_near_stations(fn, lonLat, function(near_stations, loc) {
388    fs = near_stations;
389    fl = loc;
390    if (fs == '') {
391      ShowMessage(MESSAGE3, MESSAGE_TITLE);
392      return;
393    }
394    search_submit4();
395  });
396}
397
398function search_submit4() {
399  var lonLat = endMarker.getLngLat().toArray();
400  get_near_stations(tn, lonLat, function(near_stations, loc) {
401    ts = near_stations;
402    tl = loc;
403    if (ts == '') {
404      ShowMessage(MESSAGE4, MESSAGE_TITLE);
405      return;
406    }
407    search_submit5();
408  });
409}
410
411function search_submit5() {
412  var originLonLat = startMarker.getLngLat().toArray();
413  var destinationLonlat = endMarker.getLngLat().toArray();
414  wt = 0;
415  distanceMatrixService.getDistanceMatrixWalk({
416    origins: [originLonLat],
417    destinations: [destinationLonlat],
418  },
419  function (results, status) {
420    if (status == JNRM.OsmMatrixStatus.OK) {
421      for (var i = 0; i < results.length; i++) {
422        wt -= -Math.ceil(results[i]/walkingVelocity/60);
423      }
424      search_submit6();
425    }
426  });
427}
428
429function search_submit6() {
430  var pn = '';
431  var month = $('#month').val().replace(/_/g,'/');
432  var dt = month + '/' + $('#day').val();
433  var tm = $('#hour').val() + ':' + $('#minute').val();
434  var tt = $('input[name="search_type"]:checked').val();
435  var de = 'n';   // バス到着予測は廃止。パラメタは互換のため残すが常に 'n'
436  var md = 'm';
437
438  url = './search_result.php?fn=' + encodeURI(fn) + '&tn=' + encodeURI(tn) + '&dt=' + dt + '&tm=' + tm + '&fs=' + fs;
439  url = url + '&ts=' + ts + '&fl=' + fl + '&tl=' + tl + '&de=' + de + '&tt=' + tt + '&md=' + md + '&pn=' + encodeURI(pn) + '&wt=' + wt + '&lang=' + lang + '&fi=L&ti=L';
440
441  $('#searching_message').dialog({
442    modal: true,
443    autoOpen: true,
444    dialogClass: 'ui-dialog-notitle',
445    width: 300,
446    height: 100
447  });
448
449  setTimeout(function() {
450    document.location.href = url;
451  }, 0);
452}

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.