// Use Ajax to put example boxes or code examples into a page
// Written by Jan Labanowski (jkl at ccl net) 
// Last modified on Dec 3, 2006
//
// Anyone can use it, give me credit (or not), and send "thank yous", 
// but the script comes with no warranty, and if it hurts you
// in any way, you agree not to sue me. Poniatno?
// I will be very thankful for corrections and comments and I will
// implement them and give you credit (I mean, as an acknowledgment
// in this file, not money or something...).
//
// This is a short utility that I use to write documentation or
// instructions. The idea is that in the HTML file the examples of
// code or scripts have to be given for download as links and also shown
// in the text. Since I am lazy, I prefer to have them only in one place.
// It also makes the document maintenance easier when revisions are made.
// I only need to modify text files that have the examples or code,
// and do not have to edit the main document.
//
// How it works... In the main document, I put "place holders" for files
// in the form of <div> tags with the id attribute starting from
// "getfile". Inside the <div>...</div> I put information about
// the file and the size of the <textarea>...</textarea> element
// (NO SPACES!!!). This will be replaced when document loads with
// content of the files. 
// For example:
//    <div id="getfile1">rows=10;cols=60;url=examples/example1.pl</div>
// will create <textarea> box 10 rows high and 60 chars wide and will put
// a file located in examples/example1.pl (relative to the directory
//  of the calling document). In short:
//  -- attributes are separated by ; (semicolon)
//  -- key and value are given as key=value
// If "rows" or "cols" are not given, the defaults are estimated from
// the file. The "url" is a path to the file to be imported to the
// document that uses this script (note... do not give the protocol/domain
// since it is unsafe and may not work). So, if you used the entry
// like: <div id="getfile-23a">cols=70;url=myfile_f.txt</div>
// the "rows" attribute for <textarea> would be taken from counting lines
// in the file myfile_f.txt. If file (i.e., "url") is not given,
// the file "error.txt" from the the directory where calling page resides
// is shown. Of course you can change it. The files are assumed to be
// PLAIN TEXT and they should have the ".txt" extension. Why? Since links
// to them will be automatically created above the <textarea>s. If they
// are not ".txt" then the browser may not render them as MIME text/plain
// and you will be surprised. 
//
// Function getMyFiles is supposed to be called in the <body> element
// with the onLoad event, e.g.
//     <body bgcolor="yellow" onLoad="getMyFiles();">
// The "getMyFiles" takes each qualified <div>, retrieves information
// that was placed there, and calls getStuff for each entry.
// The getStuff function takes a reference to element(el), the
// url (file path), "rows" for <textarea> (nR), "cols" for <textarea> (nC)
// and the id attribute of the current <div> tag. Then, it creates the
// XMLHttpRequest object (the Ajax stuff) and gets the files and puts
// their content into <div>...</div> block. Actually, it first wraps the
// stuff from the file in the <textarea>...</textarea> and creates a link
// (an <a href tag) before it. If you do not believe me, look at:
//   http://www.ccl.net/cca/software/PERL/mod_perl
// The whole thing is mostly educational, hence long comments and names,
// bulky syntax and lots of spaces. Moreover, I do not play games
// with "reusing" the XMLHttpRequest object, since it would have to
// have more code and checking. As you know browsers have different
// ideas about things and they mess them up with constant updates.
// (As always, MicroSoft does it much better than others since they
// are the leaders in new techniques and software technologies...
// You do not believe me? Read their ads...). This stuff was checked
// under some later versions of FireFox, IE, Opera, and Mozilla.
// Have fun... Tell me if you like it or if you hate it...
// Jan
//
var i_was_read = 1;

function getStuff(el, url, nR, nC, id) {
   el.innerHTML = "Please wait for file "+ url + " to load into element "+id;
   var req = false;
   if(window.XMLHttpRequest) { // For standard browsers (and IE7 ?)
      try { 
         req = new XMLHttpRequest();
      } catch(e) {
         req = false;
      }
   }
   if(! req) {
      if(window.ActiveXObject) {  // For special MicroSoft browsers
         try {
           req = new ActiveXObject("Msxml2.XMLHTTP");
         }
         catch(e) {
           try {
              req = new ActiveXObject("Microsoft.XMLHTTP");
           }
           catch (e) {
              req = false;
           }
         }
      }
   }
   if(! req) {  // if no luck in getting XMLHttpRequest instance
     el.innerHTML = "Could not create XMLHttpRequest for " + 
       navigator.appName;
     return;
   }
   // to prevent caching -- browsers/proxy-servers usually do not cache
   // pages with different parameters in GET request
   var stamp = '?nocache=' + (new Date()).getTime();  
   req.onreadystatechange = function() {  // anonymous event handler function
      var nLines, nColumns, newLineEnd, oldLineEnd, i, gotText, debug;
      debug = "nC=";
      if(req.readyState == 4) {  // on request competion
         if(req.status == 200) {    // if page returned OK
           // get text from the server
           gotText = req.responseText;
           nLines = 0;   // how many lines?
           nColumns = 0; // number of chars in longest line
           oldLineEnd = 0;  // position of previous EOL
           if((nC < 1) || (nR < 1)) {//find max text width/height if not given
              while((newLineEnd = gotText.indexOf("\n", oldLineEnd)) >= 0) {
                nLines++;
                // find the longest line
                if((newLineEnd - oldLineEnd + 1) > nColumns) {
                  nColumns = newLineEnd - oldLineEnd + 1;
                }
                // prepare to search for next line end search
                oldLineEnd =  newLineEnd + 1;
              }
           }
           // if rows attribute not given, set it here
           if(nR < 1) {
             nR = nLines+1;
           }

           if(nC < 1) { // if cols attribute not given, set it here
             nC = nColumns + 1;
             if(nR <= nLines) { // if scroll bar is present, add 2 for it
                nC += 2;
             }
             if((nC < 10) && (nR < 3)) { // for short files make it look good
               nC = gotText.length;
             }
             if(nC < 10) {  // short textareas look bad
               nC = 10;
             }
             if(nC > 83) {  // if long line, add scrollbars rather then width
               nC = 83;
             }
           }

           // write a textarea element with text to the <div></div> element
           // <textarea> is nice since you do not have to mess with entities
           // like < and > or whatever else          
           var tag = '<a href="'+url+stamp+
           '" target="_blank" class="link">[Get '+url+"]</a><br />\n"+
           '<textarea name="'+id+
           '" disable readonly wrap="off" rows="'+nR+
           '" cols="'+nC+
           '" id="'+id+ '">';
           // If your text has <, >, and &, encode them
	   gotText = gotText.replace(/&/, "&amp;");
           gotText = gotText.replace(/</, "&lt;");
           gotText = gotText.replace(/>/, "&gt;");
           el.innerHTML = tag + gotText +
           '</textarea>'+"<br />\n";
           // alert(el.innerHTML); // uncomment this to check what it does
         }
         else {  // status is not OK and file was not found.
           el.innerHTML = "Failed to retrieve "+url+" Status="+req.status+
             " Server Resonse: "+req.statusText;
         }
      }
   }
   req.open("GET", url+stamp, true);   // set up Ajax GET method to the server
   req.send("");   // send request to server -- we use GET method so 
}                  // nothing is send in the request body


function getMyFiles() {      // get files to load from server to <div>...<div>
   var elements = new Array();  // set up local array for <div> elements
   elements = document.getElementsByTagName("div"); // get all <div></div>
   var i, j, el, content, nR, nC, url, id;  // local variables
   var attributes = new Array();  // array to hold parsed info
   var pair = new Array();        // array to hold key/value pairs

   for(i = 0; i < elements.length; i++) {  // scan all retrieved elements
      el = elements[i];
      id = el.getAttribute('id');    // get the value of id attribute of <div>
      if(! id) {             // standard browsers have el.hasAttribute()
         continue;           // method but IE6 is better and does not need it
      }
      if(id.indexOf('getfile') != 0) {   // if id is not getfile.* skip it
         continue;                           // since it is something else
      }

      id = id + '_' + i + '_ta';       // create unique id for the <textarea>
      content = el.innerHTML;          // retrive original content of <div>
      attributes = content.split(';'); // split it and parse it
      url = "error.txt";               // default URL for file (error message)
      nR = 0;                          // default for <textarea rows=... >
      nC = 0;                          // default for <textarea cols=... >
      for(j = 0; j < attributes.length; j++) {  // parse key=value pairs
         pair = attributes[j].split('=');  // now pair[0]=key, pair[1=value
         switch(pair[0]) {             // allowed attributes at this time
           case 'rows':                // set rows if given
              nR = pair[1];
              break;
           case 'cols':                // set cols if given
              nC = pair[1];
              break;
           case 'url':                 // set url if given
              url = pair[1];
              break;
           default:
              break;
         }
      }
      // now call Ajax gizmo to get the file (url) and put it in <div>
      // I did testing: // alert("Url="+url+" nR="+nR+" nC="+nC+" id="+id);
      getStuff(el, url, nR, nC, id);  
    }                                 // end of (for(i = ...
   return true;     // to keep onLoad event happy...
}


