var toArray = Array.from = function(iterable) { if (!iterable) return []; if (iterable.toArray) { return iterable.toArray(); } else { var results = []; for (var i = 0; i < iterable.length; i++) results.push(iterable[i]); return results; } } Function.prototype.bind = function() { var theMethod = this, args = toArray(arguments), object = args.shift(); return function() { return theMethod.apply(object, args.concat(toArray(arguments))); } } // Added on Jun-30-2007. // Added on Jul-12-2007. Function.prototype.bindAsEventListener = function(object) { var theMethod = this, args = toArray(arguments), object = args.shift(); return function(event) { return theMethod.apply(object, [( event || window.event)].concat(args).concat(toArray(arguments))); } } if (!aaSuggest) { var aaSuggest = {}; } function aaSuggest() { var inputField; var suggestArea; var candidateList; var suggestedList; var suggestedIndexList; var activePosition; var timer; var inputedValueBackup; var oldText; var interval; var displayMax; var listTag; var prefix; var ignoreCase; var dispAllKey; /** * Initialize */ this.initSuggest = function(inputFieldEle, suggestAreaDivEle, candidateList) { //this.inputField = document.getElementById(inputFieldId); this.inputField =inputFieldEle; //this.suggestArea = document.getElementById(suggestAreaDivId); this.suggestArea = suggestAreaDivEle; this.candidateList = candidateList; this.timer = null; this.inputedValueBackup = ""; this.oldText = null; this.interval = 500; this.displayMax = 10; this.listTag = 'div'; //this.prefix = false; this.prefix = true; this.ignoreCase = true; this.dispAllKey = false; // Set the event handler. this.addListener(this.inputField, 'focus', this.suggestInputFocus.bind(this), false); this.addListener(this.inputField, 'blur', this.suggestInputBlur.bind(this), false); //IE系対応でkeydownイベント化 //this.addListener(this.inputField, 'keypress', this.suggestInputKeypress.bind(this), false); this.addListener(this.inputField, 'keydown', this.suggestInputKeypress.bind(this), false); // Initialize the suggest area. this.clearSuggestArea(); } /** * Handle the event for the input field when would be focused in. */ this.suggestInputFocus = function() { var text = this.getInputText(); if (text != this.oldText) { this.oldText = text; // Search the word. this.doSearch(); } if (this.timer) clearTimeout(this.timer); // Confirm the input word after some interval. this.timer = setTimeout(this.suggestInputFocus.bind(this), this.interval); } /** * Handle the event for the input field when would be focused out. */ this.suggestInputBlur = function(event) { this.unactive(); this.oldText = this.getInputText(); if (this.timer) clearTimeout(this.timer); this.timer = null; // clear the suggest area after 0.5ms. setTimeout((function(){ this.clearSuggestArea(); }).bind(this), 500); } /** * Handle the event for the input field when any key pressed. */ this.suggestInputKeypress = function(event) { if (!this.timer) this.timer = setTimeout(this.suggestInputFocus.bind(this), this.interval); if (this.dispAllKey && event.ctrlKey && this.getInputText() == '' && !this.suggestedList && event.keyCode == '40') { this.stopEvent(event); this.displayAllSuggest(); } else if (event.keyCode == '38' || event.keyCode == '40') { // UP or DOWN this.stopEvent(event); this.moveActiveList(event.keyCode); } else if (event.keyCode == '13') { // RETURN if (this.suggestedList) { this.stopEvent(event); this.clearSuggestArea(); } } else if (event.keyCode == '27') { // ESCAPE if (this.suggestedList) { this.stopEvent(event); this.clearSuggestArea(); this.inputField.value = this.inputedValueBackup; this.oldText = this.getInputText(); } } } /** * Search the inputed word from the candidate list. */ this.doSearch = function() { this.clearSuggestArea(); var text = this.getInputText(); if (text == '') return; var resultList = new Array(); var temp = null; this.suggestedIndexList = new Array(); for (var i = 0; i < this.candidateList.length; i++) { if ((temp = this.isMatch(this.candidateList[i], text)) != null) { resultList.push(temp); this.suggestedIndexList.push(i); if (this.displayMax != 0 && resultList.length >= this.displayMax) break; } } if (resultList != 0) this.createSuggestArea(resultList); } /** * Match the word of the pattern. */ this.isMatch = function(value, pattern) { var matchPos; if (this.ignoreCase) { pos = value.toLowerCase().indexOf(pattern.toLowerCase()); } else { pos = value.indexOf(pattern); } if ((this.prefix && (pos != 0)) || (!this.prefix && (pos == -1))) return null; return value; } /** * Display the suggest area. */ this.displayAllSuggest = function() { this.clearSuggestArea(); this.oldText = this.getInputText(); this.suggestedIndexList = new Array(); for (var i = 0; i < this.candidateList.length; i++) { this.suggestIndexList.push(i); } this.createSuggestArea(this.candidateList); } /** * Create the suggest area contents. */ this.createSuggestArea = function(resultList) { this.suggestedList = new Array(); this.inputValueBackup = this.inputField.value; for (var i = 0; i < resultList.length; i++) { // Create and append the element and set the text. var elm = document.createElement(this.listTag); elm.innerHTML = resultList[i]; this.suggestArea.appendChild(elm); // Set the event handler. this.addListener(elm, 'click', new Function('event', 'this.suggestedListClick(event, ' + i + ');').bind(this), false); this.addListener(elm, 'mouseover', new Function('event', 'this.suggestedListOver(event, ' + i + ');').bind(this), false); this.addListener(elm, 'mouseout', new Function('event', 'this.suggestedListOut(event, ' + i + ');').bind(this), false); this.suggestedList.push(elm); } this.suggestArea.style.display = 'block'; } /** * Clear the suggest area. */ this.clearSuggestArea = function() { this.suggestArea.innerHTML = ''; this.suggestArea.style.display = 'none'; this.suggestedList = null; this.suggestedIndexList = null; this.activePosition = null; } /** * Handle the event which move on the suggest area. */ this.moveActiveList = function(keyCode) { if (!this.suggestedList || this.suggestedList.length == 0) return; this.unactive(); //if (keyCode == Event.KEY_UP) { if (keyCode == '38') { // UP if (this.activePosition == null) { this.activePosition = this.suggestedList.length - 1; } else { this.activePosition--; if (this.activePosition < 0) { this.activePosition = null; this.inputField.value = this.inputValueBackup; return; } } } else { // DOWN if (this.activePosition == null) { this.activePosition = 0; } else { this.activePosition++; } if (this.activePosition >= this.suggestedList.length) { this.activePosition = null; this.inputField.value = this.inputValueBackup; return; } } this.active(this.activePosition); } /** * Handle the event for the suggest area when clicked. */ this.suggestedListClick = function(event, index) { this.unactive(); this.activePosition = index; this.active(index); } /** * Handle the event for the suggest area when mouse over. */ this.suggestedListOver = function(event, index) { var elm = event.target || event.srcElement; this.moverDisplay(elm); } /** * Handle the event for the suggest area when mouse out. */ this.suggestedListOut = function(event, index) { var elm = event.target || event.srcElement; if (!this.suggestedList) return; if (index == this.activePosition) { this.activeDisplay(elm); } else { this.unactiveDisplay(elm); } } /** * Get the text on the observed field. */ this.getInputText = function() { return this.inputField.value; } /** * Set the text on the observed field. */ this.setInputText = function(text) { this.inputField.value = text; } /** * Activate the suggenst area. */ this.active = function(index) { this.activeDisplay(this.suggestedList[index]); this.setInputText(this.candidateList[this.suggestedIndexList[index]]); this.oldText = this.getInputText(); this.inputField.focus(); } /** * Unactivate the suggenst area. */ this.unactive = function() { if (this.suggestedList != null && this.suggestedList.length > 0 && this.activePosition != null) { this.unactiveDisplay(this.suggestedList[this.activePosition]); } } /** * Activate the element, switch to the 'select' style. */ this.activeDisplay = function(elm) { elm.className = 'select'; } /** * Unactivate the element, drop to the style. */ this.unactiveDisplay = function(elm) { elm.className = ''; } /** * Mouse overed the element, switch to the 'over' style. */ this.moverDisplay = function(elm) { elm.className = 'over'; } /** * Add the listener function on the element. */ this.addListener = function(elm, eventType, func, cap) { if (elm.addEventListener) { elm.addEventListener(eventType, func, cap); } else if (elm.attachEvent) { elm.attachEvent('on' + eventType, func); } } /** * Stop the event handling. */ this.stopEvent = function(event) { if (event.preventDefault) { event.preventDefault(); event.stopPropagation(); } else { event.returnValue = false; event.cancelBubble = true; } } }