ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Javascript 공부하기. 알람 시계3
    공부/컴 2017. 10. 30. 18:29

    앞 과정에서 기본적인 시계는 만들었으니, 이제 알람을 만들 차례이다.

    알람 시계를 만들기 위해서는 먼저 알람 시각이 표시되는 칸이 필요한데 이것은 이미 표로 만들어 놓았고

    알람을 설정하기 위한 인터페이스와 알람이 실제로 울릴 때의 동작이 필요하다.

    알람 설정을 위한 인터페이스는 여러가지 방법이 있을 수 있는데 나는 앞의 표에서 만들어 놓았던 DIVremain 이라는 공간을 활용하려고 한다. 원래는 남은 시간을 표시하기 위해 만든 공간이었는데, 알람 설정을 할 때는 남은 시간을 볼 필요가 없으니 재활용 하기에 그만이다.

    이런 모양으로 구성하면 좋을 것 같다.


    이 과정에서 html의 div 공간을 Clock() , Alarm() 안에 종속적으로 배정하는 게 좋을 것 같아서 함수를 조금 수정했다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    function Clock(){
      this.time=new Date();
      this.interface_div;
     
    //~~이후 코드 생략
     
    } //endof function Clock
     
    function Alarm(){
      this.time;
    this.number;
      this.interface_divremain;
    this.interface_divalarm;
     
    //~~이후 코드 생략
     
    } //endof function Alarm
    cs

    this.interface_div~ 라는 변수를 추가했다. 그리고 여러 개를 생성할 알람시계의 경우는 몇 번째 알람인지 알 수 있는 number 변수도 추가했다. 뒤의 생략한 부분은 앞 글에서의 코드와 변화가 없으니 참고하자.

    또 시계를 생성하는 과정의 가독성을 늘리기 위해 function Initialize() 라는 함수를 추가해서 초기화 과정을 정리했다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    function Initialize(){
      var nowclock=new Clock();
      nowclock.interface_div=jQuery('DIVclock')[0];
     
      var alarmclock=new Array(ALARM_NUMBER);
      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];
      }
    }
    Initialize();
    cs

    프로그래밍을 하면서도 생각이 나는 대로 이렇게 정리를 해 놓으면 나중에 수정하기도 쉽다.

    함수들을 정리했으니 이제 알람시계 입력 폼을 작성해야 한다. remain 자리를 재활용하기로 했기 때문에, 버튼 같은 것을 활용해서 입력 폼/남은 시간 으로 표시되는 내용을 바꿀 수 있도록 해야 한다.

    먼저 남은 시간을 표시하는 함수는 remainformstring(), 알람시각 입력칸을 표시하는 함수는 inputformstring() 라고 해 두자.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    this.inputform= function(){
        var inputformstring="<form onsubmit='alarmclock["+this.number+"].remaintimeform()'>\
        <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
    cs

    복잡해 보이지만 서로 바꾸는 버튼만 구현한 상태이다.

    잘 읽어보면 inputformstring 에는 submit input을 사용했고, remaintimeform 에는 그냥 button input 을 사용했는데 성격상 차이가 있다고 생각해서 굳이 구분했다.

    그 다음엔 알람설정 할 때 시/분/초를 입력할 공간을 만들어야 한다. 이부분은 단순히 html 태그이기 때문에 상세 코드는 생략하고 이 글 맨 밑의 중간정리본을 확인해보도록 하자.


    입력할 form 을 구현했으면 실제로 입력을 받았을 때의 동작도 구현해야 할 것이다. 이를 위한 새 함수 submitalarm() 을 구현하고, 위 submit form 에 remaintimeform() 대신 submitalarm() 을 실행시키도록 바꾼다.

    대신 이 submitalarm() 안에 remaintimeform()도 실행시키도록 넣는다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
      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;
      //form을 바꾼다.
          this.remaintimeform();
      }//endof submitalarm
    cs


    구현과정에서 범위를 벗어나는 값을 처리하는 등 자잘한 부분도 추가했다. isNaN() 함수는 받은 인자가 수학적으로 에러가 있는 문자열인지 검사하는 함수이다.(숫자와 공백 외의 문자가 있을 때 true 를 반환한다.)


    알람시각을 입력받아 저장하는것이 구현되었으니, 알람까지 남은 시간을 보여주는 함수도 만들어야 한다. remainform 을 생성할 때 <div id=remaintime"+this.number+"> 라는 공간을 하나 더 만들었는데, 여기에 표시를 하도록 한다.

    실시간으로 변화하는 값이기 때문에 Alarm() 안의 runf 에 포함시켰다.


    1
    2
    3
    4
    5
    6
    7
    8
        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 ;
        }
    cs


    코드가 지저분한 편인데, 다양한 함수를 활용하기보다 그냥 수학적으로 해결해 버리는 게 개인적으로 편하기 때문에 이렇게 구현했다. 찬찬히 읽어보면 어떻게 작동하는지 알 수 있을 것이다. 알람시계를 판단할 때 날짜는 제외하고 시/분/초 만 확인하기 때문에 이렇게만 구현해도 동작한다.



    그리고 이 페이지를 동작시켜보면서 자질구레하게 몇 가지를 수정했다. 

    먼저 Initialize 를 실행할 때 Alarm() 들이 생성된 뒤 inputform(); submitalarm(); 을 차례대로 실행 해, 초기 설정된 알람 시각을 00:00 으로 맟추고 (GMT +900 에서는 9:00) 알람 설정 버튼이 나타나도록 했다.

    그리고 알람을 울리기 위한 시각 비교 부분을 좀 더 길고 정확하게 수정했다.


    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
    <!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;
     
    function MakeTable(){
      var divspace=jQuery('#DIValarmtable')[0];
      var tcs="<table border=1>\
      <tr>";
     
      var tcs=tcs+"<td colspan=2><div id='DIVclock'></div></td>\
      </tr>";
     
      for(var i=0;i<ALARM_NUMBER;i++){
        var tcs=tcs+"<tr>\
        <td><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.interface_divalarm;
      this.interface_divremain;
     
      //알람 울리기.
      this.ringalarm= function(){
      }
      //프레임마다 알람시계에서 작동되는 함수 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.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.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
     
    }//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].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


    지금까지 구현한 소스코드의 내용이다.

    이번 글에 미처 언급하지 못하고 지나간 변경 내용들이 꽤 있는데, 사실 나도 이것저것 시도해 보면서 글도 같이 쓰고 있기 때문에, 바뀐 내용을 모두 기억하고 있지는 못하다. 단지 이 코드가 어느정도 구현한 부분까지 작동한다는 점만 확인했다.


    대충 이런 모양으로 나온다.

    와...정말..못생겼다.....

    디자인에 관심 있는 사람이라면 css를 적용시키고 싶어 미칠 지경일 것이다. 하지만 나는 동작 자체에 관심 있기때문에 이런 광경에 익숙하다.

    다음에는 알람시각이 맞을 때 알람이 울리는 부분을 구현해보자.


    댓글

Designed by Tistory.