Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Calculating many dates after a reference date is specified in a textbox 1

Status
Not open for further replies.

waubain

Technical User
Dec 13, 2011
200
US
I don't know anything about JS (will soon be obvious), but I am trying to help a colleague.

This project aids in the calculation of many dates for a paper simulation. The html document must be in one file and work only on the client side. It will not be on a server.
Basically the end-user enters a future reference date into a text-box and clicks "Calculate Dates". At that point 6 dates in the past are calculated based on specific number of days back. Also there may be multiple of the same date embedded throughout the simulation. Eventually part of the content within the body will get printed.

I do a little VBA programming so I tried to translate what I might do in VBA into what I could find on the internet about JS.

Any help or advice is appreciated.

Here is my first try:
JavaScript:
<!DOCTYPE HTML>
<html>
<head>
<script>

function CalcDates() {
    // gets string from activitydate Textbox and formats into date as variable
    var teststring = document.getElementById("activitydate").value;  //Entered at Month/Day/Year
    var dateParts = testString.split('/');
    var referenceDate = new Date(dateParts[1] - 1, dateParts[2], dateParts[0]);   //Formatted at Month/Day/Year
    
    //for each element in array sent to function renderNewDate and return that date to 
    //to be placed in the proper location of body
    
    var a = [0,1,147,148,156,200];  //these are the number of days back from the reference date to be calculated
    for (var i=0, tot=a.length; i < tot; i++) {
        
        switch (a) {   
            case 0: var Date0 = renderNewDate(referenceDate, 0)      // pass reference date and days back to 2nd function 
                document.getElementById('day0a').innerHTML = Date0;  // place return result into body of html document
                document.getElementById('day0b').innerHTML = Date0;  //some dates may appear more than once
            break;

            case 1: var Date1 = renderNewDate(referenceDate, 1) 
                document.getElementById('day1').innerHTML = Date1;
            break;
        
            case 147: var Date147 = renderNewDate(referenceDate, 147) 
                document.getElementById('day0').innerHTML = Date147;
            break;
        
            case 148: var Date148 = renderNewDate(referenceDate, 148) 
                document.getElementById('day0').innerHTML = Date148;
            break;
        
            case 156: var Date156 = renderNewDate(referenceDate, 156) 
                document.getElementById('day0').innerHTML = Date156;
            break;
        
            case 200: var Date200 = renderNewDate(referenceDate, 200) 
                document.getElementById('day0').innerHTML = Date200;
            break;
        }
    }
          
    function renderNewDate(referenceDate, days) {
        // duplicate the reference date, then subtract the number of days;
        // JavaScript will automatically take care of switching to the next month or year if the current one is exceeded
    
        var endDate,
            formattedDate;
     
        endDate = new Date(referenceDate.getTime());
        endDate.setDate(endDate.getDate() - days);
     
        return = (endDate.getMonth() + 1) + '/' + endDate.getDate() + '/' + endDate.getFullYear();
    }
</script>
<body>
<label>Future date of activity (mm/dd/yyyy): &nbsp;</label>
    <input type="text" id="activitydate" name="activitydate" />
    <br />
    <button onclick='doAction();'>Calculate Dates</button>
   <br />
   <br />
   <p id="day0a">0 days back</p>
   <p id="day1">1 day back</p>
   <p id="day147">147 days back</p>
   <p id="day148">148 days back</p>
   <p id="day156">156 days back</p>
   <p id="day200">200 days back</p>
   <p id="day0b">0 days back</p>   
</body>
</html>

You don't know what you don't know...
 
like this?

Code:
<!DOCTYPE HTML>
    <html>
        <head>
            <style>
                .row{clear:both; overflow:hidden; width:100em;}
                .label{float:left; width:10em;}
                .field{float:left; width 65em; margin-left: 10px;}
                .field .q{float:left; width: 5em; }
                .field .r{float:left; width: 15em;}
                input[type="text"] {width: 4em;}
            </style>
            <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
            <script type="text/javascript">
            var curDate;
            $(document).ready(function(){
                /* validate dates */
                $('.row:first .field input').on('change',function(){
                    resetCurDate();
                });
                
                $('.question').on('change', function(){
                    resetCurDate();
                });
                
                function resetCurDate(){
                    curDate = new Date($('#year').val(), $('#month').val(),$('#day').val());
                    doCalcs();
                }
                function doCalcs(){
                    $('.question').each(function(i,elem){
                        //alert(i);
                        var v = $(elem).val();
                        var _d = new Date(curDate.getTime());
                        _d.setDate( _d.getDate() - v);
                        if (_d.toString() != 'Invalid Date') {
                            $('#r_' + i).text(_d.toDateString());
                        }
                    });
                }
                
            });
            
            
            </script>
        </head>
        <body>
            <div id="content">
                <form method="#" >
                    <div class="row">
                        <div class="label">
                            Reference Date:<br/>
                            Year:<br/>
                            Month:<br/>
                            Day
                        </div>
                        <div class="field">
                            <br/>
                            <input type="text" name="year" id="year" />
                            <br/>
                            <input type="text" name="month" id="month" />
                            <br/>
                            <input type="text" name="day" id="day" />
                        </div>
                    </div>
                    
                    <div class="row">
                        <div class="label">
                            Number Days ago
                        </div>
                        <div class="field">
                            <div class="q">
                                <input type="text" class="question" name="q_0" id="q_0" />
                            </div>
                            <div class="r">
                                <span id="r_0"></span>
                            </div>                  
                        </div>
                    </div>
                    <div class="row">
                        <div class="label">
                            Number Days ago
                        </div>
                        <div class="field">
                            <div class="q">
                                <input type="text" class="question" name="q_1" id="q_1" />
                            </div>
                            <div class="r">
                                <span id="r_1"></span>
                            </div>                  
                        </div>
                    </div>
                    <div class="row">
                        <div class="label">
                            Number Days ago
                        </div>
                        <div class="field">
                            <div class="q">
                                <input type="text" class="question" name="q_2" id="q_2" />
                            </div>
                            <div class="r">
                                <span id="r_2"></span>
                            </div>                  
                        </div>
                    </div>
                    <div class="row">
                        <div class="label">
                            Number Days ago
                        </div>
                        <div class="field">
                            <div class="q">
                                <input type="text" class="question" name="q_3" id="q_3" />
                            </div>
                            <div class="r">
                                <span id="r_3"></span>
                            </div>                  
                        </div>
                    </div>
                    <div class="row">
                        <div class="label">
                            Number Days ago
                        </div>
                        <div class="field">
                            <div class="q">
                                <input type="text" class="question" name="q_4" id="q_4" />
                            </div>
                            <div class="r">
                                <span id="r_4"></span>
                            </div>                  
                        </div>
                    </div>
                    <div class="row">
                        <div class="label">
                            Number Days ago
                        </div>
                        <div class="field">
                            <div class="q">
                                <input type="text" class="question" name="q_5" id="q_5" />
                            </div>
                            <div class="r">
                                <span id="r_5"></span>
                            </div>                  
                        </div>
                    </div>
                </form>
                
            </div>
        </body>
    </html>
 
jpadie,
I could not get your code to work. I entered a year, month and day but how do you call the functions to calculate the dates back in time? It may take me a while to digest your code.

With some tweaking I did get my version to work. Maybe this will better demonstrate what I needed to do.

Thank you for you help

Code:
<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript">

    function ChangeDates() 
    {
    //gets string from activitydate Textbox and formats into date as variable
    var strDate = document.getElementById("activitydate").value;  //entered at Month/Day/Year
    var referenceDate = new Date(Date.parse(strDate)); // returns date from string
        
    //to be placed in the proper location of body
    
    var a = [0,1,129,147,148,156,200];
    
    for (var i=0, tot=a.length; i < tot; i++)
      {
         switch (a[i])
        {   
            case 0: 
                var Date0 = renderNewDate(referenceDate, 0) 
                document.getElementById('day0').innerHTML = Date0;
            break;

            case 1: 
                var Date1 = renderNewDate(referenceDate, 1) 
                document.getElementById('day1').innerHTML = Date1;
            break;
            
            case 129: 
                var Date1 = renderNewDate(referenceDate, 129) 
                document.getElementById('day129').innerHTML = Date1;
            break;
        
            case 147: 
                var Date147 = renderNewDate(referenceDate, 147) 
                document.getElementById('day147').innerHTML = Date147;
            break;
        
            case 148: 
                var Date148 = renderNewDate(referenceDate, 148) 
                document.getElementById('day148').innerHTML = Date148;
            break;
        
            case 156: 
                var Date156 = renderNewDate(referenceDate, 156) 
                document.getElementById('day156').innerHTML = Date156;
            break;
        
            case 200: 
                var Date200 = renderNewDate(referenceDate, 200) 
                document.getElementById('day200').innerHTML = Date200;
            break;
        }
      }
    }
</script>
 <script type="text/javascript">         
    function renderNewDate(referenceDate, days) {
        // duplicate the reference date, then subtract the number of days;
        // JavaScript will automatically take care of switching to the next month or year if the current one is exceeded
        
        var endDate,
            formattedDate,
            calculatedDate;
        
        endDate = new Date(referenceDate.getTime());
        endDate.setDate(endDate.getDate() - days);
             
        calculatedDate = (endDate.getMonth() + 1) + '/' + endDate.getDate() + '/' + endDate.getFullYear();
        return calculatedDate;
        }
</script>
</head>

<body>
<label>Future date of activity (mm/dd/yyyy): &nbsp;</label>
    <input type="text" id="activitydate" name="activitydate" />
    <br />
    <button onclick="ChangeDates()">Change Dates</button>
    <br />
   <br />
   
   <table>
    <tr>
        <td>Today's date:&nbsp</td>
        <td id="day0"> new date</td>
    </tr>
        <tr>
        <td>Yesterday's date:&nbsp</td>
        <td id="day1"> new date</td>
    </tr>
        <tr>
        <td>129 days ago date:&nbsp</td>
        <td id="day129"> new date</td>
    </tr>
        <tr>
        <td>147 days ago date:&nbsp</td>
        <td id="day147"> new date</td>
    </tr>
        <tr>
        <td>148 days ago date:&nbsp</td>
        <td id="day148"> new date</td>
    </tr>
        <tr>
        <td>156 days ago date:&nbsp</td>
        <td id="day156">new date</td>
    </tr>
        <tr>
        <td>200 days ago date:&nbsp</td>
        <td id="day200"> new date</td>
    </tr>
   </table>
</body>
</html>

You don't know what you don't know...
 
any time that there is a change to any of the boxes, the results recalculate. no button push is required.

the code works without fault on my systems so there must be something wrong with your cutting and pasting. or perhaps an anomalous browser - check the javascript console for errata.
 
for some browsers you may need to add the http: before the // in the first <script> src.

 
waubain, your code still won't work correctly as you have a typo in the Case 129 code above.

If I understand what you are trying to do, your code:

Code:
for (var i=0, tot=a.length; i < tot; i++)
      {
         switch (a[i])
        {   
            case 0: 
                var Date0 = renderNewDate(referenceDate, 0) 
                document.getElementById('day0').innerHTML = Date0;
            break;

            case 1: 
                var Date1 = renderNewDate(referenceDate, 1) 
                document.getElementById('day1').innerHTML = Date1;
            break;
            
            case 129: 
                var Date1 = renderNewDate(referenceDate, 129) 
                document.getElementById('day129').innerHTML = Date1;
            break;
        
            case 147: 
                var Date147 = renderNewDate(referenceDate, 147) 
                document.getElementById('day147').innerHTML = Date147;
            break;
        
            case 148: 
                var Date148 = renderNewDate(referenceDate, 148) 
                document.getElementById('day148').innerHTML = Date148;
            break;
        
            case 156: 
                var Date156 = renderNewDate(referenceDate, 156) 
                document.getElementById('day156').innerHTML = Date156;
            break;
        
            case 200: 
                var Date200 = renderNewDate(referenceDate, 200) 
                document.getElementById('day200').innerHTML = Date200;
            break;
        }
      }

can be reduced to something like:

Code:
for (var i=0, tot=a.length; i < tot; i++)
      {  
            var Date + a[i] = renderNewDate(referenceDate, a[i]) 
            document.getElementById('day' + a[i]).innerHTML = Date + a[i];
      }

which when debugged would eliminate many potential typos.

Yes, I KNOW the above code will not work as written, but others here can take the idea and massage it so it will work. I simply do not know enough about Javascript.

mmerlinn


Poor people do not hire employees. If you soak the rich, who are you going to work for?

"We've found by experience that people who are careless and sloppy writers are usually also careless and sloppy at thinking and coding. Answering questions for careless and sloppy thinkers is not rewarding." - Eric Raymond
 
Hmmm, after looking at this a while, I think this might work, although it is not tested:

Code:
for (var i=0, tot=a.length; i < tot; i++)
      {  
            var Date = renderNewDate(referenceDate, a[i]) 
            document.getElementById('day' + a[i]).innerHTML = Date;
      }

mmerlinn


Poor people do not hire employees. If you soak the rich, who are you going to work for?

"We've found by experience that people who are careless and sloppy writers are usually also careless and sloppy at thinking and coding. Answering questions for careless and sloppy thinkers is not rewarding." - Eric Raymond
 
Thanks to both of you for offering improvements.

jpadie: maybe there is something happening on my end. I tried to give you a star and got the pop-up box but no contents. Will give it a try after I figure out what is different. Never had this problem before.

mmerlinn: I was thinking about your approach first, but I may need code at each case so abandoned the idea for now. Will keep for a future day.

Thanks again.

You don't know what you don't know...
 
waubain, if you need the code to work on a case by case basis, there is no reason to put it in a loop.

Though quick and dirty, you could always redefine your array as needed to [red]var a = [129][/red], [red]var a = [129,156,200][/red], or whatever and still run it through the loop to get specific cases. In a situation like that, it might be better to just pass your array to the function, rather than hard coding your array within the function.

mmerlinn


Poor people do not hire employees. If you soak the rich, who are you going to work for?

"We've found by experience that people who are careless and sloppy writers are usually also careless and sloppy at thinking and coding. Answering questions for careless and sloppy thinkers is not rewarding." - Eric Raymond
 
@waubain

It may take me a while to digest your code.

I assume we can take the html and css as read?
for the javascript here is a commented version
note that I forgot yesterday that javascript months were zero based, so the results were a month out each time. this is fixed in both code snips below.

Code:
            <script type="text/javascript">
            
            
            //set up a variable to hold a date object based on the values for y m d
            var curDate;
            
            
            $(document).ready(function(){ //wait for the DOM to load

				/* listen for a change to any of the inputs within an element of class 'field'
				on change, run the resetCurDate() function */
                $('.row:first .field input').on('change',function(){	
                    resetCurDate();	
                });

				/* listen for a change to any of the elements with a class of 'question' 
				on change, run the resetCurDate() function */                
                $('.question').on('change', function(){
                    resetCurDate();
                });
                
                /* create a new date object based on the values of year, month and day
                and then run the doCalcs function */
                function resetCurDate(){
                    curDate = new Date($('#year').val(), $('#month').val() - 1,$('#day').val());
                    doCalcs();
                }
                

                function doCalcs(){
                    $('.question').each(function(i,elem){ /* for each element with a class of 'question' pass the index (i) and node (elem) to an anon function */
                        var v = $(elem).val();		/* get the value of the element, which will be the number of days ago */
                        var _d = new Date(curDate.getTime()); /* create a new date object identical to curDate */
                        _d.setDate( _d.getDate() - v);	/*	move the date object back the number of days that are specified in the question element */
                        if (_d.toString() != 'Invalid Date') { /* check for invalid date - this does not work as seemingly the dates are automatically made valid whatever numbers get put in the ymd box) */
                            $('#r_' + i).text(_d.toDateString());	/* find the span that has the same number as the question and put a human readable version of the date in */
                        }
                        
                    });
                }
                
            });
            </script>

we could make the code and the html slightly cleaner as follows. this code will automatically add a new 'question' whenever the last one has been completed; and also contains some validation routines to check for 'incorrect' dates etc. Again, no 'button' click is needed as the code recalculates 'on the fly'. if you want specific time ranges hard coded that is easy enough to do by adding or removing elements from the periods array.

Code:
<!DOCTYPE HTML>
    <html>
        <head>
            <style>
                .row{clear:both; overflow:hidden; width:100em;}
                .label{float:left; width:10em;}
                .field{float:left; width 65em; margin-left: 10px;}
                .field .q{float:left; width: 5em; }
                .field .r{float:left; width: 15em;}
                input[type="text"] {width: 4em;}
                #fd{color:green;}
            </style>
            <script src="[URL unfurl="true"]http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>[/URL]
            <script type="text/javascript">
            var curDate = new Date();
            var valid = {y:0, m:0, d:0};
            var rs;
            var periods = [1,129,147,148,156,200];
            
            $(document).ready(function(){
                
                $('input').val(''); //reset fields
                /* add a default date to the date chooser */
                $('#year').val(curDate.getFullYear());
                $('#month').val(curDate.getMonth() + 1);
                $('#day').val(curDate.getDate());
                
                /* insert the hard coded periods */
                for(i=0; i<periods.length; i++){
                    var c = $('.row:last');
                    var d = c.clone(true);
                    d.find('input').val(periods[i]);
                    d.insertAfter(c);
                }
                
                /* move the blank box to the end */
                if(periods.length > 0)  $('.question:first').closest('.row').insertAfter('.row:last');
                
                /* update the 'nice date' and pre-respond to any pre-defined periods */
                doCalcs();
            
            
                $('body').on('keyup', 'input[type="text"]', function(e){ /* listen for keyups */
                    
                    if (!isValid()) { /* check for date validity and change backgrounds for invalid */
                        $('#year').css('background', valid.y ? 'white' : 'red');
                        $('#month').css('background', valid.m ? 'white' : 'red');
                        $('#day').css('background', valid.d ? 'white' : 'red');
                    }
                    else {
                        
                        $('#year, #month, #day').css('background','white'); /* reset backgrounds */
                        if ($(this).is('.question:last') && $(this).val() != '') { /* add another question if necessary */
                            var c = $(this).closest('.row');
                            var d = c.clone(true);
                            d.find('input').val('');
                            d.insertAfter(c);
                        }
                        doCalcs();
                    }
                });
                                
                function isValid(){
                    valid.y = valid.m = valid.d = 1;
                    if( parseInt($('#year').val()) != curDate.getFullYear()) valid.y = 0;
                    if( parseInt($('#month').val()) != curDate.getMonth() + 1) valid.m = 0;
                    if( parseInt($('#day').val()) != curDate.getDate()) valid.d = 0;
                    return (valid.y && valid.m && valid.d);
                }
                
                function doCalcs(){
                    curDate = new Date(parseInt($('#year').val()), parseInt($('#month').val()) - 1,parseInt($('#day').val()));
                    if (curDate.toString() != 'Invalid Date' && isValid()) { /* run if we have a valid date */
                        $("#fd").text(curDate.toDateString()); /* update the human readable date */
                        rs = $('.response');  /* capture a collection of response spans */
                        $('.question').each(function(i, elem){
                            var v = $(this).val(); 
                            if (v == '') return; //ignore blanks
                            var _d = new Date(curDate.getTime()); /* clone the date object */
                            _d.setDate(_d.getDate() - v); /* rewind the date by the right number of days */
                            $(this).closest('.row').find('.response').text(_d.toDateString()); /* put the answer in the right span */
                        });
                    }
                }
            });
            </script>
        </head>
        <body>
            <div id="content">
                <form method="#" >
                    <div class="row">
                        <div class="label">
                            Reference Date:
                        </div>
                        <div class="field">
                            <input type="text" name="year" id="year" />
                            &nbsp;
                            <input type="text" name="month" id="month" />
                            &nbsp;
                            <input type="text" name="day" id="day" />
                            &nbsp;
                            <span>Year, Month, Day&nbsp;</span><span id="fd"></span>
                        </div>
                    </div>
                    
                    <div class="row">
                        <div class="label">
                            Number Days ago
                        </div>
                        <div class="field">
                            <div class="q">
                                <input type="text" class="question" name="q_0" id="q_0" />
                            </div>
                            <div class="r">
                                <span class="response"></span>
                            </div>                  
                        </div>
                    </div>
                </form>
                
            </div>
        </body>
    </html>
 
jpadie,
Sorry for taking so long to response, I was having some computer trouble. This is what I needed to be able to do.

Thank you again for the time spent writing this function and explanations.

You don't know what you don't know...
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top