2016年6月29日水曜日

中間発表に向けての準備

いよいよ中間発表が迫ってきました。今日はその準備です。まず中間発表の流れを考えます。
  • これまでやってきたこと(3年生秋学期~今日まで)
    • VMware上にLinuxインストール
    • Javascriptの勉強
    • PHP+MySQL
    • 成果:ボールゲーム(オープンキャンパスでパネルからリンク)
  • 卒研テーマ:在宅医療を支援するための医事会計システム(ORCA)連携スマホアプリの開発
    • 概要:
    • 研究の目的(この研究は何のためにやるのか):
    • 目標(卒研でどこまでを目標とするか):
    • 現状(どこまで研究が進んでいるか、今後何をしなければならないか、何か問題はないか):
      • これについては、現在Monacaで開発中のスマホアプリを報告する
      • 患者一覧→患者の受診履歴

VMwareのインストール


VMwareの初期画面

VMwareはWindowsパソコンでLinuxを利用するために必要なコンピュータの仮想化ソフトウェアです。使用したのはVMware Workstation 12 Playerです。

CentOSのインストール

VMware上で稼働するCentOS 6.7

次にVMware上にCentOSをインストールしました。バージョンはCentOS 6.7です。これは、Javascriptの勉強をするためのWebサーバとして稼働させたものです。WebサーバにはApacheを用いました。

ボールゲームの作成

javascriptで開発したボールゲーム
javascriptを勉強するためにボールゲームを作成しました。このゲームは、画面上に3つのボール(バスケットボール、サッカーボール、赤いボール)を動かせ、バスケットボールを上下左右のボタンでコントロールし、サッカーボールにぶつけたら得点、赤玉にぶつけたら減点するというルールで一定の時間内に何点取れるかを競うゲームです。PCだけでなくスマホでも楽しめ、オープンキャンパスで展示しました。

在宅医療を支援するための医事会計システム(ORCA)連携スマホアプリの開発

次に4年生になってから卒研テーマを決定しました。テーマは、診療所内で動いている医療情報システムを、訪問診療の際に、スマホから利用できるようにするシステムを開発することです。なぜこのようなシステムを開発しようとしたかと言うと、医師が訪問先の患者宅や自宅で患者情報を確認したり、処方内容や検査内容を見たいとき、スマホで手軽に見ることができたら便利だと考えたからです。しかし、これはあくまでもで私たちが想像したことで、実際にそのような必要性があるかどうかはきちんと調査しなければなりません。
今回は、医療情報システムとして、日本医師会が開発した日医標準レセプトORCAを利用することにしました。これはいわゆる開業医向けのレセコンです。なぜ、ORCAを選んだかと言うと、ORCAは無料で使えるからです。それだけでなく、全国で1万6千を超えるユーザがいるので、開発したシステムが利用される可能性もあると考えたからです。また、ユーザが多い分、技術情報もたくさんネットから得られるます。しかし、何よりも魅力なのは、ORCAが日医標準レセプトAPIというWebAPIを提供していたことです。WebAPIがあれば、スマホのアプリから簡単にORCAの機能を利用できます。ORCAの内部構造を知らなくても簡単に連携ができるのです。

ORCAのクライアント(患者登録画面)

システム構成図

開発するシステムの構成は次のようになっています。

システム構成

スマホアプリからORCAサーバに向けて患者情報や受診履歴などのリクエストを行います。その際、スマホアプリは日医標準レセプトAPIを利用します。 今回、スマホアプリは3年次生の時に勉強したjavascriptで作成しました。開発環境としてはクラウド型スマホアプリ開発環境であるMonacaを利用しています。MonacaはHTML5+javascriptでハイブリッドスマホアプリを開発できる開発環境です。また、javascriptライブラリとしてはjQueryを利用しました。そのjavascriptを使ってHttpRequestを利用してORCAサーバにHTTPリクエストを送ります。すると、ORCAはリクエストに対するレスポンスをXML形式で返してきます。たとえば、次のXMLデータは、スマホが患者基本情報を要求したときのレスポンスデータです。

<?xml version="1.0" encoding="UTF-8"?>
<xmlio2>
  <patientinfores type="record">
    <Information_Date type="string">2016-06-29</Information_Date>
    <Information_Time type="string">09:18:03</Information_Time>
    <Api_Result type="string">00</Api_Result>
    <Api_Result_Message type="string">処理終了</Api_Result_Message>
    <Reskey type="string">Patient Info</Reskey>
    <Patient_Information type="record">
      <Patient_ID type="string">00001</Patient_ID>
      <WholeName type="string">川崎 太郎</WholeName>
      <WholeName_inKana type="string">カワサキ タロウ</WholeName_inKana>
      <BirthDate type="string">1958-07-06</BirthDate>
      <Sex type="string">1</Sex>
      <HouseHolder_WholeName type="string">川崎 太郎</HouseHolder_WholeName>
      <Relationship type="string">本人</Relationship>
      <Home_Address_Information type="record">
        <Address_ZipCode type="string">7010114</Address_ZipCode>
        <WholeAddress1 type="string">岡山県倉敷市松島</WholeAddress1>
        <PhoneNumber1 type="string">086-462-1234</PhoneNumber1>
        <PhoneNumber2 type="string">086-462-1111</PhoneNumber2>
      </Home_Address_Information>
      <Community_Cid_Agree type="string">False</Community_Cid_Agree>
      <FirstVisit_Date type="string">2016-06-11</FirstVisit_Date>
      <LastVisit_Date type="string">2016-06-12</LastVisit_Date>
      <HealthInsurance_Information type="array">
        <HealthInsurance_Information_child type="record">
          <Insurance_Combination_Number type="string">0001</Insurance_Combination_Number>
          <InsuranceCombination_Rate_Admission type="string">0.30</InsuranceCombination_Rate_Admission>
          <InsuranceCombination_Rate_Outpatient type="string">0.30</InsuranceCombination_Rate_Outpatient>
          <InsuranceProvider_Class type="string">060</InsuranceProvider_Class>
          <InsuranceProvider_Number type="string">330019</InsuranceProvider_Number>
          <InsuranceProvider_WholeName type="string">国保</InsuranceProvider_WholeName>
          <HealthInsuredPerson_Symbol type="string">あいう</HealthInsuredPerson_Symbol>
          <HealthInsuredPerson_Number type="string">123456</HealthInsuredPerson_Number>
          <HealthInsuredPerson_Assistance type="string">3</HealthInsuredPerson_Assistance>
          <HealthInsuredPerson_Assistance_Name type="string">3割</HealthInsuredPerson_Assistance_Name>
          <RelationToInsuredPerson type="string">1</RelationToInsuredPerson>
          <HealthInsuredPerson_WholeName type="string">川崎 太郎</HealthInsuredPerson_WholeName>
          <Certificate_StartDate type="string">2016-06-05</Certificate_StartDate>
          <Certificate_ExpiredDate type="string">9999-12-31</Certificate_ExpiredDate>
          <Insurance_CheckDate type="string">2016-06-05</Insurance_CheckDate>
        </HealthInsurance_Information_child>
      </HealthInsurance_Information>
    </Patient_Information>
  </patientinfores>
</xmlio2>
スマホアプリは受け取ったXMLデータを画面にレンダリングします。
なぜこのようなシステムを開発するのか
私たちのゼミではなぜスマホを使ったこうしたシステムを開発するのか説明しておきましょう。私たちのゼミでは、3年前からスマホを使って在宅医療を支援するシステムの開発を行ってきました。昨年はPACSサーバを構築して、訪問診察など外出先からスマホを使って画像を送ったり検索・閲覧したりするシステムを開発しました。 画像ができたので、じゃあ、今度は電子カルテをスマホから利用できるようにしたいと思い、今年のテーマに選びました。しかし、診療所向きで私たちが入手できる電子カルテがありませんでした。そこで、日本医師会が無料で提供しているORCAに注目したのです。ORCAは医事会計システム(レセプトシステム:レセコン)で、電子カルテではありません。したがって、医師が書く診療録は入っていません。患者情報と診療行為のみです。しかも、診療報酬に必要なデータしか入っていないので、例えば検査結果などは入っていません。ですから在宅診療に利用するには機能はかなり限定的です。しかし、手法自体はスマホが連携する相手がORCAであろうが電子カルテであろうが変わりません。つまり、今回の研究は実用性を目指すというよりも方法論を示すための研究です。この方法でうまくスマホ連携ができれば、あとはこの考え方で様々なシステムを連携を図ればよいのです。ですから、今回の研究の目的は「スマホを使って在宅医療を支援する」ですが、目標は「スマホとORCAの情報連携を確立する」ということになります。その際に利用するのがWebAPIというわけです。

2016年6月22日水曜日

ORCAについてもっと知ろう!

私たちのゼミではORCAの機能をスマートフォンから利用できるアプリを開発しています。ではなぜこのようなアプリを開発する必要があるのでしょうか?ORCAは診療所で利用されているオープンソフトウェアの医事会計システムです。2016-05-16現在で稼働実績は15,656施設にも達しており、非常によく利用されている医事会計システムといってよいでしょう。ちなみに平成27年1月現在の診療所の数は100,801施設です(厚生労働省医療施設実態調査)。すなわちORCAのシェアは約16%ということになります。ちなみに一般診療所向け医事会計システムのシェアNo.1はパナソニックのメディコムで38.9%(2015年9月現在)ということです。
さて、そのORCAをスマホ等のモバイル端末で操作できるソフトウェアは殆どありません(ORCA mobiClipla)。医事会計システムをモバイル端末で操作できるメリットを考えてみましょう。
  • 在宅医療など出先からでも患者の情報を参照できる
  • どんな薬をいつ出したかがわかる
  • どんな検査をいつ行ったかがわかる
  • 外出先から診療予約を入れることができる
  • 外出先から診療行為を入力することができる
このようにいろいろ考えることができますが、実際の現場で利用されるかどうか、必要性があるかどうかはわかりません。今はそういうアプリがあったらいいなという思い込みで開発を進めていますが、いずれそれについても調べる必要があるでしょう。


2016年6月15日水曜日

ORCAに触ってみよう!

ORCAは日本医師会が開発した診療所向けの医事会計システムです。オープンソフトなので自由にダウンロードして利用できます。実際の業務で利用することを想定していますので膨大な機能があります。このゼミではスマホからORCAの機能を呼び出して利用するアプリの開発を目指しています。
では、ORCAがどのようなものかを把握するために操作マニュアルに従ってORCAで職員登録と患者登録を行ってみます。
ORCAを利用するには、ORCAクライアントを使います。ORCAクライアントはGoogleドライブのORCAフォルダへ保存してあります(ORCAクライアントはここからダウンロードできます。Java Web Start版をダウンロードしてください)。起動したら次の手順でサーバの設定を行います。
  1. [ホスト(ポート)]に172.16.108.250と8000を入力
  2. [ユーザ]にormaster
  3. [パスワード]にormaster
  4. [パスワードを保存]をチェック
  5. [接続]をクリック
 ORCAクライアントが起動したら、職員登録を行います。職員登録についてはマニュアルの「第5章マスタ登録」-[5.1システム管理マスタ]の「1010 職員情報」に従って行ってください。
職員登録ができたらいったんORCAクライアントを終了させて、再び起動して、登録したユーザでログインしてください。
次に患者登録を行います。患者登録は入力マニュアルの「第2章日時業務」-「2.2登録(患者登録について)」に従って行ってください。

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'); }); }); })();

2016年4月27日水曜日

いよいよOnsen-UIへ

今日までの宿題だったMonacaカウンターにタイマー仕掛けでストップウォッチ機能を付けました。それがこれです。


このアプリは起動と同時に1秒ごとにカウントを表示していきます。プログラムは以下のようになります。
<!DOCTYPE HTML>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <meta http-equiv="Content-Security-Policy" content="default-src * data:; style-src * 'unsafe-inline'; script-src * 'unsafe-inline' 'unsafe-eval'">
    <script src="components/loader.js"></script>
    <link rel="stylesheet" href="components/loader.css">
    <link rel="stylesheet" href="css/style.css">
    <script>
    var timer_id;
    var count = 0;
    function increment() {
        count++;
        update();
    }
    function reset() {
        if (count > 0 && confirm('カウンターをリセットしますか?')) {
            count = 0;
            update();
        }
    }
    function update() {
        var str = '0000' + count;
        str = str.substring(str.length - 4, str.length);
        var digits = $('.counter-digit');
        for (var i = 0; i < str.length; i++) {
            digits.get(i).src = 'img/no_0' + str[i] + '.png'
        }
    }
    $(function() {
        $('.count-button').on("touchend", increment);
        $('.reset-button').on("touchend", reset);
        $('.counter').on("touchend", function(){
            if(timer_id >= 0) {
                clearInterval(timer_id);
                timer_id = -1;
            } else {
                timer_id = setInterval( function () {
                    increment();
                } , 1000 );
            };
            
        });
        update();
        timer_id = setInterval( function () {
            increment();
        } , 1000 );
    })
    </script>
</head>
<body>
<div class="counter">
    <img src="img/no_00.png" width="55" class="counter-digit">
    <img src="img/no_00.png" width="55" class="counter-digit">
    <img src="img/no_00.png" width="55" class="counter-digit">
    <img src="img/no_00.png" width="55" class="counter-digit">
</div>
<div class="reset-button-wrapper">
    <button class="reset-button"><img src="img/btn_reset_normal.png" width="64"></button>
</div>
<button class="count-button"><img src="img/btn_count_normal.png" width="127"></button>
</body>
</html>
また、今回からOnsen-UI(5章)を始めました。今日は 5-6 Onse UI Master-Detailテンプレートまでやりました。次回までの課題として、表示内容を次のように変えてみることになりました。
  • 表示内容を日本語にする
  • 項目タイトルは名前にする
  • 項目説明はメール内容にする
  • できれば、左の四角の箱に写真を出す