お寿司か焼き肉食べたい

まじめな事からしょーもない事まで
めにゅーを開く(投げやり)

これは【あ行】である。それ以外の何者でもない

結構レアケースなのですが、とあるサイトでこんな要望があったのですよ。

  1. 情報の絞り込み
  2. 五十音→企業名→事業所名が各プルダウン(この時はドロップダウンでやった)で選択できて
  3. 選択内容は選んだ順で絞り込まれていくのれす
  4. データ自体はDBに格納されていて、バックエンドが絡むページ
  5. よみがなのデータはありまぁす。

ほーん
五十音は固定でええのかなと思いましたが、ユーザビリティを考えるとやっぱ無いやつは出さないのがいいねと
最初五十音全部(あ い う え お)出してたのが、あ行とかそんなんがいいみたいな感じでちゃぶ台を半分ひっくり返した感じになったんです。
安易な仕様変更はやめろ。

とはいえ、そうだよなぁって内容ですし、おすしって感じでしたのでさくっとやってみたメモ書きです。

では、まずバックエンドから吐き出されるデータについて

ってなわけでバックエンドから吐き出されるデータを少し確認して見たところ
よみがなはあるが、丸々入ってる(そりゃそうだろう)と
じゃぁ先頭文字だけsliceでいける。これで問題なし。

では早速

一旦例を。データはhiddenタグで全部一気に入れてもらっています。
データ件数多くないからいいんだよ。多い場合はマネしたらアカン

  <!-- すげぇながい -->
  <input type="hidden" name="hoge" id="getData" value="1:金本:カネモト,2:榎田:エノキダ,3:能見:ノウミ,4:横山:ヨコヤマ,5:安藤:アンドウ,6:岩貞:イワサダ,7:藤川:フジカワ,8:藤浪:フジナミ,9:岩田:イワタ,10:歳内:サイウチ,11:秋山:アキヤマ,12:石崎:イシザキ,13:高宮:タカミヤ,14:マテオ:マテオ,15:髙橋:タカハシ,16:竹安:タケヤス,17:守屋:モリヤ,18:山本:ヤマモト,19:金田:カネダ,20:青柳:アオヤギ,21:メッセンジャー:メッセンジャー,22:松田:マツダ,23:望月:モチヅキ,24:桑原:クワハラ,25:岩崎:イワザキ,26:島本:シマモト,27:伊藤:イトウ,28:田面:タナボ,29:坂本:サカモト,30:小宮山:コミヤマ,31:梅野:ウメノ,32:小豆畑:アズバタ,33:岡﨑:オカザキ,34:原口:ハラグチ,35:鳥谷:トリタニ,36:北條:ホウジョウ,37:上本:ウエモト,38:西岡:ニシオカ,39:新井:アライ,40:西田:ニシダ,41:森越:モリコシ,42:今成:イマナリ,43:陽川:ヨウカワ,44:荒木:アラキ,45:植田:ウエダ,46:大和:ヤマト,47:福留:フクドメ,48:髙山:タカヤマ,49:横田:ヨコタ,50:江越:エゴシ,51:伊藤:イトウ,52:中谷:ナカタニ,53:板山:イタヤマ,54:緒方:オガタ,55:俊介:シュンスケ,56:狩野:カノウ">

さて、ここからこのデータを分けていくロジックを考えてみます。
結構単純明快な感じでやってます。

いつものデモ

そこそこ長いですが、実行したJSは以下となります。

javascript

$(function(){


  var selectHiddenData = $('#getData').val(), // input:hiddenに入っているバックエンドからのデータのいれもの
      select1Data = [], // 五十音用のいれもの
      select2Data = [], // 選手名用のいれもの
      select1DataLeng = 0, // 五十音データの件数
      kanaArr = {}, // あ行とかのマスタデータ用のいれもの
      selectHtml = ""; // 五十音順のoption用いれもの

  //--------------------------------------------
  // バックエンドからのデータ整形
  // xxx:xxx:xxx, の形で分けられており、カンマ区切りで1データって仕様にしているので
  // カンマでsplitし、実データごとにわけます。
  //--------------------------------------------
  selectHiddenData = selectHiddenData.split(',');
  selectHiddenDataLeng = selectHiddenData.length;

  //------------------------------------------------
  // 行変換用データ
  // マスタデータ。ここではベタで書いてます。
  //------------------------------------------------
  kanaArr['ア'] = 'アイウエオ';
  kanaArr['カ'] = 'カキクケコガギグゲゴ';
  kanaArr['サ'] = 'サシスセソザジズゼゾ';
  kanaArr['タ'] = 'タチツテトダヂヅデド';
  kanaArr['ナ'] = 'ナニヌネノ';
  kanaArr['ハ'] = 'ハヒフヘホパピプペポバビブベボ';
  kanaArr['マ'] = 'マミムメモ';
  kanaArr['ヤ'] = 'ヤユヨ';
  kanaArr['ラ'] = 'ラリルレロ';
  kanaArr['ワ'] = 'ワヲン';

  //------------------------------------------------
  // 五十音順の生成処理
  // 1データごとでループして判定します。
  //------------------------------------------------
  for (var i = 0; i < selectHiddenDataLeng; i++) 
  {
    // コロン区切りなので、さらにコロンでsplitし、詳細のデータをわけます。
    tmpData = selectHiddenData[i].split(':');

    // よみがなデータの先頭文字を切り取り、あ行とかの判定を行い、行名を取得します。
    kanaTmpData = cngFirstLetter(tmpData[2].slice(0,1));

    // 選手データの整形 キー名を五十音の行名にすることで
    // データをまとめることができます。その為の前準備を行います。
    if(select2Data[kanaTmpData] === undefined){
      select2Data[kanaTmpData] = [];
    }

    // 五十音の行名を追加します。
    // 同じものは入らないように制御します。
    if(kanaTmpData !== false && select1Data.indexOf(kanaTmpData) < 0)
    {
      select1Data.push(kanaTmpData);
    }

    // 選手データ用にsplitでバラバラにした詳細データをひっつけます。
    // それを対応した五十音行名のオブジェクトの中につっこんでいきます。
    // よみがなをわざわざ先頭に持っていくのは、後に実行するソート用です。
    tmpData = tmpData[2]+'_'+tmpData[1]+'_'+tmpData[0];
    select2Data[kanaTmpData].push(tmpData);
  }

  //-----------------------------------------------------------
  // 五十音行名プルダウンの生成を行います。
  // 最初にソートを行うことで順番に並べて分かりやすくします。
  // 順番にいれているので特記事項はありません。
  //-----------------------------------------------------------
  select1Data = kanaSort(select1Data);
  select1DataLeng = select1Data.length;
  selectHtml += '<option value="">五十音選択</option>';
  for (var i = 0; i < select1DataLeng; i++) {
    selectHtml += '<option value="'+select1Data[i]+'">'+select1Data[i]+'</option>';
  };
  $('#dataSelect').empty().append(selectHtml);

  //-----------------------------------------------------------
  // 五十音行名プルダウンのchangeイベント設定
  //-----------------------------------------------------------
  $('#dataSelect').on('change',function()
  {
    var selectVal = $(this).val(); // 選択された五十音行名

    changeHtml = '';

    // 選択された五十音行名に対応した選手名 これもソートします。
    applicableData = kanaSort(select2Data[selectVal]);
    applicableDataLeng = applicableData.length;

    // 選手名プルダウンの生成
    changeHtml += '<option value="">選手名選択</option>';
    for (var i = 0; i < applicableDataLeng; i++) 
    {
      // 表示名と番号を切り分けてoptionタグ生成
      applicableDataSub = applicableData[i].split('_');
      changeHtml += '<option value="'+applicableDataSub[2]+'">'+applicableDataSub[1]+'</option>';
    };
    $('#dataSelect2').empty().append(changeHtml);
  });


  /***************************
  * 
  * kanaSort
  *
  * @param {Array} dataArr - ソート対象配列
  * @returns {Array} dataArr - ソート済配列
  * 
  * 一次配列形式で渡す
  * 
  ****************************/
  function kanaSort(dataArr)
  {
    dataArr.sort(function(a, b)
    {
      a = a.toString();
      b = b.toString();
      if(a < b){
        return -1;
      }else if(a > b){
        return 1;
      }
      return 0;
    });
    return dataArr;
  }


  /***************************
  * 
  * cngFirstLetter
  *
  * @param kanaData String カナ1文字;
  * @return String 引数に対応した五十音行頭文字;
  * 
  * 引数に指定された文字が、五十音の何行に当たるかを判定し
  * 対応した五十音行頭文字を返す
  * 
  ****************************/
  function cngFirstLetter(kanaData)
  {
    var reKey = "";
    $.each(kanaArr,function(key,value)
    {
      if(value.indexOf(kanaData) >= 0)
      {
        reKey = key;
      }
    });
    return reKey;
  }

});