PageSourceSearch

https://arukumachikyoto.jp/js/suggest.js?_=tk3y6c

js arukumachikyoto.jp collected 2026-10-02 06:36:14 UTC 16,995 bytes, 495 lines download raw bytes

1var distanceMatrixService = new JNRM.OsmMatrix();
2var WALKING_VELOCITY = 1.0;
3
4// 京都付近での緯度と経度の距離比率
5var lat_lng_ratio = 912.8816392747891 / 1109.4063947762538;
6
7// 経路検索出発地・目的地の例外処理用
8var ARASHIYAMA_NAME = lang == 'en' ? 'Arashiyama' : '嵐山';
9var ARASHIYAMA_NEAR_STATIONS = '嵐山(阪急),0,嵐山(京福電気鉄道),0,嵯峨嵐山,0';
10var ARASHIYAMA_LANDMARK_CODE = 'LM00000534';  // 渡月橋
11var KIYOMIZUDERA_LANDMARK_CODE = 'LM00000001';
12var KIYOMIZUDERA_NEAR_STATIONS = '五条坂(京都市バス),8,五条坂(京阪バス),8,清水道(京都市バス),8,清水道(京阪バス),8';
13var KINKAKUJI_LANDMARK_CODE = 'LM00002093';
14var GINKAKUJI_LANDMARK_CODE = 'LM00002101';
15var GINKAKUJI_NEAR_STATIONS = '銀閣寺前(京都市バス),6,銀閣寺道(京都市バス),10';
16
17// バス事業者ID
18var CITYBUS_AGENCY_ID = 200;
19var KYOTOBUS_AGENCY_ID = 203;
20
21if (lang == 'en') {
22  var CATEGORY_NAME = { R: 'Station', B: 'Bus stop', S: 'Spot' };
23}
24else {
25  var CATEGORY_NAME = { R: '駅', B: 'バス停', S: 'スポット' };
26}
27
28// サジェスト候補のツールチップ(事業者名)を出してよい環境かどうか。
29// hover と精密ポインタを持つ環境(PC)だけ true。スマホ/タブレットは false。
30//
31// タッチ端末でツールチップを出すと、候補をタップした時点で hover がその候補に張り付き、
32// 次に別の入力欄をタップした時の合成マウスイベント列
33// (mouseout → mouseover → mousemove → mousedown → mouseup → click) の途中、
34// mouseout のところで jQuery UI Tooltip が title 属性の復帰と fadeOut を走らせて
35// DOM を書き換えてしまう。iOS Safari は「マウスイベント列の途中でページ内容が
36// 変わると残りのイベント(mousedown/mouseup/click)を送らない」ため、1 回目のタップが
37// 握り潰され、キャレットが出ない(2 回目は hover の移動が無いので通る)。
38// そもそもタッチ端末では閉じる手段が無くツールチップは機能しないので出さない。
39var AKY_HOVER_CAPABLE =
40  !window.matchMedia || window.matchMedia('(hover: hover) and (pointer: fine)').matches;
41
42// jQuery autocomplete の拡張
43$.widget("custom.catcomplete", $.ui.autocomplete, {
44  _renderMenu: function(ul, items) {
45    var that = this,
46    curr_category = '';
47    var icon_suggest_show = './img/icons/icon_suggest_show.gif';
48    var icon_suggest_hide = './img/icons/icon_suggest_hide.gif';
49    $.each(items, function(index, item) {
50      if (item.category != curr_category) {
51        var img = $('<img>')
52          .attr('src', icon_suggest_hide)
53          .data('visible', 1)
54          .click(function() {
55            var visible = $(this).data('visible') ^ 1;
56            $(this).data('visible', visible);
57            $(this).attr('src', (visible == 1) ? icon_suggest_hide : icon_suggest_show);
58            $.each(items, function(idx, i) {
59              var i2 = i.li.data('ui-autocomplete-item');
60              if (item.category == i2.category) {
61                (visible == 1) ? i.li.show() : i.li.hide();
62              }
63            });
64          });
65        var category_name = CATEGORY_NAME[item.category];
66        $('<li>')
67          .addClass('ui-autocomplete-category')
68          .append(img)
69          .append(category_name)
70          .appendTo(ul);
71        curr_category = item.category;
72      }
73
74      var li = $('<li>')
75        .append($('<a>').text(item.label))
76        .attr('title', item.companyName.join(","))
77        .data('ui-autocomplete-item', item)
78        .appendTo(ul);
79      if (AKY_HOVER_CAPABLE) {
80        li.tooltip({
81          position: {
82            my: "left+5 center",
83            at: "right center"
84          }
85        });
86      }
87      item.li = li;
88    });
89  }
90});
91
92// 出発地、目的地の候補リスト生成
93function make_od_list(word) {
94  return CITYBUS_SEARCH_MODE ? make_od_list_citybus(word) : make_od_list_all(word);
95}
96
97// 出発地、目的地の候補リスト生成(全域)
98function make_od_list_all(word) {
99  var candidate = [];
100
101  if (lang == 'en') {
102    var norm_word = normalize_word_en(word);
103
104    // 「嵐山」優先表示対応
105    if ('ARASHIYAMA'.indexOf(norm_word) != -1) {
106      candidate.push({ category: '', label: 'Arashiyama', type: 'S', yomi: 'Arashiyama', sortcls: 0, companyName: [] });
107    }
108  }
109  else {
110    var norm_word = normalize_word_ja(word);
111    var kanaOnly = norm_word.match(/[^ぁ-ん|^ー]/g) === null;
112
113    // 「嵐山」優先表示対応
114    if (!kanaOnly && ('嵐山'.indexOf(word) != -1 || '嵐山'.indexOf(norm_word) != -1)
115        || kanaOnly && ('あらしやま'.indexOf(word) != -1 || 'あらしやま'.indexOf(norm_word) != -1)) {
116      candidate.push({ category: '', label: '嵐山', type: 'S', yomi: 'あらしやま', sortcls: 0, companyName: [] });
117    }
118  }
119
120  // 駅・バス停候補
121  for (var name in Master.stationselect) {
122    var ss = Master.stationselect[name];
123    var match = 0; // 0: 不一致, 1: 前方一致, 2: 部分一致
124    if (lang == 'en') {
125      var index = ss.byname.indexOf(norm_word);
126      if (index === 0) {
127        match = 1;
128      } else if (index > 0 && norm_word.length >= 3) {
129        match = 2;
130      }
131    }
132    else {
133      if (!kanaOnly) {
134        var indexes = [
135          name.indexOf(word), name.indexOf(norm_word),
136          ss.byname.indexOf(word), ss.byname.indexOf(norm_word)
137        ];
138        if (indexes.some(i => i === 0)) {
139          match = 1;
140        } else if (indexes.some(i => i > 0)) {
141          match = 2;
142        }
143      }
144      else {
145        var index = ss.kana.indexOf(norm_word);
146        if (index === 0) {
147          match = 1;
148        } else if (index > 0 && norm_word.length >= 3) {
149          match = 2;
150        }
151      }
152    }
153    if (match) {
154      var can_r = { category: 'R', label: name, type: 'R', yomi: ss.k
154ana, sortcls: 10 + match, companyName: [] };
155      var can_b = { category: 'B', label: name, type: 'B', yomi: ss.kana, sortcls: 20 + match, companyName: [] };
156      for (var i in ss.stationnames) {
157        var stationname = ss.stationnames[i].stationname;
158        var companyid = ss.stationnames[i].companyid;
159        var sinfo = Master.station[stationname];
160        if (sinfo !== undefined) {
161          if (Master.company[companyid].ekidiv == 'R') {
162            can_r.companyName.push(Master.company[companyid].name);
163          } else {
164            can_b.companyName.push(Master.company[companyid].name);
165          }
166        }
167      }
168      if (can_r.companyName.length > 0) {
169        candidate.push(can_r);
170      }
171      if (can_b.companyName.length > 0) {
172        candidate.push(can_b);
173      }
174    }
175  }
176
177  // スポット候補
178  var category_check = {};
179  for (var i = 0; i < OD_CATEGORY_IDS.length; i++) {
180    category_check[OD_CATEGORY_IDS[i]] = true;
181  }
182  for (var code in LandmarkData.data) {
183    var lm = LandmarkData.data[code];
184    if (!(lm.category in category_check) || lm.lat == '' || lm.lng == '') {
185      continue;
186    }
187
188    var match = 0;
189    if (lang == 'en') {
190      var lmname = normalize_word_en(lm.name);
191      var index = lmname.indexOf(norm_word);
192      if (index === 0) {
193        match = 1;
194      } else if (index > 0 && norm_word.length >= 3) {
195        match = 2;
196      }
197    }
198    else {
199      if (!kanaOnly) {
200        var indexes = [
201          lm.name.indexOf(word), lm.name.indexOf(norm_word)
202        ];
203        if (indexes.some(i => i === 0)) {
204          match = 1;
205        } else if (indexes.some(i => i > 0)) {
206          match = 2;
207        }
208      }
209      else if (lm.yomi) {
210        var index = lm.yomi.indexOf(norm_word);
211        if (index === 0) {
212          match = 1;
213        } else if (index > 0 && norm_word.length >= 3) {
214          match = 2;
215        }
216      }
217    }
218    if (match) {
219      var cat = 'S';
220      var sc = 30 + match;
221      if (code == KINKAKUJI_LANDMARK_CODE || code == GINKAKUJI_LANDMARK_CODE) {
222        cat = '';
223        sc = 0;  // 金閣寺・銀閣寺を優先表示
224      }
225      candidate.push({ category: cat, label: lm.name, type: 'S,'+code, yomi: lm.yomi, sortcls: sc, companyName: [] });
226    }
227  }
228
229  candidate.sort(function(a, b) {
230    if (a.sortcls < b.sortcls) return -1;
231    if (a.sortcls > b.sortcls) return 1;
232    if (a.yomi < b.yomi) return -1;
233    if (a.yomi > b.yomi) return 1;
234    return 0;
235  });
236
237  return candidate;
238}
239
240// 出発地、目的地の候補リスト生成(市バスのみ)
241function make_od_list_citybus(word) {
242  if (lang == 'en') {
243    var norm_word = normalize_word_en(word);
244  } else {
245    var norm_word = normalize_word_ja(word);
246    var kanaOnly = word.match(/[^ぁ-ん|^ー]/g) === null;
247  }
248
249  var candidate = [];
250  for (var name in Master.stationselect) {
251    var ss = Master.stationselect[name];
252    var match = 0;
253    if (lang == 'en') {
254      var index = ss.byname.indexOf(norm_word);
255      if (index === 0) {
256        match = 1;
257      } else if (index > 0 && norm_word.length >= 3) {
258        match = 2;
259      }
260    } else {
261      if (!kanaOnly) {
262        var indexes = [
263          name.indexOf(word), name.indexOf(norm_word),
264          ss.byname.indexOf(word), ss.byname.indexOf(norm_word)
265        ];
266        if (indexes.some(i => i === 0)) {
267          match = 1;
268        } else if (indexes.some(i => i > 0)) {
269          match = 2;
270        }
271      } else {
272        var index = ss.kana.indexOf(norm_word);
273        if (index === 0) {
274          match = 1;
275        } else if (index > 0 && norm_word.length >= 3) {
276          match = 2;
277        }
278      }
279    }
280    if (match) {
281      var can = { category: '', label: name, type: 'B', yomi: ss.kana, sortcls: match, companyName: [] };
282      for (var i = 0; i < ss.stationnames.length; i++) {
283        var stationname = ss.stationnames[i].stationname;
284        var companyid = ss.stationnames[i].companyid;
285        var sinfo = Master.station[stationname];
286        if (sinfo !== undefined) {
287          if (companyid == CITYBUS_AGENCY_ID) {
288            can.companyName.push(Master.company[companyid].name);
289          }
290        }
291      }
292      if (can.companyName.length > 0) {
293        candidate.push(can);
294      }
295    }
296  }
297
298  candidate.sort(function(a, b) {
299    if (a.sortcls < b.sortcls) return -1;
300    if (a.sortcls > b.sortcls) return 1;
301    if (a.yomi < b.yomi) return -1;
302    if (a.yomi > b.yomi) return 1;
303    return 0;
304  });
305
306  return candidate;
307}
308
309
310
311
312// 出発地・目的地の最寄駅・バス停候補リスト生成
313function search_near_stations(lonLat, name, type, ranking, callback) {
314/*
315  return CITYBUS_SEARCH_MODE
316    ? search_near_stations_citybus(latlng, name, ranking, callback)
317    : search_near_stations_all(latlng, name, type, ranking, callback);
318*/
319  return search_near_stations_all(lonLat, name, type, ranking, callback);
320}
321
322// 出発地・目的地の最寄駅・バス停候補リスト生成(全域)
323function search_near_stations_all(lonLat, name, type, ranking, callback) {
324  var rMin = {len: Number.MAX_VALUE, name: '', lat: 0, lng: 0, ekidiv: 'R', extra: 1};
325  outer:
326  for (var stationname in Master.station) {
327    var sinfo = Master.station[stationname];
328    for (var j = 0; j < ranking.length; j++) {
329      if (stationname == ranking[j].name) {
330        ranking[j].lat = sinfo.lat;
331        ranking[j].lng = sinfo.lng;
332        ranking[j].ekidiv = sinfo.ekidiv;
333        ranking[j].extra = 0;
334        continue outer;
335      }
336    }
337    len = (lonLat[1] - sinfo.lat) * (lonLat[1] - sinfo.lat)
338        + (lonLat[0] - sinfo.lng) * (lonLat[0] - sinfo.lng) * lat_lng_ratio * lat_lng_ratio;
339    for (var j = 0; j < ranking.length; j++) {
340      if (ranking[j].name == '' || ranking[j].len > len) {
341        for (var k = ranking.length-1; k > j; k--) {
342          ranking[k].len = ranking[k-1].len;
343          ranking[k].name = ranking[k-1].name;
344          ranking[k].lat = ranking[k-1].lat;
345          ranking[k].lng = ranking[k-1].lng;
346          ranking[k].ekidiv = ranking[k-1].ekidiv;
347          ranking[k].extra = ranking[k-1].extra;
348        }
349        ranking[j].name = stationname;
350        ranking[j].lat = sinfo.lat;
351        ranking[j].lng = sinfo.lng;
352        ranking[j].len = len;
353        ranking[j].ekidiv = sinfo.ekidiv;
354        ranking[j].extra = 0;
355        break;
356      }
357    }
358    if (sinfo.ekidiv == 'R' && rMin.len > len) {
359      rMin.len = len;
360      rMin.name = stationname;
361      rMin.lat = sinfo.lat;
362      rMin.lng = sinfo.lng;
363      rMin.ekidiv = 'R';
364      rMin.extra = 1;
365    }
366  }
367  var ekiFlag = false;
368  for (var j = 0; j < ranking.length; j++) {
369    if (ranking[j].ekidiv == 'R') {
370      ekiFlag = true;
371    }
372  }
373  if (!ekiFlag) {
374    ranking[ranking.length] = rMin;
375  }
376  origins = [ lonLat ];
377  destinations = [];
378  for (var i = 0; i < ranking.length; i++) {
379    if (name == Master.station[ranking[i].name].selectname && type == ranking[i].ekidiv
380        || ranking[i].len == 0) {
381      ranking[i].destination = false;
382    }
383    else {
384      ranking[i].destination = true;
385      destinations.push([ranking[i].lng, ranking[i].lat]);
386    }
387  }
388  if (destinations.length == 0) {
389    var return_value = '';
390    for (var i = 0; i < ranking.length; i++) {
391      return_value += encodeURI(ranking[i].name) + ',0,';
392    }
393    if (return_value != '') {
394      return_value = return_value.slice(0, -1);
395    }
396    callback(return_value);
397  }
398  distanceMatrixService.getDistanceMatrixWalk({
399    origins: origins,
400    destinations: destinations,
401  },
402  function (results, status) {
403    if (status == JNRM.OsmMatrixStatus.OK) {
404      var return_value = '';
405      var idx = 0;
406      distances = results[0]
407      for (var i = 0; i < ranking.length; i++) {
408        if (ranking[i].destination && distances[idx] !== undefined) {
409          walking_time = Math.ceil(distances[idx]/WALKING_VELOCITY/60);
410          idx++;
411        } else {
412          walking_time = 0;
413        }
414        if (ranking[i].extra == 0 || walking_time <= 10) {
415          return_value += encodeURI(ranking[i].name) + ',' + walking_time+',';
416        }
417      }
418      if (return_value != '') {
419        return_value = return_value.slice(0, -1);
420      }
421      callback(return_value);
422    }
423  });
424}
425
426// 出発地・目的地の最寄駅・バス停候補リスト生成(市バスのみ検索)
427function search_near_stations_citybus(lonLat, name, ranking, callback) {
428
429  for (var stationname in Master.station) {
430    var sinfo = Master.station[stationname];
431    if (!sinfo.isCityBus) continue;
432
433    len = (lonLat[1] - sinfo.lat) * (lonLat[1] - sinfo.lat)
434        + (lonLat[0] - sinfo.lng) * (lonLat[0] - sinfo.lng) * lat_lng_ratio * lat_lng_ratio;
435    for (var j = 0; j < ranking.length; j++) {
436      if (ranking[j].name == '' || ranking[j].len > len) {
437        for (var k = ranking.length-1; k > j; k--) {
438          ranking[k].len = ranking[k-1].len;
439          ranking[k].name = ranking[k-1].name;
440          ranking[k].lat = ranking[k-1].lat;
441          ranking[k].lng = ranking[k-1].lng;
442        }
443        ranking[j].name = stationname;
444        ranking[j].lat = sinfo.lat;
445        ranking[j].lng = sinfo.lng;
446        ranking[j].len = len;
447        break;
448      }
449    }
450  }
451  origins = [ lonLat ];
452  destinations = [];
453  for (var i = 0; i < ranking.length; i++) {
454    if (name == Master.station[ranking[i].name].selectname || ranking[i].len == 0) {
455      ranking[i].destination = false;
456    }
457    else {
458      ranking[i].destination = true;
459      destinations.push([ranking[i].lng, ranking[i].lat]);
460    }
461  }
462  if (destinations.length == 0) {
463    var return_value = '';
464    for (var i = 0; i < ranking.length; i++) {
465      return_value += encodeURI(ranking[i].name) + ',0,';
466    }
467    if (return_value != '') {
468      return_value = return_value.slice(0, -1);
469    }
470    callback(return_value);
471  }
472  distanceMatrixService.getDistanceMatrixWalk({
473    origins: origins,
474    destinations: destinations,
475  },
476  function (results, status) {
477    if (status == JNRM.OsmMatrixStatus.OK) {
478      var return_value = '';
479      var idx = 0;
480      for (var i = 0; i < ranking.length; i++) {
481        if (ranking[i].destination && results[idx] !== undefined) {
482          walking_time = Math.ceil(results[idx]/WALKING_VELOCITY/60);
483          idx++;
484        } else {
485          walking_time = 0;
486        }
487        return_value += encodeURI(ranking[i].name) + ',' + walking_time+',';
488      }
489      if (return_value != '') {
490        return_value = return_value.slice(0, -1);
491      }
492      callback(return_value);
493    }
494  });
495}

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.