// Gizmo 20: McCain quotes
// By Steve Stoft, Dan Kirshner & Tim Wood - zFacts.com

// <a id="MCQ" href="http://zfacts.com">McCain Iraq</a>
// <span id="MCQz" ref="speed=5"></span>
// <script type="text/javascript" src="http://zfacts.com/giz/G20mcq.js"></script>

// valid()     Check for zFacts link, grabs user params, runs initializations and starts looper()
// pram()          Save and get user parameters
// setup()         Replaces zFacts link with Div containing gizmo
// getDiv()        Initialize Div pointers, and get them as needed
// speed()         initialize speed, get wait-time for quotes
// infoUp()        Make visible or hide the source-popup window
// showInfo()      Get info and put in popup <div>
// PHPrequest()    Get info from server for showInfo
// URL()           Format the URL for info pupUp
// looper()        The quote loop. Params:  0 => restart from quote 1.  
//                    1       =>  start going forward. 
//                    -1      => start going backwards
//                    9       => go to the end and stop. 'stop' => stop.  
//                    'pause' => continue if stopped, stop if going.
//                    'go'    => next quote and continue (used when already 
//                               going, and "Faster" is clicked.
// showQuote()     gets the next quote and shows it.
// getQuote()      Return quote of a given #
// putQuoteInDiv() Figure out which of 2 Divs, and font, the put quote in Div 
// slideQuote()    slides oldQuote up and out; new quote up and in    

var site_20 = "zfacts.com/giz/G20/";
var quotes_20 = site_20 + "quotes2.php";
var facts_20  = site_20 + "facts.php";
var pics_20   = [ "mccain1_55.jpg",  "mccain12_55.jpg", "mccain3_55.jpg",
                  "mccain16_55.jpg", "mccain19_55.jpg", "mccain20_55.jpg",
                  "mccain26_55.jpg" ];

var logProg   = "http://zfacts.com/giz/udat/rec.php";
var gizName   = "G20mcq";

valid_20();             // Validate link and read setup parameters

// -----------------------------------------------------------------------------
function valid_20() {

   // Quickstart getting quotes

   getQuote_20(1, "\"As long as Saddam Hussein is in power, I am convinced that he will pose a threat to our security\"|McCain|0/0/0|Feb 2000. Fact: Saddam was all bluster, no weapons");
   m = valid_20;
   var rpage="http://zfacts.com";
   var oops = 0;
   var MCQ = "MCQ";
   var linkDiv = document.getElementById(MCQ);
   if ( ! linkDiv ) {
      MCQ = "mcq";
      linkDiv = document.getElementById(MCQ);
   }
   if ( !linkDiv || (typeof(linkDiv) == 'undefined') ) {
      alert("Need id='MCQ' in Link to zfacts.com\nSee http://zfacts.com/p/948.html for Help.");
      return;
   }
   if (linkDiv != null) {  
      if ( linkDiv.getAttribute("href") != rpage ) {
         if ( linkDiv.getAttribute("href") != rpage + "/" ) {
            oops = 1;
         }
      }
      var linked = linkDiv.innerHTML;
      if ( linked.toLowerCase().indexOf('iraq') < 0 
                               || linked.toLowerCase().indexOf('mccain') < 0 ) {
         oops = 2;
      }
      if ( linkDiv.nodeName != 'A' ) {
         oops = 3;
      }
   } else  {
      oops = 4;
   }
   if ( oops != 0 ) {
      alert( oops + " Need link to zfacts.com\nSee http://zfacts.com/p/948.html for Help.");
      return;
   }

   // Logging.

   udat_20();

   var paramDiv = document.getElementById('MCQz');
   if ( paramDiv && (typeof(paramDiv) != 'undefined') ) {
      var paramList = paramDiv.getAttribute("ref");
      if ( paramList && (paramList.length > 2) ) {
         loadPrams_20(paramList);
      }
   }
   setUp_20(MCQ);        // Install gizmo HTML in page
   getDiv_20('init');      // Initialize Div pointers
   speed_20('init', pram_20('speed'));    // initialize speed to medium.
   info_20('controls');
   info_20('offOnly');     // Set the info-controls-popup window invisible
   looper_20(0);           // Start the quote loop at the first quote
}


// -----------------------------------------------------------------------------
function loadPrams_20(pString) { 

   // takes parameter values from user list and stores them in pram_20();

   pNames=['speed', 'size', 'cQ', 'cF', 'cL', 'cB', 'pic'];
   var params = pString.split(',');
   for (var i=0; i<params.length; i++) {
      var peqv = params[i].replace(/ /g, '');         // remove blanks
      peqv = peqv.split('=');
      var pram = peqv[0]; 
      var val  = peqv[1];
      for (var j=0; j<pNames.length; j++) {
         if ( pram.toLowerCase() == pNames[j].toLowerCase() ) 
            pram_20(pNames[j], val);            
      }
   }  
}


// -----------------------------------------------------------------------------
function pram_20(name, val) {
   var my = pram_20;
   if ( typeof(my.init) == 'undefined' ) {
      my.size  = 5;        // default font size (scales gizmo)
      my.speed = 5;        // default speed is 5
      my.cQ    = '#FFF';   // quote background color
      my.cF    = '#FCC';   // fact BG color
      my.cL    = '#CCF';   // Left area background color
      my.cB    = '#900';   // gizmo border color
      my.pic   = 'yes';    // McCain picture
      my.init = 1;         // not a parameter
   }
   if ( typeof(val) != 'undefined' ) {
      eval( 'my.' +name+ '=val;' );    // set name = val
   } else {
      return eval( 'my.' +name );      // get val of name
   }
}


// -----------------------------------------------------------------------------
var loop_20;            // name of delayed call to looper

// 1         => forward. 
// -1        => backward. 
// 0         => back to quote 1 then forward. 
// 9         => last quote & stop.
// 'go'      => hesitate then continue my.way.  
// 'stop'    => stop.  
// 'pause'   => stop if going, go if stopped
// (nothing) => call as part of loop, or to take next step now in same 
//              way we were going.
// what = 1, -1, 0, 9, go, goNow, stop, pause, undef.    
// way = 1,-1.  
// going = 1,0.  
// slow = 1,0.
// 'go' is sent when closing info window (not when 'go' is clicked, then 
// 'pause' is sent.) 'goNow' avoids delay (for "faster")

function looper_20(what) {
   var my = looper_20;
   if ( typeof(my.init) == 'undefined' ) {  
      my.init=1;           // initialize state variables
      my.waiting = 0;      // 1 => waiting for quotedata loadJSA()
      my.way = 1;          // 1 => forward, -1 = backwards looping
      my.going=1;          // 1 =>  looping, not paused.
   }
   if ( typeof(what)=='undefined' ) {
      what = 'undef';   // value 'undef' used in tests below
   }
   if ( what != 'undef' ) {

      // New request, starting new loop.

//    if (what != 'stop') {
//       info_20('offOnly');   // close info window if they choose to see more quotes
//    }

      clearTimeout(loop_20);   // If not called in loop, stop loop so we don't get 2 loops when we start it up.
      if ( typeof(waitLoop_20) != 'undefined') {
         clearTimeout(waitLoop_20);
      }
      my.waiting = 0;          // Stop waiting and service new requqest
   }

   // must use what to  my.way, my.going, slow

   if ( ! my.waiting ) {

      // If not just waiting, figure out which quote is next

      var slow = 0;       // default = not slow
      var nxt = what;     // default guess at how to find net quote #
      if ( what == -1 )                      my.way = -1;
      if ( inStr(what, '1,0,9') )            my.way = 1;
      if ( what == 'go' )                 {  nxt = 'skip';   slow=1; }
      if ( inStr(what, 'undef,goNow') )      nxt = my.way;
      if ( inStr(what, '1,0,-1,go,goNow') )  my.going = 1;
      if ( what=='pause' )                   my.going = 1 - my.going; // go if stopped, stop if going.
      if ( what=='pause' && my.going )       nxt = my.way;
      if ( inStr(what, 'stop,9' ) )          my.going = 0;
      
      if ( my.going )   getDiv_20.pause.innerHTML = 'Stop';
      else              getDiv_20.pause.innerHTML = 'Go';
      
      if ( inStr(nxt, '-1,1,0,9') ) {
         my.qN = nextQN_20(nxt);
      }
      if ( ! my.going && ! (nxt==9) ) return;
   }

   // getQuote will call continueLoop(quote, n) with n=my.qN and the right 
   // quote.

   var quote = getQuote_20(my.qN); 

   // Change the picture.

   if ( pram_20.pic == 'yes' ) {
      getPic_20(my.qN);
   }

// getDiv_20.dbug.innerHTML = quote;
   if ( quote == -1 ) {
      my.waiting = 1;
   // alert('waiting='+my.waiting+' qN='+my.qN);
      waitLoop_20 = setTimeout("looper_20();", 300);  // just using looper_20, sets way=12 for some goofy reason
   } else  {  
      my.waiting = 0;                // quote available so finish processing
      if ( ! slow ) processQuote_20(my.qN, quote);
      if ( ! my.going ) return;      // Jump to last quote, requires processQuote_20, but then stops
      var sf = 1; if (slow) sf = 1.6;              // If a slow start wait, but only by 1/sf the normal wait. Else we are already going
      var qDelay = speed_20('get', 'qLen')/sf;     // millisec delay needed to read quote.
      var fDelay = speed_20('get', 'fLen')/sf;     // millisec delay needed to read fact.
      setTimeout("showFact_20();", qDelay);
      loop_20 = setTimeout("looper_20();", qDelay+fDelay);  // just using looper_20, sets way=12 for some goofy reason
//    alert(qDelay+' : '+fDelay);
   }
}


// -----------------------------------------------------------------------------
// dN==0 => get quote 1.  1 => get next, -1=>get previous, 9=>get last
function nextQN_20(dN) {                        // set globals: quote, qWho16, qDate
   var my = nextQN_20;                          // my is another name for the function.
   var look = 0;     // assume not looking ahead
//alert('dN='+dN+' qN='+my.qN);
   my.shrtList = 0;
// if (dN == 'short')  { my.shrtList = 1; return; }
// if (dN == 'full')   { my.shrtList = 0; return; }
   if (dN == 'lookAhead') {
      dN = my.way;
      var qN = my.qN;
      var look = 1;
   } else {
      my.way = 1; if (dN == -1) my.way = -1;    // remember direction for lookAhead.
   }
   if ( typeof(qSet)=='undefined' ) {
      my.qSet = new Array(4,5,8,9,13,14,15,16,24,27,28,29,30,33,39,46,49,50,54);
   }
   var L = my.qSet.length;
   var maxQN = getQuote_20.maxQ;             // Even though Qts[0] is empty it is counted.
//alert('dN='+dN+' my.qN='+my.qN);
   if (dN == 0)   my.qN = 1;                 // reset to start of quotes
   if (dN == 1) { 
      my.qN ++; 
      if (my.qN >= maxQN) my.qN = 1;          // inc and wrap 
   }
   if (dN == -1) { 
      my.qN --; 
      if (my.qN < 1) my.qN = maxQN-1;          // dex and wrap
   }        
   if (dN == 9)   my.qN = maxQN;             // reset to end
   if (my.shrtList) {
      var sqn = shorti(my.qN);
      if (dN == 0) my.qN = sqn=0;
      if (dN == 9) my.qN = sqn=L-1;
      if (dN == 1)   {  sqn = Math.ceil(sqn);  if (sqn>L) sqn=0;  }
      if (dN == -1)  {  sqn = Math.floor(sqn); if (sqn<0) sqn=L-1;  }
      my.qN = my.qSet[sqn];
   }
   if (look) { 

      // undo changed my.qN return prediction

      var ahead = my.qN; 
      my.qN = qN; 
      return ahead }   
   return my.qN;


// -----------------------------------------------------------------------------
   function shorti(qn) {
      for (i=0; i<L; i++) {
         if (qn < my.qSet[i]) return(i-.5);
         if (qn == my.qSet[i]) return i;
      }
      return i+0.5;
   }
}


// -----------------------------------------------------------------------------
// qN' returns value of qN.  
function processQuote_20(n, quotePlus) {
   var my = processQuote_20;
   if (n == 'qN')       return my.qN;        // showQuote() is the only way to lean qN, the current quote number
   if (n == 'qLen')     return my.qLen;      // used by speed()
   if (n == 'fLen')     return my.fLen;      // used by speed()
   if (n == 'WhoDate') {                        // Called by slideQuote() when it finishes
      //getDiv_20.who.innerHTML    = my.who +'<br>'+ my.date;
      setTimeout('showFact_20();', 2000);
//    getDiv_20.QN.innerHTML     = '\xA0#' + my.qN + '\xA0';
      return;
   }
   my.qN = n;
   var qData = quotePlus.split('|');   // This gets the quote, who and date and splits them up <==== get Quote
   var quote = qData[0];
   my.qLen = quote.length;
   
   showFact_20("&nbsp;");
   putQuoteInDiv_20(quote);
   slideQuote_20('start');                         // initialize for new slide
// getDiv_20.who.innerHTML = ''           // clear old who and date while sliding quote
// getDiv_20.date.innerHTML = '';
   
   //my.who =  '<b>'+qData[1]+'</b>';    //    mdash = '\u2013'

   var mdy = qData[2].split('/');            // split up date, formatted as 12/25/2005
   my.date = mdy[0] + ' / ' + mdy[2];
   my.fact = qData[3]; //alert(quotePlus);
   my.fLen = my.fact.length;
// var m = Array('Jan.','Feb.','Mar.','Apr.','May','June','July','Aug.','Sept.','Oct.','Nov.','Dec.');//
// var d = mdy[1]*1;                            //remove initial 0 if any.
// my.date = m[mdy[0]-1] + ' ' + d + ', ' + mdy[2];
} 
function showFact_20(fact) {
   if (typeof(fact)=='undefined') fact = processQuote_20.fact
   getDiv_20.fact.innerHTML = fact;
}
function putQuoteInDiv_20(quote) {
   if ( slideQuote_20('topDiv') == 2 )             // if Div2 is top, use Div
      var bottomDiv = getDiv_20.quote;
   else                                      // if Div is top, use Div2                               
      var bottomDiv = getDiv_20.quote2;   
   var code = quote.match(/^.;/);                  // matches B; or other code at start of string. B == big quote.
   if ( code ) quote = quote.substr(2);            // chop off code if present.
   bottomDiv.innerHTML = quote;                    // put quote in.
   if ( code == 'B;' )  bottomDiv.style.fontFamily = 'arial';     // use arial for large quotes
   else                 bottomDiv.style.fontFamily = 'verdana,helvetica,arial';  // use verdana for normal quotes
}


function slideQuote_20(what) { 

   // quoteDiv and quoteDiv2 take turns sliding in the current quote.

   var my = slideQuote_20;
   my.Ymax = 35;
   if ( typeof(what) != 'undefined' ) {
//    if (what=='setSize0') my.Ymax = 50;          // without control buttons
//    if (what=='setSize1') my.Ymax = 35;          // with control buttons
      if ( typeof(my.topDivN) == 'undefined' ) {
         my.topDivN = 2;      my.hiVis = 1;        // Div2 starts out in place but empty. It is topDiv.
         my.topDiv = getDiv_20.quote2.style;
         my.botDiv = getDiv_20.quote.style;
         my.yLow = my.Ymax;                        // Ymax = how low a Div starts it slide up.
      }
      if (what=='topDiv')     return my.topDivN;
      if (what == 'start') { 
         my.botDiv.visibility = 'visible';
         my.topDiv.visibility = 'hidden';
      }
      else return;
   }
   my.botDiv.top = my.yLow + 'px';           // position of bottom Div
   if ( my.yLow == 0 ) {                        // Quote is in place
      my.topDivN = 3 - my.topDivN;           // switches from 1 to 2 to 1 to ...
      var tmp = my.topDiv;
      my.topDiv = my.botDiv;  my.botDiv = tmp;  // switch DIVs 
      my.yLow = my.Ymax;                     // All set for next quote.
      processQuote_20('WhoDate');
   }  else  {
      if ( my.yLow > 20 )        my.yLow = my.yLow -10;
      else if ( my.yLow > 10 )   my.yLow = my.yLow -4;
      else if ( my.yLow > 3 )    my.yLow = my.yLow -2;
      else my.yLow--;
      setTimeout("slideQuote_20();", 50);             // Keep sliding quote if not in place yet
   }
}


function speed_20(what, val) {         // return millisec delay
   var my = speed_20;   
   if (what=='init') {
      my.spd = val*1;  // initialize speed (user param sets it to a string)
      my.m = [2.7, 1.7, 1.35, 1.15, 1, .85, .7, .5, .1];
   } else if (what=='inc') {
      my.spd = Math.min(my.spd+1,9); 
      looper_20('goNow');   // jump to next quote and go, so they feel like 
                            // it's working
   } else if (what=='dec') {
      my.spd = Math.max(my.spd-1,1);
   } else if (what=='get') {
      var Len = processQuote_20(val)   // the length of the current quote
      var s = my.m[my.spd-1];       // spd = 1 => 3 times longer.  
                                    // spd = 9 => 10 times faster.
      if (val == 'qLen') {
         return 800 + s * (900 + 2800 * Len/50);   // 0.7 to scrole, 0.8 sec to read who & date.  2.5 sec to read 50 chars of quote.
      } else {
         return 1100 + s * 2800 * Len/50;
      }
   }
   getDiv_20.speed.innerHTML = "\xA0" + my.spd + "\xA0";
}


// -----------------------------------------------------------------------------
function onOffCBs_20(x) {
   var my = onOffCBs_20;
   if ( typeof(my.state)=='undefined' ) { my.state = 'off'; my.busy = 0; my.offWait = 0; }
   if (x=='offNow')  my.D = 'off';
   switch (x) {
      case 'on':
      case 'off':
//    bug('st='+my.state);
         my.D = x;                           // record desired state, either 0 or 1
         if ( my.offWait ) { clearTimeout(my.offWait); my.offWait=0; }
         if ( my.D == my.state ) {
            return;
         }
         if (x=='off') {
            my.offWait = setTimeout("onOffCBs_20('set0');", 1300);   // come back later to set state=0, controls off
            return;
         }  
      case 'offNow':                   // If the user clicks X this is deliberate
      case 'set0':
      case 'setB':
         if ( my.D == my.state ) return;        // Return of state ok.
         if ( my.busy ) {                          // can be busy if mouse over while changing state           
            setTimeout("onOffCBs_20('setB');", 300);  // come back soon
            return;
         }
         my.busy = 1;
         var D = my.D;        // Freeze D so it cannot change before state is set.
         my.state = D;        // The state will certainly change to D, so call it D now.
//       bug('S'+D);
         info_20(D);          // <== Actually turns info 'on' or 'off'  
         my.busy = 0;      // no l
//       bug('bsy='+my.busy);
   }
}


// -----------------------------------------------------------------------------
function udat_20() {

   // Call logging program as javascript.

   var file = logProg + "?gizName=" + gizName;
   var script = document.createElement("script");
   script.src = file + "&domain="   + document.domain 
                     + "&location=" + document.location;
   script.type = "text/javascript";

   // Put the javascript in the document head.

   document.getElementsByTagName("head").item(0).appendChild(script);
}


// -----------------------------------------------------------------------------
function setUp_20(ID)   {  // IE does not seem to like   box.setAttribute('style', ' ...)
   my = setUp_20;
   var cQ   = pram_20('cQ');  // #FFF  quote background.  Default set in pram_20()
   var cF   = pram_20('cF');  // #FF9  fact background
   var cL   = pram_20('cL');  // #CCF  control-bar background color
   var cB   = pram_20('cB');  // #900  border
   var pic  = pram_20('pic'); // picture yes/no
   var cCBG = '#9BA';         // colors controls background
   var cCBT = '#FFC';         // colors control buttons
   var cIC  = 'background-color:#ACB; '   // info-control-button color. See showInfo_20()
   var cLSty = 'background-color:' +cL+ '; ';   // used 4 times
   var cIBG = '#FFd';         // color of info background
   var cIB  = '#060';         // color of info border

   var tapeBG  = 'background-color:' +cCBG+ '; '; 
   var tapeBtn = 'background-color:' +cCBT+ '; border:1px solid ' +cCBG+ '; cursor:hand; cursor:pointer; ';       // tape control button button cursor
   var mbp0 = 'margin:0; border:0; padding:0; ';
   
   var fSz = 12, lHt = 16;    // font size and line height in pixels

   // gizmo width and Left width, right/left margin widths

   var wd = 350, LWd = 0, rmWd = 3, lmWd = 0;  
   var ht = 55,  qHt = 36, fHt = 16 // quote, fact heights.,  qHt +fHt + 3 = ht

   // fonts in 1.Left-Labels, 2.Quote, 3.Fact, 4.Info

   var fontFam = 'font-family:arial,\'sans-serif\';' ;

   // TapeDect controls, short quotes

   var fontFamBig = 'font-family:verdana,helvetica,arial;' ;
   var fontTapeCntrl = 'font-family:verdana,helvetica,arial;' ;
   if (pram_20.size == 3) {
      fSz = 11;  lHt=15;   // font size and line height
      wd=308;  LWd=0; rmWd=2, lmWd=0;
      ht=48;  qHt=30;  fHt=15;   // 30 + 15 + 3 = 48

      // fonts in 1.Left-Labels, 2.Quote, 3.Fact, 4.Info

      var fontFam = 'font-family:Times,\'Times New Roman\',serif;' ;

      // TapeDect controls, short quotes

      var fontFamBig = 'font-family:arial,\'sans-serif\';' ;
   }

   // See if IE.

   var browser = navigator.userAgent.toLowerCase();
   var IE = browser.indexOf("msie") >= 0;

   var overall_wd = wd;
   if ( pram_20.pic == 'yes' ) {

      // Picture width

      var pic_wd = ht;
      overall_wd += pic_wd;
   }


   var fontSize = 'font-size:' +fSz+ 'px; line-height:' +lHt+ 'px; ';
   // F = full,  F2 = F-2,  L = left, RM = Right margin of L and of quote/fact, ML = Left margin of quote/fact
   var Fwd  = 'width:' +wd+ 'px; ';
   if ( IE ) {
      var F2 = 4;
   } else {
      var F2 = 2;
   }
   var F2wd = 'width:' +(wd-F2)+ 'px; ';   // fix: 2=>F2
   var Lwd  = 'width:' +LWd+ 'px; ';      // left width style
   var Qwd  = 'width:' +(wd-F2-LWd-rmWd-lmWd-rmWd)+ 'px; ';     // quote width
   var MRwd = 'margin:0 ' +rmWd +'px 0 0;'      // right margin width style
   var MLwd = 'width:' +lmWd+ 'px; ';     // left margin width style
   // F = full, Q = quote, R = fact, control rows (1-Line)
   var Fht = 'height:' +ht+ 'px; ';
   var Qht = 'height:' +qHt+ 'px; ';
   var Rht = 'height:' +fHt+ 'px; ';
   var iBox = 'line-height:' +(lHt-2) +'px; height:' +(fHt-2) +'px; bottom:1px; font-family:courier; font-weight:bold; color:#FFF; background-color:#33F;';

// outerBox is an extra layer, but needed because onmouseover attributes cannot be placed directly into outerBox,
//    and box cannot be replaceChilded into Giz.parentNode.
// So we have this layout: outerBox( box ( popupBox(), mainBox(), Fact-ControlBox() ) )
   var outerBox = document.createElement('div');      // build Gizmo box inside.
   Giz = document.getElementById(ID);                 // The tag of the obligatory link to zFacts
   Giz.parentNode.replaceChild(outerBox, Giz);
   var gizTag = '<div id="box_20" '
   +  'style="width:'+overall_wd+'px; ' + Fht + 'position:relative; text-align:left;'
   +  mbp0 + fontSize + fontFam
   +  'background-color:' +cB+ ';"' // this produces the border and keeps the gizmos the same size in FF and IE
   +  'onmouseover="onOffCBs_20(\'on\')" onmouseout="onOffCBs_20(\'off\')"></div>'
   outerBox.innerHTML = gizTag;
   var box = document.getElementById('box_20');       // This is the DIV that contains the gizmo

   content = ""

   // Picture.

   if ( pram_20.pic == 'yes' ) {
      var pic_wd1 = pic_wd - 0;
      content += '<div style="float:left; position:relative; left:0px; top:0px;'
               +             'width:'+pic_wd1+'px; height:'+pic_wd1+'px; '
               +             'overflow:hidden; border:0px;">'
               +  '<img id="pic_20" src="mccain1_55.jpg" border="0" '
               +        'width="'  + pic_wd + '" '
               +        'height="' + pic_wd + '" />'
               + '</div>';
   }

   // popup box

   content +=
     '<div id="popUp_20" style="position:absolute; visibility:hidden; top:' +ht+ 'px; left:0px; ' 
     + 'width:'+overall_wd+'px; ' + mbp0 + ' background-color:' +cIB+'; text-align:left; z-index:99; opacity:1.0; -moz-opacity:1.0; filter:Alpha(opacity=100);">' // this provide border, hiding, positioning, etc.

      // Control strip

      + '<div id="CBs_20" style="width:'+(overall_wd-2)+'px; ' +Rht +fontSize +mbp0 +'top:0px; left:1px; ' +tapeBG+ '; ' // top:0px means no top border (could be omitted)
      + 'visibility:hidden; overflow:hidden;">'
         + '<div style="float:right; ' +mbp0 +'">&nbsp;'

            // Popup info.    could use: <img src="http://zfacts.com/giz/G20/info_i.gif" />
         /* REPLACED BY LINK TO ZFACTS
            + '<span style="'+tapeBtn +'font-weight:bold;" onclick="info_20(\'fact\')">\xA0\xA0more info\xA0\xA0</span>'
            + '<span style="'+tapeBtn +iBox +'" onclick="info_20(\'about\')">i</span>' // iBox
         */
         + '<a href="http://zfacts.com/p/925.html">Sources, more info</a>'
         + '</div>'
         + '<div style="float:left; ' +mbp0 +'text-align:right;">'
            // Faster-Slower
            + '<span style="'+tapeBtn+'" onclick="speed_20(\'dec\')">\xA0Slower\xA0</span>'
            + '<span id="speed_20" style="background-color:#FFF;"></span>'
            + '<span style="'+tapeBtn+'" onclick="speed_20(\'inc\')">\xA0Faster\xA0</span>'
         + '</div>'
         + '<div style="float:left; ' +mbp0 +fontTapeCntrl +'font-weight:bold;">'
            // rewind, back, pause, forth, final
            + '<span style="'+tapeBG+'"> &nbsp; </span>'
            + '<span style="'+tapeBtn+'" onclick="looper_20(0)">|<</span>'
            + '<span style="'+tapeBtn+'" onclick="looper_20(-1)">\xA0<\xA0</span>'
            + '<span id="pause_20" style="'+tapeBtn+'font-weight:normal;" onclick="looper_20(\'pause\')">Stop</span>'
            + '<span style="'+tapeBtn+'" onclick="looper_20(1)">\xA0>\xA0</span>'
            + '<span style="'+tapeBtn+'" onclick="looper_20(9)">>|</span>'
         + '</div>'
      + '</div>'     // End of controls strip

      // Info box: quote & fact details

      + '<div id="info_20" style="' +F2wd +mbp0 +'top:0px; left:1px; background-color:' +cIBG +';">'  // 
         + '<div id="iText_20" style="width:' +(wd-2-4-3) +'px; position:relative; top:3px; left:4px;"></div>'    // controls and info text goes inside here. See my.infoControl.Div
         + '<div style="width:100px; height:4px; ' +mbp0 +'font-size:0px; line-height:0px;">&nbsp;</div>' // 
      + '</div>'
   // spacer line to let popUp box BG color show thru for 1-px bottom border. (partly covered by down-shifted content box)
   + '<div style="' +Fwd +mbp0 +'height:1px; font-size:0px; line-height:0px;">&nbsp;</div>'
   + '</div>';     // End of popup box 

   // quote box: hides slide-in overflow but not popup box

   if ( IE ) {
      var left = -2; // fix 1==>-2
   } else {
      var left = 1;
   }
   content +=
     '<div id="qtBox_20" style="' +F2wd +mbp0 +Qht +'position:relative; top:1px; left:'+left+'px; background-color:'+cQ+'; text-align:left; overflow:hidden;">'

      // who-date box - UNUSED

      /*
      + '<div id="who_20" style="float:left; display: none;' +Lwd +Qht +mbp0 +cLSty+ '; text-align:right;">Who<br>Date</div>'
      */
      + '<div style="float:left; ' +MLwd +MRwd +Qht +cLSty + 'border:0px; padding:0px;"></div>' // margins

      // quote box

      + '<div style="float:left; position:relative; ' +Qwd +Qht +mbp0 +fontFamBig +'text-align:left;">'
         + '<div id="quote_20" style="position:absolute; '+mbp0+'">Quote</div>'
         + '<div id="quote2_20" style="position:absolute; '+mbp0+'">Quote</div>'
      + '</div>'
   + '</div>'

   // Fact Box - NOW SOURCE OR COMMENT.

   + '<div id="fBox_20" style="' +F2wd +Rht + 'position:relative; top:2px; left:'+left+'px; background-color:' +cF+ '; '
   + mbp0+ 'overflow:hidden;">'     // 
      + '<div id="i_20" style="position:absolute; left:2px; width: 12px; ' +iBox +'">i</div>'                                  // "i" box
/*
      + '<div style="float:left; '+Lwd +Rht +mbp0 +cLSty + 'text-align:right; color:#333;"><b>Fact:</b></div>'    // Fact heading
*/
      + '<div style="float:left; ' +MLwd +MRwd +Rht +cLSty + 'border:0px; padding:0px;"></div>'                   // margins
      + '<div id="fact_20" style="float:left; margin-left:12px; width:'+(wd-LWd-24)+'px; text-align:left;">This is a Fact.</div>'   // Fact
   + "</div>"
   + '';
   box.innerHTML = content;

   /* NOT USED
   my.infoControlDiv = ""           // The upper-right control box.
   + '<div style="float:right; position:relative; top:-3px; right:-3px; font-weight:bold; cursor:hand; cursor:pointer;">'
      +  '<span onclick="info_20(BACK)" style="' +cIC+ '">&nbsp;back&nbsp;</span>&nbsp;'        // "BACK" is replaced with target in showInfo_20()
      +  '<span onclick="onOffCBs_20(\'offNow\')" style="' +cIC+ '">&nbsp;X&nbsp;</span>&nbsp;'
      +  '<span onclick="info_20(MORE)" style="' +cIC+ '">&nbsp;more&nbsp;</span>'              // "MORE" is replaced
   + '</div>';
   */
   my.infoControlDiv = '';
}
function getDiv_20(which) {
   var my = getDiv_20;
   if (which != 'init') return;
// my.dbug     = document.getElementById('dbug');
   my.box      = document.getElementById('box_20');
   if ( pram_20.pic == 'yes' ) {
      my.pic   = document.getElementById('pic_20');
   }
   my.qtBox    = document.getElementById('qtBox_20');
   my.quote    = document.getElementById('quote_20');
   my.quote2   = document.getElementById('quote2_20');
   //my.who      = document.getElementById('who_20');
   my.popUp    = document.getElementById('popUp_20');
   my.info     = document.getElementById('info_20');
   my.iText    = document.getElementById('iText_20');
   my.fBox     = document.getElementById('fBox_20');
   my.i        = document.getElementById('i_20');
   my.fact     = document.getElementById('fact_20');
   my.CBs      = document.getElementById('CBs_20');
   my.speed    = document.getElementById('speed_20');
   my.pause    = document.getElementById('pause_20');
}
function info_20(what) {      // State = my.what: 0=>off, about,fact,source => on
   var my = info_20;          // my.up inialized to 0 by early call to infoUp('off')
// alert('info top, what= '+what);
   switch (what) {               // upDown: fact, source, about, off, offGo
      case  'on':
//    bug('info on');
         looper_20('stop');
         getDiv_20.i.innerHTML = '';
         showInfo_20(0, 'controls');
         return;
      case  'off':                  // called by X in info window
         showInfo_20(0, 'off');
         getDiv_20.i.innerHTML = 'i';
         looper_20('go')            // and make quotes go
         return;                    // what = either 'off' for 'offGo'
      case  'offOnly':              // called by looper(). Looper is going, so looper('go') is not appropriate. Also called to initialize
         showInfo_20(0, 'off');
         getDiv_20.i.innerHTML = 'i';
         return;
      case  'controls':
         showInfo_20(0, 'controls');
         return;
      case 'about':
      case 'fact':
      case 'quote':
      case 'fSource':
      case 'qSource':                  // Source button clicked
         looper_20('stop')
         var qN = processQuote_20('qN');
         if ( what == 'about' ) qN = 0;
         showInfo_20(qN, what);
   }
}
// showInfo() is called only by info() and getInfo()
function showInfo_20(n, what, info) {        // fills shows and hides info popup DIV. Only access to the popUp DIV
//alert ('n='+n+', what='+what);
   my = showInfo_20;
   switch (what) {
      case 'ready':           // Got info, so go on through
         break;
      case 'off':
         getDiv_20.popUp.style.visibility = 'hidden';
         getDiv_20.CBs.style.visibility   = 'hidden';
         getDiv_20.CBs.style.position     = 'absolute';        // CBs are never removed, but hidden & absolute is pretty much equivalent
         getDiv_20.iText.innerHTML = '';  // hide info popup
         return;
      case 'controls':
//    bug('controls');
         getDiv_20.popUp.style.visibility = 'visible';
         getDiv_20.CBs.style.position     = 'relative';
         getDiv_20.CBs.style.visibility   = 'visible';
         getDiv_20.info.style.position = 'absolute';  // Needed for IE. Empty div still takes room.
         getDiv_20.info.style.visibility = 'hidden';  // Needed for IE. Empty div still takes room.
         getDiv_20.iText.innerHTML = '';  // hide info popup
         return;
      default:                      // Initial request.
          my.what = what;           // Remember which case we are working on as info comes back with what='ready' for all cases
          getInfo_20(n, 'get');     // Now go get info and call again with what=='ready'
          return; 
   }
   getDiv_20.CBs.style.position   = 'absolute';
   getDiv_20.CBs.style.visibility = 'hidden';
   getDiv_20.info.style.position = 'relative';
   getDiv_20.info.style.visibility = 'visible'; // Needed for IE. Empty div still takes room.
   var UC = info.split('|');     // Back from PHPrequest with info. UC[i]; 0=> Qsource, 1=> fullQuote, 2=> Fsource, 3=>fullFact
   var moreInfo, backInfo, Text = "";
// alert ('showInfo: '+my.what);

   /* NOT USED
   switch (my.what) {                  // QC[0] = quote Source, 1=> full quote, 2=> fact source, 3=> fullfact
      case 'about':
         moreInfo='fact'; backInfo='controls';
         Text = UC[0];  break
      case 'fact':
         moreInfo='quote'; backInfo='controls';
         Text = '<b>Full Fact:</b> &nbsp; ' + UC[3];
         break;
      case 'quote':
         moreInfo='fSource'; backInfo='fact';
         Text = '<b>Full Quote:</b> &nbsp; ' + UC[1];
         break;
      case 'fSource':
         moreInfo='qSource'; backInfo='quote';
         Text = url_20(n, 'Fact Source: ', UC[2]);
         break;
      case 'qSource':
         moreInfo='controls'; backInfo='fSource';
         Text = url_20(n, 'Quote Source: ', UC[0]);
   }
   */
   moreInfo = 'controls';
   backInfo = 'controls';
   Text = 'Sources: <a href="http://zfacts.com/p/925.html">zfacts.com</a>';

   moreInfo = "'" +moreInfo+ "'";
   backInfo = "'" +backInfo+ "'";

   var cntrls = setUp_20.infoControlDiv;
   cntrls = cntrls.replace(/MORE/, moreInfo);
   cntrls = cntrls.replace(/BACK/, backInfo);
   getDiv_20.iText.innerHTML = cntrls + Text;
}

// This function builds and accesses the qInfo[] array. Adding to it as needed.
// It calls showInfo() once it has what's needed.

function getInfo_20(n, what, info) {

   // called by showInfo(n, 'blank')  AND  by  JS returned by loadJSA(n, info)

   var my = getInfo_20; 
   if ( typeof(my.qInfo)=='undefined' ) { my.qInfo = new Array(); }
   if ( what == 'get' ) {                    // info requested
      if ( typeof(my.qInfo[n])!='undefined' ) { // info available
         showInfo_20( n, 'ready', my.qInfo[n] );
         return;
      }  else {                              // info not available
         loadJSA( facts_20, n );          // this will call getInfo with the new information
         return;
      }
   } else if ( what == 'new' ) {                               // new info provided
      my.qInfo[n] = info;
      showInfo_20( n, 'ready', info );
   } 
   else alert ('problem in getInfo');
}
function loadJSA( file, ndx ) {
   var my = loadJSA;
   if ( typeof(my.n) == 'undefined' ) my.n = 1;
   var sid = 'JSAsync' + (my.n ++);
   var head = document.getElementsByTagName('head').item(0);
   var script = document.createElement('script');
   script.src = "http://" +file+ "?sid=" +sid+ "&index=" +ndx;
// alert(script.src);
   script.type = 'text/javascript';
   script.id = sid;
   head.appendChild(script);
}
// put line breaks into presentation of date + source URL for info-window
function url_20(n, label, url) {
   var nc = 64;         // number of chars that fit on a line.
   var ml = '';
   var daurl = '<b>' +label+ '</b>' + url;
   while (daurl.length > nc) {
      for (i=nc-1; i>0; i--) {
         var c = daurl.substr(i,1);
         if (c=='/' | c==' ') {  break;   }
      }
      if (i<3) break;
      ml = ml + daurl.substr(0,i+1) +'<br>';
      daurl = daurl.substr(i+1);
   }
   return ml + daurl;
}

function getQuote_20(n, quote) {             // 3 jobs: (1) how many quotes? (2) add a quote to list, (3) return a quote or missing flag
   var my = getQuote_20;
// alert('n='+n+', quote='+quote);
// getDiv_20.dbug.innerHTML = my.nn++;
   if ( typeof(my.init)=='undefined' ) {
      my.init = 1;
      my.nn = 0;
      my.URL = quotes_20;
      my.quotes = new Array();
      loadJSA( my.URL, 'max' );
   }
   if (n == 'max') {                                  // Job 1: how many quotesw
      if (typeof(my.maxQ) == 'undefined') return 2;
      else return my.maxQ;
   }
   if ( typeof(quote) != 'undefined' ) {              // Job 2: add a quote to list.  If a quote has been delivered
      my.quotes[n] = quote;                              // add it to the data array
      return;                                            // return to nowhere (on-demand script that added new quote)
   }
   if ( undef(n) )   {     // if quote missing        // Job 3: return a quote
      my.quotes[n] = 'fetched';                          // if missing fetch it an return -1 => being fetched, try again soon
   // alert('loadJSL:'+my.URL+' = '+n);
      loadJSA( my.URL, n );      // go get it
      return -1;                                         // return missing quote flag                                      
   }
   else if ( my.quotes[n] == 'fetched' )  {              // to soon, keep waithing
      return -1;}
   else     {                                            // else if quote is available
      getNextQ();                                        // Start lookAhead process
      return my.quotes[n];                               // return quote
   }
   //---------------------
   function getNextQ() {                              // get 3 upcoming quotes, look up to 4 ahead
      var nextN = nextQN_20('lookAhead');
      if ( undef(nextN) )
         loadJSA( my.URL, nextN );
   }
   function undef(n) {
      if (typeof(my.quotes[n])=='undefined') return 1; else return 0;
   }
}

// -----------------------------------------------------------------------------
function getPic_20(qN) {

   // Change picture with each quote.
   // Fewer pictures than quotes.  Use mod function to associate each quote with
   // a picture.

   var i_pic = qN % pics_20.length;
   getDiv_20.pic.src = "http://" + site_20 + pics_20[i_pic];
}


// -----------------------------------------------------------------------------
// Eg. inStr('needs', 'this,needs') == 1, but inStr('need', 'this,needs') == 0,
function inStr(needle, hay) { // needel must be found separated by commas. z is not found in hay='zfacts' only in hay='z,facts'
   needle = needle+'';        // convert to a string, just in case
   hay = ','+hay+',';
   w = hay.indexOf(','+needle+',');
   if (w==-1) return 0;
   return 1;
}
function pop_20(w,h,url)
{  var purl='http://'+url;
   FN = window.open(purl,'FN','resizable=yes,scrollbars=yes,width='+w+',height='+h+',left=0,screenX=0,top=0,screenY=0');
   FN.focus();
}
// function bug(x) { return;
// var my = bug;
// if ( typeof(my.info) == 'undefined' ) my.info='Z';
// if (x=='clear') my.info = '';
// else my.info += ', '+x;
// getDiv_20.dbug.innerHTML = my.info;
//}
