質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.64%

if分の中にif分を書くコードについての質問。課題を進めて息詰まったところを解決したい。

解決済

回答 5

投稿

  • 評価
  • クリップ 0
  • VIEW 1,024

12345678910

score 15

 前提・実現したいこと

ここに質問の内容を詳しく書いてください。
<前提の説明>
javascriptで生年月日入力欄をつくり、入力された日付の曜日を出力できるようにする。
入力欄は年、月、日の3つに分ける。「曜日を調べる」というボタンをつくる。
フォーカスを外すとエラー文がでるようにし、曜日を調べるボタンを押せなくする。
どこかの入力欄が不適切であればボタンが押せない。
問題文はこんな感じ。
(1)formで入力された日付の曜日を表示する
HTMLで下記の入力フォームを作る
[数値]年 [数値]月 [数値]日←入力部、フォーカスが外れたら入力チェックを行い間違っていたら
ここにエラー表示
[調べる]←ボタンがクリックされたら(ボタンは、エラーなど入力がきちんとされていない場合は押せないようにして下さい)
結果:○曜日です←結果が表示される。

<作業経過>
日付入力して曜日が出力されるとこまでできた。(うるう年も考慮して)
方法はif文の中にif文を書いてやりました。
<わからない所、質問したいところ>
3つの入力欄があるのですが、一つ入力すると他の二つが空欄のため、間違った表記と判断しエラー文が先にでてしまう。エラー分は入力欄が空欄のときはでないようにしたい。if文で年、月、日の入力欄のどれかが空欄ならばボタンを押せなくする。という
条件にし、エラー文がでるという条件は付けないようにしたのですが、違うif文に飛びエラー文がでてしまう。
うるう年がなければif文の中にif文を書かなくても出来たし、空欄部分がある際のエラー文もうまくできたのですが、うるう年を考慮するとif文の中にif文をつくる必要があり、そうすると、空欄がある際のエラーがうまくできません。
長々すみません。伝わりましたでしょうか?
下にコード乗せるので、問題点を指摘いただければと思います。
宜しくお願いします。

 該当のソースコード

HTMLコード
<h1>総合課題1</h1>
<p>日付を入力してください。</p>
<form method="POST"  action="example.cgi" name="form1"   >
<input type="text"  style="height:30px;" style="width:20px;" id="userYear"  onblur="check()" >年
<input type="text"  style="height:30px;" style="width:20px;" id="userMonth" onblur="check()" >月
<input type="text"  style="height:30px;" style="width:20px;" id="userDate"  onblur="check()">日
<input type="button"  input id="botan" value="日付の曜日を調べる" onclick="showUserWeekDay();">
</form>
<p id="kekka1"></p>

javascriptコード
console.log("総合課題1");
var day1 = 1;
var day2 =31;
console.log(day1);
/クリックしたときの処理/
function showUserWeekDay() {
// 曜日の配列を作る
var WeekChars = [ "日曜日", "月曜日", "火曜日", "水曜日", "木曜日", "金曜日", "土曜日" ];
var userYear = document.getElementById("userYear").value;
var userMonth = document.getElementById("userMonth").value;
var userDate = document.getElementById("userDate").value;
// 入力された数値から日付オブジェクトを作る
var userDate = new Date( userYear, userMonth, userDate );
// 日付と曜日を表示する
kekka1.innerHTML="指定された「" + 
userDate.getFullYear() + "年" + 
(userDate.getMonth()) + "月" + 
userDate.getDate() + "日」は、" + 
WeekChars[userDate.getDay()] + "です。";
}/関数showUserWeekDay()締め/

/フォーカスをあてたときの判定/
function check(){
var field =  document.getElementById('botan');
var userYear = document.getElementById("userYear").value;
var userMonth = document.getElementById("userMonth").value;
var userDate = document.getElementById("userDate").value;
var saniti=userDate>=1&&userDate<=31 && 
userMonth==1||userDate>=1&&userDate<=31 && userMonth==3||
userDate>=1&&userDate<=31 && 
userMonth==5||userDate>=1&&userDate<=31 && userMonth==7||
userDate>=1&&userDate<=31 && 
userMonth==8||userDate>=1&&userDate<=31 && userMonth==10||
userDate>=1&&userDate<=31 && userMonth==12
 
varsanzero=1<=userDate&&userDate<=30&&userMonth==4||
1<=userDate&&userDate<=30&&userMonth==6||
1<=userDate&&userDate<=30&&userMonth==9||
1<=userDate&&userDate<=30&&userMonth==11 

質問したいif文のところ。
if(userYear==""||userMonth==""||userDate==""){
field.setAttribute("disabled", "disabled");}
else{console.log("空欄なし");
field.removeAttribute("disabled");  }
if(userYear>=1900&&userYear<=2050){     
if(userMonth==2){
if(userYear % 400 == 0 || (userYear % 100 != 0 && userYear % 4 == 
0)){
if(userDate>=1 && userDate<=29){
console.log("2月うるう年");
field.removeAttribute("disabled");}
else{console.log("日付エラー");}
}else{console.log("うるうどしではない");}
}else if(saniti){console.log("31日の月");}
else if(sanzero){console.log("30日の月");}
else{console.log("月日エラー");}
}else{console.log("年エラー");
field.setAttribute("disabled", "disabled");}
}/関数締め/

/フォーカスをあてる前にボタンを押せなくする処理/  
var userYear = document.getElementById("userYear").value;
var userMonth = document.getElementById("userMonth").value;
var userDate = document.getElementById("userDate").value;
var field =  document.getElementById('botan');
if(userYear==""|| userMonth=="" ||userDate==""){
field.setAttribute("disabled", "disabled");
}else{
field.removeAttribute("disabled");}     

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • azuapricot

    2018/11/30 09:59

    めっちゃ見にくいし再現するのもめんどくさいのでコードはきちんと <code>で囲って質問してください

    キャンセル

  • Lhankor_Mhy

    2018/11/30 10:05

    そんな捨て垢っぽいユーザーIDで質問されると、回答に躊躇するじゃないですか。

    キャンセル

回答 5

checkベストアンサー

+2

要件(というか課題の前提)がブレているように思います。

どこかの入力欄が不適切であればボタンが押せない。

とのことですが、空文字(未入力)は、不適切入力でよいのではないでしょうか。確かに、最初に開いて年だけ入れたときに月日エラーと出るのは、やや不適切にも思えます。ところが、そこでエラーを抑制しても、3つとも入れたあとに、日付だけ消した(バックスペースなどで)場合には、まさに「月日エラー」だと思いますがその区別までするのでしょうか(ここで言っているのは11日の曜日を調べたあと1日の曜日を調べようとしたがバックスペースを誤って連打してしまい空白になった場合などです)。

  • 対処
    アドホックな対処としては
if(userYear>=1900&&userYear<=2050){


↑ここからはじまるifとelseのブロックを"空欄なし"と書いてあるelseの中に全部入れることですね。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+2

1点、この手のうるう年の処理は無駄なのでやめたほうがいい。
月末最終日は、翌月の0日(1日の1日前)というロジックだけで十分

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

関数中にreturn文がある時そこで関数から抜けることを応用すると、ifをネストする必要はないと思います。

if(userYear==""||userMonth==""||userDate==""){
  field.setAttribute("disabled", "disabled");
  return;
}
if(userYear>=1900&&userYear<=2050){
  //...
}

のような感じで。
あと、個人的にはこれ、型変換しないのちょっと気持ち悪いです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

曜日同様に、うるう年の計算はDateオブジェクトがあるので不要では?

document.forms['form1'].addEventListener('input', function(event) {
  // name属性をつけているとして
  var form = event.currentTarget;
  var year = parseInt(form.elements['userYear'].value, 10);
  var month = parseInt(form.elements['userMonth'].value, 10);
  var date = parseInt(form.elements['userDate'].value, 10);
  if (isNaN(year) || isNaN(month) || isNaN(date)) {
    event.target.setCustomValidity('エラー');
    return true;
  }

  var dt = new Date(year, month - 1, date);
  if (year !== dt.getFullYear() || month !== dt.getMonth() + 1 || date !== dt.getDate()) {
    event.target.setCustomValidity('エラー');
    return true;
  }

  Array.from(form.elements).forEach(a => a.setCustomValidity(''));
  return true;
}, false);

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

 <input type="date">

https://developer.mozilla.org/ja/docs/Web/HTML/Element/Input/date
IE11- をサポートするなら対策を考える必要がありますが、基本は標準機能を使い、未対応ブラウザ向けに後方互換機能を実装するのが現実的だと思います。

<input type="date" required pattern="[0-9]{4}-[0-9]{2}-[0-9]{2}">

 <input type="number">

https://developer.mozilla.org/ja/docs/Web/HTML/Element/Input/number
https://caniuse.com/#feat=input-number
互換機能で <select> を使う方法もありますが、<input type="number"> を使う方がキーボード入力出来て、私は好きですね。

<input type="number" pattern="\d{1,4}" min="1" max="9999">/<input type="number" pattern="[01]?\d" min="1" max="12">/<input type="number" pattern="[0-3]?\d" min="1" max="31">

後はどこまで後方互換機能を実装するか、要件との兼ね合いになります。
(この例では、 <input type="number"> 未対応ブラウザまでが範疇ですが、今時ならそこまでは要らないですかね…。)

Re: 12345678910 さん

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/30 13:14

    selectでもキーボード入力できませんか?
    ブラウザ依存かもしれませんが

    キャンセル

  • 2018/12/01 22:46

    To: x_x さん
    なるほど、確かにGoogle Chromeでは入力できました。
    1回目の選択は期待通りで、キー入力で一度選択した後に変更する時の挙動がGoogle Chromeでは変でしたが…。

    1. "7" を入力 ([7] を選択)
    2. "1" を入力 ([10] を選択)
    3. "1" を入力 ([11] を選択)
    4. "1" を入力 ([12] を選択)
    5. "1" を入力 ([1] を選択)

    個人的には、マウス操作ユーザに配慮するとしても、<datalist> or <input type="number"> がキーボード入力ユーザにも優しくて好きです。
    http://jsfiddle.net/sc6gyvjk/2/

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.64%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る