SitePoint Sponsor

User Tag List

Results 1 to 7 of 7
  1. #1
    SitePoint Zealot fredep57's Avatar
    Join Date
    Aug 2009
    Location
    Pacific Northwest
    Posts
    137
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Dates not working in this

    This is in PHP forum by mistake - maybe someone can delete the PHP one and keep this one, I don't know how, sorry.

    I put a thread out previously and got some responses. I found a help area that gave me what I wanted - kind of.

    If the code below is run and NO DATE is put in, the function runs as I expect. However, if there is a date in the DATE box, then, well, the number of days does not change! That seems weird....

    I would like this to put the proper number of days via the selected month if it can. Just not sure what is really going on and/or where the issue could be. Looks like this should work like I want, but.... well, let the experts beat me and it up!

    Oh, I really don't have a lick of Javascript experience and am doing this for learning more than anything

    Here is my code:
    HTML Code:
    HTML Code:
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
      <meta http-equiv="content-type" content="text/html; charset=windows-1250">
      <meta name="generator" content="PSPad editor, www.pspad.com">
      <title></title>
      
      
      </head>
      <body>
     <form name="myform"><fieldset>
        <legend>Date Selection</legend>
        <label for="year">Year: </label><select name="eventYear" id="eventYear" size="1">
        <option value=" " selected="selected"> </option>
        <option value="2000">2000</option>
        <option value="2001">2001</option>
        <option value="2002">2002</option>
        </select>
        <label for="month">Month: </label>
        <select name="eventMonth" id="eventMonth" size="1">
        <option value=" " selected="selected"> </option>
        <option value="1">January</option>
        <option value="2">February</option>
        <option value="3">March</option>
        <option value="4">April</option>
        <option value="5">May</option>
        <option value="6">June</option>
        <option value="7">July</option>
        <option value="8">August</option>
        <option value="9">September</option>
        <option value="10">October</option>
        <option value="11">November</option>
        <option value="12">December</option>
         
        </select>
         
        <label for="day">Day: </label><select name="eventStartDate" id="eventStartDate" size="1">
        <option value=" " selected="selected"> </option>
        <option value="1">1</option>
        <option value="2">2</option>
        <option value="3">3</option>
        <option value="4">4</option>
        <option value="5">5</option>
        <option value="6">6</option>
        <option value="7">7</option>
        <option value="8">8</option>
        <option value="9">9</option>
        <option value="10">10</option>
        <option value="11">11</option>
        <option value="12">12</option>
        <option value="13">13</option>
        <option value="14">14</option>
        <option value="15">15</option>
        <option value="16">16</option>
        <option value="17">17</option>
        <option value="18">18</option>
        <option value="19">19</option>
        <option value="20">20</option>
        <option value="21">21</option>
        <option value="22">22</option>
        <option value="23">23</option>
        <option value="24">24</option>
        <option value="25">25</option>
        <option value="26">26</option>
        <option value="27">27</option>
        <option value="28">28</option>
        <option value="29">29</option>
        <option value="30">30</option>
        <option value="31">31</option>
        </select>
        </fieldset>
      </form> 
    <script type="text/javascript"> 
      function daysInMonth(month,year) 
      {
        var dd = new Date(year, month, 0);
        return dd.getDate();
      } 
      function setDayDrop(dyear, dmonth, dday)
      {
        var year = dyear.options[dyear.selectedIndex].value;
        var month = dmonth.options[dmonth.selectedIndex].value;
        var day = dday.options[dday.selectedIndex].value;
        if (day == ' ')
        {
        var days = (year == ' ' || month == ' ') ? 31 : daysInMonth(month,year);
        dday.options.length = 0;
        dday.options[dday.options.length] = new Option(' ',' ');
        for (var i = 1; i <= days; i++) 
          dday.options[dday.options.length] = new Option(i,i);
        }
      }
     
      function setDay() 
      {
        var year = document.getElementById('eventYear');
        var month = document.getElementById('eventMonth');
        var day = document.getElementById('eventStartDate');
        setDayDrop(year,month,day);
      }
      document.getElementById('eventYear').onchange = setDay;
      document.getElementById('eventMonth').onchange = setDay;
    </script>
    
      </body>
    </html>

  2. #2
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,701
    Mentioned
    101 Post(s)
    Tagged
    4 Thread(s)
    Doctype

    First up, this transitional doctype is badly out of date.
    Code:
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    That was used 12 to 13 years ago when HTML transitioned in 1999 from HTML3 to HTML4, allowing you to use HTML3 on your page while you transition and test HTML4 techniques.

    These days you can just use the following, which includes support for HTML5 too.

    Code javascript:
    <!DOCTYPE HTML>


    Form name

    With the form, in the following line the name serves a useless purpose.

    Code:
    <form name="myform">
    In fact, it's worse than useless, it's somewhat harmful because it gives the mistaken impression that it's somehow related to the named form fields.
    What the name="myform" is actually doing is the same as the ancient style of using <a name="myform">, which has long been surpassed by using a unique identifier for it instead.

    So use a unique identifier on the form instead. That will also allow CSS and scripting to more easily work with the form too.
    Also, use an identifier that's more descriptive than just "myform". Right now there's no information about what the form is supposed to do. Giving it an identifier of "addNewEvent" helps to improve on that.

    Code javascript:
    <form id="addNewEvent">


    Labels

    The for attribute is now no longer needed when using labels in todays web browsers.

    Code:
    <label for="year">Year: </label>
    <select name="eventYear" id="eventYear" size="1">
        ...
    </select>
    Another problem is that the for attribute is broken, because the for="year" doesn't have a matching id="year" with which to relate it to.

    So instead of using explicit association which is easily broken, you can instead use implicit association where you wrap the label element around the field that it's for, which also means that you don't need to clutter your HTML code with for attributes and unique identifiers throughout your form fields.

    Code javascript:
    <label>Year: 
        <select name="eventYear" size="1">
            ...
        </select>
    </label>


    Size

    The size attribute is misleading because it is only useful when you are also using the multiple attribute.
    where the size indicates how many options are shown at the same time on the screen.

    Code:
    <select name="eventYear" size="1">
        ...
    </select>
    The size attribute only leads to confusion if you use it without the multiple attribute, so it should be removed.

    Code javascript:
    <select name="eventYear">
        ...
    </select>


    Empty option

    It's also a common convention to use an empty option attribute, instead of one with a space.

    Code:
    <option value=" " selected="selected"> </option>
    One of the reasons for this is that when you use scripting to get the value, " " is considered to be truthy, whereas "" is considered to be falsy.
    So when using "" you can use if (year) instead of if (year === ' ')

    Code javascript:
    <option value="" selected="selected"></option>


    So that's the HTML code all tidied up. Let's now move on to learning about the scripting.
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  3. #3
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,701
    Mentioned
    101 Post(s)
    Tagged
    4 Thread(s)
    Form identifier

    Now that the form has an identifier, that can be made good use of in the scripting. Not only to get the form, but to work with the named elements within the form itself too.

    Code javascript:
    var form = document.getElementById('addNewEvent');
    form.elements.eventYear.onchange = setDay;
    form.elements.eventMonth.onchange = setDay;


    Auto days when selected

    To fix the problem where days are only adjusted if there's nothing selected, let's look at the setDayDrop function from before.

    Code:
    function setDayDrop(dyear, dmonth, dday) {
        var year = dyear.options[dyear.selectedIndex].value;
        var month = dmonth.options[dmonth.selectedIndex].value;
        var day = dday.options[dday.selectedIndex].value;
        if (day == '') {
            var days = (year == '' || month == '') ? 31 : daysInMonth(month, year);
            dday.options.length = 0;
            dday.options[dday.options.length] = new Option('', '');
            for (var i = 1; i <= days; i++) {
                dday.options[dday.options.length] = new Option(i, i);
            }
        }
    }
    There are many minor issues with that code. I invite you to jslint.com to learn about those issues.

    The major issue that's getting in your way though is the if condition. Get rid of that, and get rid of the year or month condition too. That can be applied within the daysInMonth function instead.

    In terms of setting the days, you only now need to decide what to do is 31 is selected and someone choose February. I suggest that you set the day to the smaller of the available and currently selected day.

    Code javascript:
    dday.selectedIndex = Math.min(day, days);

    That leaves the setDayDrop function looking like this:

    Code javascript:
    function setDayDrop(dyear, dmonth, dday) {
        var year = dyear.options[dyear.selectedIndex].value;
        var month = dmonth.options[dmonth.selectedIndex].value;
        var day = dday.options[dday.selectedIndex].value;
        var days = daysInMonth(month, year);
        dday.options.length = 0;
        dday.options[dday.options.length] = new Option('', '');
        for (var i = 1; i <= days; i++) { 
            dday.options[dday.options.length] = new Option(i, i);
        }
        dday.selectedIndex = Math.min(day, days);
    }

    With the daysInMonth function, it's currently like this:

    Code:
    function daysInMonth(month,year) {
        var dd = new Date(year, month, 0);
        return dd.getDate();
    }
    That can be made to work regardless of what the month or year is set to, by setting them to a default value if the don't contain anything.

    Code javascript:
    function daysInMonth(month, year) {
        month = month || 1;
        year = year || 1;
     
        // The month variable uses a value from 0-11, but we are using a value from 1-12
        // From the next month we get the last day of this month by going to day 0
        var dd = new Date(year, month, 0);
        return dd.getDate();
    }

    Or perhaps in a way that doesn't require as many comments:

    Code javascript:
    function daysInMonth(month, year) {
        month = month || 1;
        year = year || 1;
     
        month = month - 1; // From human month to JavaScript Date month (0 - 11)
     
        var dd = new Date(year, month + 1, 0);
        return dd.getDate();
    }
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  4. #4
    SitePoint Zealot fredep57's Avatar
    Join Date
    Aug 2009
    Location
    Pacific Northwest
    Posts
    137
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Paul, thanks for the critique. Always wanting to learn more and since this was an excersize in trying to learn more about Javascript it has been helpful.

    I modified my code with your suggestions but still not working. Please let me know what I am not seeing here as I am a very novice with Javascript but want to learn more as I am needing this in things I am now asked to do.

    Here is my NEW form and code:
    HTML Code:
    <!DOCTYPE HTML>
    <html>
      <head>
      <meta http-equiv="content-type" content="text/html; charset=windows-1250">
      <meta name="generator" content="PSPad editor, www.pspad.com">
      <title></title>
      
      
      </head>
      <body>
     <form id="addNewEvent">
     <fieldset>
        <legend>Date Selection</legend>
        <label>Year: </label>
          <select name="eventYear">
            <option value="" selected="selected"> </option>
            <option value="2000">2000</option>
            <option value="2001">2001</option>
            <option value="2002">2002</option>
            </select>
          <label>Month: </label>
            <select name="eventMonth" id="eventMonth" size="1">
            <option value="" selected="selected"> </option>
            <option value="1">January</option>
            <option value="2">February</option>
            <option value="3">March</option>
            <option value="4">April</option>
            <option value="5">May</option>
            <option value="6">June</option>
            <option value="7">July</option>
            <option value="8">August</option>
            <option value="9">September</option>
            <option value="10">October</option>
            <option value="11">November</option>
            <option value="12">December</option>
             
          </select>
         
        <label>Day: </label>
        <select id="eventStartDate">
          <option value="" selected="selected"> </option>
          <option value="1">1</option>
          <option value="2">2</option>
          <option value="3">3</option>
          <option value="4">4</option>
          <option value="5">5</option>
          <option value="6">6</option>
          <option value="7">7</option>
          <option value="8">8</option>
          <option value="9">9</option>
          <option value="10">10</option>
          <option value="11">11</option>
          <option value="12">12</option>
          <option value="13">13</option>
          <option value="14">14</option>
          <option value="15">15</option>
          <option value="16">16</option>
          <option value="17">17</option>
          <option value="18">18</option>
          <option value="19">19</option>
          <option value="20">20</option>
          <option value="21">21</option>
          <option value="22">22</option>
          <option value="23">23</option>
          <option value="24">24</option>
          <option value="25">25</option>
          <option value="26">26</option>
          <option value="27">27</option>
          <option value="28">28</option>
          <option value="29">29</option>
          <option value="30">30</option>
          <option value="31">31</option>
        </select>
        </fieldset>
      </form> 
      
    <script type="text/javascript"> 
    
    function daysInMonth(month, year) {
        month = month || 1;
        year = year || 1;
     
        // The month variable uses a value from 0-11, but we are using a value from 1-12
        // From the next month we get the last day of this month by going to day 0
        var dd = new Date(year, month, 0);
        return dd.getDate();
    }
    function setDayDrop(dyear, dmonth, dday) {
      var year = dyear.options[dyear.selectedIndex].value;
      var month = dmonth.options[dmonth.selectedIndex].value;
      var day = dday.options[dday.selectedIndex].value;
      var days = daysInMonth(month, year);
    
      dday.options.length = 0;
      dday.options[dday.options.length] = new Option('', '');
      for (var i = 1; i <= days; i++) { 
          dday.options[dday.options.length] = new Option(i, i);
      }
      dday.selectedIndex = Math.min(day, days);
    }
     
    function setDay() 
    {
      var year = document.getElementById('eventYear');
      var month = document.getElementById('eventMonth');
      var day = document.getElementById('eventStartDate');
      
      setDayDrop(year,month,day);
    }
    var form = document.getElementById('addNewEvent');
    form.elements.eventYear.onchange = setDay;
    form.elements.eventMonth.onchange = setDay;
     /* document.getElementById('eventYear').onchange = setDay;
      document.getElementById('eventMonth').onchange = setDay; */
    </script>
    
      </body>
    </html>

  5. #5
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,701
    Mentioned
    101 Post(s)
    Tagged
    4 Thread(s)
    The final piece is to make good use of the onchange event.

    When scripting is used to attach an event to an element, triggering that event causes the this keyword to refer to the element that triggered that event.
    That means that you can use this.form from within the setDay function to easily gain a reference to the form, and from there to any of the named form elements via the elements collection.

    Code javascript:
    function setDay() {
        var form = this.form,
            year = form.elements.eventYear,
            month = form.elements.eventMonth,
            day = form.elements.eventStartDate;
     
        setDayDrop(year, month, day);
    }
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  6. #6
    SitePoint Zealot fredep57's Avatar
    Join Date
    Aug 2009
    Location
    Pacific Northwest
    Posts
    137
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Paul,

    Thanks for the explanation but when I replaced the setDay routine with your latest post, it still does not work.

    What am I doing wrong - I know it is me???

    E

  7. #7
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,701
    Mentioned
    101 Post(s)
    Tagged
    4 Thread(s)
    Do you have a test page that demonstrates the problem? Because everything looks fine from here.
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •