最初に/お詫び
前回質問した内容とほぼ同じ内容になっています。
#前提
クリック時の処理
問題なくクリック処理が実行されると、「エラーは取れましたね」とアラートが表示される。
起きているエラー
schedule.setHoliday()
の中が空の時カレンダーをクリックするとエラーになってしまう。
関数の処理について
setHoilday関数では、引数の値を元に定休日の日には表示されているカレンダーのセルが「×」と表示される処理になっています。
エラーの原因
setHoilday()の引数が関数に返された時に値が空の状態だと関数内の処理が実行されないため
setHoilday(1,2,4)と一つでも値が入っていれば、エラーは起きない。
どうしたいのか
定休日を設定したくない時はschedule.setHoliday()
を空で返したい。
コード量が多いためcodepenに関連する全コードを載せています。
codepen 全コード
#実現したいこと
現状では、定休日を最低1日セットしないとエラーが出てしまうので、それをsetHoilday()
と定休日をセットしない時でもクリック時にアラートを表示できるようにしたい。
#追記
ご指摘を受けた点
codepenのcssとjsを分けました。
コード量が文字数上、全てお載せすることができないため、該当するコードを追記しました。
該当コード
js
1 setHoliday (...dayNo) { 2 let 3 year = this.current.getFullYear (), 4 start = new Date (year, 0, 1), 5 end = new Date (year, 12, 1), 6 7 b = new Date (Date.UTC (1970,0,1, 0, 0)),//列のスタート時間 8 e = new Date (Date.UTC (1970,0,1,24, 30)),//列の終了時間 9 s = new Date (Date.UTC (1970,0,1, 0,30));//列の感覚調整時間 10 11 //schedule.setHoliday();の時コンソール結果が配列が空になっている。 12 console.log(dayNo); 13 14 dayNo.forEach (n => { 15 let current = new Date (start); 16 17 current.setDate (7 - current.getDate () + n); 18 19 for (; current < end; current.setDate (current.getDate () + 7)) { 20 let idx = F (current); 21 22 for (let c = b; c < e; c = new Date (+s + (+c))) { 23 let key = I (c); 24 if (! this.plan[key]) 25 this.plan[key] = [ ]; //ここの配列が空によりエラーが起きている? 26 this.plan[key][idx] = true; 27 } 28 } 29 }); 30 31 return this; 32 } 33 34 // 定休日と昼休みの設定 35 //0:sun 1:mon 2:tue 3:wed 4:thu 5:fri 6:sat 36 //setHolidayを設定しないとエラーが起きる。setHoliday()だとエラーになる。なんで? 37 schedule.setHoliday(1).setLunchTime (0, 2, 4, 6); 38 39 //クリック処理 40 table.addEventListener('click', event => { 41 const target = event.target; 42 43 if (target.nodeName !== 'TD') 44 return; 45 46 if ('◎' !== target.textContent) 47 return; 48 49 let booktime = parseInt (document.querySelector ('#booktime').value, 10); 50 //表の始まりの日付 51 let cur = schedule.current; 52 //クリック時の表の(セル)座標x 53 let x = target.cellIndex; 54 //クリック時の表の(セル)座標y 55 let y = target.parentNode.rowIndex - 2; 56 //クリックされた列の日付を取得 57 let tgt = new Date (cur); 58 tgt.setDate (tgt.getDate () + x -1); 59 //その日のスケジュールを取得 60 ////schedule.setHoliday();の時下記のコードでエラーが発生 61 let plan = Schedule.getDayPlan (schedule, tgt); 62 // console.log(plan); 63 //plan から9時~15時までを抜き出す 64 plan = plan.slice (18, 31); 65 //予約コースの判定 66 let rng = booktime / 30 |0; 67 plan = plan.slice (y, y + rng); 68 69 if (rng === plan.length && plan.every (a=> !a[1])){ 70 //console.log (rng ? 'ok': 'Invalid'); 71 var id = Array.from(document.getElementsByName('id'), x => x.value); 72 73 if (!(target.closest('tbody') && 1 <= target.cellIndex && target.cellIndex <= 14)) { 74 return true; 75 } 76 const 77 time = target.parentNode.cells[0].textContent, 78 table = target.closest('table'), 79 date = table.tHead.rows[1].cells[target.cellIndex - 1].textContent.replace(/[^0-9]/g, ''), 80 ymrow = table.tHead.rows[0], 81 ym = (target.cellIndex <= ymrow.cells[1].colSpan ? ymrow.cells[1] : ymrow.cells[2]).textContent; 82 83 let 84 value = ym + date + '日' + time, 85 param = document.getElementById( "booktime" ).value; 86 //newに飛ぶ 87 alert('エラーは取れましたね'); 88 //window.location.href = `new.${id}`+`confirm?datetime=${value + '-' + param + '分コース' + id}`; 89 }else{ 90 alert("その時間帯は予約は出来ません。"); 91 } 92 }, false);
問題の再現方法
通常処理
schedule.setHoliday(1)
orschedule.setHoliday(1,3,6)
とsetHolidayの中に、数字がある場合、カレンダー内の◎のセルをクリックすると「エラーは取れましたね」とアラートが表示されます。
エラーが起きる時
schedule.setHoliday()
とsetHolidayの中に、数字がない場合、カレンダー内の◎のセルをクリックしてもアラートが表示されなくなります。
#解決した方法
私の力ではどうしても分からなかったため、@hai_haiさんからご教示いただきました。
a = Array(24).fill(0).reduce((a,b,c)=>(b=('0'+c).slice(-2),[...a,b+':00',b+':30']),[]).reduce((a,b)=>(a[b]=Array(366).fill(false),a),{});
実際のコード
js
1setHoliday (...dayNo) { 2 let 3 year = this.current.getFullYear (), 4 start = new Date (year, 0, 1), 5 end = new Date (year, 12, 1), 6 // ここでdayNoが0の時に実行される処理。全てを初期化する。this.planにaを代入する。 7 a = Array(24).fill(0).reduce((a,b,c)=>(b=('0'+c).slice(-2),[...a,b+':00',b+':30']),[]).reduce((a,b)=>(a[b]=Array(366).fill(false),a),{}), 8 b = new Date (Date.UTC (1970,0,1, 0, 0)),//列のスタート時間 9 e = new Date (Date.UTC (1970,0,1,24, 30)),//列の終了時間 10 s = new Date (Date.UTC (1970,0,1, 0,30));//列の感覚調整時間 11 //setHolidayのdayNoに戻り値が返されるので、dayNoの中の配列が空かどうか確認し、空の場合のみにthis.planにaを代入する。 12 if (!dayNo.length > 0){ 13 this.plan = a; 14 } 15 dayNo.forEach (n => { 16 let current = new Date (start); 17 18 current.setDate (7 - current.getDate () + n); 19 20 for (; current < end; current.setDate (current.getDate () + 7)) { 21 let idx = F (current); 22 23 for (let c = b; c < e; c = new Date (+s + (+c))) { 24 let key = I (c); 25 if (! this.plan[key]) 26 this.plan[key] = [ ]; 27 this.plan[key][idx] = true; 28 } 29 } 30 });
#今後について
今回質問させていただくにあたり、ご回答して頂いた多数の方から身の丈にあったところから勉強していくべきとご指摘を受けたことを踏まえ、私もその通りだと感じました。
今後については、javascriptをちゃんと勉強した上で再度カレンダーの実装について取り組んでいきたいと思います。
何度も質問してしまいご迷惑をおかけして申し訳ございませんでした。
回答3件
あなたの回答
tips
プレビュー