マッシュアップ3(GMap+YUI+じゃらんAPI)



今回も、前回のマッシュアップサンプルのブラッシュアップ、といいますか、ソースの整理です。マッシュアップとは直接関係有りませんが、今回の「整理されていない」サンプルコードは、JavaScript Tips 素材として丁度良いので簡単に解説しておこうと思います。

今回のポイントは、冗長になりがちなDOMスクリプトを関数で短くし、繰り返し処理をfor文でシンプルに記述するというものです。

マッシュアップの内容そのものは、前回前々回同様に じゃらんWebサービス/じゃらん宿表示APIとバージョン2になったGoogle Maps APIを組み合わせて、「マッシュアップ」を行ってみようというもので、 ユーザーインターフェイスには、フェイドインやドラッグ、フロートなどで自作のエフェクト(ドラッガブルフロートなDIV)とパブリックドメインのインジケータ画像AJAX Activity indicatorsを利用しています。

利用するサービスやライブラリの使用方法等については、前回紹介した各サイトのドキュメントなどをご参照ください。

関数でショートカット


前回は、 前々回のホテル情報を、 オブジェクトで扱うように書換えました。今回は、そのホテル情報を、XMLDOMから取り出す関数を整理してみます。

その部分を、もう一度見てみましょう。
//ホテル毎のデータセット
function mk_hotelsOj(h_id,hotelDom){

    h_Oj[h_id] = new hotelsOj();

    //XMLからホテル毎のデータを取り出します
    //ホテル名
    h_Oj[h_id].h_name=hotelDom.getElementsByTagName('HotelName')[0].firstChild.nodeValue;
    //経度 Longitude
    h_Oj[h_id].h_x=hotelDom.getElementsByTagName('X')[0].firstChild.nodeValue;
    //緯度 Latitude
    h_Oj[h_id].h_y=hotelDom.getElementsByTagName('Y')[0].firstChild.nodeValue;
    //大エリア
    h_Oj[h_id].h_la=hotelDom.getElementsByTagName('LargeArea')[0].firstChild.nodeValue;
    //小エリア
    h_Oj[h_id].h_sa=hotelDom.getElementsByTagName('SmallArea')[0].firstChild.nodeValue;
    //画像
    if(hotelDom.getElementsByTagName('PictureURL')[0].firstChild!=null)
      h_Oj[h_id].h_ph=hotelDom.getElementsByTagName('PictureURL')[0].firstChild.nodeValue;
    else  h_Oj[h_id].h_ph="http://jsgt.guide.withabout.net/guide_jsgt/gp333/mt/01/yagi.jpg";
    wkOj.preLoad(h_id);//wkOj.hotelImg[h_id].src;

    //キャッチ
    h_Oj[h_id].h_catch=hotelDom.getElementsByTagName('HotelCatchCopy')[0].firstChild.nodeValue;
    //宿詳細ページURL
    h_Oj[h_id].h_url=hotelDom.getElementsByTagName('HotelDetailURL')[0].firstChild.nodeValue;

    return h_Oj[h_id];
}
長いですね。しかも、hotelDom.getElementsByTagNameや[0].firstChild.nodeValueは、行毎に何度も同じ処理を繰り返しています。 このgetElementsByTagNameメソッドに限らず、DOMの言い回しは、とても長いものが多く、このように繰り返すとどうしても文字だらけの読みにくいコードになりやすいものです。

そこで、このコードに何度も現れている主な基本構成を取り出してみましょう。
hotelDom.getElementsByTagName('XML内の要素名')[0].firstChild.nodeValue
これは、hotelDom.getElementsByTagName('XML内の要素名')により、 'XML内の要素名'の配列を取得し、その最初のノードの値(oj[0].firstChild.nodeValue)を取り出しています。 コード内では、この処理を、 'XML内の要素名'部分を取り替えながら繰り返しています。

たとえば、もし、下記のようなXML要素なら、その下のスクリプトようにして取り出します。 この場合、取り出される文字は「石狩・空知・千歳」です。
<LargeArea>石狩・空知・千歳</LargeArea> 
hotelDom.getElementsByTagName('LargeArea')[0].firstChild.nodeValue
そこで、 この、XMLDOMから要素名を指定して値を取り出す処理だけを行う短い名前のショートカット関数を作ってみます。
//第二引数のDOM内からタグ名を検索し最初のノード値を返します
function getHv(nodeName,dom){
  return dom.getElementsByTagName(nodeName)[0].firstChild.nodeValue;
}
これで、第一引数で渡された太字の部分を差し替えてノード値を返す関数ができました。先ほどの「石狩・空知・千歳」という文字列を取り出すなら、
getHv('LargeArea',dom)
でOKです。短くなりましたね。
この関数を利用して、 上記のスクリプトを書換えると下記のようになります。これで、少しすっきりしました。
  //ホテル毎のデータセット
  function mk_hotelsOj(h_id,hotelDom){

      h_Oj[h_id] = new hotelsOj();

      //XMLからホテル毎のデータを取り出します
      h_Oj[h_id].h_name  = getHv('HotelName',hotelDom);//ホテル名
      h_Oj[h_id].h_x     = getHv('X',hotelDom);//経度 Longitude
      h_Oj[h_id].h_y     = getHv('Y',hotelDom);//緯度 Latitude
      h_Oj[h_id].h_la    = getHv('LargeArea',hotelDom);//大エリア
      h_Oj[h_id].h_sa    = getHv('SmallArea',hotelDom);//小エリア
      if(hotelDom.getElementsByTagName('PictureURL')[0].firstChild!=null)
            h_Oj[h_id].h_ph  = getHv('PictureURL',hotelDom);//画像
      else  h_Oj[h_id].h_ph  = "http://jsgt.guide.withabout.net/guide_jsgt/gp333/mt/01/yagi.jpg";
      wkOj.preLoad(h_id);//wkOj.hotelImg[h_id].src;

      h_Oj[h_id].h_catch = getHv('HotelCatchCopy',hotelDom);//キャッチ
      h_Oj[h_id].h_url = getHv('HotelDetailURL',hotelDom);//宿詳細ページURL

      return h_Oj[h_id];
  }
  function getHv(nodeName,dom){
    return dom.getElementsByTagName(nodeName)[0].firstChild.nodeValue;
  }
サンプル

参考までに、prototype.jsなど最近のJavaScriptライブラリでよく見かけるドル関数 $() もDOMの長い言い回しdocument.getElementById('id名')を短く置き換えるショートカットとして使われることの多い関数です。