2016年5月25日水曜日

今日は試験です!

さて、これまでMonacaのOnsenUI Master-Detaiをカスタマイズして、JSONデータを組み合わせてアプリを作ってきました。今回は前回の宿題(詳細画面にJSONデータを表示する)を確認した後、確認テストをします。テスト問題は以下の通りです。

 問題1 プログラムリスト1について以下の設問に答えなさい。
  1. patient.idの値を答えなさい。
  2. patient. genderと同じ意味を表すのは patient[A] である。Aには何が入るか?
  3. 患者オブジェクト patientに属性emailを加えたい。どうすればよいか。ただし、メールアドレスはA0001@kwmw.jpとする。

 問題2 プログラムリスト2について以下の設問に答えなさい。
  1. patientList[2].nameの値は何か
  2. 次の命令を実行したときの実行結果を書きなさい
    $.each(patientList, function(i, patient) {
      console.log(i + ',' + patient.id);
     }
    );
    
  3. これは上記と同じ実行結果を出力するプログラムである。AとBには何が入るか?
    for(var i = 0; i < A; i++) {
     console.log(i + ',' + patientList[B].id);
    }
    
問題3 プログラムリスト3について以下の設問に答えなさい。
  1. 下記の変数の値は何か
    visitData['A0001'][1].date
    visitData['A0002'][0].diseaseName
    visitData['A0003'][2].dept
    visitData['A0003'][3].diseaseName
  2. 次の命令を実行したときの実行結果を書きなさい
    var patientId = 'A0002';
    for(var i = 0; i < visitData[patientId].length; i++) {
     var visit = visitData[patientId][i];
     console.log(i + ',' + visit.date);
    }
    
  3. これは上記と同じ実行結果を出力するプログラムである。AとBには何が入るか?
    var patientId = 'A0002';
    A(visitData[B], function(i, visit) {
      console.log(i + ',' + visit.date);
     }
    );
    

なお、問題文中のプログラムリストは下記の通りです。

プログラムリスト1
var patient = {
 "id": "A0001",
 "name": "在本 璃奈",
 "gender": "female",
 "birthdate": "1996/4/1",
 "address": "岡山県倉敷市山田町1丁目-2-3"
};

プログラムリスト2
var patientList = [
 {
  "id": "A0001",
  "name": "在本 璃奈",
  "gender": "female",
  "birthdate": "1996/4/1",
  "address": "岡山県倉敷市山田町1丁目-2-3"
 },
 {
  "id": "A0002",
  "name": "清水 伸平",
  "gender": "male",
  "birthdate": "1995/5/10",
  "address": "岡山県岡山市苦米地3丁目-5-6"
 },
 {
  "id": "A0003",
  "name": "田中 昌昭",
  "gender": "male",
  "birthdate": "1958/7/6",
  "address": "岡山県瀬戸内市大岡5丁目-9-8"
 }
];

プログラムリスト3
var visitData = {
 "A0001": [
  {
   "date": "2016/5/20",
   "dept": "内科",
   "diseaseName": "気管支炎"
  },
  {
   "date": "2014/1/29",
   "dept": "外科",
   "diseaseName": "大腿骨骨折"
  },
  {
   "date": "2015/8/6",
   "dept": "耳鼻科",
   "diseaseName": "中耳炎"
  }
 ],
 "A0002": [
  {
   "date": "2016/3/19",
   "dept": "内科",
   "diseaseName": "インフルエンザ"
  },
  {
   "date": "2015/2/10",
   "dept": "外科",
   "diseaseName": "虫垂炎"
  }
 ],
 "A0003": [
  {
   "date": "2016/4/8",
   "dept": "眼科",
   "diseaseName": "白内障"
  },
  {
   "date": "2013/2/5",
   "dept": "内科",
   "diseaseName": "心筋梗塞"
  },
  {
   "date": "2011/11/4",
   "dept": "皮膚科",
   "diseaseName": "アトピー性皮膚炎"
  },
  {
   "date": "2014/12/15",
   "dept": "精神科",
   "diseaseName": "気分障害"
  }
 ]
};

応用 

上記の問題文中のpatientList(プログラムリスト2)とvisitData(プログラムリスト3)を使って次のようなアプリを作ってみよう。

 

左側の患者リストはプログラムリスト2のpatientListを使っている。表示項目はカルテ番号(id)、性別(gender)、氏名(name)、生年月日(birthdate)、住所(address)で、患者をタップするとその患者の受診一覧が表示される(右側)。この画面には患者の基本属性(カルテ番号、性別、氏名、生年月日、住所)に加えてこれまで受診した診療科(dept)と受診日(date)、そして診断名(diseaseName)が一覧となって表示される。この受診履歴は1患者につき受診した診療科とその受診日の数だけある。
プログラムを作成するうえでの注意点としては、これまではtitle, label, desc, photoという項目だったのに対して、今度はid, gender, name, birthdate, addressという項目になるので、それに合わせてclass名やスタイルシートの変更が必要になる。

2016年5月17日火曜日

詳細画面を完成させよう!

前回はリスト画面でタップして詳細画面を出したら写真が出なかったのでどうしてだろうということで時間切れになった。今回はその原因究明とさらに詳細画面の充実を図る!



まず、写真が出ていない件。これはタップしたリストから画像ファイル名が詳細画面へ引き継がれていないため。もともとサンプルプログラムはリストからタップした項目の情報(タイトル、ラベル、説明)をそのまま詳細画面へ表示しているだけ。それを行っているのがテキストP.126~127のコード。だから、それらの情報と同じようにして画像ファイル名も引き継げばいい。それをやっているのが次のコード。
(function(){
  'use strict';

  var currentItem = {};

    $('.item-title', this).text(currentItem.title);
    $('.item-desc', this).text(currentItem.desc);
    $('.item-label', this).text(currentItem.label);
    $('.item-thum-photo', this).attr('src', currentItem.photo);
    $('.add-note-action-item', this).click(function () {
        alert('dummy message');
    });
  });

  $(document).on('pageinit', '#list-page', function() {
    var html = '';
    $.each(listData, function(i, item) {
        html += '';
        html += '';
        html += '';
        html += '
'; html += ''; html += '
'; html += '
'; html += ''; html += '
'; html += '' + item.title + ''; html += '' + item.label + ''; html += '
'; html += '
' + item.desc + '
'; html += '
'; html += '
'; html += '
'; } ); $("#item-list").html(html); var content = $("#item-list").get(0); ons.compile(content); $('.item', this).on('click', function() { currentItem = { title : $('.item-title', this).text(), desc : $('.item-desc', this).text(), label : $('.item-label', this).text(), photo : $('.item-thum-photo', this).attr('src') }; app.navi.pushPage('detail.html'); }); }); })();
49行目でリスト画面で項目がタップされたとき画像ファイル名をcurrentItem.photoに保存し、9行目で詳細画面が表示されるときimgタグのsrcプロパティにcurrentItem.photoを設定しています。
次に、詳細画面の表示内容をタップされた項目ごとに変えます。そのために、まず、detail.htmlを次のように修正します。
<ons-template id="detail.html">
    <ons-page id="detail-page">
      <ons-toolbar>
        <div class="left"><ons-back-button>Back</ons-back-button></div>
        <div class="center">Details</div>
      </ons-toolbar>

      <ons-list modifier="inset" style="margin-top: 10px">
        <ons-list-item class="item">
          <ons-row>
            <ons-col width="60px"> 
              <div class="item-thum">
                <img src="" class="item-thum-photo" width="50px"></img>  
              </div>
            </ons-col>
            <ons-col>
              <header>
                <span class="item-title">Title</span>
                <span class="item-label">Foobar</span>
              </header>
              <p class="item-desc">desc</p>
            </ons-col>
          </ons-row>
        </ons-list-item>

        <ons-list-item modifier="chevron" id="add-note-action" class="add-note-action-item">
          <ons-icon icon="ion-chatboxes" fixed-width="true" style="color: #ccc"></ons-icon>
          Add a note
        </ons-list-item>

      </ons-list>

      <ons-list id="detail-item-list" style="margin-top: 10px">
      </ons-list>

    </ons-page>
</ons-template>

修正したのは33~34行目です。もともとはこのons-listタグ内にons-list-itemタグが3つあり、その中に前の画面でタップされた項目のタイトルと説明が表示されていました。今度は前にリスト画面でやったのと同じようにデータをHTMLから分離しjavascriptファイルとして独立させ、javascriptのプログラムでデータからons-list-itemタグを作ってやります。まず、detailData.jsというファイル名で次のようなデータを作成し、index.htmlからscriptタグで読み込ませます。
var detailData = {
 "在本 璃奈": [
  {
   "title": "我が家の子供用品の選び方",
   "desc": "冬は子供たちもココアや紅茶などを飲むので、キッズマグを探していましたがセリアでなかなかいい感じのマグを見つけました。"
  },
  {
   "title": "好みや成長具合によって選ぶ",
   "desc": "ずっと使うことを意識して、大人と同じマグやグラスという選択肢もありますが、モノに対する大人の思い入れを子供と共有できる自信もないので、子供のモノは、それなりに子供ウケしそうなもので…と割り切っています。"
  },
  {
   "title": "一番のお気に入りポイント",
   "desc": "お友達が遊びにきてくれたとき用のプラコップ(IKEA)はほんの時々しか出番はないので、他の場所に仕舞っています。"
  }
 ],
 "犬飼 佑汰": [
  {
   "title": "ソフトB 若鷹育てるファーム60億円基地",
   "desc": "ソフトバンクが2・3軍の施設を福岡県福岡市から同県筑後市の「HAWKSベースボールパーク筑後」に移転して、約2カ月が過ぎた。"
  },
  {
   "title": "完成間もないタマホームスタジアム筑後",
   "desc": "その正面入り口の横には「めざせ 世界一!」と書かれた竣工(しゅんこう)の碑がある。孫正義オーナー(58)が掲げるスローガンは、ファーム施設にまで行き届いていた。"
  }
 ],
 "臼井 彰生": [
  {
   "title": "車の購入価格とは",
   "desc": "実はインターネット上で掲載されている中古車情報は全体の約30%に過ぎません。"
  },
  {
   "title": "スマートカーライフプランナー",
   "desc": "燃費がよく小回りがきく車がいいです。また、子供が2人いるので、スペースが広い車で。できるだけ高年式でキズやヘコミがなく、内装もシンプルで状態の良いものだとありがたいです。"
  },
  {
   "title": "片道30分程度の通勤",
   "desc": "アメリカで人気のピックアップトラックを探しています。中古ではなかなか見つからないため苦労しています。左ハンドル・年式が新しい・色は黒を希望しています。"
  }
 ],
 "中村 綾斗": [
  {
   "title": "素晴らしい打楽器奏者リンゴ",
   "desc": "今回のリマスターは素晴らしいですね。アナログの良さを充分引き出して高音質に仕上げたエンジニアの方々へ感謝です。後期のビートルズのアルバムは何百回聴いただろうか?数えきれない回数であることに違いない・・・。"
  }
 ],
 "清水 伸平": [
  {
   "title": "Forever Man",
   "desc": "初回限定オブジェ付を買ったはずが普通のパッケージ。嫌な予感がして商品裏を見ると、薄い箱が。取り出すと、オブジェとは思えない貧相なおまけ。"
  },
  {
   "title": "仁義を通すってことはこういうことなのだろう",
   "desc": "「Old Sock」以来、僅か1年足らずで発売された昨年亡くなった敬愛するJ・J・ケイルに捧げる作品。まずゲスト陣が豪華、ウィリー・ネルソン、マーク・ノップラー、トムペティ、ジョン・メイヤーなどだ。"
  },
  {
   "title": "JJへの感謝とECへの感謝",
   "desc": "Pilgrim以降のECのアルバムはCFGは別物として惰性で聞き流す程度で真剣に聞き入ることもありませんでした。JJのことは昔からAfter MidnightやCocaineの作者であるくらいの認識でRoad to Escondidoもお気に入りではありませんでした。"
  },
  {
   "title": "到着した翌日からヘビロテ盤!",
   "desc": "クラプトン先生のこういう企画は最早や商業的成功なんて全く考えてないんでしょうね。JJ.ケイルに対する敬愛だけは充分に伝わってくる。JJ.ケイルの韜晦なところを聴き易く万人向けにアレンジした感じで、僕は気に入ったのでこの数日間ヘビロテで聴いております。でも音楽にとって「個性」って何なの?とかフト思っちゃいます。"
  }
 ],
 "田中 昌昭": [
  {
   "title": "天国への階段",
   "desc": "6曲目のbornだけで天国へいける。何度繰り返し聴いてもあきない。信じる者は救われるで、この一曲のおかげでアメリカがまた好きになった。"
  },
  {
   "title": "最高のバンドと最高のオーディエンス",
   "desc": "バンドももちろんなのですが、年齢層の高いオーディエンスの皆さんが素晴らしかった!皆さんパットの曲を古いものまで熟知しており、Letter From Homeあたりの曲ではイントロ一小節で「オオッ」と歓声があがり、バンドのメンバーもびっくり。"
  },
  {
   "title": "百花繚乱!ザッツ メセニーミュージック!",
   "desc": "個人的に、日本の歌謡界にも影響を与えたと考えているパットお得意の転調と上昇のアンサンブルが展開します。ジュリオがホーンも演ってるようで、オーケストリオンも自然ですし、ビッグバンドなのかと錯覚してしまいます。ベンのエレベはジャコを思い出させます。"
  },
  {
   "title": "心地よいジャズ・フュージョン最高!!",
   "desc": "このアルバムは、Metheny Groupとしては20年前に発表されたものですが、そのサウンドは今聞いても新鮮な感じがしていてブラジル・ティスト溢れる仕上がりになっています。"
  }
 ]
};
このデータがdata.jsと違うところは名前をキーとした連想配列になっているところです。たとえばリスト画面で「在本 璃奈」さんがタップされたら「在本 璃奈」をキーとして詳細表示データにアクセスします。それはdetailData['在本 璃奈']です。そして、detailData['在本 璃奈']がオブジェクト配列になっているので、要素を一つずつ取り出してはtitleとdescをons-list-itemタグへ設定していきます。それを書いたのが次のコードです。
  var html = '';
  $.each(detailData[currentItem.title], function(i, item) {
   html += '';
   html += '
'; html += '' + item.title + ''; html += '
'; html += '
' + item.desc + '
'; html += '
'; } ); $("#detail-item-list").html(html); var content = $("#detail-item-list").get(0); ons.compile(content);
これは、app.jsで詳細画面(#detail-page)が表示されるとき(pageinitイベント発生時)に実行します。

2016年5月11日水曜日

Onsen UI Master-Detail テンプレート

前回、Onsen UI Master-Detail テンプレートを少しかじって終わりました。そして今回までの宿題として、このアプリをメールアプリに見立てて、タイトル(title)や説明(desc)を日本語にし、できればサムネイルに顔写真を出してみるという課題を与えました。たとえば次のような感じです。


まず、日本語にするにはlist.htmlを修正します。class="item-title"のspanタグに差出人氏名を、class="item-label"のspanタグに経過時間を、そしてclass="item-desc"のpタグにメール本文を書きます。さらに、サムネイルを表示するには顔写真のファイルを用意し、それをimagesフォルダを作ってその中に入れ、class="item-thum"のdivタグ内にimgタグを挿入して写真を出します。このとき、写真の横サイズは50pxに設定しておきます。これだけです。HTMLファイルは次のようになります。
    <ons-page id="list-page">
      <ons-toolbar>
        <div class="center">Master Details</div>
      </ons-toolbar>

      <ons-list>
        <ons-list-item modifier="chevron" class="item">
          <ons-row>
            <ons-col width="60px"> 
              <div class="item-thum">
                <img src="images/arimoto.jpg" class="item-thum-photo" width="50px"></img>  
              </div>
            </ons-col>
            <ons-col>
              <header>
                <span class="item-title">在本 璃奈</span>
                <span class="item-label">3day ago</span>
              </header>
              <p class="item-desc">
                お仕事お疲れ様です。本社営業部の在本です。
                先日(4月30日)の出張の際には、さまざまなお心遣いをいただき、
                誠にありがとうございました。
                深くお礼申し上げます。
                </p>
            </ons-col>
          </ons-row>                          
        </ons-list-item>

        <ons-list-item modifier="chevron" class="item">
          <ons-row>
            <ons-col width="60px"> 
              <div class="item-thum">
                <img src="images/inukai.jpg" class="item-thum-photo" width="50px"></img>  
              </div>
            </ons-col>
            <ons-col>
              <header>
                <span class="item-title">犬飼 佑汰</span>
                <span class="item-label">4h</span>
              </header>
              <p class="item-desc">
                ご多忙中にもかかわらず、
                工場・店舗視察にご同行くださったことを、
                心より感謝しております。
                おかげさまで右往左往することなく、
                仕事に邁進することができました。
                今回いただいたアドバイスを生かし、
                しっかりと精進していきたいと存じます。
                今後ともよろしくご指導のほどお願い申し上げます。
              </p>
            </ons-col>
          </ons-row>                          
        </ons-list-item>

        <ons-list-item modifier="chevron" class="item">
          <ons-row>
            <ons-col width="60px"> 
              <div class="item-thum">
                <img src="images/usui.jpg" class="item-thum-photo" width="50px"></img>  
              </div>
            </ons-col>
            <ons-col>
              <header>
                <span class="item-title">臼井 彰生</span>
                <span class="item-label">6h</span>
              </header>
              <p class="item-desc">
                  お疲れ様です。臼井彰生です。
                    先日お借りしました資料、5月31日にお返しに伺います。
                    お陰様で、大変参考になるデータが多くあり、仕事の上で有意義に生かすことが
                    できました。ご好意に感謝しております。
                    まずは御礼かたがたご連絡まで。
              </p>
            </ons-col>
          </ons-row>                          
        </ons-list-item>

        <ons-list-item modifier="chevron" class="item">
          <ons-row>
            <ons-col width="60px"> 
              <div class="item-thum">
                <img src="images/nakamura.jpg" class="item-thum-photo" width="50px"></img>  
              </div>
            </ons-col>
            <ons-col>
              <header>
                <span class="item-title">中村 綾斗</span>
                <span class="item-label">2m</span>
              </header>
              <p class="item-desc">
                お疲れ様です。営業部の中村です。
                昨日は、ご馳走になりましてありがとうございました。
                また、課長からたくさんの話を伺うことができ、とても勉強になりました。
                正直なところ、今抱えている仕事が行き詰まっていまして、
                課長にご相談したいと思ってはいましたが、なかなか言い出せずにおりました。
              </p>
            </ons-col>
          </ons-row>                          
        </ons-list-item>

        <ons-list-item modifier="chevron" class="item">
          <ons-row>
            <ons-col width="60px"> 
              <div class="item-thum">
                <img src="images/shimizu.jpg" class="item-thum-photo" width="50px"></img>  
              </div>
            </ons-col>
            <ons-col>
              <header>
                <span class="item-title">清水 伸平</span>
                <span class="item-label">5day ago</span>
              </header>
              <p class="item-desc">
                いつもお世話になっております。
                清水伸平です。
                昨日、ご紹介いただいた弁護士の竹田先生にお会いし、お話を伺ってきました。
                先ほど、東京に戻ってきたところです。
              </p>
            </ons-col>
          </ons-row>                          
        </ons-list-item>

        <ons-list-item modifier="chevron" class="item">
          <ons-row>
            <ons-col width="60px"> 
              <div class="item-thum">
                <img src="images/tanaka.jpg" class="item-thum-photo" width="50px"></img>  
              </div>
            </ons-col>
            <ons-col>
              <header>
                <span class="item-title">田中 昌昭</span>
                <span class="item-label">1week ago</span>
              </header>
              <p class="item-desc">
                いつもお世話になっております。
                株式会社川崎システムズ ヘルプデスクです。
                平素は弊社のサービスをご利用いただきまして、誠にありがとうございます。
                6月1日より、レセコンORCAにスマホでアクセスできる
                アプリmyORCAの販売を開始いたしますのでご案内いたします。                  
              </p>
            </ons-col>
          </ons-row>                          
        </ons-list-item>

      </ons-list>
    </ons-page>
とても長いですね。もっと簡略化したいところです。また、このHTMLではメールの数は6件と固定ですが、実用的なものにしようとすればメールの数がいくらあっても表示できるようにしたいところです。そこで、javascriptを使って任意の件数のメールを表示できるようにしてみましょう。そのために、まずメールデータを独立させます。メールデータを次のようにjavascriptオブジェクト形式で表現します。
var listData = [
 {
  "title": "在本 璃奈",
  "label": "3day ago",
  "desc": "お仕事お疲れ様です。本社営業部の在本です。先日(4月30日)の出張の際には、さまざまなお心遣いをいただき、誠にありがとうございました。深くお礼申し上げます。",
  "photo": "images/arimoto.jpg"
 },
 {
  "title": "犬飼 佑汰",
  "label": "4h",
  "desc": "ご多忙中にもかかわらず、工場・店舗視察にご同行くださったことを、心より感謝しております。おかげさまで右往左往することなく、仕事に邁進することができました。今回いただいたアドバイスを生かし、しっかりと精進していきたいと存じます。今後ともよろしくご指導のほどお願い申し上げます。",
  "photo": "images/inukai.jpg"
 },
 {
  "title": "臼井 彰生",
  "label": "6h",
  "desc": "お疲れ様です。臼井彰生です。  先日お借りしました資料、5月31日にお返しに伺います。  お陰様で、大変参考になるデータが多くあり、仕事の上で有意義に生かすことが  できました。ご好意に感謝しております。  まずは御礼かたがたご連絡まで。",
  "photo": "images/usui.jpg"
 },
 {
  "title": "中村 綾斗",
  "label": "2m",
  "desc": "お疲れ様です。営業部の中村です。昨日は、ご馳走になりましてありがとうございました。また、課長からたくさんの話を伺うことができ、とても勉強になりました。正直なところ、今抱えている仕事が行き詰まっていまして、課長にご相談したいと思ってはいましたが、なかなか言い出せずにおりました。",
  "photo": "images/nakamura.jpg"
 },
 {
  "title": "清水 伸平",
  "label": "5day ago",
  "desc": "いつもお世話になっております。清水伸平です。昨日、ご紹介いただいた弁護士の竹田先生にお会いし、お話を伺ってきました。先ほど、東京に戻ってきたところです。",
  "photo": "images/shimizu.jpg"
 },
 {
  "title": "田中 昌昭",
  "label": "1week ago",
  "desc": "いつもお世話になっております。株式会社川崎システムズ ヘルプデスクです。平素は弊社のサービスをご利用いただきまして、誠にありがとうございます。6月1日より、レセコンORCAにスマホでアクセスできるアプリmyORCAの販売を開始いたしますのでご案内いたします。",
  "photo": "images/tanaka.jpg"
 }
];
javascriptオブジェクト形式と言うのは、(属性:属性値)のペアを必要なだけ{と}で囲んだものです。上の例では、title, label, desc, photoという4つの属性があり、それが6人分配列として定義されています(配列は[と]でカンマ区切りの要素を羅列します)。このようにすると、例えばdataList[0].titleの値は"在本 璃奈"となります。これを使ってlist.html内のons-listタグの中身を作成する処理が次のようになります。この処理はapp.jsのlist-pageが表示されるタイミングで実行されるようにしてあります。
(function(){
  'use strict';

  var currentItem = {};

  $(document).on('pageinit', '#detail-page', function() {
    $('.item-title', this).text(currentItem.title);
    $('.item-desc', this).text(currentItem.desc);
    $('.item-label', this).text(currentItem.label);
    $('.item-thum-photo', this).attr('src', currentItem.photo);
    $('.add-note-action-item', this).click(function () {
        alert('dummy message');
    });
  });

  $(document).on('pageinit', '#list-page', function() {
    var html = '';
    $.each(listData, function(i, item) {
        html += '';
        html += '';
        html += ' ';
        html += '
'; html += ''; html += '
'; html += '
'; html += ''; html += '
'; html += '' + item.title + ''; html += '' + item.label + ''; html += '
'; html += '

' + item.desc + '

'; html += '
'; html += '
'; html += '
'; } ); $("#item-list").html(html); var content = $("#item-list").get(0); ons.compile(content); $('.item', this).on('click', function() { currentItem = { title : $('.item-title', this).text(), desc : $('.item-desc', this).text(), label : $('.item-label', this).text(), photo : $('.item-thum-photo', this).attr('src') }; app.navi.pushPage('detail.html'); }); }); })();