会社のWEBにサジェスト機能を付けたくて、「サジェストができそうなライブラリ使っていいですか?」とお伺いをたてたら「駄目」と言われたので、初心者なりにjavascriptを勉強して作ってみました。駄目な点などありましたら、ぜひ教えてください。
##必要なhtmlとcss##
<input type="text" class="suggest_input -1"><br>
<div id="output" class="suggest_option dpnone"></div>
<style type="text/css">
.suggest_option{
background-color: rgb(255, 255, 255);
border: 1px solid rgb(162, 162, 162);
border-width: 0px 1px 1px 1px;
max-width: 140px;
padding: 3px;
font-size: 12px;
position: absolute;
}
.suggest_input{
display: inline-block;
}
.onmouse:hover{
background-color: rgb(107, 151, 216);
}
.select{
background-color: rgb(107, 151, 216);
}
.dpnone{
display: none;
}
</style>
##サジェスト候補を配列に格納する##
function SuggestOption(){
let Option = [
'aaaa',
'テスト',
'2テスト',
'',
];
return(Option);
}
##読み込み時のイベント##
聞くところによると、addEventListener
でやるのがナウい方式らしいので、htmlにonclickで書くレトロ形式から脱却してみました。
window.addEventListener('load', function() {
let SuggesJs = document.getElementsByClassName('suggest_input');
SuggesJs[0].addEventListener('keyup', SuggestJS, false);
})
##サジェスト候補を絞り込む関数##
function StrFilterTheAry(array, str){
let SuggestOption = [];
// let regexp = '/' + str + '(.*?)' + ',/gmi'; //リテラルでできるパターンを考える//
let regexp = new RegExp(str + '(.*?)', 'gmi');
const map1 = array.filter(x => x.match(regexp)); //サジェスト候補を正規表現で評価
for(let i = 0,length = map1.length; i < length; i++){
SuggestOption[i] = map1[i];
}
return(SuggestOption)
}
最初に組んだ時は、汎用性のカケラもない構成だったのですが、4回ほど書き直すと多少改善した気がします。
regxp変数には正規表現リテラルを使いたいのですが、イマイチやりかたがわかりません。
##メインの関数##
function SuggestJS(ele){
let SuggestOp = '', SuggestOpLeng, SelectLeng, Count, result;
let KeyCode = ele.keyCode;
let SuggestClass = document.getElementsByClassName('suggest_input');
let SuggestArray = StrFilterTheAry(SuggestOption(), this.value);
let SuggestPullDown = document.querySelector('.suggest_option');
//サジェスト結果を成型してプリント//
for(let i = 0, length = SuggestArray.length; i < length; i++){
if(i === 0){
SuggestOp += '<div class="onmouse">' + SuggestArray[i] + '</div>';
}
else if(i == length - 1){
SuggestOp += '<div class="onmouse">' + SuggestArray[i] + '</div>';
}
else{
SuggestOp += '<div class="onmouse">' + SuggestArray[i] + '</div>';
}
}
document.getElementById('output').innerHTML = SuggestOp;
console.log(SuggestOp);
if(SuggestOp != ''){
SuggestPullDown.classList.remove('dpnone');
}else{
SuggestPullDown.classList.add('dpnone');
}
//キーコードに応じて、フォーカスを移動しているように見せる//
SuggestOp = document.querySelectorAll('.onmouse');
SuggestOpLeng = SuggestOp.length;
Count = SuggestClass[0].className.replace( /suggest_input/g , "" ) ;
Count = Count.replace( / /g , "" ) ;
Count = Number(Count);
if( Count != -1){
if(KeyCode === 40 && Count != SuggestOpLeng - 1){
SuggestOp[Count].classList.remove('select');
Count++;
SuggestOp[Count].classList.add('select');
}else{
SuggestOp[Count].classList.add('select');
}
if(KeyCode === 38 && Count != 0){
SuggestOp[Count].classList.remove('select');
Count--;
SuggestOp[Count].classList.add('select');
}
}else{
SuggestOp[0].classList.add('select');
Count = '0';
}
Count = String(Count);
SuggestClass[0].classList.remove('-1', '0', '1', '2', '3', '4', '5', '6');
SuggestClass[0].classList.add('suggest_input', Count);
for(let i = 0; i < SuggestOpLeng; i++){
//マウスオーバーの際にclass="select"を非表示にする//
SuggestOp[i].addEventListener('mouseover', function() {
for(let i = 0; i < SuggestOpLeng; i++){
SuggestOp[i].classList.remove('select');
}
}, false);
//サジェストをクリックしたらinputに内容を入れてサジェストを削除する//
SuggestOp[i].addEventListener('click', function() {
document.querySelector('.suggest_input').value = this.innerHTML;
for(let i = 0; i < SuggestOpLeng; i++){
SuggestOp[i].classList.add('dpnone');
}
let a = document.querySelector('.suggest_option').classList.add('dpnone');
}, false);
}
}
キーボードの↓↑でサジェスト候補を移動するために、かなりコード量が増えました。矢印で移動するたびに移動した数値を記録してinputのclass=""に記載します。再度関数を実行する際にその数値を取得します。マウスオーバーによる選択もできるようにして、それを行った場合は矢印で選択する際に使用するclass="select"を消すようにしてあります。
とりあえず動作自体は問題ありませんでしたが、表示上限を設けていませんし、漢字のカナにも対応していません。改善していきたいですが、とりあえず今はこれでよしとしておきます。