PageSourceSearch

https://www.tapmarche.jp/contents/js/suggest.js?var=release_20260622

js tapmarche.jp collected 2026-10-05 04:03:50 UTC 12,600 bytes, 489 lines download raw bytes

1/*
2--------------------------------------------------------
3suggest.js - Input Suggest
4Version 2.3.1 (Update 2013/02/11)
5Copyright (c) 2006-2013 onozaty (http://www.enjoyxstudy.com)
6Released under an MIT-style license.
7For details, see the web site:
8 http://www.enjoyxstudy.com/javascript/suggest/
9--------------------------------------------------------
10*/
11
12if (!Suggest) {
13  var Suggest = {};
14}
15/*-- KeyCodes -----------------------------------------*/
16Suggest.Key = {
17  TAB:     9,
18  RETURN: 13,
19  ESC:    27,
20  UP:     38,
21  DOWN:   40
22};
23
24/*-- Utils --------------------------------------------*/
25Suggest.copyProperties = function(dest, src) {
26  for (var property in src) {
27    dest[property] = src[property];
28  }
29  return dest;
30};
31
32/*-- Suggest.Local ------------------------------------*/
33Suggest.Local = function() {
34  this.initialize.apply(this, arguments);
35};
36Suggest.Local.prototype = {
37  initialize: function(input, suggestArea, candidateList) {
38
39    this.input = this._getElement(input);
40    this.suggestArea = this._getElement(suggestArea);
41    this.candidateList = candidateList;
42    this.oldText = this.getInputText();
43
44    if (arguments[3]) this.setOptions(arguments[3]);
45
46    // reg event
47    this._addEvent(this.input, 'focus', this._bind(this.checkLoop));
48    this._addEvent(this.input, 'blur', this._bind(this.inputBlur));
49    this._addEvent(this.suggestArea, 'blur', this._bind(this.inputBlur));
50
51    this._addEvent(this.input, 'keydown', this._bindEvent(this.keyEvent));
52
53    // init
54    this.clearSuggestArea();
55  },
56
57  // options
58  interval: 500,
59  dispMax: 20,
60  listTagName: 'div',
61  prefix: false,
62  ignoreCase: true,
63  highlight: false,
64  dispAllKey: false,
65  classMouseOver: 'over',
66  classSelect: 'select',
67  hookBeforeSearch: function(){},
68
69  setOptions: function(options) {
70    Suggest.copyProperties(this, options);
71  },
72
73  inputBlur: function() {
74
75    setTimeout(this._bind(function(){
76
77      if (document.activeElement == this.suggestArea
78          || document.activeElement == this.input) {
79        // keep suggestion
80        return;
81      }
82
83      this.changeUnactive();
84      this.oldText = this.getInputText();
85
86      if (this.timerId) clearTimeout(this.timerId);
87      this.timerId = null;
88
89      setTimeout(this._bind(this.clearSuggestArea), 500);
90    }, 500));
91  },
92
93  checkLoop: function() {
94    var text = this.getInputText();
95    if (text != this.oldText) {
96      this.oldText = text;
97      this.search();
98    }
99    if (this.timerId) clearTimeout(this.timerId);
100    this.timerId = setTimeout(this._bind(this.checkLoop), this.interval);
101  },
102
103  search: function() {
104
105    // init
106    this.clearSuggestArea();
107
108    var text = this.getInputText();
109
110    if (text == '' || text == null) return;
111
112    this.hookBeforeSearch(text);
113    var resultList = this._search(text);
114    if (resultList.length != 0) this.createSuggestArea(resultList);
115  },
116
117  _search: function(text) {
118
119    var resultList = [];
120    var temp; 
121    this.suggestIndexList = [];
122
123    for (var i = 0, length = this.candidateList.length; i < length; i++) {
124      if ((temp = this.isMatch(this.candidateList[i], text)) != null) {
125        resultList.push(temp);
126        this.suggestIndexList.push(i);
127
128        if (this.dispMax != 0 && resultList.length >= this.dispMax) break;
129      }
130    }
131    return resultList;
132  },
133
134  isMatch: function(value, pattern) {
135
136    if (value == null) return null;
137
138    var pos = (this.ignoreCase) ?
139      value.toLowerCase().indexOf(pattern.toLowerCase())
140      : value.indexOf(pattern);
141
142    if ((pos == -1) || (this.prefix && pos != 0)) return null;
143
144    if (this.highlight) {
145      return (this._escapeHTML(value.substr(0, pos)) + '<strong>' 
146             + this._escapeHTML(value.substr(pos, pattern.length)) 
147               + '</strong>' + this._escapeHTML(value.substr(pos + pattern.length)));
148    } else {
149      return this._escapeHTML(value);
150    }
151  },
152
153  clearSuggestArea: function() {
154    this.suggestArea.innerHTML = '';
155    this.suggestArea.style.display = 'none';
156    this.suggestList = null;
157    this.suggestIndexList = null;
158    this.activePosition = null;
159  },
160
161  createSuggestArea: function(resultList) {
162
163    this.suggestList = [];
164    this.inputValueBackup = this.input.value;
165
166    for (var i = 0, length = resultList.length; i < length; i++) {
167      var element = document.createElement(this.listTagName);
168      element.innerHTML = resultList[i];
169      this.suggestArea.appendChild(element);
170
171      this._addEvent(element, 'click', this._bindEvent(this.listClick, i));
172      this._addEvent(element, 'mouseover', this._bindEvent(this.listMouseOver, i));
173      this._addEvent(element, 'mouseout', this._bindEvent(this.listMouseOut, i));
174
175      this.suggestList.push(element);
176    }
177
178    this.suggestArea.style.display = '';
179    this.suggestArea.scrollTop = 0;
180  },
181
182  getInputText: function() {
183    return this.input.value;
184  },
185
186  setInputText: function(text) {
187    this.input.value = text;
188  },
189
190  // key event
191  keyEvent: function(event) {
192
193    if (!this.timerId) {
194      this.timerId = setTimeout(this._bind(this.checkLoop), this.interval);
195    }
196
197    if (this.dispAllKey && event.ctrlKey 
198        && this.getInputText() == ''
199        && !this.suggestList
200        && event.keyCode == Suggest.Key.DOWN) {
201      // dispAll
202      this._stopEvent(event);
203      this.keyEventDispAll();
204    } else if (event.keyCode == Suggest.Key.UP ||
205               event.keyCode == Suggest.Key.DOWN) {
206      // key move
207      if (this.suggestList && this.suggestList.length != 0) {
208        this._stopEvent(event);
209        this.keyEventMove(event.keyCode);
210      }
211    } else if (event.keyCode == Suggest.Key.RETURN) {
212      // fix
213      if (this.suggestList && this.suggestList.length != 0) {
214        this._stopEvent(event);
215        this.keyEventReturn();
216      }
217    } else if (event.keyCode == Suggest.Key.ESC) {
218      // cancel
219      if (this.suggestList && this.suggestList.length != 0) {
220        this._stopEvent(event);
221        this.keyEventEsc();
222      }
223    } else {
224      this.keyEventOther(event);
225    }
226  },
227
228  keyEventDispAll: function() {
229
230    // init
231    this.clearSuggestArea();
232
233    this.oldText = this.getInputText();
234
235    this.suggestIndexList = [];
236    for (var i = 0, length = this.candidateList.length; i < length; i++) {
237      this.suggestIndexList.push(i);
238    }
239
240    this.createSuggestArea(this.candidateList);
241  },
242
243  keyEventMove: function(keyCode) {
244
245    this.changeUnactive();
246
247    if (keyCode == Suggest.Key.UP) {
248      // up
249      if (this.activePosition == null) {
250        this.activePosition = this.suggestList.length -1;
251      }else{
252        this.activePosition--;
253        if (this.activePosition < 0) {
254          this.activePosition = null;
255          this.input.value = this.inputValueBackup;
256          this.suggestArea.scrollTop = 0;
257          return;
258        }
259      }
260    }else{
261      // down
262      if (this.activePosition == null) {
263        this.activePosition = 0;
264      }else{
265        this.activePosition++;
266      }
267
268      if (this.activePosition >= this.suggestList.length) {
269        this.activePosition = null;
270        this.input.value = this.inputValueBackup;
271        this.suggestArea.scrollTop = 0;
272        return;
273      }
274    }
275
276    this.changeActive(this.activePosition);
277  },
278
279  keyEventReturn: function() {
280
281    this.clearSuggestArea();
282    this.moveEnd();
283  },
284
285  keyEventEsc: function() {
286
287    this.clearSuggestArea();
288    this.input.value = this.inputValueBackup;
289    this.oldText = this.getInputText();
290
291    if (window.opera) setTimeout(this._bind(this.moveEnd), 5);
292  },
293
294  keyEventOther: function(event) {},
295
296  changeActive: function(index) {
297
298    this.setStyleActive(this.suggestList[index]);
299
300    this.setInputText(this.candidateList[this.suggestIndexList[index]]);
301
302    this.oldText = this.getInputText();
303    this.input.focus();
304  },
305
306  changeUnactive: function() {
307
308    if (this.suggestList != null 
309        && this.suggestList.length > 0
310        && this.activePosition != null) {
311      this.setStyleUnactive(this.suggestList[this.activePosition]);
312    }
313  },
314
315  listClick: function(event, index) {
316
317    this.changeUnactive();
318    this.activePosition = index;
319    this.changeActive(index);
320
321    this.clearSuggestArea();
322    this.moveEnd();
323  },
324
325  listMouseOver: function(event, index) {
326    this.setStyleMouseOver(this._getEventElement(event));
327  },
328
329  listMouseOut: function(event, index) {
330
331    if (!this.suggestList) return;
332
333    var element = this._getEventElement(event);
334
335    if (index == this.activePosition) {
336      this.setStyleActive(element);
337    }else{
338      this.setStyleUnactive(element);
339    }
340  },
341
342  setStyleActive: function(element) {
343    element.className = this.classSelect;
344
345    // auto scroll
346    var offset = element.offsetTop;
347    var offsetWithHeight = offset + element.clientHeight;
348
349    if (this.suggestArea.scrollTop > offset) {
350      this.suggestArea.scrollTop = offset
351    } else if (this.suggestArea.scrollTop + this.suggestArea.clientHeight < offsetWithHeight) {
352      this.suggestArea.scrollTop = offsetWithHeight - this.suggestArea.clientHeight;
353    }
354  },
355
356  setStyleUnactive: function(element) {
357    element.className = '';
358  },
359
360  setStyleMouseOver: function(element) {
361    element.className = this.classMouseOver;
362  },
363
364  moveEnd: function() {
365
366    if (this.input.createTextRange) {
367      this.input.focus(); // Opera
368      var range = this.input.createTextRange();
369      range.move('character', this.input.value.length);
370      range.select();
371    } else if (this.input.setSelectionRange) {
372      this.input.setSelectionRange(this.input.value.length, this.input.value.length);
373    }
374  },
375
376  // Utils
377  _getElement: function(element) {
378    return (typeof element == 'string') ? document.getElementById(element) : element;
379  },
380  _addEvent: (window.addEventListener ?
381    function(element, type, func) {
382      element.addEventListener(type, func, false);
383    } :
384    function(element, type, func) {
385      element.attachEvent('on' + type, func);
386    }),
387  _stopEvent: function(event) {
388    if (event.preventDefault) {
389      event.preventDefault();
390      event.stopPropagation();
391    } else {
392      event.returnValue = false;
393      event.cancelBubble = true;
394    }
395  },
396  _getEventElement: function(event) {
397    return event.target || event.srcElement;
398  },
399  _bind: function(func) {
400    var self = this;
401    var args = Array.prototype.slice.call(arguments, 1);
402    return function(){ func.apply(self, args); };
403  },
404  _bindEvent: function(func) {
405    var self = this;
406    var args = Array.prototype.slice.call(arguments, 1);
407    return function(event){ event = event || window.event; func.apply(self, [event].concat(args)); };
408  },
409  _escapeHTML: function(value) {
410    return value.replace(/\&/g, '&amp;').replace( /</g, '&lt;').replace(/>/g, '&gt;')
411             .replace(/\"/g, '&quot;').replace(/\'/g, '&#39;');
412  }
413};
414
415/*-- Suggest.LocalMulti ---------------------------------*/
416Suggest.LocalMulti = function() {
417  this.initialize.apply(this, arguments);
418};
419Suggest.copyProperties(Suggest.LocalMulti.prototype, Suggest.Local.prototype);
420
421Suggest.LocalMulti.prototype.delim = ' '; // delimiter
422
423Suggest.LocalMulti.prototype.keyEventReturn = function() {
424
425  this.clearSuggestArea();
426  this.input.value += this.delim;
427  this.moveEnd();
428};
429
430Suggest.LocalMulti.prototype.keyEventOther = function(event) {
431
432  if (event.keyCode == Suggest.Key.TAB) {
433    // fix
434    if (this.suggestList && this.suggestList.length != 0) {
435      this._stopEvent(event);
436
437      if (!this.activePosition) {
438        this.activePosition = 0;
439        this.changeActive(this.activePosition);
440      }
441
442      this.clearSuggestArea();
443      this.input.value += this.delim;
444      if (window.opera) {
445        setTimeout(this._bind(this.moveEnd), 5);
446      } else {
447        this.moveEnd();
448      }
449    }
450  }
451};
452
453Suggest.LocalMulti.prototype.listClick = function(event, index) {
454
455  this.changeUnactive();
456  this.activePosition = index;
457  this.changeActive(index);
458
459  this.input.value += this.delim;
460
461  this.clearSuggestArea();
462  this.moveEnd();
463};
464
465Suggest.LocalMulti.prototype.getInputText = function() {
466
467  var pos = this.getLastTokenPos();
468
469  if (pos == -1) {
470    return this.input.value;
471  } else {
472    return this.input.value.substr(pos + 1);
473  }
474};
475
476Suggest.LocalMulti.prototype.setInputText = function(text) {
477
478  var pos = this.getLastTokenPos();
479
480  if (pos == -1) {
481    this.input.value = text;
482  } else {
483    this.input.value = this.input.value.substr(0 , pos + 1) + text;
484  }
485};
486
487Suggest.LocalMulti.prototype.getLastTokenPos = function() {
488  return this.input.value.lastIndexOf(this.delim);
489};

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.