JavaScriptで検索ツールを作ってみよう
JavaScriptで簡単な検索ツールを作ってみようと思い立ちました。
どういうものかというと、複数の商品やサービスがある中から特定の条件にマッチするものを抽出して表示させる。ECサイトなんかによくあるツールです。
そういった無料ツールは転がってそうですが、自分自身のエンジョイのために作ってみようと思ったのです。
もしアド広告(YahooリスティングとかGoogle広告とか)回しててこういうツールを簡単にサクッっと導入しようと思ってる方がいれば、自作できるので参考になれば幸いです。
簡単な検索ツールで何を作るか
このブログ用の検索ツールになるので、プログラミングスクールをユーザーの希望する条件で抽出して一覧で表示させるツールです。
トップページに置いてあります。
簡単な検索ツールの設計
簡単に設計をしようと思いました。
検索項目
項目は以下のとおり。
検索項目 | フォーム | 選択肢 |
---|---|---|
目的 | チェックボックス | プログラミング/転職・就職/副業・フリーランス・起業 |
スキル選択 | チェックボックス | WEBサイト制作/WEBアプリ開発/フロントエンド/iPhoneアプリ/Androidアプリ/ゲーム開発/AI/データサイエンス/デザイン/Linux/AWS/副業/オリジナル開発 |
言語選択 | チェックボックス | HTML/CSS/PHP/Laravel/Ruby/Ruby on Rails/JavaScript/jQuery/Vue.js/Java/Servlet/JSP/Python/Unity/Kotlin/C++/C# |
料金 | ラジオボタン | 指定なし/10万円未満/20万円未満/30万円未満/月額課金制 |
メンタリング | ラジオボタン | こだわらない/あり |
チャットサポート | ラジオボタン | こだわらない/あり |
転職保証 | ラジオボタン | こだわらない/あり |
ハローワーク給付金 | ラジオボタン | こだわらない/あり |
資格試験対策 | ラジオボタン | こだわらない/あり |
全教材見放題 | ラジオボタン | こだわらない/あり |
卒業後教材閲覧 | ラジオボタン | こだわらない/可能 |
コミュニティ | ラジオボタン | こだわらない/あり |
最初に画面にこれらの検索項目を表示させ、ユーザーにチェックを入れて貰ったりして、結果を表示します。
結果表示項目
抽出された後表示する項目を以下のように考えました。
・スクール名
・スクールのバナー
・3つのトピック
・概要
・料金プラン
・カリキュラム
・学べる言語
・筆者の感想
・オプション
・内部リンク
・公式ページへのリンク
ところで、1個1個項目ごとに抽出して表示するよりは、スクールで1単位のHTML文を保有して、それを表示するだけにしたほうが簡単だぞ、と思いました。
なので結果表示項目はこれら項目の全ての内容を含むHTML文そのものです。
データの保有方法とデータの作成
データベースは使わないでCSV形式のテキストファイルをサーバー上に保存して、そこからデータを取り出す形にしました。
データは以下のようにエクセルで作成しました。
保持しているデータ項目は以下のものだけ。
項目 | プロパティ |
---|---|
名称 | name |
表示用HTML | desc |
目的 | goal |
スキル | skill |
言語 | lang |
料金下限 | minRyokin |
料金上限 | maxRyokin |
月額課金フラグ | subscFlg |
メンタリング | mentaling |
チャットサポート | chat |
転職保証 | tenshokuHosyo |
ハローワーク給付金対象 | kyufukin |
資格試験対策 | sikaku |
教材見放題 | mihodai |
卒業後教材見れる | forever |
コミュニティ | community |
このエクセルをそのままTXTファイルにコピペして保存。
つまりタブセパレートバリュー(tsv)形式のTXTファイル。
簡単な検索ツールのJavaScript部分
JavaScriptのフロントだけで全部やっちゃう、サーバーサイドはやらない。
HTMLからJSファイルを読み込みます。
JavaScript ファイル読み込み
JavaScript ローカルファイル読み込み
JavaScript サーバー上のファイルを読み込む
HTMLをロードした時点のイベントでjsを起動するようにしました。
window.addEventListener('load', function(){ document.getElementById("srcbtn").onclick = search; readSearchData(); });
これで検索ボタンのonclickイベントにsearchという関数を登録し、その後データ読み込み関数を起動(readSearchData)。
サーバー上のTXTファイルを読み込みます。
function readSearchData() { var request = new XMLHttpRequest(); request.open('GET', filePath, true); request.send(); request.onload = function() { //リクエストの終了 var lines = extractLine(request.responseText); //1行ずつ取り出し for(var i=0; i<lines.length; i++) { var items = tabSeparate(lines[i]); if(items.length == 17) { //項目数は17個であることをチェック var tmp = new School(items); searchData.push(tmp); }else { console.log('TXTファイルの書式がおかしい'); } } }; }
サーバー上のTXTファイルを読み込むには、XMLHttpRequestのオブジェクトじゃないと取り出せないみたいでした。またTXTファイルの文字コードはUTF-8で保存しないと文字化けするのでUTF-8としました。
書式に倣っています。
request.openで読み込みURLと方式(GET)を指定。
sendメソッドでリクエスト開始。
onloadでリクエストが終了した時の処理を無名関数で記述しています。
extractLine関数は自作の関数。改行コード(\n)でファイル内の文字列を分割して1行ずつ取り出して配列linesに入れています。
取り出したlines配列の数だけforループでまわして、やはり自作の関数(tabSeparate)にて、今度はタブ(\t)で分割して配列itemsに入れていっています。
項目数が17個であることを確認して、items配列をSchoolオブジェクトに渡してスクール毎のオブジェクトを生成しています。
ユーザーがトップページを読み込みしたらここまでが完了状態でスタンバイです。
あとは「検索ボタン」が押されたらsearch関数が動きます。
search関数でやってることは
まず最初の1つ目の以下の条件をgetElementsByNameで取得しています。
検索項目 | フォーム | 選択肢 |
---|---|---|
目的 | ラジオボタン | プログラミング/転職・就職/副業・フリーランス・起業 |
例えば「目的」のラジオボタンであればHTML側は以下のようになっているので
<label><input class="m10-r" value="プログラミング" type="radio" name="goal" checked />プログラミング</label> <label><input class="m10-r" value="転職・就職" type="radio" name="goal" />転職・就職</label> <label><input class="m10-r" value="副業・フリーランス・起業" type="radio" name="goal" />副業・フリーランス・起業</label>
JavaScript側では以下のようにして要素を取得しています。
var goals = document.getElementsByName('goal'); for(var i=0; i<goals.length; i++) { if (goals[i].checked) { goal = goals[i].value; break; } }
要素を配列goalsで取得してから、goalsの中の要素に対して1つ1つcheckedプロパティのtrue/falseを確認し、trueのところのvalueプロパティを取得するようにしました。
例えばユーザーが「転職・就職」にチェックを入れて検索したら、「転職・就職」に対応しているプログラミングスクールを探していきます。
Schoolオブジェクトは最初の読み込み時点で配列searchDataに入れていますので
var tmp1 = []; for (var i=0; i<searchData.length; i++) { if(searchData[i].goal.indexOf(goal) !== -1) { //目的に対応してるスクールなら tmp1.push(searchData[i]); } }
このように各スクールオブジェクトのプロパティgoalはただの文字列なので、その中をindexOfメソッドを使って検索しています。
indexOfメソッドでは検索文字列があればそのインデックス値を返しますが、検索文字列が無ければ-1を返す仕様です。なので-1じゃなければ検索文字列が見つかったと言う事なので、それを条件にしました。
目的「転職・就職」に対応してるスクールが見つかれば、そのオブジェクトを仮の表示用配列tmp1に入れています。
こういうのを以下の全ての条件に対してマッチしてるかしてないかでふるいにかけています。データベースを使ってたらSELECT文で1発なんでしょうけど(汗
スキル選択 | チェックボックス |
---|---|
言語選択 | チェックボックス |
料金 | ラジオボタン |
メンタリング | ラジオボタン |
チャットサポート | ラジオボタン |
転職保証 | ラジオボタン |
ハローワーク給付金 | ラジオボタン |
資格試験対策 | ラジオボタン |
全教材見放題 | ラジオボタン |
卒業後教材閲覧 | ラジオボタン |
コミュニティ | ラジオボタン |
最終的に該当するスクール達が残ります。
検索結果のスクールを表示する際には次のように対象スクールのdescプロパティをそのままinnerHTMLにぶち込んで表示しています。
document.getElementById('result').innerHTML = school.desc;
これだけ。
汎用的な機能じゃないけど、取り合えず満足しています
このブログだけで動く簡易な検索ツールは出来ました。
もっとイイやり方、スムーズなやり方はあると思いますがベタ書きで完成することができました。満足。
JavaScriptでデータ数も少ないしフロントだけでやってるので、スピードは速いです。