- 投稿日:2021-08-15T22:26:01+09:00
履歴書の年表アプリ
まえがき こんにちは、今回も練習の一環で自作物を作りました。 お題は「履歴書で使用する年表を計算してくれるアプリ」です。 言葉で説明されてもわかりにくいと思うので、とりあえず完成品をお見せします。 この様に生年月日を入力すると、いつ入学して、いつ卒業したのかの一覧を作ってくれる簡素なアプリです。 自分で計算するとなると面倒くさいですよね?少なくとも前回の閏年判定アプリよりは使えますね! 小学校入学・卒業なんて履歴書に書かないとは思いますが… 今回も制作の記録をここに残します。 制作時間は12時間です。 もくじ 1.目的 2.結果 3.制作の流れ 4.ふりかえり 1. 目的 このアプリのメインである履歴年表の処理自体は非常に簡単だと思います。 生まれた年から足し算をして、その結果を画面に表示させるだけなのだから。 難しそうなのは4月2日の判定と入力制限だと思います。 特に入力制限に関して、31日がない月と、2月の閏年は厄介そうな問題だと思いました。 ということで今回の目的は、キッチリと入力制限が施された実用的なアプリを作ることを目的にします。 2. 結果 完成品は以下のような見た目です。 1: 「なし」のラジオボタンをチェックした状態で履歴年表作成を押すと高校卒業以降は表示されません。 2: 「専門・短大」のラジオボタンをチェックした状態で履歴年表作成を押すと専門・短大の年表が表示されます。 3: 「4年制大学」のラジオボタンをチェックした状態で履歴年表作成を押すと4年制大学の年表が表示されます。 4: 値が入力されたいない状態で履歴年表作成を押すと、未入力であると注意されます。 5: 存在しない月日の状態で履歴年表作成を押すと、値が不正であると注意されます。 6: 閏年を判定します。閏年以外は2月29日を存在しない月日と判断します。 3. 制作の流れ 「1.目的」でも触れましたが、このアプリで厄介そうな”4月2日の判定と入力制限(31日がない月と、2月の閏年)”の問題を中心に話を進めます。 そして、後に判明した「プルダウンで未入力だった時の判定」について最後に話したいと思います。 4月2日の判定 入力制限 プルダウンで未入力だった時の判定 また、今回は製作途中の変数名などは日本語です。これは私の英語力の問題です。 完成時には英語に直しています。 4月2日の判定 日本では4月1日生まれか、4月2日生まれかで学年が変わります。 つまり、4月1日生まれなら生年から6年を足せば小学校入学ですが、4月2日生まれなら7年を足さないといけません。 入力された値が4月1日よりも値が大きければ、7年を足し、小さければ6年を足す。 という処理になると思います。 ということで以下のように月を100倍し、その後月と日の値を足して401より大きかどうか判定します。 (後で気が付きましたがmonthStatasの渡す値は最初から100倍にしててもよさそうですね…) const monthStatas = 4; const dayStatas = 2; const 月 = Number(monthStatas) * 100; const 日 = Number(dayStatas); let 月日 = 月 + 日; let 自分の履歴; const 履歴 = function(set){ let 履歴配列 = []; if(set > 401){ 履歴配列.push(7); return 自分の履歴 = 履歴配列; }else{ 履歴配列.push(6); return 自分の履歴 = 履歴配列; } } console.log(履歴(月日)); ”自分の履歴”という配列を使用しているのは、完成版では表示させる際にインデックスで指定して値を表示させたいからです。 出力結果 ちなみに月日が401の時は以下のように出力されます。 大丈夫そうですね。 入力制限 31日がない月と、2月の閏年の問題… より具体的に考えると 2月30日、2月31日、4月31日、6月31日、9月31日、11月31日 それと閏年でない場合は2月29日、以上の7日の入力制限をする必要があります。 順番としては、まず閏年の判定を行い、その後閏年ならば上記の6日を除外、閏年でない場合は上記の6日に加えて2月29日も除外します。 閏年の判定 前に書いた記事”『閏年判定アプリ』を作った”にてコメントで教えていただいた方法で判定しようと思います。 if( new Date(生年, 1, 29).getDate() === 29 ){ console.log("閏年です"); } console.log("閏年ではない"); これはnew Date()に変数yearと2月の29番目を設定し、それが存在する年の場合は29を返すのでtrueになります。 他にも方法がありますので。詳しくは 閏年の判定方法について をご参照ください。 閏年の場合、閏年でない場合の判定 閏年の場合と閏年でない場合で除外する配列を作り、includes()で判定しようと思います。 const 閏年の時の除外日 = [230, 231, 431, 631, 931, 1131]; const 閏年でないの時の除外日 = [229, 230, 231, 431, 631, 931, 1131]; 入力された月日が、閏年なら上の配列、閏年でなければ下の配列を参照して一致する数字列があるかどうか確認します。 function 入力制限(生年, 月日){ if( new Date(生年, 1, 29).getDate() === 29 ){ if(閏年の時の除外日.includes(月日)){ return; //閏年で、なおかつ存在しない月日 }else{ return; //閏年で、存在する月日 } }else{ if(閏年でないの時の除外日.includes(月日)){ return; //閏年でなく、なおかつ存在しない月日 }else{ return; //閏年でなく、存在する月日 } } } この判定が正しいのかどうかを1990年~2000年にかけて境界値分析を行い、問題ないことを確認しました。 プルダウンで未入力だった時の判定 今回、プルダウンメニューを使用しており、見栄えの関係上、一番上の数値はハイフンにしています。 そして、このハイフンを選択した状態でボタンを押された時 「注意!未入力の箇所があります。」と表示されるようにしたいと思います。 一番簡単だと思ったのは、ハイフンの箇所に設定する値(value)をInfinityにするという方法です。 19<select name="num" id = "pulldownYear"> <option value=Infinity>-</option><!--年--> <!--以下中略--> <select name="month" id = "pulldownMonth"><!--月--> <option value=Infinity>-</option> <!--以下中略--> <select name="day" id = "pulldownDay"><!--日--> <option value=Infinity>-</option> <!--以下省略--> こうすることで、JavaScriptで以下のような判定ができます。 if(!(生年 + 月 + 日 === Infinity)){} この様な強引な判定ができます。3つの値のどれか一つでもInfinityが含まれていたらInfinityになります。 ORを使うほうが正しいと思いますが… 4. ふりかえり 今回は「3.制作の流れ」にて触れてはいませんでしたが、try{}catch{}を使うなど色々教科書に書かれていたことを実際に導入することができて楽しかったです。制作の目的としていたキッチリと入力制限が施された実用的なアプリを作ることは満足いく結果でした。次はオブジェクト指向を用いた、アプリケーションの自作に挑戦してみたいです。 ここまで読んでいただきありがとうございました。 最後に、(CSSは特に面白いことはしてないので…)HTMLとJavaScriptを公開します。 もっと綺麗なコードが書けるよう精進していきます。 <!DOCTYPE html> <html> <head> <meta charset = "UTF-8"> <title>自分の履歴年表作成アプリ</title> <link rel = "stylesheet" href = "styles.css"> </head> <body> <!--全体の親要素---> <div class = "relative"> <!--プルダウンメニュー親要素---> <div class = "pulldownM"> <!--0~99までの年数用プルダウンメニュー---> 19<select name="num" id = "pulldownYear"> <option value=Infinity>-</option> <!--中略---> <option value="99">99</option> </select>年 <!--1~12までの月数用プルダウンメニュー---> <select name="month" id = "pulldownMonth"> <option value=Infinity>-</option> <!--中略---> <option value="12">12</option> </select>月 <!--1~31までの日数用プルダウンメニュー---> <select name="day" id = "pulldownDay"> <option value=Infinity>-</option> <!--中略---> <option value="31">31</option> </select>日 </div> <!--注意書き表示用要素---> <div id = "cautionId"> </div> <!--履歴年表作成ボタン要素---> <div class = buttonM> <div id = "button">履歴年表作成</div> </div> <!--履歴年表表示用要素---> <div class = "historyList"> <div id = "output1">----</div> <div id = "output2">----</div> <div id = "output3">----</div> <div id = "output4">----</div> <div id = "output5">----</div> <div id = "output6">----</div> <div id = "output7">----</div> <div id = "output8">----</div> </div> <!--ラジオボタン用要素---> <div class = "ridiobuttonM"> <input type="radio" name="q2" id = "radioA" checked> なし <input type="radio" name="q2" id = "radioB" > 専門・短大 <input type="radio" name="q2" > 4年制大学 </div> </div> <script src = main.js></script> </body> </html> //履歴年表作成ボタンを押したらイベントスタート const RirekiNenpyouSakusei = document.getElementById('button'); RirekiNenpyouSakusei.addEventListener('click', () => { //プルダウンメニューの3つの値 const yearStatas = document.getElementById("pulldownYear"); const monthStatas = document.getElementById("pulldownMonth"); const dayStatas = document.getElementById("pulldownDay"); //プルダウンメニューの3つの値の前処理 const yearStatasN = Number(yearStatas.value) + 1900; const monthN = Number(monthStatas.value) * 100; const dayN = Number(dayStatas.value); //100倍した月の値と、日の値を足す let monthDayN = monthN + dayN; //閏年の時(上)と閏年でない時(下)の除外する値 const NonDayLyear = [230, 231, 431, 631, 931, 1131]; const NonDayNotLyear = [229, 230, 231, 431, 631, 931, 1131]; //結果を表示させる際に使用する大域変数 let myHistory; //入力制限用関数 function InputLimit(year, monthDay){ if(!(year + monthDay === Infinity)){//プルダウンメニューでハイフンが選択されているかどうかの判定 if( new Date(year, 1, 29).getDate() === 29 ){//閏年の判定 if(NonDayLyear.includes(monthDay)){//閏年の時に除外する値の判定 const cautionA = document.getElementById("cautionId"); cautionA.textContent = `値が不正です。`; return Sakuzyo(); }else{ const erase = document.getElementById("cautionId"); erase.textContent = ``; return history(monthDay); } }else{ if(NonDayNotLyear.includes(monthDay)){//閏年でない時に除外する値の判定 const cautionB = document.getElementById("cautionId"); cautionB.textContent = `値が不正です。`; return Sakuzyo(); }else{ const erase = document.getElementById("cautionId"); erase.textContent = ``; return history(monthDay); } } }else{ const cautionC = document.getElementById("cautionId"); cautionC.textContent = `注意!未入力の箇所があります。`; return Sakuzyo(); } } const history = function(set){//大域変数myHistoryに配列を設定するための関数 let historyArray = []; if(set > 401){//4月1日以降であるかどうかを判定 historyArray.push(yearStatasN + 7); historyArray.push(yearStatasN + 13); historyArray.push(yearStatasN + 16); historyArray.push(yearStatasN + 19); historyArray.push(yearStatasN + 21); historyArray.push(yearStatasN + 23); return myHistory = historyArray; }else{ historyArray.push(yearStatasN + 6); historyArray.push(yearStatasN + 12); historyArray.push(yearStatasN + 15); historyArray.push(yearStatasN + 18); historyArray.push(yearStatasN + 20); historyArray.push(yearStatasN + 22); return myHistory = historyArray; } } InputLimit(yearStatasN, monthDayN);//入力制限用関数の呼び出し try{//入力制限用関数で処理がはじかれた際にエラーを出してしまうのでそれを捕えるためのtry..catch... const pa1 = document.getElementById("output1"); pa1.textContent = `小学校入学${myHistory[0]}年4月`; const pa2 = document.getElementById("output2"); pa2.textContent = `小学校卒業${myHistory[1]}年3月`; const pa3 = document.getElementById("output3"); pa3.textContent = `中学校入学${myHistory[1]}年4月`; const pa4 = document.getElementById("output4"); pa4.textContent = `中学校卒業${myHistory[2]}年3月`; const pa5 = document.getElementById("output5"); pa5.textContent = `高校入学${myHistory[2]}年4月`; const pa6 = document.getElementById("output6"); pa6.textContent = `高校卒業${myHistory[3]}年3月`; const radiocheckA = document.getElementById('radioA'); const radiocheckB = document.getElementById('radioB'); if(radiocheckA.checked){//ラジオボタンの値によって表示を変化させる const pa7 = document.getElementById("output7"); pa7.textContent = `----`; const pa8 = document.getElementById("output8"); pa8.textContent = `----`; return; }else if(radiocheckB.checked){ const pa7 = document.getElementById("output7"); pa7.textContent = `専門・短大入学${myHistory[3]}年4月`; const pa8 = document.getElementById("output8"); pa8.textContent = `専門・短大卒業${myHistory[4]}年3月`; return; }else{ const pa7 = document.getElementById("output7"); pa7.textContent = `大学入学${myHistory[3]}年4月`; const pa8 = document.getElementById("output8"); pa8.textContent = `大学卒業${myHistory[5]}年3月`; return; } }catch(err){ console.log(`出力部分エラー:${err.message}`);//特に意味はない } }); const Sakuzyo = () => {//入力制限用関数ではじかれた際に出力済みの結果を消去する const pa1 = document.getElementById("output1"); pa1.textContent = `----`; const pa2 = document.getElementById("output2"); pa2.textContent = `----`; const pa3 = document.getElementById("output3"); pa3.textContent = `----`; const pa4 = document.getElementById("output4"); pa4.textContent = `----`; const pa5 = document.getElementById("output5"); pa5.textContent = `----`; const pa6 = document.getElementById("output6"); pa6.textContent = `----`; const pa7 = document.getElementById("output7"); pa7.textContent = `----`; const pa8 = document.getElementById("output8"); pa8.textContent = `----`; } 参考文献:初めてのJavaScript
- 投稿日:2021-08-15T22:26:01+09:00
履歴書の年表アプリ 2021/8/17更新
まえがき こんにちは、今回も練習の一環で自作物を作りました。 お題は「履歴書で使用する年表を計算してくれるアプリ」です。 言葉で説明されてもわかりにくいと思うので、とりあえず完成品をお見せします。 この様に生年月日を入力すると、いつ入学して、いつ卒業したのかの一覧を作ってくれる簡素なアプリです。 自分で計算するとなると面倒くさいですよね?少なくとも前回の閏年判定アプリよりは使えますね! 小学校入学・卒業なんて履歴書に書かないとは思いますが… 今回も制作の記録をここに残します。 制作時間は12時間です。 もくじ 1.目的 2.結果 3.制作の流れ 4.ふりかえり 5.更新版 2021/8/17更新 1. 目的 このアプリのメインである履歴年表の処理自体は非常に簡単だと思います。 生まれた年から足し算をして、その結果を画面に表示させるだけなのだから。 難しそうなのは4月2日の判定と入力制限だと思います。 特に入力制限に関して、31日がない月と、2月の閏年は厄介そうな問題だと思いました。 ということで今回の目的は、キッチリと入力制限が施された実用的なアプリを作ることを目的にします。 2. 結果 完成品は以下のような見た目です。 1: 「なし」のラジオボタンをチェックした状態で履歴年表作成を押すと高校卒業以降は表示されません。 2: 「専門・短大」のラジオボタンをチェックした状態で履歴年表作成を押すと専門・短大の年表が表示されます。 3: 「4年制大学」のラジオボタンをチェックした状態で履歴年表作成を押すと4年制大学の年表が表示されます。 4: 値が入力されたいない状態で履歴年表作成を押すと、未入力であると注意されます。 5: 存在しない月日の状態で履歴年表作成を押すと、値が不正であると注意されます。 6: 閏年を判定します。閏年以外は2月29日を存在しない月日と判断します。 3. 制作の流れ 「1.目的」でも触れましたが、このアプリで厄介そうな”4月2日の判定と入力制限(31日がない月と、2月の閏年)”の問題を中心に話を進めます。 そして、後に判明した「プルダウンで未入力だった時の判定」について最後に話したいと思います。 4月2日の判定 入力制限 プルダウンで未入力だった時の判定 また、今回は製作途中の変数名などは日本語です。これは私の英語力の問題です。 完成時には英語に直しています。 4月2日の判定 日本では4月1日生まれか、4月2日生まれかで学年が変わります。 つまり、4月1日生まれなら生年から6年を足せば小学校入学ですが、4月2日生まれなら7年を足さないといけません。 入力された値が4月1日よりも値が大きければ、7年を足し、小さければ6年を足す。 という処理になると思います。 ということで以下のように月を100倍し、その後月と日の値を足して401より大きかどうか判定します。 (後で気が付きましたがmonthStatasの渡す値は最初から100倍にしててもよさそうですね…) const monthStatas = 4; const dayStatas = 2; const 月 = Number(monthStatas) * 100; const 日 = Number(dayStatas); let 月日 = 月 + 日; let 自分の履歴; const 履歴 = function(set){ let 履歴配列 = []; if(set > 401){ 履歴配列.push(7); return 自分の履歴 = 履歴配列; }else{ 履歴配列.push(6); return 自分の履歴 = 履歴配列; } } console.log(履歴(月日)); ”自分の履歴”という配列を使用しているのは、完成版では表示させる際にインデックスで指定して値を表示させたいからです。 出力結果 ちなみに月日が401の時は以下のように出力されます。 大丈夫そうですね。 入力制限 31日がない月と、2月の閏年の問題… より具体的に考えると 2月30日、2月31日、4月31日、6月31日、9月31日、11月31日 それと閏年でない場合は2月29日、以上の7日の入力制限をする必要があります。 順番としては、まず閏年の判定を行い、その後閏年ならば上記の6日を除外、閏年でない場合は上記の6日に加えて2月29日も除外します。 閏年の判定 前に書いた記事”『閏年判定アプリ』を作った”にてコメントで教えていただいた方法で判定しようと思います。 if( new Date(生年, 1, 29).getDate() === 29 ){ console.log("閏年です"); } console.log("閏年ではない"); これはnew Date()に変数yearと2月の29番目を設定し、それが存在する年の場合は29を返すのでtrueになります。 他にも方法がありますので。詳しくは 閏年の判定方法について をご参照ください。 閏年の場合、閏年でない場合の判定 閏年の場合と閏年でない場合で除外する配列を作り、includes()で判定しようと思います。 const 閏年の時の除外日 = [230, 231, 431, 631, 931, 1131]; const 閏年でないの時の除外日 = [229, 230, 231, 431, 631, 931, 1131]; 入力された月日が、閏年なら上の配列、閏年でなければ下の配列を参照して一致する数字列があるかどうか確認します。 function 入力制限(生年, 月日){ if( new Date(生年, 1, 29).getDate() === 29 ){ if(閏年の時の除外日.includes(月日)){ return; //閏年で、なおかつ存在しない月日 }else{ return; //閏年で、存在する月日 } }else{ if(閏年でないの時の除外日.includes(月日)){ return; //閏年でなく、なおかつ存在しない月日 }else{ return; //閏年でなく、存在する月日 } } } この判定が正しいのかどうかを1990年~2000年にかけて境界値分析を行い、問題ないことを確認しました。 プルダウンで未入力だった時の判定 今回、プルダウンメニューを使用しており、見栄えの関係上、一番上の数値はハイフンにしています。 そして、このハイフンを選択した状態でボタンを押された時 「注意!未入力の箇所があります。」と表示されるようにしたいと思います。 一番簡単だと思ったのは、ハイフンの箇所に設定する値(value)をInfinityにするという方法です。 19<select name="num" id = "pulldownYear"> <option value=Infinity>-</option><!--年--> <!--以下中略--> <select name="month" id = "pulldownMonth"><!--月--> <option value=Infinity>-</option> <!--以下中略--> <select name="day" id = "pulldownDay"><!--日--> <option value=Infinity>-</option> <!--以下省略--> こうすることで、JavaScriptで以下のような判定ができます。 if(!(生年 + 月 + 日 === Infinity)){} この様な強引な判定ができます。3つの値のどれか一つでもInfinityが含まれていたらInfinityになります。 ORを使うほうが正しいと思いますが… 4. ふりかえり 今回は「3.制作の流れ」にて触れてはいませんでしたが、try{}catch{}を使うなど色々教科書に書かれていたことを実際に導入することができて楽しかったです。制作の目的としていたキッチリと入力制限が施された実用的なアプリを作ることは満足いく結果でした。次はオブジェクト指向を用いた、アプリケーションの自作に挑戦してみたいです。 ここまで読んでいただきありがとうございました。 最後に、(CSSは特に面白いことはしてないので…)HTMLとJavaScriptを公開します。 もっと綺麗なコードが書けるよう精進していきます。 <!DOCTYPE html> <html> <head> <meta charset = "UTF-8"> <title>自分の履歴年表作成アプリ</title> <link rel = "stylesheet" href = "styles.css"> </head> <body> <!--全体の親要素---> <div class = "relative"> <!--プルダウンメニュー親要素---> <div class = "pulldownM"> <!--0~99までの年数用プルダウンメニュー---> 19<select name="num" id = "pulldownYear"> <option value=Infinity>-</option> <!--中略---> <option value="99">99</option> </select>年 <!--1~12までの月数用プルダウンメニュー---> <select name="month" id = "pulldownMonth"> <option value=Infinity>-</option> <!--中略---> <option value="12">12</option> </select>月 <!--1~31までの日数用プルダウンメニュー---> <select name="day" id = "pulldownDay"> <option value=Infinity>-</option> <!--中略---> <option value="31">31</option> </select>日 </div> <!--注意書き表示用要素---> <div id = "cautionId"> </div> <!--履歴年表作成ボタン要素---> <div class = buttonM> <div id = "button">履歴年表作成</div> </div> <!--履歴年表表示用要素---> <div class = "historyList"> <div id = "output1">----</div> <div id = "output2">----</div> <div id = "output3">----</div> <div id = "output4">----</div> <div id = "output5">----</div> <div id = "output6">----</div> <div id = "output7">----</div> <div id = "output8">----</div> </div> <!--ラジオボタン用要素---> <div class = "ridiobuttonM"> <input type="radio" name="q2" id = "radioA" checked> なし <input type="radio" name="q2" id = "radioB" > 専門・短大 <input type="radio" name="q2" > 4年制大学 </div> </div> <script src = main.js></script> </body> </html> //履歴年表作成ボタンを押したらイベントスタート const RirekiNenpyouSakusei = document.getElementById('button'); RirekiNenpyouSakusei.addEventListener('click', () => { //プルダウンメニューの3つの値 const yearStatas = document.getElementById("pulldownYear"); const monthStatas = document.getElementById("pulldownMonth"); const dayStatas = document.getElementById("pulldownDay"); //プルダウンメニューの3つの値の前処理 const yearStatasN = Number(yearStatas.value) + 1900; const monthN = Number(monthStatas.value) * 100; const dayN = Number(dayStatas.value); //100倍した月の値と、日の値を足す let monthDayN = monthN + dayN; //閏年の時(上)と閏年でない時(下)の除外する値 const NonDayLyear = [230, 231, 431, 631, 931, 1131]; const NonDayNotLyear = [229, 230, 231, 431, 631, 931, 1131]; //結果を表示させる際に使用する大域変数 let myHistory; //入力制限用関数 function InputLimit(year, monthDay){ if(!(year + monthDay === Infinity)){//プルダウンメニューでハイフンが選択されているかどうかの判定 if( new Date(year, 1, 29).getDate() === 29 ){//閏年の判定 if(NonDayLyear.includes(monthDay)){//閏年の時に除外する値の判定 const cautionA = document.getElementById("cautionId"); cautionA.textContent = `値が不正です。`; return Sakuzyo(); }else{ const erase = document.getElementById("cautionId"); erase.textContent = ``; return history(monthDay); } }else{ if(NonDayNotLyear.includes(monthDay)){//閏年でない時に除外する値の判定 const cautionB = document.getElementById("cautionId"); cautionB.textContent = `値が不正です。`; return Sakuzyo(); }else{ const erase = document.getElementById("cautionId"); erase.textContent = ``; return history(monthDay); } } }else{ const cautionC = document.getElementById("cautionId"); cautionC.textContent = `注意!未入力の箇所があります。`; return Sakuzyo(); } } const history = function(set){//大域変数myHistoryに配列を設定するための関数 let historyArray = []; if(set > 401){//4月1日以降であるかどうかを判定 historyArray.push(yearStatasN + 7); historyArray.push(yearStatasN + 13); historyArray.push(yearStatasN + 16); historyArray.push(yearStatasN + 19); historyArray.push(yearStatasN + 21); historyArray.push(yearStatasN + 23); return myHistory = historyArray; }else{ historyArray.push(yearStatasN + 6); historyArray.push(yearStatasN + 12); historyArray.push(yearStatasN + 15); historyArray.push(yearStatasN + 18); historyArray.push(yearStatasN + 20); historyArray.push(yearStatasN + 22); return myHistory = historyArray; } } InputLimit(yearStatasN, monthDayN);//入力制限用関数の呼び出し try{//入力制限用関数で処理がはじかれた際にエラーを出してしまうのでそれを捕えるためのtry..catch... const pa1 = document.getElementById("output1"); pa1.textContent = `小学校入学${myHistory[0]}年4月`; const pa2 = document.getElementById("output2"); pa2.textContent = `小学校卒業${myHistory[1]}年3月`; const pa3 = document.getElementById("output3"); pa3.textContent = `中学校入学${myHistory[1]}年4月`; const pa4 = document.getElementById("output4"); pa4.textContent = `中学校卒業${myHistory[2]}年3月`; const pa5 = document.getElementById("output5"); pa5.textContent = `高校入学${myHistory[2]}年4月`; const pa6 = document.getElementById("output6"); pa6.textContent = `高校卒業${myHistory[3]}年3月`; const radiocheckA = document.getElementById('radioA'); const radiocheckB = document.getElementById('radioB'); if(radiocheckA.checked){//ラジオボタンの値によって表示を変化させる const pa7 = document.getElementById("output7"); pa7.textContent = `----`; const pa8 = document.getElementById("output8"); pa8.textContent = `----`; return; }else if(radiocheckB.checked){ const pa7 = document.getElementById("output7"); pa7.textContent = `専門・短大入学${myHistory[3]}年4月`; const pa8 = document.getElementById("output8"); pa8.textContent = `専門・短大卒業${myHistory[4]}年3月`; return; }else{ const pa7 = document.getElementById("output7"); pa7.textContent = `大学入学${myHistory[3]}年4月`; const pa8 = document.getElementById("output8"); pa8.textContent = `大学卒業${myHistory[5]}年3月`; return; } }catch(err){ console.log(`出力部分エラー:${err.message}`);//特に意味はない } }); const Sakuzyo = () => {//入力制限用関数ではじかれた際に出力済みの結果を消去する const pa1 = document.getElementById("output1"); pa1.textContent = `----`; const pa2 = document.getElementById("output2"); pa2.textContent = `----`; const pa3 = document.getElementById("output3"); pa3.textContent = `----`; const pa4 = document.getElementById("output4"); pa4.textContent = `----`; const pa5 = document.getElementById("output5"); pa5.textContent = `----`; const pa6 = document.getElementById("output6"); pa6.textContent = `----`; const pa7 = document.getElementById("output7"); pa7.textContent = `----`; const pa8 = document.getElementById("output8"); pa8.textContent = `----`; } 5. 更新版 コメントで日付を扱うときはDateオブジェクトを使用したほうが良い。というアドバイスを頂きました。 それを受けて、「入力制限」と「4月2日の判定」の箇所をDateオブジェクトに置き換えましたので、その更新内容を発表します。 なお、Dateオブジェクト置き換えに伴い、「閏年の判定」はする必要がなくなりました。 入力制限 まず新しく入力された値をDateオブジェクトに代入した変数setDateを用意しました。 const yearStatasN = Number(yearStatas.value) + 1900; const monthN = Number(monthStatas.value) - 1; const dayN = Number(dayStatas.value); let setDate = new Date(yearStatasN, monthN, dayN); それを入力値の月(monthN)と比較してfalseならば、閏年の場合も含めた存在しない月日となります。 InputLimit(hantei, setDate, monthN); function InputLimit(HT, dateT, month){ if(!(HT === Infinity)){ if(dateT.getMonth() === month){//その月日が存在するかどうかを判定する const erase = document.getElementById("cautionId"); erase.textContent = ``; return history(dateT); }else{ const cautionA = document.getElementById("cautionId"); cautionA.textContent = `値が不正です。`; return Sakuzyo(); } }else{ const cautionC = document.getElementById("cautionId"); cautionC.textContent = `注意!未入力の箇所があります。`; return Sakuzyo(); } } この方法は JavaScriptで簡単に日付が有効かチェックする方法 の記事を参考にしました。 これはDateオブジェクトに値を入力したとき、その月日が存在しない場合は翌月にズレるという特性を利用しています。 4月2日の判定 以下のように判定方法をDateオブジェクトに置き換えただけです。 if( new Date(yearStatasN, monthN, dayN) > new Date(yearStatasN, 3, 1)){} ふりかえり 苦手だったDateオブジェクトから逃げていましたが、今回の課題を消化したことでDateオブジェクトに対し理解が深まりました。 アドバイスありがとうございました! 以下に更新したJavaScriptを載せます。 //履歴年表作成ボタンを押したらイベントスタート const RirekiNenpyouSakusei = document.getElementById('button'); RirekiNenpyouSakusei.addEventListener('click', () => { //プルダウンメニューの3つの値 const yearStatas = document.getElementById("pulldownYear"); const monthStatas = document.getElementById("pulldownMonth"); const dayStatas = document.getElementById("pulldownDay"); //プルダウンメニューの3つの値の前処理 const yearStatasN = Number(yearStatas.value) + 1900; const monthN = Number(monthStatas.value) - 1; const dayN = Number(dayStatas.value); //入力された値をDateオブジェクトに代入 let setDate = new Date(yearStatasN, monthN, dayN); //プルダウンメニューでハイフンが選択されているかどうかの判定用定数 const hantei = yearStatasN + monthN + dayN; let myHistory = []; function InputLimit(HT, dateT, month){ if(!(HT === Infinity)){//プルダウンメニューでハイフンが選択されているかどうかの判定 if(dateT.getMonth() === month){//存在する月日かどうかを判定 const erase = document.getElementById("cautionId"); erase.textContent = ``; return history(dateT); }else{ const cautionA = document.getElementById("cautionId"); cautionA.textContent = `値が不正です。`; return Sakuzyo(); } }else{ const cautionC = document.getElementById("cautionId"); cautionC.textContent = `注意!未入力の箇所があります。`; return Sakuzyo(); } } //大域変数myHistoryに配列を設定するための関数 const history = function(set){ const myHistoryPush = () =>{ myHistory.push(set.setFullYear(set.getFullYear() + 6)); myHistory.push(set.setFullYear(set.getFullYear() + 3)); myHistory.push(set.setFullYear(set.getFullYear() + 3)); myHistory.push(set.setFullYear(set.getFullYear() + 2)); myHistory.push(set.setFullYear(set.getFullYear() + 2)); } if( new Date(yearStatasN, monthN, dayN) > new Date(yearStatasN, 3, 1)){ myHistory.push(set.setFullYear(set.getFullYear() + 7)); myHistoryPush(); return output(myHistory); }else{ myHistory.push(set.setFullYear(set.getFullYear() + 6)); myHistoryPush(); return output(myHistory); } } InputLimit(hantei, setDate, monthN);//入力制限用関数の呼び出し function output(MH){//出力用 try{ const pa1 = document.getElementById("output1"); pa1.textContent = `小学校入学${new Date(MH[0]).getFullYear()}年4月`; const pa2 = document.getElementById("output2"); pa2.textContent = `小学校卒業${new Date(MH[1]).getFullYear()}年3月`; const pa3 = document.getElementById("output3"); pa3.textContent = `中学校入学${new Date(MH[1]).getFullYear()}年4月`; const pa4 = document.getElementById("output4"); pa4.textContent = `中学校卒業${new Date(MH[2]).getFullYear()}年3月`; const pa5 = document.getElementById("output5"); pa5.textContent = `高校入学${new Date(MH[2]).getFullYear()}年4月`; const pa6 = document.getElementById("output6"); pa6.textContent = `高校卒業${new Date(MH[3]).getFullYear()}年3月`; const radiocheckA = document.getElementById('radioA'); const radiocheckB = document.getElementById('radioB'); if(radiocheckA.checked){//ラジオボタンの値によって表示を変化させる const pa7 = document.getElementById("output7"); pa7.textContent = `----`; const pa8 = document.getElementById("output8"); pa8.textContent = `----`; return; }else if(radiocheckB.checked){ const pa7 = document.getElementById("output7"); pa7.textContent = `専門・短大入学${new Date(MH[3]).getFullYear()}年4月`; const pa8 = document.getElementById("output8"); pa8.textContent = `専門・短大卒業${new Date(MH[4]).getFullYear()}年3月`; return; }else{ const pa7 = document.getElementById("output7"); pa7.textContent = `大学入学${new Date(MH[3]).getFullYear()}年4月`; const pa8 = document.getElementById("output8"); pa8.textContent = `大学卒業${new Date(MH[5]).getFullYear()}年3月`; return; } }catch(err){ console.log(err); } } }); const Sakuzyo = () => {//入力制限用関数ではじかれた際に出力済みの結果を消去する const pa1 = document.getElementById("output1"); pa1.textContent = `----`; const pa2 = document.getElementById("output2"); pa2.textContent = `----`; const pa3 = document.getElementById("output3"); pa3.textContent = `----`; const pa4 = document.getElementById("output4"); pa4.textContent = `----`; const pa5 = document.getElementById("output5"); pa5.textContent = `----`; const pa6 = document.getElementById("output6"); pa6.textContent = `----`; const pa7 = document.getElementById("output7"); pa7.textContent = `----`; const pa8 = document.getElementById("output8"); pa8.textContent = `----`; } 参考文献:初めてのJavaScript
- 投稿日:2021-08-15T21:49:41+09:00
Web制作の学習で使用したサイト・サービス
はじめに Web制作の学習で使用した無料サイト・サービスの自分用メモ 随時更新☺ フロントエンド Progate 言わずとしれたサービス jsFiddle ブラウザ上でHTML/CSS/JavaScriptのコード実装と動作チェックができる JavaScrip実装時に、()の付け忘れとかあるとエラー出してくれるから超便利◎ VSCodeの代わりに使える!(^^)! 仕事ですぐに使えるTypeScript フューチャー株式会社(Future Corporation)が公開してるドキュメント サーバーサイド・API Talend API Tester - Free Edition Chromeブラウザの拡張機能で、簡単にAPIのGET/POSTリクエストが送信できる。 JSON Server JSONを返すだけのサーバー API作成前にサクっとJSONレスポンス~画面に表示するところを作りたいときに使った DB Airtable Googleスプレッドシートっぽく使える簡易データベース DBにデータ登録できるフォームやAPIがデフォルトで準備されていて超便利◎ 参考サイト ● Next.js で Airtable を簡易データベースとして使ってみるよ
- 投稿日:2021-08-15T19:50:16+09:00
11ty(eleventy)のcollectionsとfront-matterで、有機的なナビゲーションを自動生成する
ナビゲーションを自動化したい目的で、自分のサイトのドキュメントを11tyとPugで書き直しています。 11tyではcollections.allでサイト全体の情報をオブジェクトで取得できます。 また、各ページの先頭に以下のようにfront-matterを記述することで、ページごとの変数を渡すことができます。 --- sample: "これはページ内のテンプレートエンジンや、11tyのcollectionsで変数sampleとして取得できます" --- これらを利用して、下の画像のように擬似的な階層を持ちつつ、順番に読ませるリンクも表示するナビゲーションを、ページを増やすごとに自動更新できないかと考えました。 同じ小カテゴリーの 次のページが存在していれば、次ページへのリンクボタンを表示する 次のページが存在しなければ、次の小カテゴリーの1番目へのリンクボタンを表示する いずれもなければボタンは表示しない 以下、実装できたのでコードを記載します。 front-matterの内容 各ページにorder変数を定義しておきます。小カテゴリー内で連番とし、カテゴリーが変わった場合は10の位を1増やした1番目のページから再度カウントします。 つまり、先ほどの図の場合は「コーディングルール」のページはorder: 16で、「カラーテーブル」のページはorder:21となります。 --- order: 16 pageTitle: "コーディングルール" --- mixinを作成する 次ページの情報を表示するmixinは以下の通りです。Pugで記述していますが他のテンプレートエンジンも同様の考え方となります。 mixin nextNav(order) - let nextID = Number.parseInt(order)+1; let next = collections.all.filter((a) => Number.parseInt(a.data.order) === nextID); if next.length === 0 - nextID = (Math.trunc(order/10)*10)+11; next = collections.all.filter((a) => Number.parseInt(a.data.order) === nextID); each item in next p a(href=item.url) Next: #{item.data.pageTitle} 処理の流れ まず、order変数がorder+1となっているページをリクエストします。このmixinでは、collections.allにJavaScriptのfilterをかけていますが、もっとスマートな方法があるかもしれません。 - let nextID = Number.parseInt(order)+1; let next = collections.all.filter((a) => Number.parseInt(a.data.order) === nextID); 結果が空であれば、10の位を上げ、さらに1増やして再試行します。 10で割ってからMath.truncで整数部分を取り、もう一度10倍すると、10の位のぴったりの数字となります(3なら0、16なら10です)。これに11を足して位を上げています。 if next.length === 0 - nextID = (Math.trunc(order/10)*10)+11; next = collections.all.filter((a) => Number.parseInt(a.data.order) === nextID); 最後にページ情報を展開します。1件か0件であるはずです。リンクのラベルテキストはfront-matterで定義しているページタイトルを出したいのでdata.pageTitleとなります。 each item in next p a(href=item.url) Next: #{item.data.pageTitle} テンプレートで呼び出す テンプレート側ではorder変数を渡して呼び出します。Pugは継承が使えるので、レイアウトテンプレートに書いておけばよいと思います。 +nextNav(order) サイトマップの生成は、JSONでデータを書いて展開する方法がよく紹介されているのですが、これだと実際のHTMLを変更・削除したときに漏れが出そうなので、ジェネレーターらしい手段を考えてみました。 11tyは、サイト内のページ情報を常に整理してくれているようです。うまく利用すれば静的なサイトも破綻やリンク切れを起こさずに作成できるかなと感じています。
- 投稿日:2021-08-15T18:38:48+09:00
HTMLの主なタグと用途(4) フォーム
本記事は筆者の独学のメモ書きのようなものなので、 読者の皆様は参考にしないで下さい。 あくまで、筆者の復習用です。 目次 1.はじめに 2.フォームの概要 3.input要素 4.フォーム作成物 5.プルダウン機能 6.ラジオボタン 7.テキストエリア 8.チェックボックス 9.送信ボタンの実装 10.ラベル 11.バリデーション 12.おわりに 1. はじめに ・フォームとは? →ユーザーより、ウェブページからデータをサーバに送信するためのもの。 ・ログイン画面 ・Google検索キーワード画面 ・アカウント登録画面 2. フォームの概要 ・form要素で記述する。 【サンプル】 index.html <form action="#" method="POST"></form> ① ② ①action属性:どこにデータを送信するかを記述。(今回はダミーとして"#"と記述している) ②method属性:HTTPリクエストメソッドの種類を記述。 ・ブラウザからサーバに対して依頼する処理の種類。 ・利用頻度が高い。 GET ・サーバからデータを取得したいとき。 【例】 ・ウェブページを取得。 ・画像の取得。 ・RSSフィードの取得。 POST ・サーバへデータを送信したいとき。 【例】 ログインフォーム、ECサイトでの商品注文フォーム、アンケート送信。 3. input要素 ・データを入力するためのフォーム部品を作る要素。 ・type属性をすることで、様々な入力フォームを作成可能。 【サンプル】 index.html <input type="text"> ※ ※単一行のテキスト入力欄 参考:https://developer.mozilla.org/ja/docs/Web/HTML/Element/input 4. フォーム作成物 今回は、サーバへログイン情報を送るためのフォーム作成例。 【サンプル】 index.html <form action="#" method="POST"> ① ② <input type="text" name="username" placeholder="ユーザーネーム"> ③ ④ ⑤ <input type="password" name="password" placeholder="パスワード"> ③ ④ ⑤ <input type="submit" value="ログイン"> ③ ⑥ </form> <解説> ①どこへデータを送信するか記述。 ※今回の例で作成したのでダミーの"#"を配置。 ②今回はログインに必要なデータをサーバへ送るので"POST"を記入。 ③type属性の主な種類。 ・text:単一行のテキスト入力欄。 ・password:入力値を隠す単一行のテキスト入力欄。 ・submit:フォームを送信するボタン。 ④ ・入力欄コントロールの名前。 ・名前、値の組の部分としてフォームと一緒に送信される。 ⑤フォームコントロールが空の場合に、フォームコントロール内に表示される内容。 ⑥input要素の値を指定する属性。以下凡例。 ・テキスト入力欄においての初期入力値。 ・チェックボックスやラジオボタン(後述)において選択したときだけ送信する値。 ・送信ボタンにおいてはボタン名を表す。 【表示例】 5. プルダウン機能 ・ドロップダウン機能のこと。 【サンプル】 index.html <dt>お住いの地域</dt> <dd> <select name="area"> ① <option value="" selected>選択して下さい</option> ② ③ ④ <option value="hokkaido">北海道</option> <option value="tohoku">東北</option> <option value="kanto">関東</option> <option value="chubu">中部</option> <option value="hokushinetu">北信越</option> <option value="kinki">近畿</option> <option value="chugoku">中国</option> <option value="shikoku">四国</option> <option value="kyushu">九州</option> <option value="okinawa">沖縄</option> </select> </dd> <解説> ①フォーム内にプルダウン機能を付与。 ②プルダウンの内容。 ③サーバに送信する値を定義。 ④selectedを属性にすると、選択肢が初期状態で選択される。 ・この属性には値が無い。 ・selectedは、要素内に1つだけしか持つことができない。 【表示例(プルダウン開放前)】 【表示例(プルダウン開放後)】 6. ラジオボタン ・ラジオボタンとは? →複数の項目から1つを選択するための小さな丸いボタン状の入力要素。 【サンプル】 index.html <dt>性別</dt> <dd> <input type="radio" name="gender" value="male" checked>男性 ① ② ③ ④ <input type="radio" name="gender" value="female">女性 </dd> ①ラジオボタンの型。 ② ・入力欄コントロールの名前。 ・名前、値の組の部分としてフォームと一緒に送信される。 ③ラジオボタンを選択したときだけ送信する値。 ④初期から選択された状態にする。 【表示例】 7. テキストエリア ・テキストエリアとは? →文字を複数行入力できる部品のこと。 【サンプル】 index.html <dt>お問い合わせ内容</dt> <dd> <textarea name="contents"></textarea> </dd> 【表示例】 8. チェックボックス ・チェックボックスとは? →機能としてはラジオボタンと同様だが、チェックボックスは四角。 【サンプル】 index.html <dt>プライバシーポリシーに同意する</dt> <dd> <input type="checkbox" name="privacy" value="1" checked> </dd> 【表示例】 \ 9. 送信ボタンの実装 【サンプル】 index.html <input type="submit" name="submit" value="送信"> 【表示例】 10. ラベル ・ラベルとは? →各フォーム部品が何の入力欄かを示しているのかを説明するためのテキスト。 【サンプル】 index.html <dl> <dt><label for="username">お名前</label></dt> ① ② <dd><input id="username" type="text" name="username" /></dd> ③ </dl> ①:labelタグ ②、③:フォーム部品のidを、labelタグのfor属性に割り当て紐付ける。 ※フォーム部品をlabelタグで囲う方法もある。 【表示例】 【ラベルを使用する際のメリット】 ・文章の意味付けがより正しくできる。 ・チェックボックスやラジオボタンで、ラベルの部分をチェックしても選択できるようになる。 ・テキスト入力に関しては、マークアップした文字をクリックするとテキスト入力できるようになる。 11. バリデーション ・バリデーションとは? →入力された内容が要件を満たしているか、妥当性を確認すること。 エラー表示 【サンプル】 index.html <form action="#" method="POST"> <input type="text" required /> <input type="submit" value="送信" /> </form> ・リクワイアードと読む。 ・フォーム部品に記述することにより、文字が記載されていない状態で送信ボタンを押下するとエラー表示され次へ進むことはできない。 【表示例】 文字数制限 【サンプル】 index.html <form action="#" method="POST"> <input type="text" required maxlength="5"/> <input type="submit" value="送信" /> </form> ・maxlength:文字数制限。 (サンプルでは数値を5にしているが、これは5文字まで入力を許可されているが6文字以上は入力不可) 【表示例】 ☆注意点☆ ・クライアント側(ホームページを訪れた利用者)のフォームバリデーションは、ユーザーが簡単に書き換えることができる。(Google Chrome Developer Toolなどで) ・HTMLのフォームバリデーションは、不正対策には使えない。 〜対策として〜 サーバサイド側(アプリケーションの提供側)のフォームからのデータを受け取るプログラム側での値の正当性のチェックを行う。 12. おわりに 本記事で説明不足な点もあると思うので、以下MDN参照リンクあり。 MDNのリンク:https://developer.mozilla.org/ja/
- 投稿日:2021-08-15T18:07:51+09:00
Vueでお絵かきアプリ作成1(canvas使用)
趣向 vueでお絵かき機能を作成する機会があったため作ってみました! はじめに このページではお絵描きできるCanvasの実装まで行います。 まずはvueの作成。 widthとheight で枠の大きさ、lineWidthでペンの太さ。strokeStyleでペンの色を決めることができます。 JavaScript new Vue({ el: '#app', data() { return { weightNum: 5, canvas: null, color: "black", context: null, } }, mounted () { // カンバス作成 this.canvas = document.querySelector('#myCanvas') this.context = this.canvas.getContext('2d') this.context.lineCap = 'round' this.context.lineCap = 'round' this.canvas.width = 700 this.canvas.height = 600 this.context.lineWidth = this.weightNum this.context.strokeStyle = this.color }, }); 次にhtml。canvasを作成し、マウスを動かした時の処理を書いていきます。 html <div id="app"> <main> <div> <canvas id="myCanvas" ref="myCanvas" style="border:1px solid #aaa" @mousedown="dragStart" @mouseup="dragEnd" @mouseout="dragEnd" @mousemove="draw"></canvas> </div> </main> </div> このままではエラーになってしまうのでマウスを動かした時の処理をvueにも追加 JavaScript methods: { // 描画 draw :function(e) { let x = e.layerX let y = e.layerY if(!this.isDrag) return; this.context.lineTo(x, y); this.context.stroke(); }, // 描画開始(mousedown) dragStart:function(e) { let x = e.layerX let y = e.layerY this.context.beginPath(); this.context.lineTo(x, y); this.context.stroke(); this.isDrag = true; this.context.getImageData(0, 0, this.canvas.width, this.canvas.height) }, // 描画終了(mouseup, mouseout) dragEnd: function() { this.context.closePath(); this.isDrag = false; } } とりあえずこれでかけるようになったと思います。 次回はペン機能と消しゴム機能をわけ。ペンの太さと色を変更できるようにしたいと思います。