前回まで
前回は月の切り替えボタンを作った。
月を変えても、表示内容の変更だけで同じ画面を使い続けるので微妙。
月を変えたら画面自体を新しく作り直したい
というわけでindex.jsをいじって、読み込みごとにカレンダーを作るように修正。
index.js
'use strict';constmoment=require("moment");constipcRenderer=require("electron").ipcRenderer;window.onload=function(){constmonth=parseURLParam(location.search).month;constcallendar=newCallendar(month);callendar.show();//先月ボタン押下時document.getElementById('preMonth').onclick=function(){ipcRenderer.sendSync('month',this.value);}//来月ボタン押下時document.getElementById('nextMonth').onclick=function(){ipcRenderer.sendSync('month',this.value);}}/**
* URLパラメータを分解してkey:valueの形式で返す。
* @param URL
*/functionparseURLParam(URL){// URLパラメータを"&"で分離するconstparams=URL.substr(1).split('&');varparamsArray=[];varkeyAndValue=null;for(vari=0;i<params.length;i++){// "&"で分離したパラメータを"="で再分離keyAndValue=params[i].split("=");// パラメータを連想配列でセットparamsArray[keyAndValue[0]]=keyAndValue[1];}// 連想配列パラメータを返すreturnparamsArray;}/**
* カレンダークラス
* @param month(YYYY-MM)
*/constCallendar=function(month){//コンストラクタthis._moment=moment(month);/**
* カレンダーを表示する。
*/this.show=function(){const__moment=this._moment;//captionを表示document.getElementById('caption').innerText=__moment.format("YYYY年MM月");//当月の日数を取得constdaysOfMonth=__moment.daysInMonth();//月初の曜日を取得(index.htmlと合わせるために+1する)constfirstDayOfManth=__moment.startOf('month').day()+1;//カレンダーの各セルに日付を表示させるletcellIndex=0;for(leti=1;i<daysOfMonth+1;i++){if(i===1){cellIndex+=firstDayOfManth;}else{cellIndex++;}document.getElementById("cell"+cellIndex).innerText=i;}//6行目の第1セルが空白なら6行目自体を非表示にする。if(document.getElementById("cell36").innerText===""){document.getElementById('row6').style.visibility="hidden";}//先月document.getElementById('preMonth').value=__moment.add(-1,'month').format("YYYY-MM");//来月(先月のmomentオブジェクトとなっているので+2ヶ月)document.getElementById('nextMonth').value=__moment.add(2,'month').format("YYYY-MM");}}
新しくCallendarクラスを作成し、状態としてmomentオブジェクトを持つようにした。
window.onload=function(){constmonth=parseURLParam(location.search).month;constcallendar=newCallendar(month);callendar.show();
window.onload内で画面読み込み毎にURLパラメータから表示月を読み込んでカレンダーを作成する。
main.jsにも少し手を加える。
main.js
'use strict';// Electronのモジュールconstelectron=require("electron");// Momentのモジュールconstmoment=require("moment");// アプリケーションをコントロールするモジュールconstapp=electron.app;// ウィンドウを作成するモジュールconstBrowserWindow=electron.BrowserWindow;// メインウィンドウはGCされないようにグローバル宣言letmainWindow;// 全てのウィンドウが閉じたら終了app.on('window-all-closed',function(){if(process.platform!='darwin'){app.quit();}});// Electronの初期化完了後に実行app.on('ready',function(){// 当月をYYYY-MM形式で取得constmonth=moment().format('YYYY-MM');// メイン画面の表示。ウィンドウの幅、高さを指定できるmainWindow=newBrowserWindow({width:800,height:650});// 初期表示は当月をパラメータで渡すmainWindow.loadURL('file://'+__dirname+'/index.html?month='+month);// ウィンドウが閉じられたらアプリも終了mainWindow.on('closed',function(){mainWindow=null;});// ipc通信受信時の処理constipcMain=electron.ipcMain;ipcMain.on('month',(event,arg)=>{// 受信した値をパラメータに渡して画面再読み込みmainWindow.loadURL('file://'+__dirname+'/index.html?month='+arg);})});
ipc通信でメッセージのやり取りを作る
Electronはipc通信とやらでプロセス間のメッセージの送受信機能を実現しているらしい。
使うの自体は簡単。
送信側(index.js)
//ipcモジュールconstipcRenderer=require("electron").ipcRenderer;//先月ボタン押下時document.getElementById('preMonth').onclick=function(){ipcRenderer.sendSync('month',this.value);}//来月ボタン押下時document.getElementById('nextMonth').onclick=function(){ipcRenderer.sendSync('month',this.value);}
ボタンが押されたらipcRenderer.sendSync('month',this.value)で「month」というキーの値を同期送信している。
受信側(main.js)
// ipc通信受信時の処理constipcMain=electron.ipcMain;ipcMain.on('month',(event,arg)=>{// 受信した値をパラメータに渡して画面再読み込みmainWindow.loadURL('file://'+__dirname+'/index.html?month='+arg);})
ipcMain.on('month', コールバック関数)で「month」キーのメッセージ受信時の処理を記述。
受け取った値はコールバック関数の第二引数(ここではargs)で取得可能。
受信した値(YYYY-MM)をパラメータに設定して画面を読み込みなおす。
$ electron .
問題なく月の変更が出来ていそう。
TODO
・月を変える度に画面更新が行われて数秒真っ白画面になっちゃうのが微妙。もっとフレキシブルな切り替えにしたい。
・見た目をどうにかしたい。
あとがき
結局再読み込みになるのでCallendarクラスのメリットがほぼ無い気がしてる。
画面を裏で複数作っておいて、それを切り替えていくとかが良いのかな。
明日、お仕事の方で本番リリースなので寝ます。