ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Javascript 공부하기. 알람 시계 6 타이머 기능 추가
    공부/컴 2017. 12. 13. 22:50

    이전에 만든 알람 시계에는 특정 시각에 알람이 울리는 기능만 구현했지만, 쓰다 보니 일정 시간 후에 알람이 울리는 기능, 즉 "타이머" 기능이 있으면 좋겠다는 생각이 들었다.


    구현이 그렇게 어려울 것 같지 않아서 원래의 코드에 더해 보았다.



    일단 원래 코드는 아래와 같다.


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    <!DOCTYPE html>
    <meta charset='utf-8'>
    <html>
      <head>
        <title>Alarm</title>
      </head>
      <body>
     
    <div id='DIValarmtable'></div>
      </body>
    </html>
     
    <script type="text/javascript" src="jquery.js" charset="utf-8"></script>
     
    <script type='text/javascript'>
    var ALARM_NUMBER=5;
    var ALARM_SOUND_PATH="justice.mp3";
    var ALARM_MESSAGE="알람 시각입니다.";
    function MakeTable(){
      var divspace=jQuery('#DIValarmtable')[0];
      var tcs="<table border=1>\
      <tr>";
      var tcs=tcs+"<td colspan=3><div id='DIVclock'></div></td>\
      </tr>";
      for(var i=0;i<ALARM_NUMBER;i++){
        var tcs=tcs+"<tr>\
        <td><div id='alarmlight"+i+"' align=center onClick='javascript:alarmclock["+i+"].toggle_enable()' style='color:#40FF40;'>●</div></td>\
        <td><audio id='alarmsound"+i+"' src='"+ALARM_SOUND_PATH+"'></audio>\
        <div id='DIValarm"+i+"'></div></td>\
        <td><div id='DIVremain"+i+"'></div></td>\
        </tr>";
      }
      var tcs=tcs+"</table>";
      divspace.innerHTML=tcs;
    }
    MakeTable();
    function Clock(){
      this.time=new Date();
      this.interface_div;
      this.runf=function(){
        this.time=new Date();
        jQuery('#DIVclock')[0].innerHTML=this.time;
      }//endof runf
    } //endof function Clock
    function Alarm(){
      this.time=new Date(0);
      this.number;
      this.alarmsound;
      this.interface_divalarm;
      this.interface_divremain;
      this.alarm_enabled=true;
      //알람 울리기.
      this.ringalarm=function(){
          this.alarm_enabled=false;
          this.alarmsound.play();
          ALARM_MESSAGE=(this.number+1)+"번 알람입니다.";
          setTimeout(function(){alert(ALARM_MESSAGE);},1000);
      }
      //프레임마다 알람시계에서 작동되는 함수 runf
      this.runf= function(){
        //현재시간을 비교해서 알람을 울리도록 한다.
        var nowtime=new Date()
        if(this.time.getHours()==nowtime.getHours() &&
            this.time.getMinutes()==nowtime.getMinutes() &&
            this.time.getSeconds()==nowtime.getSeconds() &&
            this.alarm_enabled){
          this.ringalarm();
        }
        var atime=this.time.getHours()*3600 + this.time.getMinutes()*60 + this.time.getSeconds();
        var ctime=nowtime.getHours()*3600 + nowtime.getMinutes()*60 + nowtime.getSeconds();
        if(atime<ctime)atime+=24*60*60;
        //유효성 검사.
        if(typeof($('#remaintime'+this.number)[0])=='object'){
         $('#remaintime'+this.number)[0].innerHTML=parseInt((atime-ctime)/3600) + " : " + parseInt(((atime-ctime)%3600)/60) + " : " + (atime-ctime)%60 ;
        }
      }//endof runf
      //알람 설정
      this.submitalarm=function(){
          var hhh=$("#hhh"+this.number)[0].value;
          var mmm=$("#mmm"+this.number)[0].value;
          var sss=$("#sss"+this.number)[0].value;
          if(hhh<=0 || hhh>23 || isNaN(hhh)){hhh='00';}
          if(mmm<=0 || mmm>59 || isNaN(mmm)){mmm='00';}
          if(sss<=0 || sss>59 || isNaN(sss)){sss='00';}
          this.time.setHours(hhh);
          this.time.setMinutes(mmm);
          this.time.setSeconds(sss);
          this.interface_divalarm.innerHTML=hhh + " : " + mmm + " : " + sss;
          this.alarm_enabled=true;
          this.remaintimeform();
      }//endof submitalarm
      this.inputform= function(){
        var inputformstring="<form onsubmit='alarmclock["+this.number+"].submitalarm()'>\
        <input id='hhh"+this.number+"' type='text' size='2' maxlength='2' value="+this.time.getHours()+"> : \
        <input id='mmm"+this.number+"' type='text' size='2' maxlength='2' value="+this.time.getMinutes()+"> : \
        <input id='sss"+this.number+"' type='text' size='2' maxlength='2' value="+this.time.getSeconds()+">\
        <input id='setalarm' type='submit' value='OK' ></form>";
        this.interface_divremain.innerHTML=inputformstring;
      }//endof inputform
      this.remaintimeform= function(){
        var remainformstring="<div id=remaintime"+this.number+"></div>\
        <input type='button' value='알람설정' onclick='alarmclock["+this.number+"].inputform()'>";
        this.interface_divremain.innerHTML=remainformstring;
      }//endof remaintimeform
      this.toggle_enable=function(){
        if(this.alarm_enabled){
          this.alarm_enabled=false;
          $("#alarmlight"+this.number)[0].style.color="#FF0000";
        }//endof if this.alarm_enabled is true
        else{
          this.alarm_enabled=true;
          $("#alarmlight"+this.number)[0].style.color="#40FF40";
        }//endof else
      }//endof toggle_enable
    }//endof Alarm
    //초기화 함수
    var nowclock=new Clock();
    var alarmclock=new Array(ALARM_NUMBER);
    function Initialize(){
      nowclock=new Clock();
      nowclock.interface_div=jQuery('#DIVclock')[0];
      for(var i=0;i<ALARM_NUMBER;i++){
        alarmclock[i]=new Alarm();
        alarmclock[i].number=i;
        alarmclock[i].interface_divalarm=jQuery('#DIValarm'+i)[0];
        alarmclock[i].interface_divremain=jQuery('#DIVremain'+i)[0];
        alarmclock[i].alarmsound=jQuery('#alarmsound'+i)[0];
        alarmclock[i].inputform();
       alarmclock[i].submitalarm();
      }
    }
    Initialize();
    //Run Interval
    function RunInterval(){
      nowclock.runf();
      for(var i=0;i<ALARM_NUMBER;i++){
        alarmclock[i].runf();
      }
      setTimeout(RunInterval,50);
    }
    RunInterval();
    </script>
    cs


    여기에 타이머 기능을 추가해야 하는데, 알람을 울릴 시간을 정할 때, 타이머로 정하는 버튼과, 시각으로 정하는 버튼을 각각 만들기로 했다. 원래 고려하지 않았던 부분이기 때문에, 알람을 정하는 버튼이 submit 버튼으로 만들어져 있었는데, 이것을 button 으로 바꾼 뒤에 onclick 을 부여했다.


    1
    2
    3
    4
    5
    6
    7
    8
    9
      this.inputform= function(){
        var inputformstring="<form>\
        <input id='hhh"+this.number+"' type='text' size='2' maxlength='2' value="+this.time.getHours()+"> : \
        <input id='mmm"+this.number+"' type='text' size='2' maxlength='2' value="+this.time.getMinutes()+"> : \
        <input id='sss"+this.number+"' type='text' size='2' maxlength='2' value="+this.time.getSeconds()+">\
        <input id='setalarm' type='button' value='에 알람' onclick='alarmclock["+this.number+"].submitalarm()' >\
        <input id='settimer' type='button' value='후에 알람' onclick='alarmclock["+this.number+"].submittimer()'>";
        this.interface_divremain.innerHTML=inputformstring;
      }//endof inputform
    cs


     OK라고 되어 있던 value 도  "에 알람" / "후에 알람" 으로 구분할 수 있게 바꾸었다.

    원래 있었던 함수가 submitalarm 함수였기 때문에, 새로 만드는 함수는 submittimer 로 정했다.



    외형적으로는 만들어졌고, 이제 submittimer 함수를 구현하기만 하면 끝난다. 일단 알람을 설정한다는 점에서 submitalarm 함수와 비슷하기 때문에 submitalarm 함수를 복사해 와서 수정하자.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
      this.submittimer=function(){
          var hhh=$("#hhh"+this.number)[0].value;
          var mmm=$("#mmm"+this.number)[0].value;
          var sss=$("#sss"+this.number)[0].value;
     
          if(hhh<=0 || hhh>23 || isNaN(hhh)){hhh='00';}
          if(mmm<=0 || mmm>59 || isNaN(mmm)){mmm='00';}
          if(sss<=0 || sss>59 || isNaN(sss)){sss='00';}
     
          var thhh=(new Date().getHours()+(hhh/1));
          var tmmm=(new Date().getMinutes()+(mmm/1));
          var tsss=(new Date().getSeconds()+(sss/1));
          if((tsss/1)>=60){
            tsss=tsss%60;
            tmmm++;
          }
          if((tmmm/1)>=60){
            tmmm=tmmm%60;
            thhh++;
          }
          if((thhh/1)>=24){
            thhh=thhh%24;
          }
     
          this.time.setHours(thhh);
          this.time.setMinutes(tmmm);
          this.time.setSeconds(tsss);
     
          this.interface_divalarm.innerHTML=thhh + " : " + tmmm + " : " + tsss;
          this.alarm_enabled=true;
          this.remaintimeform();
      }//endof submittimer
    cs


    위가 최종적으로 만들어진 submittimer 함수인데 한 가지 중요한 점은 hhh/mmm/sss 가 String 이기 때문에, 정수로 쓰기 위해서 /1 같은 것들을 붙여 놓은 점이다. 

    또 원래 알람 시계였던 점의 한계로, 24시간 이상의 타이머가 구현되지 않는다... 

    이걸 구현하려면 아예 알람 울리는 부분의 함수를 수정해야 하기 때문이다.


    그리고 24시간/60분/60초가 넘는 경우에 대한 처리도 들어가 있다.

    그것만 제외하면 내용 자체는 단순한데, 원래의 알람 설정 함수에서 현재시각+입력시각 으로 지정하는 부분이 들어갔을 뿐이다.


    결과적으로 아주 잘 작동했기 때문에, 당분간 이대로 쓸 수 있을 것 같다.




    ==================================================================


    버그 수정 내용 추가.


    위 내용대로 코드를 그대로 짜면, 알람이 울린 뒤에도 알람이 꺼지지 않은 것처럼 보인다. 

    내부적으로는 꺼지게 되지만, 알람이 울리는 부분에 알람 ON/OFF 표시칸을 바꾸는 함수를 넣어 놓지 않아서 그렇다.


    이 문제를 해결하려면 알람이 울릴 때 색깔을 바꿔주는 명령을 추가해도 되지만, 나는 확장성과 범용성을 위해서 toggle_enable 함수를 단순히 켰다 껐다 하는 것 뿐만 아니라, 인자를 받아서 true/false 를 결정할 수 있게 변형했다.


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
      this.toggle_enable=function(ss){
        if(ss==true){
          this.alarm_enabled=true;
          $("#alarmlight"+this.number)[0].style.color="#40FF40";
        } //endof if
        else if(ss==false){
          this.alarm_enabled=false;
          $("#alarmlight"+this.number)[0].style.color="#FF0000";
        }//end of elseif
        else if(this.alarm_enabled){
          this.alarm_enabled=false;
          $("#alarmlight"+this.number)[0].style.color="#FF0000";
        }//endof elseif this.alarm_enabled is true
        else{
          this.alarm_enabled=true;
          $("#alarmlight"+this.number)[0].style.color="#40FF40";
        }//endof else
      }//endof toggle_enable
    cs


    이렇게 한 뒤에, 알람이 울리는 부분에 있는 this.alarm_enabled=false 부분을

    this.toggle_enable(false) 로 바꾸었다.


    간단한 버그인데 발견하는 데 시간이 좀 걸려서 늦게 고치게 되었다.

    댓글

Designed by Tistory.