left-hand header picture right-hand header picture

HAILSCAPE.COM::d20 fantasy

BIRCHED'S D&D 3.0 NPC GENERATOR

...MORE THAN 100,000 NPCS SERVED

problems/comments to birched [at] hailscape [dot] com


Javascript and CSS Pointers from the Making of these Pages

back to NPC Generator main page

Making a form that grows depending on user demand top

The cleric domain and cleric weapon fields on the page expand on user demand. How does this work? It uses elements of css and javascript. I will describe here how it was done for the cleric domains. I am indebted to many others who put directions and code snippets on the web, without whom I might never have been able to put this page together. Any comments or suggestions regarding what I say here should be directed to the e-mail address in the header.

  • CSS element 1: In the css sheet, there is the following definition that sets up the cleric domain division as being hidden when the page is first loaded.

    #cleric_hidden {
      display:none;
    } 
  • CSS element 2: On the page index.html, there is a division labelled with the id "cleric_hidden." Everything inside that division is hidden when the page loads.

    <div id="cleric_hidden">
  • CSS element 3: On the page index.html, there are several calls to javascript scripts that check whether 'cleric' has been selected for any of the chosen classes. There are two principal kinds:

    1. Calls that occur on loading and resetting the form. These are handled using the script "resetHidden." Here is an example:

      <body onload="javascript:resetHidden(true);">

      This can be tied to a form reset button like this:

      <input type="reset" onclick="resetHidden(false);" value="Reset Form" />
    2. Calls that occur when class selection is made. These are handled by the script "insertContent." Here is an example:

      <select name="cls1" class="npcform" id="cls1" onchange="insertContent(document.getElementsByTagName('*'), 'cls', 'clr', 'cleric_hidden');">
  • Javascript element 1: The onclick, onload, and onchange javascript event handlers were mentioned in the previous section. Each of these ties a user event (clicking a button, loading the page, selecting something from a menu) to a script event.

    The following code is the backbone of the hide/reveal event. It starts with a call to 'getElementsByTagName('*')', which sends a list of all the html tagged elements for processing by the script (see the previous snippet.)

    function insertContent(obj, identifier, searchStr, divToSwitch) {
    
      for (j=0; j<obj.length; j++) {
        if (obj[j].value == searchStr ) {
          if (obj[j].id) { 
            var matchStr = obj[j].id.substr(0, identifier.length);
            if (matchStr == identifier) {
              document.getElementById(divToSwitch).style.display = "inline";
              return;
            }
          }
        }
      }
      // turn it off by default
      document.getElementById(divToSwitch).style.display = "none";
    }
    
    
  • Javascript element 2: And here is the code that was used to reset the form and also to make sure that when the page is reloaded it loads the right fields.

    function resetHidden(checks) {
      if (!checks) {
        document.getElementById("cleric_hidden").style.display = "none";
        document.getElementById("cleric_war_weap").style.display = "none";
      } else {
        insertContent(document.getElementsByTagName('*'), 'cls', 'clr', 'cleric_hidden');   
        insertContent(document.getElementsByTagName('*'), 'cdom', 'war', 'cleric_war_weap');
      }
    }

Making a form that puts script output right onto the page top

This form runs through a cgi script that runs on the server. The output is directed straight to the lighter coloured window on the bottom half of the main part of the page, directly under the form. How is this done? Any comments or suggestions regarding what I say here should be directed to the e-mail address in the header.

  • CSS element 1: The CSS part of this is pretty straightforward. First, it involves creating a division with a defined id to load into. Any content in this division will be replaced by the script. I load my revision information into that field using a php include when the page is first loaded.

    <div id="textoutput">
    <?php
      include 'revisioninfo.html';
    ?>
  • CSS element 2: Next, there has to be a javascript handler, like this.

    <form action="javascript:get(document.getElementsByTagName('*'));" id="npcform" class="npcform">
  • Javascript: The javascript here is more involved. Some of this code is taken from the helpful tutorial here. The javascript function 'get' is sent a list of the elements on the page by the function 'getElementsByTagName' shown in the previous snippet. This function gathers the information important for the script and calls 'makeRequest', which executes the script. The function alertContents feeds the results of the script into the designated 'textoutput' div.

    var http_request = false;
    function makeRequest(url, parameters) {
      http_request = false;
      if (window.XMLHttpRequest) { // Mozilla, Safari,...
         http_request = new XMLHttpRequest();
         if (http_request.overrideMimeType) {
          // set type accordingly to anticipated content type
            //http_request.overrideMimeType('text/xml');
            http_request.overrideMimeType('text/html');
         }
      } else if (window.ActiveXObject) { // IE
         try {
            http_request = new ActiveXObject("Msxml2.XMLHTTP");
         } catch (e) {
            try {
               http_request = new ActiveXObject("Microsoft.XMLHTTP");
            } catch (e) {}
         }
      }
      if (!http_request) {
         alert('Cannot create XMLHTTP instance');
         return false;
      }
      http_request.onreadystatechange = alertContents;
      //document.write(url+parameters);
      http_request.open('GET', url + parameters, true);
      http_request.send(null);
    }
    
    function alertContents() {
      if (http_request.readyState == 4) {
         if (http_request.status == 200) {
            //alert(http_request.responseText);
            result = http_request.responseText;
            document.getElementById('textoutput').innerHTML = result;            
         } else {
            alert('There was a problem with the request.');
         }
      }
    }
    
    function get(obj) {
      var getstr = "?";
      for (j=0; j<obj.length; j++) {
        if (obj[j].className == "npcform") {
         if (obj[j].tagName == "INPUT") {
            if (obj[j].type == "text") {
               getstr += obj[j].name + "=" + obj[j].value + "&";
            }
            if (obj[j].type == "hidden") {
               getstr += obj[j].name + "=" + obj[j].value + "&";
            }
         }   
         if (obj[j].tagName == "SELECT") {
            var sel = obj[j];
            getstr += sel.name + "=" + sel.options[sel.selectedIndex].value + "&";
         }
        }
         
      }
      makeRequest('http://www.hailscape.com/cgi-bin/npc', getstr);
    }

Valid XHTML 1.0 Strict