2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

jsでサジェストっぽい事をやってみた

Last updated at Posted at 2018-02-11

会社の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"を消すようにしてあります。

とりあえず動作自体は問題ありませんでしたが、表示上限を設けていませんし、漢字のカナにも対応していません。改善していきたいですが、とりあえず今はこれでよしとしておきます。

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?