// This file contains intellectual property and artistic creations 
// by Dennis Sandow and is copyright 2000-2010 by the author. 
// For use only on websites maintained by Dennis Sandow, or with
// specific permission.  Do not remove this notice.

var sortKey='', prevsortKey='', yrRange=new Array(), reptCtr=0, PostDashes='', PreDashes='', ValignTopBot='', exportTownList='', outColPtr=0, outCols=new Array() ;
function DoIt( pkey ){
  pageOrSpawn=1;
  for (blot in ma) if ( blot.indexOf('Chg') >=0 ) ma[blot]='';
  AL=''; CellFont='c6'; pistonCols=''; prevDerivingMneYn='';
  aa=document.forms.FZ

// If auto-start from PISTON

  if ( typeof pistons[pkey] != udf ) {
    clearEm(0);
    document.forms.FZ['pistName'].value=pkey;
    document.forms.FZ['reportTitle'].value=pistons[pkey][0];
    document.forms.FZ['reportFootnote'].value=pistons[pkey][1];
    
    sortKey=pistons[pkey][2]?pistons[pkey][2]:'Towns';
    for (x=0; x < aa.sort1.length ; x++){
      if ( aa.sort1[x].value == sortKey ) { 
        document.forms.FZ.sort1[x].checked = true; break; 
      } ;
    };

    includeTownsA=pistons[pkey][3]; 
// if object, then this already is a list of towns - slide through.
    if ( typeof includeTownsA != 'object' ) {
      selectKey = includeTownsA;
      if ( typeof selectKey == 'number' ||
           '|DFGIJ|L8R12|Morris|'.indexOf('|'+selectKey+'|') >= 0
         ) { preSetTowns(selectKey); selectKey = 'Include' ; 
      } ;
    } else {
      for ( xt in includeTownsA) setTownChecks(xt);
      selectKey = 'Include' ; 
    };

    p4=pistons[pkey][4]
    for (argm=0; argm<p4.length; argm++ ) {
      p4word =  "ckbx"+p4[argm]
      if ( typeof aa[p4word] != udf ) document.forms.FZ[p4word].checked = true;
    };

  } else 

// end PISTON start. NORMAL start below.
  { document.forms.FZ['pistName'].value='NewName';
    sortKey=''; 
    for (x=0; x<aa.sort1.length; x++){
      if (aa.sort1[x].checked) {
        sortKey = aa.sort1[x].value ; 
        break;
      };
    };
    if (! sortKey ){
      if (prevsortKey) sortKey=prevsortKey ; else {
        alert('You must choose a sort key'); return;
      };
    }
    selectKey = pkey; includeTownsA='';
    if ( pkey == 'Alltowns' || pkey == 'Short' ) exportTownList=pkey;
  };

  prevsortKey=sortKey;
  if ( selectKey == 'Short' && rankNotPrintable(sortKey)  ) 
    selectKey=exportTownList='Alltowns'; 

// collect checked towns and make includeTownsA[] arrays
  if ( typeof includeTownsA != 'object' && selectKey == 'Include'){
    includeTownsA = new Array(); st=0;
    for (x=0;x< aa.length;x++){
      if ( aa[x].name.indexOf('Twn') <0 ) continue;
      if ( ! aa[x].checked ) { 
        continue ;
      };
      includeTownsA[aa[x].name.replace('Twn','')] = true;
    };
  };

// ranking and sorting of all checked sequences
  var outColPtr=0, outCols=new Array( 'Towns' ) ;
  for (x=0;x< aa.length;x++){
    aax=document.forms.FZ[x]
    if (aax.type != 'checkbox' ) continue
    ckbxName=aax.name.replace(/ckbx/,'')  // ckbxValPolice06 -> ValPolice06
                                         // ckbxPctChgValPolice -> PctChgValPolice
    if ( ckbxName == 'sort1' || ! ckbxName.indexOf('pist') || ! ckbxName.indexOf('Twn') || ckbxName.indexOf('Tog') >= 0 ) continue
    if ( ckbxName.indexOf('Val') <0  && ckbxName.indexOf('Rk') <0 && 
         ckbxName.indexOf('Pct') <0 && ckbxName.indexOf('Chg') <0 && ckbxName.indexOf('Avgg') <0 
       ) continue;
    if ( ! aax.checked ) continue;
    dotBaseMneYn=ckbxName.replace(/Val/,'').replace(/Rk/,''); // Police06 PctChgPolice
    yrF = extractYear(ckbxName).replace(/^0/,''); //octal thing // 6
    yR2=''; yR4='';if ( yrF != '' ) {yR4 = 2000 + parseInt(yrF);  yR2=Yr2(yrF) };
// alert(97+' '+dotBaseMneYn+' '+typeof isInput[dotBaseMneYn]+' '+dotBaseMneYn.indexOf('Suppress') )
    if ( typeof isInput[dotBaseMneYn] == udf ) { // Police06 PctChgPolice
// alert(99+' X '+dotBaseMneYn+' X '+yR2 )     
      derivedVals(stripYear(dotBaseMneYn,'sp101'),yR2,'s98') // Police, 06 
                                                      // PctChgPolice,''
    };
    if ( typeof ma[rankKey(dotBaseMneYn)] != 'object' ) { // RkPolice06 PctChgRkPolice
      basicRanking(dotBaseMneYn,'sp105') // Police, 06 
                                        // PctChgPolice,''
    };
// set outcols and hide columns flagged as Suppress
    pistonCols += ckbxName+', ' ;
    if (ckbxName.indexOf('Suppress')>=0) {
      ab=outCols; outCols=new Array( 'Towns' ); outColPtr=0;
      testName=ckbxName.replace('SuppressVal','')
      for (abx=1; abx<ab.length; abx++ ){
// alert(112+' '+testName+' '+ab[abx])      
        if ( ab[abx].indexOf(testName) == 0 ||
             ab[abx].indexOf('Rk'+testName) == 0) continue;
        outCols[++outColPtr] = ab[abx];
      };
      continue;
    };
    outCols[++outColPtr]=ckbxName.replace(/Val/,'');
  };
//  alert(119+' XX '+ckbxName+' '+pistonCols+' XX '+outCols)
  

  townsInOrder = new Array(); basicRanking(sortKey,'sp126');
  for (twn in ma['Towns'] ){
    townsInOrder[ QW(rankKey(sortKey),'',twn,'123') -1 ] = twn;
  };
  if ( typeof includeTownsA != 'object' && selectKey == 'Short'){
    LHTRank = QW(rankKey(sortKey),'','Long Hill','f642');
    LHTValue = QW(sortKey,'','Long Hill','f643');
    hiBreak = townsInOrder.length -5;
    exportTownList=selectKey;
  };

  if ( aa.BiggerFont.checked ) { CellFont='c8';  };
  if ( aa.BiggestFont.checked ) { CellFont='c10';  };
  
// Now all the rank and value  

// Boilerplate
  wholeGuts='<table align=center border=0 cellpadding=0 cellspacing=0>'+
   '<tr valign=bottom align=center>';

// Col Headings and Mesage[]. Mesage is declared in the DOM of the opener.  The child calls hintPop(), which looks for Mesage[] in the this.DOM, then also checks the opener.
  klor=-1; pinkBold=new Array(); colKlor=new Array();
  for ( z = 0; z < outCols.length; z++) {
  
    bMne = outCols[z]; nxtMne = ( typeof outCols[z+1] != udf )?outCols[z+1]:0
//alert(151+' '+z+' '+outCols[z]+' '+bMne)
    popWrap=popThings(bMne,'');
    pinkBold[z] = ( 
      bMne == rankKey(sortKey) ||
      ( bMne == sortKey && 
        ( nxtMne != rankKey(sortKey) || rankNotPrintable(sortKey) ) 
      )
    ) ;
    colKlor[z] = pinkBold[z]?'bgcolor=#ffc0c0':( (++klor%2)?'':'bgcolor=#c0ffc0')
    wholeGuts += '<td '+ colKlor[z] +' class='+CellFont+'>';
      wholeGuts += ( popWrap?'<a href="javascript:void(0)" onMouseover="overlibSetup();return HintPop(\''+bMne+'\',\'\',\'-450\')" onMouseOut="xnd()" class=h>':'' );

      yrF = extractYear(bMne).replace(/^0/,''); yr4=''; //octal thing
      if ( yrF ) yr4 = 2000 + parseInt(yrF);  
//alert(163+' '+bMne)
      mneKey = stripMne(bMne ,'sp165');
      CB3=CB[mneKey].split('|')[3].replace(/.*>/,'');
      CB4=CB[mneKey].split('|')[4]; if(!CB4) CB4=CB3;
      if ( bMne.indexOf('PctChgRk') >= 0 ) {
        colTitl = '% Change'+(CB4.replace(/<.*/,'').length >4?'<br>':' ')+CB4+'<br>SUBSTYRS<br>Rank';
      } else if ( bMne.indexOf('PctChg') >= 0 ) {
        colTitl = '% Change'+(CB4.replace(/<.*/,'').length >4?'<br>':' ')+CB4+'<br>SUBSTYRS';
      } else if ( bMne.indexOf('ChgRnk') >= 0 ) {
        colTitl = 'Change'+(CB4.replace(/<.*/,'').length >4?'<br>':' ')+CB4+'<br>Ranking<br>SUBSTYRS';
      } else if ( bMne.indexOf('ChgVl') >= 0 ) {
        colTitl = 'Change'+(CB4.replace(/<.*/,'').length >4?'<br>':' ')+CB4+'<br>Rank<br>SUBSTYRS';
      } else if ( bMne.indexOf('ChgVvl') >= 0 ) {
        colTitl = 'Change'+(CB4.replace(/<.*/,'').length >4?'<br>':' ')+CB4+'<br>SUBSTYRS';
      } else if ( bMne.indexOf('AvggRk') >= 0 ) {
        colTitl = 'Average'+(CB4.replace(/<.*/,'').length >4?'<br>':' ')+CB4+'<br>SUBSTYRS<br>Rank';
      } else if ( bMne.indexOf('Avgg') >= 0 ) {
        colTitl = 'Average'+(CB4.replace(/<.*/,'').length >4?'<br>':' ')+CB4+'<br>SUBSTYRS';
      } else if ( bMne.indexOf('Rk') >= 0 ) {
        colTitl = (yr4?yr4+(CB4.replace(/<.*/,'').length >4?'<br>':' '):'')+CB4+(CB4.replace(/.*>/,'').length >4?'<br>':' ')+'Rank';
      } else {
        colTitl = (yr4?yr4+(CB4.replace(/<.*/,'').length >4?'<br>':' '):'')+CB4;
      };
    wholeGuts += '<b>_'+colTitl.replace(/ /g,HS).replace('SUBSTYRS',yrRange[bMne.replace(/Rk/,'')])+'</b>'
    wholeGuts += popWrap?'</a>':'';
    wholeGuts += '</td>';
  }; // end colheads
  wholeGuts+='</tr>';
  wholeGuts+='<form name=childform>';

  doMorrisTest=( CB[stripMne(sortKey,'sp194')].split('|')[3].indexOf('Morris') >=0 )
  for (y=0; y < townsInOrder.length; y++){
    town = townsInOrder[y];
    if ( doMorrisTest && ! QW('isMorris','',town,'f122') ) continue;
    yValue = QW(sortKey,'',town,'f590');
    if ( selectKey == 'Short' && ! Quartile( y,town,yValue,hiBreak,LHTRank,LHTValue, 6 ) ) continue;
    if ( selectKey == 'Include' && typeof includeTownsA[town] == udf) continue;

// Now assemble the line
// alert(184+' '+outCols)
    wholeGuts+='<tr>';
    for ( z = 0; z < outCols.length; z++) {
      zbMne = outCols[z]; nxtzMne = ( typeof outCols[z+1] != udf )?outCols[z+1]:0

      Bold='';unBold='';popWrap=false;
// if(typeof ma[outCols[z]] == udf ) alert(190+' '+z+' '+outCols[z])
//alert(211+' '+z+' '+outCols[z]+' '+town)
      if ( (ma[outCols[z]][town]+'*').split('*')[1] ) {
        Mesage[zbMne+town] = (ma[zbMne][town]+'*').split('*')[1].replace(/'/g,"\\'");
        popWrap=popThings(zbMne+town,town);
      };
      if (town == 'Long Hill' || pinkBold[z] ) { Bold='<b>'; unBold='</b>'; } ;
      wholeGuts += '<td class='+CellFont+' '+colKlor[z]+' '+nAlign(outCols[z]) + ValignTopBot +'>';
      
      wholeGuts += popWrap?'<a href="javascript:void(0)" onMouseover="overlibSetup();return HintPop(\''+zbMne+town+'\',\'\')" onMouseOut="nd()" class="ht">':'';
      wholeGuts += Bold + ( z==0?PreDashes:'' );
      wholeGuts += '<nobr>'+( ( z > 0 || ! PreDashes )?'_':'' )+
        ( ''+Neat( zbMne, town ) ).replace(/ /g,HS)+'_</nobr>';
        wholeGuts += ( z==0?PostDashes:'' ) + unBold ;
        wholeGuts += (popWrap?'</a>':'');
      wholeGuts += '</td>';
    };
    wholeGuts+='</tr>' ;
  };
  
  wholeGuts += '</form></table>';
//alert(wholeGuts)
  aa=document.forms.FZ
  dotTitle=(aa['pistName'].value?aa['reportTitle'].value:childTitle[sortKey] ).replace('SUBSTYRS',yrRange[sortKey]);
  wholePop = '<html><head>'+
    '<title>'+dotTitle.replace(/<br>/g,' ')+'</title>'+
    '<script type="text/javascript">'+
      'isWeb='+isWeb+';'+'MenuItems='+MenuItems+';'+
      'WorkDir="'+WorkDir+'";'+'pixPath="'+pixPath+'";'+
    '</script>'+
    '<script type="text/javascript" src="'+NxPg('js/misc.js')+'"></script>'+
    '<link rel=stylesheet type="text/css" href="'+ NxPg('js/lhts.css') +'">'+
    '</head>'+
    '<body>'+
    '<div id="overDiv" style="position:absolute; visibility:hidden; z-index:1000;"></div><script type="text/javascript" src="js/overlib.js"></script>'+    
    '<div align="right"><form name="junk">'+
      '<input type="button" value = "Close" onclick="window.opener.focus(); window.close();">&nbsp;'+
      '<input type="button" value = "Don\'t lose this report" onclick="window.opener.focus()">'+
    '</form></div>'+
    '<table align=center border=0 cellpadding=10 cellspacing=0>'+
    '<tr><td align=center class="v16"><b>'+dotTitle+'</b></td></tr>'+
    '<tr><td align=left>'+
      ( wholeGuts.replace(/\<br\>/g,'_<br>_').replace(/_/g,HS) )+
    '</td></tr>'+
    (aa['reportFootnote'].value?'<tr><td align=left class='+CellFont+'>'+aa['reportFootnote'].value.replace(/_/g,HS)+'</td></tr>':'');
    
  wholePop += '</table></body></html>' ;
  reloadExport();
  
  ++reptCtr;
  NewWd('', 'rankChild'+reptCtr);
  setTimeout("WPop.document.write(wholePop); WPop.document.close();",1000)
  return;
};

function reloadExport(){
  if ( typeof document.forms.FZ['pistContent'] == udf ) return;
  aa=document.forms.FZ;
  if ( ! exportTownList ) {
    exportTownList=''; 
    for (x=0;x< aa.length;x++){
      if(aa[x].type == 'checkbox' && !aa[x].name.indexOf('Twn') && aa[x].checked) {
         exportTownList += aa[x].name.replace('Twn','')+',' ;
      };
    };
    exportTownList = exportTownList.replace(/,$/,'')
  };
  
  exportFootnote=''; tFoot=aa['reportFootnote'].value;
  for (qq=0; qq<tFoot.length; qq++){
    exportFootnote+= escape(tFoot.charAt(qq)) == '%0A'?' ':tFoot.charAt(qq);
  };
  
  document.forms.FZ['pistContent'].value=''+
    "pistStore('"+(aa['pistName'].value?aa['pistName'].value:'NAME')+"',\n"+
    "'"+aa['reportTitle'].value+"',\n"+
    "'"+exportFootnote.replace(/'/g,"\\'")+"',\n"+
    "'"+sortKey+"',\n"+
    ""+(typeof exportTownList == 'number'?exportTownList:"'"+exportTownList+"'")+",\n"+
    "'"+pistonCols.replace(/, $/,'')+"'\n"+
    ");";
};

function preSetTowns(arg){
  exportTownList=arg;
// INVERT the checkboxes
  if (arg == 'Invert') {
    document.forms.FZ['pistName'].value='NewName'; exportTownList='';
    for (x=0;x< document.forms.FZ.length;x++){
      if ( document.forms.FZ[x].type == 'checkbox' && 
           ! document.forms.FZ[x].name.indexOf('Twn') 
         ) {
           document.forms.FZ[x].checked = ! document.forms.FZ[x].checked;
         };
    };
    return;
  };
// CLEAR the checkboxes, then set new selection
  for (x=0;x< document.forms.FZ.length;x++){
    if ( document.forms.FZ[x].type == 'checkbox' && 
         ! document.forms.FZ[x].name.indexOf('Twn')
       ) document.forms.FZ[x].checked = false;
  };
  if (typeof arg == 'number') {
    setTownChecks('Long Hill','Berkeley Heights','Warren Twp','Bernards Twp','Harding','Chatham Twp');
    if (arg == 5 ) return;
    setTownChecks('New Providence','Watchung','Bernardsville','Mendham Twp','Morris Twp','Madison','Chatham Bor');
    return;
  };
  for (twn in ma['Towns'] ){
    if ( arg == "DFGIJ" && ( 'IJ'.indexOf(ma['DFG'][twn])>=0||twn=='Morris Twp') )
      setTownChecks(twn);
    if ( arg == "L8R12" && ma['SchType'][twn].split('*')[0] == 'L8R12') 
      setTownChecks(twn);
    if ( arg == "Morris" && ma['isMorris'][twn] == 1 ) setTownChecks(twn);
  };
};

function setTownChecks(){
  for (argm=0; argm<arguments.length; argm++ ) {
    if ( typeof document.forms.FZ['Twn'+arguments[argm]] != udf ) 
      document.forms.FZ['Twn'+arguments[argm]].checked = true;
  };
};

function Quartile(qtTownRank,qtNameTown,qtTownValue,hiBreak,LHTRank,LHTValue,six) {
  PostDashes = ''; PreDashes = ''; ValignTopBot = '';
  if ( Math.abs(qtTownRank+1-LHTRank) <= six ) return true;
// inserted to pick up all DFG=I
  if ( qtTownValue == LHTValue ) return true;
  if ( qtTownRank > 4 && qtTownRank < hiBreak ) return false;
  if ( qtTownRank == 4 ) {
    PostDashes = '<br>----------'; ValignTopBot = ' valign=top'; };
  if ( qtTownRank == hiBreak ) {
    PreDashes = '----------<br>' ; ValignTopBot = ' valign=bottom'; };
  return true;
};

function derivedVals(dotPrefMneBase,yr2arg,from){
  if( prevDerivingMneYn == dotPrefMneBase+yr2arg ) return false;
  prevDerivingMneYn = dotPrefMneBase+yr2arg;  // ValPolice07 PctChgPolice+''
  actionMneRootNoYr=dotPrefMneBase.replace(/^Val/,'').replace(/^Rk/,''); // Police PctChgPolice
  DvMneRootYr2=actionMneRootNoYr+yr2arg // Police07 PctChgPolice
  sTripped=stripMne(actionMneRootNoYr, 'sp352') // Police Police

  if ( ( actionMneRootNoYr.indexOf('Chg') >=0 || actionMneRootNoYr.indexOf('Avgg') >=0  ) && isTwoYears(sTripped) ) {
    deltaYrs = parseFloat(hiYr) - parseFloat(loYr);
// alert(337+' '+ actionMneRootNoYr+' '+deltaYrs+' '+loYr+' '+hiYr+' '+from )
    yrRange[actionMneRootNoYr.replace('Val','')]='20'+loYr+'-'+'20'+hiYr;
  } ;

  if (typeof ma[DvMneRootYr2] != 'object') ma[DvMneRootYr2]=new Array();

  if (actionMneRootNoYr.indexOf('PctChg') >=0 ) {
// Virginize multiyear derived each pass, in case range of years changes between runs
    ma[actionMneRootNoYr] = new Array();
    for (twn4_A in ma['Towns'] ){
// Reject if either data point is null or zero.  Meaningless (or illegal) ratio
      if( QW(sTripped,hiYr,twn4_A,322) && QW(sTripped,loYr,twn4_A,322) ) {
        ratio = QW(sTripped,hiYr,twn4_A,323)/QW(sTripped,loYr,twn4_A,323);
        annl=neatGuts('%.1',Math.pow( ratio,1/deltaYrs ) -1,'');
        ma[actionMneRootNoYr][twn4_A] = (ratio-1) +
          (deltaYrs>1?'*' +annl +' annualized over '+deltaYrs+' years.':'') ;
      } else ma[actionMneRootNoYr][twn4_A] ='' ;
    };
  } else

  if (actionMneRootNoYr.indexOf('ChgRnk') >=0 ) {
    Mesage['ChgRnk'+sTripped] = 'A positive number means the town moved up closer to the top of the list.'
    for (twn4_B in ma['Towns'] ){
      if( QW('Rk'+sTripped,hiYr,twn4_B,834) && QW('Rk'+sTripped,loYr,twn4_B,834) ) {
        ratio = QW('Rk'+sTripped,loYr,twn4_B,835) - QW('Rk'+sTripped,hiYr,twn4_B,835);
        ma['ChgRnk'+sTripped][twn4_B] = ratio;
      } else ma['ChgRnk'+sTripped][twn4_B] ='' ;
    };
  } else

  if (actionMneRootNoYr.indexOf('ChgVl') >=0 ) { // best places to live. Value IS a rank
    Mesage['ChgVl'+sTripped] = 'A positive number means the town moved up closer to the top of the list.'
    for (twn4_C in ma['Towns'] ){
      if( QW(sTripped,hiYr,twn4_C,834) && QW(sTripped,loYr,twn4_C,834) ) {
        ratio = QW(sTripped,loYr,twn4_C,835) - QW(sTripped,hiYr,twn4_C,835);
        ma['ChgVl'+sTripped][twn4_C] = ratio;
      } else ma['ChgVl'+sTripped][twn4_C] ='' ;
    };
  } else

  if (actionMneRootNoYr.indexOf('ChgVvl') >=0 ) { //Cnty/Sch/Muni tax as % of total taxes
//    Mesage['ChgVvl'+sTripped] = 'A positive number means the town moved up closer to the top of the list.'
    for (twn4_D in ma['Towns'] ){
      if( QW(sTripped,hiYr,twn4_D,834) && QW(sTripped,loYr,twn4_D,834) ) {
        ratio = QW(sTripped,hiYr,twn4_D,835) - QW(sTripped,loYr,twn4_D,835);
        ma['ChgVvl'+sTripped][twn4_D] = ratio;
      } else ma['ChgVvl'+sTripped][twn4_D] ='' ;
    };
  } else

  if (actionMneRootNoYr.indexOf('Avgg') >=0 ) { //Crime Rate
//alert(385+' '+actionMneRootNoYr+' , '+sTripped)
    ma[actionMneRootNoYr] = new Array();
    for (twn4_D in ma['Towns'] ){
      ma['Avgg'+sTripped][twn4_D]=0;
      for (yr=parseInt(loYr); yr<=parseInt(hiYr); yr++){
        yr2=Yr2(yr);
// alert(395+' '+twn4_D+' '+yr2+' '+QW('CrimeRate',yr2,twn4_D,395))
        ma['Avgg'+sTripped][twn4_D] += QW('CrimeRate',yr2,twn4_D,395); 
      };
//alert(397+' '+twn4_D+' '+QW('Avgg'+sTripped,'',twn4_D,404)+' '+(deltaYrs+1))
      ma['Avgg'+sTripped][twn4_D] = QW('Avgg'+sTripped,'',twn4_D,404)/(deltaYrs+1);
    };
  } else
  
  derivedValsSpecific(actionMneRootNoYr,yr2arg,346);
   
};

function QW(roW,yR,twN,src){
// if roW is a derived var, on the first pass through QW(), go to derivedVals() to create the ma[][twn] VALUES array for all towns (so they can be simply fetched on calls for subsequent towns.) 
  if ( typeof ma[roW+yR] == udf ) { // [Val|Rk]Police06 PctChgPolice
    if (yR == '') {
      yR = extractYear(roW);
//alert(427+' X '+roW+' X '+yR+' X '+twN+' X '+src )     
      roW = stripYear(roW,'sp431');
    };
    derivedVals(roW,yR,'from QW from '+src);
  };
  
  vaL=ma[roW+yR][twN];
  if( typeof vaL == 'number' ) return vaL;
// return non-numeric  
  if ( ('+Towns+SchType+DFG+').indexOf(roW) >0 ) return vaL.split('*')[0];
// If *Note, then strip note and return numeric
if( typeof vaL == udf ) alert(roW+' '+yR+' '+twN+' '+src)
  return parseFloat(vaL.split('*')[0])
};

function rankNotPrintable(arg){
  return '|DFG|SchType|MuniCode|Towns|'.indexOf('|'+arg+'|') >=0 ;
};

function deduceRankSequence(rMne){
  if (rMne.indexOf('Suppress')>=0) return;
  stripedMne=stripMne(rMne,'sp451');
  if( typeof CB[stripedMne] == udf ) {
    alert ('No CB[] for '+rMne);
    return;
  };
  AUD = (CB[stripedMne]+'|||||||').split('|')[8]; 
// override base sort  
  if( rMne.indexOf('PctChg')>=0 && stripedMne.indexOf('ax') >=0 ) AUD='U';
  if( rMne.indexOf('ChgVl')>=0 ) AUD='';
  if( rMne.indexOf('ChgVvl')>=0 ) AUD='U';
  return AUD;
};

function basicRanking(sKey, xln) {
// alert(438+' '+sKey+' '+xln)
  if (sKey.indexOf('Suppress')>=0) return;
  rkVals = new Array(); ord=0; rKey=rankKey(sKey);
  ma[rKey] = new Array();
  sAUD=deduceRankSequence(sKey);
// if the full name of the var includes 'Morris', then set up to do the Morris test  
  doMorrisTest=( CB[stripMne(sKey,'sp471<'+xln)].split('|')[3].indexOf('Morris') >=0 )
  for (stwn in ma['Towns'] ){
    ma[rKey][stwn]=''; // declare the cell
    if ( doMorrisTest && ! QW('isMorris','',stwn,'413') ) {
      ma[sKey][stwn] = "*Not Morris County";
      continue;
    };
    dotVal=QW(sKey,'',stwn,'417') ;
    rkVals[ord++] = ( typeof dotVal=='number'
        ? ( 50000000000.0001 + (sAUD=='U'?dotVal:-dotVal) )
        : dotVal ) +
      '|'+stwn;
  };
  rkVals.sort();
  for (xr=0;xr<rkVals.length;xr++) {
    ma[rKey][rkVals[xr].split('|')[1] ] = xr+1 ;
  };
  if ( sKey.indexOf('ChgRnk')>=0  && sAUD == 'U' ) {
    for (xr=0;xr<rkVals.length;xr++){
      ma[rKey][rkVals[xr].split('|')[1] ] = rkVals.length-xr ;
    };
  };
};

function nAlign(fMne){ 
  alignment='ZZ';
  if ( typeof CB[stripMne(fMne, 'sp497a')] != udf ) alignment = (CB[stripMne(fMne,'sp497b')]+'||||||||||||').split('|')[9] ;
  if ( fMne.indexOf('Rk') >= 0 ) alignment='C';
  if ( fMne.indexOf('ChgRnk') >= 0 ) alignment='C';
  if ( fMne.indexOf('ChgVl') >= 0 ) alignment='C';
//  if ( fMne.indexOf('PctChg') >= 0 ) alignment='C';

  if ( alignment == '' ) return 'align="right"';
  if ( alignment == 'R' ) return 'align="right"';
  if ( alignment == 'C' ) return 'align="center"';
  if ( alignment == 'L' ) return '';
};  

function Neat(fMne, fTwn ){
  if ( typeof ma[fMne] == udf ) return 'NA/m';
  if ( typeof ma[fMne][fTwn] == udf ) return 'NA/mt';
  rawVal = (ma[fMne][fTwn]+'*').split('*')[0];
  numVal = QW(fMne,'',fTwn,'f949');
  if ( ! rawVal ) return '-';
  if ( rawVal == 'Infinity' ) return '-';
  if ( fMne == 'Towns' ) return rawVal.replace('Troy Hills','TrHls');
  if ( fMne.indexOf('Rk') >= 0 ) {
    postOp='';
  } else if ( fMne.indexOf('ChgRnk') >= 0 ) {
    postOp='';
//  } else if ( fMne.indexOf('ChgVl') >= 0 ) {
//    postOp='';
  } else if ( fMne.indexOf('PctChg') >= 0 ) {
    postOp='%.1';
  } else {
    postOp = (CB[stripMne(fMne,'sp526')]+'|||||||||||').split('|')[10];
  };
  return neatGuts(postOp,numVal,rawVal);
};

function neatGuts(argOp,valIn,rawIn) {
  plusSign='';
  if ( argOp.indexOf('+') >= 0 ) { 
    if( valIn > 0 ) plusSign='+' ;
    argOp = argOp.replace('+','') ;
  };
  if ( argOp == ',' ) return Comma( Math.round( valIn ) ) ;
  if ( argOp == '$-,' && ! valIn ) return '-' ;
  if ( argOp == '$-,' ) return '$ '+Comma(  Math.round( valIn ) ) ;
  if ( argOp == '$,' ) return '$ '+Comma(  Math.round( valIn ) ) ;
  if ( argOp == '0' ) return ''+Math.round( valIn ) ;
  if ( argOp == '1' ) return MyRounder( valIn,1 ) ;
  if ( argOp == '2' ) return MyRounder( valIn,2 ) ;
  if ( argOp == '4' ) return MyRounder( valIn,4 ) ;
  if ( argOp == '$2' ) return '$ '+MyRounder( valIn,2 ) ;
  if ( argOp == '$1' ) return '$ '+MyRounder( valIn,1 ) ;
  if ( argOp == '%100' ) return plusSign+Math.round(valIn*100)+' %' ;
  if ( argOp == '%' ) return plusSign+valIn+' %' ;
  if ( argOp == '%.1' ) {
    raw = Math.round(valIn*1000)/10 ;
    return plusSign+raw+((raw == Math.round(valIn*100))?'.0':'') +' %' ;
  };
  if ( argOp == '%.2' ) {
    raw = Math.round(valIn*10000)/100 ;
    return plusSign+raw+((raw == Math.round(valIn*100))?'.00':'')+
      ((raw == Math.round(valIn*1000)/10)?'0':'')+' %' ;
  };
  return plusSign+rawIn;
};      

function Comma(arg) {
  d3 = 3; arg += ''; Len = arg.length; OutC = ''
  for ( c = Len-d3; c >=0; c-=d3 ) {
    OutC = arg.substr(c,d3)+ (OutC?','+OutC:'') ;
  };
  if ( d3+c ) OutC = arg.substr(0,d3+c)+ (OutC?','+OutC:'');
  return OutC;
};

function MyRounder(inNo,Dig){
// Builds the rounded number to Dig decimal places one char at a time - to keep it as a string var.
// If the output is ever allowed to get Numeric, then IE (only) will display 0.nnn vs NS displays .nnn which is desired.
  outTb = Math.round(inNo*Math.pow(10,Dig))/Math.pow(10,Dig);     // 12.34567 || 12.14
  if ( outTb >= 1 ) outNo = new String( Math.floor( outTb )+'.' ); else outNo = new String( '.' );  // 12. || 12.96
  outTb = Math.round( 1000000* (outTb - Math.floor( outTb ) ) ) / 1000000;   
     // .34567
  for (xd=1; xd<Dig; xd++) {
    outTb = outTb * 10;                     // 3.4567  4.567
    outNo = outNo + Math.floor( outTb );    // 12.3    12.34
    outTb = outTb - Math.floor( outTb )+.000001;    // .4567   .567
  };
  outTb = outTb * 10;                       //  5.67
  outNo = outNo + Math.round( outTb );      //  12.346
  return outNo;
};

