Jump to Content

RSS Feeds:

Posts | Comments

http://ivanwlam.com/experiments/programming

One Response to “Reusable Calendar Project Update 4”

  1. [...] “Perpetual Calendar,” and I immediately thought of my experiment concept for a “reusable calendar.” The product ended up not being what my experiment was, but I quickly searched online for [...]

Leave a Reply


Example

Update 4: calendar-090819.php
Ongoing version: calendar.php

PHP in <head>

 <?php    function getInputYr(){  //    $y=2009;      $y=date("Y",time());      return $y;      }  function getInputMonth(){  //    $m=8;      $m=date("n",time());      return $m;      }  function getInputDay(){  //    $d=1;      $d=date("j",time());      return $d;      }      /* calendar math */    function getDow($y=1582,$m=10,$d=1){      //dow=day of the week            $yd=$y-1583;            //constants      $con4=$yd+2;      $con100=$yd+82;      $con400=$yd+382;            //potentials/maximum leaps      $pot4=floor($con4/4);      $pot100=floor($con100/100);      $pot400=floor($con400/400);                  $numNoLeaps=$pot100-$pot400;      $numLeaps=$pot4-$numNoLeaps;        //    $yrStart=($yd+$numLeaps+6)%7;            //values to add for each month. going to pull only one digit at any given time      $monthStartList="033614625035";            //add 1 if it's a leap year and it's march or later      if(isLeap()==true && $m>=3){$leapConst=1;}          else {$leapConst=0;}            //put all the values together, find the remainder to get day of the week that date lands on      $dow=($yd+$numLeaps+6+$monthStartList[$m-1]+$d-1+$leapConst)%7;            //have the format just in case  //    $days_arr=array("Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday");            return $dow;      }    function isLeap(){      $y=getInputYr();            //every year divisible by 100 doesn't get a leap day      //but every year divisible by 400 gets a leap,      //so the 400 must be sought out first      if($y%400==0){$leap=true;}      elseif($y%100==0){$leap=false;}      elseif($y%4==0){$leap=true;}      else{$leap=false;}            return $leap;      }    /* end calendar math */    function getMonth_F($m=1){        //formatting the date to text      $monthList=array("January","February","March","April","May","June","July","August","September","October","November","December");      $str=$monthList[(getInputMonth()-1)];            return $str;      }    function getWkStartPos(){      //find the dow of the 1st of the month      //adjust the wkStartPos according to the dow value      //example: if 1st of month starts on thursday (dow==4),      //the start of the week (sunday) will have to be at dow==0, but its position in the reusable calendar is wkStartPos==2      $dow=getDow(getInputYr(),getInputMonth(),1);      $wkStartPos=6-$dow;            return $wkStartPos;      }    function getDowHeader($i){      //pretty much for non-script/non-style version, since the css and js overrides the actual text      $dowHeaderList="SMTWRFA";      $wkStartPos=getWkStartPos();      //when the php generates the <th> and count by $i, if it's between the columns that the calendar is showing, put the day of the week in the <th>      if($i>=$wkStartPos && $i<=$wkStartPos+6){          echo tabs(2).'<th class="dowHeader" id="dowHeader'.($i-$wkStartPos).'" >';          echo '<span>';          echo $dowHeaderList[($i-$wkStartPos)];          echo '</span>';          echo '</th>';          } else {          echo tabs(2).'<th></th>';          }      }    //for css-less and js-less versions  function formatShowDayPre(){echo '<big><b>';}  function formatHideDayPre(){echo '<small><del>';}    //mainly for css-less and js-less versions  //shrink and cross out the days on the reusable calendar that don't apply to the month  //but bold and enlarge the days that do so it's visually distinguishable even if you don't have css or js  function currentMonthCellPre($rowNum,$i){        $dow=getDow(getInputYr(),getInputMonth(),1);      $wkStartPos=getWkStartPos();            $wkStartPos=getWkStartPos();      if($i>=$wkStartPos && $i<=$wkStartPos+6){//within columns          if($rowNum<4){ //rows that don't have 29-31              formatShowDayPre();              } else {              $m=getInputMonth();              if($m==1 || $m==3 || $m==5 || $m==7 || $m==8 || $m==10 || $m==12){ //if month has 31 days, show all days                  formatShowDayPre();                  } elseif($m==4 || $m==6 || $m==9 || $m==11){//if it's 30 days                  //cross out 31                  if(($wkStartPos>1 && $i==8 && $rowNum==4)                   || ($wkStartPos<=1 && $i==1 && $rowNum==5)){                      formatHideDayPre();                      } else {                      formatShowDayPre();                      }                  } else { //if it's february                  if(($rowNum==5) || ($i>6)){                      formatHideDayPre(); //automatically cross it out since february's don't have 30 or 31                      } else {                      if(isLeap()==false){                          if($i==6){                              formatHideDayPre();                              } else {                              formatShowDayPre();                              }                          } else {                          formatShowDayPre();                          }                      }                  //if it has 28 days, cross out 29, 30, 31                  //if it has 29 days, cross out 30, 31                  }              }          } else {          formatHideDayPre();          }      }    //for css-less and js-less versions  function formatShowDayPost(){echo '</b></big>';}  function formatHideDayPost(){echo '</del></small>';}    //mainly for css-less and js-less versions  //closing tags for shrink/cross and enlarge/bold  function currentMonthCellEnd($rowNum,$i){        $wkStartPos=getWkStartPos();      if($i>=$wkStartPos && $i<=$wkStartPos+6){          if($rowNum<4){ //rows that don't have 29-31              formatShowDayPost();              } else {              $m=getInputMonth();              if($m==1 || $m==3 || $m==5 || $m==7 || $m==8 || $m==10 || $m==12){ //if month has 31 days, show all days                  formatShowDayPost();                  } elseif($m==4 || $m==6 || $m==9 || $m==11){//if it's 30 days                  //cross out 31                  if(($wkStartPos>1 && $i==8 && $rowNum==4)                   || ($wkStartPos<=1 && $i==1 && $rowNum==5)){                      formatHideDayPost();                      } else {                      formatShowDayPost();                      }                  } else { //if it's february                  if(($rowNum==5) || ($i>6)){                      formatHideDayPost(); //automatically cross it out since february's don't have 30 or 31                      } else {                      if(isLeap()==false){                          if($i==6){                              formatHideDayPost();                              } else {                              formatShowDayPost();                              }                          } else {                          formatShowDayPost();                          }                      }                  //if it has 28 days, cross out 29, 30, 31                  //if it has 29 days, cross out 30, 31                  }              }          } else {          formatHideDayPost();          }      }  ?>

External CSS file linked in <head>

 @charset "utf-8";  /* CSS Document */    body{background-color:#ddeeff;}    th.dowHeader span{display:none;}    #calendarContainer{      position:relative;      }    #calendarGridUnit{      width:260px;      height:160px;      position:relative;      left:0px;      top:0px;      background-image:url('/images/fauxTrans/090430-fauxTrans_centerCenter.png');      background-repeat:repeat;      padding:20px;      }    table#calendarTable{      width:260px;      height:140px;      position:absolute;      }    #calendarTable tr{      height:20px;      }  #calendarTable td,  #calendarTable th{      width:20px;      height:20px;      }        #calendarTable,  #calendarTable tr,  #calendarTable th,  #calendarTable td{padding:0;}    #calendarTable td.dateCell{      background-image:url('/images/calendar/090811-mainCalText.png');      background-repeat:no-repeat;      }    #calendarTable th.dowHeader span,  #calendarTable td.dateCell span{display:none;}    #dowHeader0{background-position:0px 0px;}  #dowHeader1{background-position:-20px 0px;}  #dowHeader2{background-position:-40px 0px;}  #dowHeader3{background-position:-60px 0px;}  #dowHeader4{background-position:-80px 0px;}  #dowHeader5{background-position:-100px 0px;}  #dowHeader6{background-position:-120px 0px;}    #dateCell-0-6{background-position:-120px -20px;}  #dateCell-0-7{background-position:-140px -20px;}  #dateCell-0-8{background-position:-160px -20px;}  #dateCell-0-9{background-position:-180px -20px;}  #dateCell-0-10{background-position:-200px -20px;}  #dateCell-0-11{background-position:-220px -20px;}  #dateCell-0-12{background-position:-240px -20px;}    #dateCell-1-0{background-position:0px -40px;}  #dateCell-1-1{background-position:-20px -40px;}  #dateCell-1-2{background-position:-40px -40px;}  #dateCell-1-3{background-position:-60px -40px;}  #dateCell-1-4{background-position:-80px -40px;}  #dateCell-1-5{background-position:-100px -40px;}  #dateCell-1-6{background-position:-120px -40px;}  #dateCell-1-7{background-position:-140px -40px;}  #dateCell-1-8{background-position:-160px -40px;}  #dateCell-1-9{background-position:-180px -40px;}  #dateCell-1-10{background-position:-200px -40px;}  #dateCell-1-11{background-position:-220px -40px;}  #dateCell-1-12{background-position:-240px -40px;}    #dateCell-2-0{background-position:0px -60px;}  #dateCell-2-1{background-position:-20px -60px;}  #dateCell-2-2{background-position:-40px -60px;}  #dateCell-2-3{background-position:-60px -60px;}  #dateCell-2-4{background-position:-80px -60px;}  #dateCell-2-5{background-position:-100px -60px;}  #dateCell-2-6{background-position:-120px -60px;}  #dateCell-2-7{background-position:-140px -60px;}  #dateCell-2-8{background-position:-160px -60px;}  #dateCell-2-9{background-position:-180px -60px;}  #dateCell-2-10{background-position:-200px -60px;}  #dateCell-2-11{background-position:-220px -60px;}  #dateCell-2-12{background-position:-240px -60px;}    #dateCell-3-0{background-position:0px -80px;}  #dateCell-3-1{background-position:-20px -80px;}  #dateCell-3-2{background-position:-40px -80px;}  #dateCell-3-3{background-position:-60px -80px;}  #dateCell-3-4{background-position:-80px -80px;}  #dateCell-3-5{background-position:-100px -80px;}  #dateCell-3-6{background-position:-120px -80px;}  #dateCell-3-7{background-position:-140px -80px;}  #dateCell-3-8{background-position:-160px -80px;}  #dateCell-3-9{background-position:-180px -80px;}  #dateCell-3-10{background-position:-200px -80px;}  #dateCell-3-11{background-position:-220px -80px;}  #dateCell-3-12{background-position:-240px -80px;}    #dateCell-4-0{background-position:0px -100px;}  #dateCell-4-1{background-position:-20px -100px;}  #dateCell-4-2{background-position:-40px -100px;}  #dateCell-4-3{background-position:-60px -100px;}  #dateCell-4-4{background-position:-80px -100px;}  #dateCell-4-5{background-position:-100px -100px;}  #dateCell-4-6{background-position:-120px -100px;}  #dateCell-4-7{background-position:-140px -100px;}  #dateCell-4-8{background-position:-160px -100px;}  #dateCell-4-9{background-position:-180px -100px;}  #dateCell-4-10{background-position:-200px -100px;}  #dateCell-4-11{background-position:-220px -100px;}  #dateCell-4-12{background-position:-240px -100px;}    #dateCell-5-0{background-position:0px -120px;}  #dateCell-5-1{background-position:-20px -120px;}  #dateCell-5-2{background-position:-40px -120px;}  #dateCell-5-3{background-position:-60px -120px;}  #dateCell-5-4{background-position:-80px -120px;}  #dateCell-5-5{background-position:-100px -120px;}  #dateCell-5-6{background-position:-120px -120px;}  #dateCell-5-7{background-position:-140px -120px;}  #dateCell-5-8{background-position:-160px -120px;}    #dateCell-6-0{background-position:0px -140px;}  #dateCell-6-1{background-position:-20px -140px;}    #calFrame{      width:180px;      height:20px;      position:relative;      left:-20px;      top:0px;      }        #calFrame-top,  #calFrame-bottom{width:180px;height:20px;}    #calFrame-left,  #calFrame-right{width:20px;height:120px;}    #calFrame-left,  #calFrame-right,  #calFrame-bottom{position:absolute;}    .calFrameElem{      background-image:url('/images/calendar/090811-calFrameWHeader.png');      background-repeat:no-repeat;      }    #calFrame-top{background-position:0px 0px;}  #calFrame-left{      background-position:0px -20px;      top:20px;      }  #calFrame-right{      background-position:-160px -20px;      right:0px;      top:20px;      }  #calFrame-bottom{      background-position:0px -140px;      top:140px;      }    #calCross{      width:200px;      height:20px;      position:absolute;      top:140px;      left:80px;      }    .calCrossElem{      height:20px;      background-image:url('/images/calendar/090811-calCross.png');      background-repeat:no-repeat;      position:absolute;      }    #calCross-top{      width:200px;      background-position:0px -20px;      }    #calCross-bottom{      width:60px;      background-position:-140px 0px;      right:0px;      top:-20px;      }        /* date display */    #dateDisplay{      width:220px;      height:60px;      position:absolute;      top:20px;      left:320px;      }    #ddMonth,  #ddYear1,  .ddYear234{      background-image:url('/images/calendar/090812-dd-words-strips-shrink.png');      background-repeat:no-repeat;      position:absolute;      top:10px;      }        #ddMonth{      width:36px;      height:260px;      background-position:0px 0px;      left:52px;      }        #ddYear1{      width:16px;      height:200px;      background-position:-40px 0px;      left:92px;      }        .ddYear234{      width:16px;      height:220px;      background-position:-60px 0px;      }    #ddYear2{left:112px;}  #ddYear3{left:132px;}  #ddYear4{left:152px;}          #dateFrame{      width:220px;      height:20px;      position:relative;      }        .dateFrameElem{      background-image:url('/images/calendar/090812-dateFrame.png');      background-repeat:no-repeat;      position:absolute;      }        #dateFrame-top,  #dateFrame-bottom{      width:220px;      height:20px;      }    #dateFrame-left,  #dateFrame-right{      width:40px;      height:20px;      top:20px;      }    #dateFrame-top{background-position:0px 0px;}  #dateFrame-left{background-position:0px -20px;}  #dateFrame-right{      background-position:-180px -20px;      right:0px;      }  #dateFrame-bottom{      background-position:0px -40px;      top:40px;      }        #dateFrame-leftArrow,  #dateFrame-rightArrow{      width:20px;      height:20px;      background-repeat:no-repeat;      position:absolute;      top:20px;      cursor:pointer;      }    #dateFrame-leftArrow{      background-image:url('/images/calendar/090812-dateFrame-leftArrow.png');      left:10px;      }    #dateFrame-rightArrow{      background-image:url('/images/calendar/090812-dateFrame-rightArrow.png');      right:10px;      }

PHP in Example

 <div>  <h3>Reusable Calendar - Working Version</h3>  <p>Click on the arrows to change months. Or, drag the strips up and down or click on the month/digit to change the date. Try choosing a date before Oct 1582!</p>  <p id="message">Messages: <span id="oct1582Restr"></span> </p>  <p><a href="http://ivanwlam.com/experiments/" title="Back to Experiments">Go back to Experiments section</a></p>      <div id="calendarContainer">          <div id="dateDisplay">              <?php                            //calculate and offset the css top values of the display strips depending on what month and year it is              $m=getInputMonth();              $monthTop=(25-(15*$m));                            $y=getInputYr();              $y1=floor(($y/1000));              $y2=floor(($y-($y1*1000))/100);              $y3=floor(($y-($y1*1000)-($y2*100))/10);              $y4=$y-($y1*1000)-($y2*100)-($y3*10);                            $y1Top=25-(15*$y1);              $y2Top=10-(15*$y2);              $y3Top=10-(15*$y3);              $y4Top=10-(15*$y4);              ?>              <!-- some things in this div need to be built in js              basically, js-less versions won't see any of this, which means users won't see the date display, since they can't really interactive with the display w/o js.              -->              <div id="dateFrame">                  <div id="dateFrame-top" class="dateFrameElem"></div>                  <div id="dateFrame-left" class="dateFrameElem"></div>                  <div id="dateFrame-right" class="dateFrameElem"></div>                  <div id="dateFrame-bottom" class="dateFrameElem"></div>                                    <!-- dateFrame arrows supposed to be added in js -->              </div>              <div id="ddMonth" style="top:<?php echo $monthTop; ?>px;"></div>              <div id="ddYear1" style="top:<?php echo $y1Top; ?>px;" ></div>              <div id="ddYear2" class="ddYear234" style="top:<?php echo $y2Top; ?>px;" ></div>              <div id="ddYear3" class="ddYear234" style="top:<?php echo $y3Top; ?>px;" ></div>              <div id="ddYear4" class="ddYear234" style="top:<?php echo $y4Top; ?>px;" ></div>                    </div><!-- end #dateDisplay -->          <div id="calendarGridUnit">              <table id="calendarTable" cellpadding="0" cellspacing="0">                  <col align="center" />                  <col align="center" />                  <col align="center" />                  <col align="center" />                  <col align="center" />                  <col align="center" />                  <col align="center" />                  <col align="center" />                  <col align="center" />                  <col align="center" />                  <col align="center" />                  <col align="center" />                  <col align="center" />                  <tr><?php                      for($i=0;$i<13;$i++){                          getDowHeader($i);                          }                      ?>                  </tr>                                    <?php                                    //just listing out the parameters for filling the table with calendar values                  $calRowData=array(                      array("rowStartVal" => 6, "rowEndVal" => 13, "cellValConst" => (-5), "preColspan" => 6),                      array("rowStartVal" => 0, "rowEndVal" => 13, "cellValConst" => (2)),                      array("rowStartVal" => 0, "rowEndVal" => 13, "cellValConst" => (9)),                      array("rowStartVal" => 0, "rowEndVal" => 13, "cellValConst" => (16)),                      array("rowStartVal" => 0, "rowEndVal" => 9, "cellValConst" => (23), "postColspan" => 4),                      array("rowStartVal" => 0, "rowEndVal" => 2, "cellValConst" => (30), "postColspan" => 12)                      );                                    //go through the array above and output the days. if there's empty space before and after, output them                  foreach($calRowData as $key => $datum){                      echo tabs(1).'<tr id="calRow-'.$key.'">';                      if($datum["preColspan"]){                          echo tabs(2).'<td colspan="'.$datum["preColspan"].'"></td>';                          }                      for($i=$datum["rowStartVal"];$i<$datum["rowEndVal"];$i++){                          echo tabs(2).'<td class="dateCell" id="dateCell-'.$key.'-'.$i.'">';                          echo '<span>';                          currentMonthCellPre($key,$i);                          echo ($i+$datum["cellValConst"]);                          currentMonthCellEnd($key,$i);                          echo '</span>';                          echo '</td>';                          }                      if($datum["postColspan"]){                          echo tabs(2).'<td colspan="'.$datum["postColspan"].'"></td>';                          }                      echo tabs(1).'</tr>';                      nl();                      }                                                      ?>                                                                            </table>              <div id="calCross" style="left:<?php                  //determine position of the crosses                  $calCrossLeft=0;                                    //similar to the css-less stylings: find out what month it is, and move the cross-out strip accordingly to cross out days that don't exist in those months                  $m=getInputMonth();                  if($m==1 || $m==3 || $m==5 || $m==7 || $m==8 || $m==10 || $m==12){ //if month has 31 days, show all days                      $calCrossLeft=60+20;                      } elseif($m==4 || $m==6 || $m==9 || $m==11){//if it's 30 days                      //cross out 31                      if(($wkStartPos>1)                       || ($wkStartPos<=1)){                          $calCrossLeft=20+20;                          } else {                          $calCrossLeft=60+20;                          }                      } else { //if it's february                      if(isLeap()==false){                          $calCrossLeft=(-20+20);                          } else {                          $calCrossLeft=0+20;                          }                      //if it has 28 days, cross out 29, 30, 31                      //if it has 29 days, cross out 30, 31                      }                                    echo ($calCrossLeft);                  ?>px;">                  <div id="calCross-top" class="calCrossElem"></div><!--end #calCross-top -->                  <div id="calCross-bottom" class="calCrossElem"></div><!--end #calCross-bottom -->              </div><!-- end #calCross -->                                          <!-- again, css-less/js-less won't see the frame, since the highlighting is already done by enlarging and bolding -->              <div id="calFrame" style="left:<?php echo ((20*getWkStartPos())-20); ?>px;">                  <div id="calFrame-top" class="calFrameElem" ></div><!-- end #calFrame-top -->                  <div id="calFrame-left" class="calFrameElem" ></div><!-- end #calFrame-left -->                  <div id="calFrame-right" class="calFrameElem" ></div><!-- end #calFrame-right -->                  <div id="calFrame-bottom" class="calFrameElem" ></div><!-- end #calFrame-bottom -->                                </div><!--end #calFrame-->          </div><!--end #calendarGridUnit -->        </div><!--end #calendarContainer -->  </div>

Written-out JavaScript at the end of the document

 <script type="text/javascript">  <!--    $("#dateFrame")      .append('<div id="dateFrame-leftArrow" title="Previous Month"></div><div id="dateFrame-rightArrow" title="Next Month"></div>'); //add the arrows    //trigger functions when the arrow are clicked  $("#dateFrame-leftArrow").click(function(){leftArrowClicked();});  $("#dateFrame-rightArrow").click(function(){rightArrowClicked();});    var currY=<?php echo getInputYr();?>;  var currM=<?php echo getInputMonth(); ?>;    var newY=currY;  var newY1=Math.floor(newY/1000);  var newY2=Math.floor((newY-(newY1*1000))/100);  var newY3=Math.floor((newY-(newY1*1000)-(newY2*100))/10);  var newY4=newY-(newY1*1000)-(newY2*100)-(newY3*10);  var newM=currM;    //positioning values that may change depending on the graphics  var ddMonthOffset=25;  var ddY1Offset=25;  var ddY234Offset=10;    var ddMonthIncrem=15;  var ddY1Increm=15;  var ddY234Increm=15;    var calFrameOffset=20;  var calFrameIncrem=20;    var earlierOct1582=false;    function globalCheck(){      }    function globalUpdate(){  //always update the values and positions of things when an interactive event is triggered  //    console.log("global update");        //check oct 1582 restraints      checkRestraint();            //move the display and calendar fauxTrans      updateDdTops();      updateCal();            //assign the new values to the old values      currM=newM;      currY=newY;            //change the tooltip when rolling over the arrows      updateArrowTitleAttr();            //display or clear the message about the Oct 1582 restriction      updateOct1582Message();        //    console.log("//");      }        function leftArrowClicked(){  //    console.log("left");      //always start with a check      globalCheck();            //determine the new months and years depending on the conditions, such as year change and the october 1582 start-of-gregorian-calendar limit      if(currY==1582 && currM==10){          //can't go any earlier than october 1582, when the gregorian calendar was first adopted          newM=currM;          newY=currY;          message="oct1852";          } else if(currM==1){          //year change          newM=12;          newY=currY-1;          clearMessage();          } else {          //normal          newM=currM-1;          newY=currY;          clearMessage();          }            //update everything when it's all said that d one      globalUpdate();      }    function rightArrowClicked(){  //    console.log("right");      // always start with a check      globalCheck();            //determine the new months and years depending on the conditions, such as year change and the dec 9999 end-of-four-digit years limit      if(currY==9999 && currM==12){          newM=currM;          newY=currY;          message="dec9999";          } else if (currM==12){          //year change          newM=1;          newY=currY+1;          clearMessage();          } else {          //normal          newM=currM+1;          newY=currY;          clearMessage();          }      globalUpdate();      }        function updateDdTops(){      //find out new position for the strips, the mov them        var newDdMonthTop=ddMonthOffset-(ddMonthIncrem*newM);            var newY1=Math.floor(newY/1000);      var newY2=Math.floor((newY-(newY1*1000))/100);      var newY3=Math.floor((newY-(newY1*1000)-(newY2*100))/10);      var newY4=(newY-(newY1*1000)-(newY2*100)-(newY3*10));            var newDdY1Top=ddY1Offset-(ddY1Increm*newY1);      var newDdY2Top=ddY234Offset-(ddY234Increm*newY2);      var newDdY3Top=ddY234Offset-(ddY234Increm*newY3);      var newDdY4Top=ddY234Offset-(ddY234Increm*newY4);            $("#ddMonth").animate(          {"top":newDdMonthTop+"px"}          );                $("#ddYear1").animate(          {"top":newDdY1Top+"px"}          );                $("#ddYear2").animate(          {"top":newDdY2Top+"px"}          );                $("#ddYear3").animate(          {"top":newDdY3Top+"px"}          );                $("#ddYear4").animate(          {"top":newDdY4Top+"px"}          );      }    function updateCal(){      //two things to update/move: the frame, and the cross strip      updateCalFrame();      updateCalCross();      }    function updateCalFrame(){      //move the the new position based on the month and the presets      $("#calFrame").stop().animate(          {"left":((calFrameIncrem*getWkStartPos())-calFrameOffset)+"px"} //value is temporary          );      }        function updateCalCross(){      //determine position of the crosses      var calCrossLeft=0;      var wkStartPos=getWkStartPos();            m=newM;      if(m==1 || m==3 || m==5 || m==7 || m==8 || m==10 || m==12){ //if month has 31 days, show all days          calCrossLeft=60+20;          } else if(m==4 || m==6 || m==9 || m==11){//if it's 30 days          //cross out 31          if((wkStartPos>1)           || (wkStartPos<=1)){              calCrossLeft=20+20;              } else {              calCrossLeft=60+20;              }          } else { //if it's february          if(isLeap()==false){              calCrossLeft=(-20+20);              } else {              calCrossLeft=0+20;              }          //if it has 28 days, cross out 29, 30, 31          //if it has 29 days, cross out 30, 31          }                        $("#calCross").stop().animate(          {"left":calCrossLeft+"px"} //value is temporary          );      }    //calendar math  //similar to php version    function getDow(y,m,d){            var yd=y-1583;            var con4=yd+2;      var con100=yd+82;      var con400=yd+382;            var pot4=Math.floor(con4/4);      var pot100=Math.floor(con100/100);      var pot400=Math.floor(con400/400);            var numNoLeaps=pot100-pot400;      var numLeaps=pot4-numNoLeaps;            var yrStart=(yd+numLeaps+6)%7;            var monthStartList="033614625035";            if(isLeap()==true && m>=3){var leapConst=1;}          else {var leapConst=0;}            var dow=(yd+numLeaps+6+Number(monthStartList.substring(m-1,m))+d-1+leapConst)%7;            return dow;      }    function isLeap(){      var y=newY;      var leap;            if(y%400==0){leap=true;}      else if(y%100==0){leap=false;}      else if(y%4==0){leap=true;}      else{leap=false;}            return leap;      }    function getWkStartPos(){      //find the dow of the 1st of the month      //adjust the wkStartPos according to the dow value      var dow=getDow(newY,newM,1);      var wkStartPos=6-dow;            return wkStartPos; // temp: 0 is the left most position      }    //end calendar math      function updateArrowTitleAttr(){      //change tooltip values by determining id of next and previous months      var newMPrev;      var newYPrev;      var newMNext;      var newYNext;            $("#dateFrame-leftArrow").css({"display":"block"});      $("#dateFrame-rightArrow").css({"display":"block"});      if(currY==1582 && currM==10){          $("#dateFrame-leftArrow").css({"display":"none"});          newYPrev=1582;          newMPrev=10;          newYNext=1582;          newMNext=11;          } else if(currY==9999 && currM==12){          $("#dateFrame-rightArrow").css({"display":"none"});          newYPrev=9999;          newMPrev=11;          newYNext=9999;          newMNext=12;          } else if(currM==1){          newYPrev=currY-1;          newMPrev=12;          newYNext=currY;          newMNext=2;          } else if(currM==12){          newYPrev=currY;          newMPrev=11;          newYNext=currY+1;          newMNext=1;          } else {          newYPrev=currY;          newMPrev=currM-1;          newYNext=currY;          newMNext=currM+1;          }            //change the tooltips      $("#dateFrame-leftArrow").attr("title",dateFormat_F(newMPrev)+" "+newYPrev);      $("#dateFrame-rightArrow").attr("title",dateFormat_F(newMNext)+" "+newYNext);            }        //like php version  function dateFormat_F(monthNumNoLeadZeros){      var monthList=new Array("January","February","March","April","May","June","July","August","September","October","November","December");            return monthList[(monthNumNoLeadZeros-1)];      }        //start dd drags      //drag months (similar with y1 and y234)  //find the last position of the strip  var ddMonthOffsetEnd=10-(11*ddMonthIncrem);  //find the offsetTop of the dateFrame (which is also where the offsetTops of the strips)  //to offset the top and bottom range values of the strip  //can be used for all strips  var dateFrameOffsetTop=$("#dateFrame").offset().top;  //define the drag range. since the date value goes up as the positioning decreases, Y1 is the last position, Y2 is the first position.  var containDdMonthY1=Math.floor(dateFrameOffsetTop+ddMonthOffsetEnd);// round to give room  var containDdMonthY2=Math.ceil(dateFrameOffsetTop+10); //round to give room    //define the draggable UI (pretty much the same for Y1 and Y234):  //only move vertical,  //follow a drag grid so it locks at the particular positions to show the value,  //when dragging, update the current month based on the strip's position so the calendar can be updated  //define the range,  //when moving, show the cursor as moving up and down  //when stopped dragging, global update everything to get all elements on the same page    $("#ddMonth").draggable({      axis: 'y',      grid: [0,ddMonthIncrem],      drag: function(e,ui){          var uiTop=ui.position.top;          updateDdMonthStatus(uiTop);  //        console.log("top: "+uiTop+" || newM: "+newM);          $(this).css("cursor","n-resize");          },      containment: [0,containDdMonthY1,0,containDdMonthY2],      stop: function(e,ui){          globalUpdate();          }      });    //set newM value to whatever position the strip is dragged to      function updateDdMonthStatus(uiTop){      uiTop=Math.round(uiTop); //round because sometimes the position get off by less than a px      var month=(25-uiTop)/15; //just formula to turn position to the date value      newM=month;      checkRestraint();      updateCal();      }    //see month drag's explanation  var ddY1OffsetEnd=10-(8*ddY1Increm);  var containDdY1Y1=Math.floor(dateFrameOffsetTop+ddY1OffsetEnd);// round to give room  var containDdY1Y2=Math.ceil(dateFrameOffsetTop+10); //round to give room    $("#ddYear1").draggable({      axis: 'y',      grid: [0,ddY1Increm],      drag: function(e,ui){          var uiTop=ui.position.top;          updateDdY1Status(uiTop);  //        console.log("top: "+uiTop+" offsetTop: "+uiOffsetTop+" || newY1: "+newY1+" newY: "+newY);          $(this).css("cursor","n-resize");          },      containment: [0,containDdY1Y1,0,containDdY1Y2],      stop: function(e,ui){          globalUpdate();          }      });    function updateDdY1Status(uiTop){      uiTop=Math.round(uiTop);      var year1=(25-uiTop)/15;      newY1=year1;      updateNewY();      checkRestraint();      updateCal();      }    //see month drag's explanation  var ddY234OffsetEnd=10-(9*ddY234Increm);  var containDdY234Y1=Math.floor(dateFrameOffsetTop+ddY234OffsetEnd);// round to give room  var containDdY234Y2=Math.ceil(dateFrameOffsetTop+10); //round to give room    $("#ddYear2").draggable({      axis: 'y',      grid: [0,ddY234Increm],      drag: function(e,ui){          var uiTop=ui.position.top;          updateDdY234Status(uiTop,2);  //        console.log("top: "+uiTop+" offsetTop: "+uiOffsetTop+" || newY2: "+newY2+" newY: "+newY);          $(this).css("cursor","n-resize");          },      containment: [0,containDdY234Y1,0,containDdY234Y2],      stop: function(e,ui){          globalUpdate();          }      });    $("#ddYear3").draggable({      axis: 'y',      grid: [0,ddY234Increm],      drag: function(e,ui){          var uiTop=ui.position.top;          updateDdY234Status(uiTop,3);  //        console.log("top: "+uiTop+" offsetTop: "+uiOffsetTop+" || newY3: "+newY3+" newY: "+newY);          $(this).css("cursor","n-resize");          },      containment: [0,containDdY234Y1,0,containDdY234Y2],      stop: function(e,ui){          globalUpdate();          }      });    $("#ddYear4").draggable({      axis: 'y',      grid: [0,ddY234Increm],      drag: function(e,ui){          var uiTop=ui.position.top;          updateDdY234Status(uiTop,4);  //        console.log("top: "+uiTop+" offsetTop: "+uiOffsetTop+" || newY4: "+newY4+" newY: "+newY);          $(this).css("cursor","n-resize");          },      containment: [0,containDdY234Y1,0,containDdY234Y2],      stop: function(e,ui){          globalUpdate();          }      });    //get the new year digit, then update the year and calendar  function updateDdY234Status(uiTop,yDigit){      uiTop=Math.round(uiTop);      var yearDigit=(10-uiTop)/15;      switch(yDigit){          case 2:              newY2=yearDigit;              break;          case 3:              newY3=yearDigit;              break;          case 4:              newY4=yearDigit;              break;          default:              break;          }      updateNewY();      checkRestraint();      updateCal();      }    //when changing a year digit, update the newY  function updateNewY(){      var yearConcat=(newY1*1000)+(newY2*100)+(newY3*10)+newY4;      newY=yearConcat;      }    // end dd drag    // start dd click    //for click and oct 1582 restraint  var lowM=1;  var lowY1=1;  var lowY2=0;  var lowY3=0;  var lowY4=0;    //when clicked, use the position of the mouse to determine which is clicked, set the new date, then update the calendar and everything else  $("#ddMonth").click(function(e){      newM=getMyValue($(this),"month",e);      if(newM<lowM){newM=lowM;} // limit the month value to the low range set by oct 1582 restraint      if(newM>12){newM=12;} //limit the month value to what is available      checkRestraint();      globalUpdate();      });    $("#ddYear1").click(function(e){      newY1=getMyValue($(this),"y1",e);      if(newY1<lowY1){newY1=lowY1;} // limit the Y1 value to the low range set by oct 1582 restraint      if(newY1>9){newY1=9;} //limit the y1 value to what is available      updateNewY();      checkRestraint();      globalUpdate();      });    $(".ddYear234").click(function(e){      var newY234=getMyValue($(this),"y234",e);      if(newY234>9){newY234=9;} //limit the y234 value to what is available      var thisIdNum=$(this).attr("id").substring(6); //use the id to find out which digit is clicked      switch(thisIdNum){          case "2":              if(newY234<lowY2){newY234=lowY2;} // limit the Y2 value to the low range set by oct 1582 restraint              newY2=newY234;              break;          case "3":              if(newY234<lowY3){newY234=lowY3;} // limit the Y3 value to the low range set by oct 1582 restraint              newY3=newY234;                            break;          case "4":              if(newY234<lowY4){newY234=lowY4;} // limit the Y4 value to the low range set by oct 1582 restraint              newY4=newY234;              break;          default:              break;          }      updateNewY();      checkRestraint();      globalUpdate();      });    //function to use the event's mouse position to determine what value is clicked  function getMyValue(jqObj,ddName,e){      var pageY=e.pageY;      if(!pageY){          pageY=e.clientY;          }      var objOffsetTop=jqObj.offset().top;      var objRelY=pageY-objOffsetTop;      var objRelYTrim=objRelY-10;            switch(ddName){          case "month":              var clickValue=Math.ceil(objRelYTrim/ddMonthIncrem);              break;          case "y1":              var clickValue=Math.ceil(objRelYTrim/ddY1Increm);              break;          case "y234":              var clickValue=Math.floor(objRelYTrim/ddY234Increm);              break;          default:              var clickValue=(-1);              break;          }  //    console.log("pageY: "+pageY+" objOffsetTop: "+objOffsetTop+" objRelY: "+objRelY+" objRelYTrim: "+objRelYTrim+" clickMonth: "+clickValue);      return clickValue;      }    // end dd click    // start dd hover    //when the mouse is moving over a clickable value, the cursor turns into a pointer.  $("#ddMonth").mousemove(function(e){      var moveVal=getMyValue($(this),"month",e);      if(moveVal>=lowM && moveVal<=12){          $(this).css({"cursor":"pointer"});          } else {          $(this).css({"cursor":"auto"});          }      });    $("#ddYear1").mousemove(function(e){      var moveVal=getMyValue($(this),"y1",e);      if(moveVal>=lowY1 && moveVal<=9){          $(this).css({"cursor":"pointer"});          } else {          $(this).css({"cursor":"auto"});          }      });    $(".ddYear234").mousemove(function(e){      var moveVal=getMyValue($(this),"y234",e);      var thisIdNum=$(this).attr("id").substring(6); //use the id to find out which digit is clicked      switch(thisIdNum){          case "2":              var lowY234=lowY2;              break;          case "3":              var lowY234=lowY3;              break;          case "4":              var lowY234=lowY4;              break;          default:              break;          }      if(moveVal>=lowY234 && moveVal<=9){          $(this).css({"cursor":"pointer"});          } else {          $(this).css({"cursor":"auto"});          }      });    // end dd hover    // start dd restraint  function checkRestraint(){      updateNewY(); //update the newY value in case it hasn't been done.      if(newY<1582){          // not supposed to happen, set date to oct 1582          // when global update is run, the calendar and date display will set to oct 1582          newM=lowM=10;          newY1=lowY1=1;          newY2=lowY2=5;          newY3=lowY3=8;          newY4=lowY4=2;          newY=1582;                    earlierOct1582=true;          } else if(newY==1582){          //set ddMonth containment to october to december          if(newM<=10){              newM=10;              earlierOct1582=true;              } else {              earlierOct1582=false;              }          lowM=10;          lowY1=1;          lowY2=5;          lowY3=8;          lowY4=2;                    } else { //newY>1582          //make all strips movable to full range          lowM=1;          lowY1=1;          lowY2=lowY3=lowY4=0;          earlierOct1582=false;          }      updateNewY();      }          // end dd restraint    //messages    function updateOct1582Message(){            if(earlierOct1582==true){          $("#oct1582Restr").html("The earliest available month is October 1582! That's when the Gregorian calendar was first adopted!");          } else {          $("#oct1582Restr").html("");          }      }    //end messages    //do an update with everything when the page loads  globalUpdate();    //-->  </script>