読者です 読者をやめる 読者になる 読者になる

javacriptでインクリメンタルサーチとjQueryのchange

jQuery javascript

インクリメンタルサーチをしたかったのだけど1文字打つごとにapiコールするアレなコードしか書けなかったので先輩に聞いたらインクリメンタルサーチソースコードをそのままくれた.そのコードのこれさえあれば動くっていうのがこれ

var
preFunc = null,
ajaxPost = function(input) {
  // apiコール
};
    
$('#ajax_form').on('keyup change',function() { //keyupまたはchangeイベントで発火
  clearTimeout(preFunc);
  preFunc = setTimeout(ajaxPost(input), 500);  //500ミリ秒後に関数(ajaxPost)呼び出しイベントを設定
});

onメソッドの発火に対してイベント(関数呼び出し)を500ミリ秒後に設定し,設定した500ミリ秒よりも前に同じ関数が呼んだら1つ前に設定していたイベントをクリアして新しく500ミリ秒後にイベントを設定する.これで1文字打つごとにapiコールというアレなやつを回避できる.
しかし,このchangeイベントが予想していた挙動と違った.

jQuery .change()を見てみるとこうやって書いてあった

The change event is sent to an element when its value changes. This event is limited to <input> elements, <textarea> boxes and <select> elements. For select boxes, checkboxes, and radio buttons, the event is fired immediately when the user makes a selection with the mouse, but for the other element types the event is deferred until the element loses focus.

  • input,textarea,select要素にだけ使える
  • select boxes,checkboxes,radio buttonでは変更があったらすぐ発火する
  • それ以外の要素は変更した後フォーカスが外れたら発火

だいたいこんな感じ,フォームの内容が変更されたらという意味でchangeを使っていたが実は変更されてもフォーカスをはずさないと発火してなかった,なので$('#ajax_form').on('keyup change',function() {この行のchangeは要らない.

changeが使えなかったがフォームの内容が変更されたら発火を実現したかったので新しく書きなおしてみた.

var
preFunc = null,
preInput = '',
input = '',
ajaxPost = function(input) {
  // apiコール
};

$('#ajax_form').on('keyup', function() {
  input = $.trim($(this).val());   //前後の不要な空白を削除
    if(preInput !== input){
      clearTimeout(preFunc);
      preFunc = setTimeout(ajaxPost(input), 500);
    }
  preInput = input;
});

1つ前のフォームに入力された値(preInput)を保存しておいて現在のフォームに入力された値(input)と比較するという至って普通なことをした.
それにしてもchangeっていう名前のフェイントがやばい