#!/usr/local/bin/php

Here are the answers to the JavaScript exercises in the previous sections.

  1. Write a JavaScript that outputs the string "Hello, World!" into a web page.
  2. <script language="JavaScript">
      document.write("Hello, World!")
    </script>
  3. Write a JavaScript that outputs the string "" into a web page (this is the Greek version of #1!).
  1. Following the example of the Amherst College Founding, create a web page that calculates how old you are and displays the result.
  2. I was born
    <script language="JavaScript">
      var now = new Date
      var thisYear = now.getYear()
      if (thisYear < 1900) {
        thisYear += 1900
      }
      document.write(thisYear - 1985)
    </script>
    years ago.

    I was born years ago.

  3. Following the example of the College Check, create a web page that uses a form with a text input, providing a number of years in the property this.value, and calculate the year when you will be that age. Use the method window.alert('string') to display the result.
  4. <form>
      <input
        type="text" value="Age" size="4"
        onChange="window.alert('In the year ' +
          (this.value - 0.0 + 1985) + ' I will be ' +
          this.value + ' years old.')"
      >
    </form>
      

  1. For the Spreadsheet Object, modify its special version of toString so that it outputs a form in each cell of the spreadsheet. Then modify the spreadsheet so that an entry in each form changes the corresponding value stored in the spreadsheet. Add a method to check the values in the spreadsheet independently from the form.
  2. function c2name(column) {
      var name = ''
      do {
        name = String.fromCharCode(column%26 + 65) + name
        column = Math.floor(column/26)
      } while (column > 0)
      return name
    }

    function cr2name() {
      var name = c2name(this.column)
      name += this.row + 1
      return name
    }

    function ssToString() {
      var ssDisplay = '<table width="' + (50 + this.length * 100) + '"' +
          ' border="1" cellspacing="1" cellpadding="1">' +
          '<tr><td width="50" align="center"></td>'
      for (var column = 0; column < this.length; column++) {
        ssDisplay += '<td width="100" align="center"><b>' +
            c2name(column) +
            '</b></td>'
      }
      for (row = 0; row < this[0].length; row++) {
        ssDisplay += '</tr><tr><td align="center"><b>' + (row + 1) + '</b>'
        for (column = 0; column < this.length; column++) {
          ssDisplay += '</td><td align="center">' +
                '<form name="' + this[column][row].name() +
                '"><input type="text" size="10" value="' +
                this[column][row].value + '" onChange="' +
                this.name + '[' + column + '][' +
                row + '].value = this.value' +
                '"></form>'
        }
      }
      ssDisplay += '</td></tr></table>'
      return ssDisplay
    }

    function SSCell(column, row, value) {
      this.column = column
      this.row = row
      this.name = cr2name
      this.value = value ? value : ''
    }

    function SSCol(column, rows) {
      var i
      var sscol = new Array(rows)
      for (i = 0; i < rows; i++) {
        sscol[i] = new SSCell(column, i)
      }
      return sscol
    }

    function SSheet(name, columns, rows) {
      var i
      var ssheet = new Array(columns)
      for (i = 0; i < columns; i++) {
        ssheet[i] = new SSCol(i, rows)
      }
      ssheet.name = name
      ssheet.toString = ssToString
      return ssheet
    }

    mySheet = SSheet("mySheet", 2, 2)

    document.write(mySheet)

    <form name="check">
      
    <input type="button" name ="Check" value="Check"
        onClick="txtSheet = document.createTextNode(mySheet);
                 document.checkSheet.appendChild(txtSheet)">
    </form>

    <p id="checkSheet">
    </p>

     

    This is initially just a paragraph place-holder.

    A more complete answer would track multiple displays of the spreadsheet, and when one is changed update the forms in the others.

  1. Write a JavaScript function that takes one parameter, returns it unchanged if it can't be converted to a number, and otherwise writes it out as a string in "abbreviated" form, using the standard numerical abbreviations:

    http://www.bipm.fr/enus/3_SI/si-prefixes.html

    Hint: use the base 10 logarithm to calculate the power-of-ten exponent.

  2. Abbreviation:

    The power-of-ten exponent of the number can be used as an index into a string to find the appropriate abbreviation:

    abbrevLetter = "y..z..a..f..p..n..µ..mcd.DHK..M..G..T..P..E..Z..Y"

    <script language="JavaScript">
      // From http://www.bipm.fr/enus/3_SI/si-prefixes.html:
      //
      // 24 yotta Y
      // 21 zetta Z
      // 18 exa E
      // 15 peta P
      // 12 tera T
      // 9 giga G
      // 6 mega M
      // 3 kilo k
      // 2 hecto h
      // 1 deca da
      // -1 deci d
      // -2 centi c
      // -3 milli m
      // -6 micro µ
      // -9 nano n
      // -12 pico p
      // -15 femto f
      // -18 atto a
      // -21 zepto z
      // -24 yocto y
      // Adding 24 to any exponent, we'll get a non-negative integer,
      // which can be an index.
      // For unabbreviated values, use a unique symbol, e.g. '.'.
      // For consistency, use "D" instead of da to represent a
      // factor of 10.

      function abbreviateIt()
      {
        var abbrevLetter =
          "y..z..a..f..p..n..µ..mcd.DHK..M..G..T..P..E..Z..Y"

        with (document.abbrev)
        {
          var value = input.value - 0
          if (isNaN(value) || !isFinite(value))
            // not a valid representation of a number, or too large!
            output.value = input.value
          else
          {
            var exponent = Math.floor(Math.log(value)/Math.LN10)
                      // base e - base 10 log relation
            if (exponent == 0) // if == 0, no prefix is necessary
              output.value = input.value
            else
            {
              if (exponent < -24) // too small
                exponent = -24
              else if (exponent > 24) // too large
                exponent = 24
              else // lower exponent if necessary; not more than twice
                while (abbrevLetter.charAt(exponent + 24) == ".")
                  exponent--
              output.value = (value/Math.pow(10, exponent)) + ' ' +                          abbrevLetter.charAt(exponent + 24)
            }
          }
        }
      }
    </script>

    <form name="abbrev">
      <input type="text" name="input" size=40>
      <input type="button" value="Abbreviate" onclick="abbreviateIt()">
      <hr align="left" width="50%">
      Abbreviation: <input type="text" name="output" readonly size=40>
    </form>

Write a constructor for a "planet" object, and use it to create ten objects that store the planetary information on this web page:

http://www.opencourse.info/astronomy/introduction/05.motion_planets/#sidereal%20period http://www.opencourse.info/astronomy/introduction/05.motion_planets/#aphelion

Use the Sun as the first, with all values set to zero.

Write a web form that has a radio button input, one for each planet, and that onChange writes out the planet's information.

Why might it be a good idea to use PHP as part of this exercise?

SunMercuryVenusEarthMarsJupiterSaturnUranusNeptunePluto

The form provides the name of the planet, which can be used in an associative array to reference the planet's information. Its data is written into a textarea field, which allows more than one line of text.

Written strictly in JavaScript, the form can be implemented as follows:

<script language="JavaScript">
  function data()
  {
    return 'Distance = ' + this.distance + ' AU\n' +
           'Sidereal Period = ' + this.sidPeriod + ' years\n' +
           'Synodic Period = ' + this.synPeriod + ' days\n' +
           'Eccentricity = ' + this.eccentricity + '\n' +
           'Orbital Inclination = ' + this.inclination + '\xB0'
  }
  // Planet constructor to be used with "new" keyword,
  // so "this" refers to new object
  function Planet(name, distance, sidPeriod, synPeriod,
            eccentricity, inclination)
  {
    this.name = name
    this.distance = distance // AU
    this.sidPeriod = sidPeriod // years
    this.synPeriod = synPeriod // days
    this.eccentricity = eccentricity
    this.inclination = inclination // degrees
    this.data = data
  }

  solarSystem = new Object
  solarSystem.Sun = new Planet("Sun", 0, 0, 0, 0, 0)
  solarSystem.Mercury =
    new Planet("Mercury", 0.3871, 0.2408, 115.88, 0.206, 7.00)
  solarSystem.Venus =
    new Planet("Venus", 0.7233, 0.6152, 583.92, 0.007, 3.39)
  solarSystem.Earth =
    new Planet("Earth", 1.0000, 1.0000, '-', 0.017, 0.00)
  solarSystem.Mars =
    new Planet("Mars", 1.5237, 1.8809, 779.94, 0.093, 1.85)
  solarSystem.Jupiter =
    new Planet("Jupiter", 5.2028, 11.862, 398.9, 0.048, 1.31)
  solarSystem.Saturn =
    new Planet("Saturn", 9.5388, 29.458, 378.1, 0.056, 2.49)
  solarSystem.Uranus =
    new Planet("Uranus", 19.1914, 84.01, 369.7, 0.046, 0.77)
  solarSystem.Neptune =
    new Planet("Neptune", 30.0611, 164.79, 367.5, 0.010, 1.77)
  solarSystem.Pluto =
    new Planet("Pluto", 39.5294, 248.5, 366.7, 0.248, 17.15)

  function planetClick(btn)
  {
    document.planetForm.planetData.value =
      solarSystem[btn.value].data()
  }
</script>

<form name="planetForm">
  <input type="radio" name="planetButtons" value="Sun"
    onClick="planetClick(this)">Sun
  <input type="radio" name="planetButtons" value="Mercury"
    onClick="planetClick(this)">Mercury
  <input type="radio" name="planetButtons" value="Venus"
    onClick="planetClick(this)">Venus
  <input type="radio" name="planetButtons" value="Earth"
    onClick="planetClick(this)">Earth
  <input type="radio" name="planetButtons" value="Mars"
    onClick="planetClick(this)">Mars
  <input type="radio" name="planetButtons" value="Jupiter"
    onClick="planetClick(this)">Jupiter
  <input type="radio" name="planetButtons" value="Saturn"
    onClick="planetClick(this)">Saturn
  <input type="radio" name="planetButtons" value="Uranus"
    onClick="planetClick(this)">Uranus
  <input type="radio" name="planetButtons" value="Neptune"
    onClick="planetClick(this)">Neptune
  <input type="radio" name="planetButtons" value="Pluto"
    onClick="planetClick(this)">Pluto
  <br>
  <textarea name="planetData" value="" readonly rows="5" cols="100">
  </textarea>
</form>

<script language="JavaScript">
</script>

Note that some of this material is highly repetitious, varying only in small details. PHP can be useful to "loop through" this material, providing a more compact representation, especially with larger quantities of data (which might also be loaded from a file).

Written with PHP, the form can be implemented as follows:

<script language="JavaScript">
  function data()
  {
    return 'Distance = ' + this.distance + ' AU\n' +
           'Sidereal Period = ' + this.sidPeriod + ' years\n' +
           'Synodic Period = ' + this.synPeriod + ' days\n' +
           'Eccentricity = ' + this.eccentricity + '\n' +
           'Orbital Inclination = ' + this.inclination + '\xB0'
  }
  // Planet constructor to be used with "new" keyword,
  // so "this" refers to new object
  function Planet(name, distance, sidPeriod, synPeriod,
            eccentricity, inclination)
  {
    this.name = name
    this.distance = distance // AU
    this.sidPeriod = sidPeriod // years
    this.synPeriod = synPeriod // days
    this.eccentricity = eccentricity
    this.inclination = inclination // degrees
    this.data = data
  }

  solarSystem = new Object
  <?php
    $solarSystem = array(
      "Sun" => array(0, 0, 0, 0, 0),
      "Mercury" => array(0.3871, 0.2408, 115.88, 0.206, 7.00),
      "Venus" => array(0.7233, 0.6152, 583.92, 0.007, 3.39),
      "Earth" => array(1.0000, 1.0000, "'-'", 0.017, 0.00),
      "Mars" => array(1.5237, 1.8809, 779.94, 0.093, 1.85),
      "Jupiter" => array(5.2028, 11.862, 398.9, 0.048, 1.31),
      "Saturn" => array(9.5388, 29.458, 378.1, 0.056, 2.49),
      "Uranus" => array(19.1914, 84.01, 369.7, 0.046, 0.77),
      "Neptune" => array(30.0611, 164.79, 367.5, 0.010, 1.77),
      "Pluto" => array(39.5294, 248.5, 366.7, 0.248, 17.15)
    );
    foreach ($solarSystem as $key => $value) {
      echo 'solarSystem.' . $key . ' = new Planet("' . $key . '"';
      for ($i = 0; $i < 5; $i++)
        echo ', ', $value[$i];
      echo ")\n";
    }
  ?>

  function planetClick(btn)
  {
    document.planetForm.planetData.value =
      solarSystem[btn.value].data()
  }
</script>

<form name="planetForm">
  <p>
    <?php
      foreach ($solarSystem as $key => $value)
      echo '<input type="radio" .
        name="planetButtons" value="' . $key .
        '"onClick="planetClick(this)">' . $key;
    ?>
    <br>
    <textarea name="planetData" value="" readonly rows="5" cols="70">
    </textarea>
  </p>
</form>

<script language="JavaScript">
</script>

Write a form and button combination that, "onClick", activates the window method

window.alert('A string of your choice')

<form name="announce">
  <input type="button" value="What's the frequency, Kenneth?"
         onclick="window.alert('88.5 MHz')">
</form>

Write a JavaScript that outputs the browser version type, using the object property

navigator.appVersion

<script language="JavaScript">
  document.write("This browser is version " + navigator.appVersion)
document.write(". It is running on the platform " + navigator.platform)
document.write(" with the language " + navigator.language + ".")
</script>