// 3    8      15            30   35   40        50        60                  80                  100
// -------------------------------------------------------------------------------------------------
// Project:  Wireless Data Lookup Chart
// Module:   Set
// -------------------------------------------------------------------------------------------------
// URL:      http://www.classaxe.com/wireless/data/set.js
// Filename: set.js                     Version:  1.0
// Date:     11/06/2001                 Author:   Martin Francis, David Thomas
// -------------------------------------------------------------------------------------------------

// ************************************
// * SET.constructor()                *
// ************************************
// Properties of SET objects:
//   SET.bands        [SPECIFIED] (Array of) Wavebands in format X:mmmm-nnnn (M or MHz)
//   SET.date          SPECIFIED  The year of release
//   SET.devices      [SPECIFIED] (Array of) Devices - alternatives are bounded by ()
//   SET.deviceCount   CALCULATE  count of devices not shown in brackets
//   SET.gram          SPECIFIED  Null, Ax (Auto x-speed) or Mx (Manual x-speed)
//   SET.gramDeck      SPECIFIED  Description of record deck if installed
//   SET.gramSpeed     EXTRACTED  Number of speeds on record deck
//   SET.gramType      EXTRACTED  "A", "M" or ""
//   SET.hasCL         CALCULATE  True if clock built in, false if not
//   SET.hasFM         CALCULATE  True if FM/VHF capable, false if not
//   SET.hasGram       CALCULATE  True if gramophone fitted, false if not
//   SET.hasTI         CALCULATE  True if has tuning eye, false if not
//   SET.icons         CALCULATE  Array of icons with padded spaces, but no trailing spaces
//   SET.IF            Specified  String containing IF frequency (or frequencies)
//   SET.isAC          CALCULATE  Boolean value for AC powered
//   SET.isBA          CALCULATE  Boolean value for Battery powered
//   SET.isCA          CALCULATE  Boolean value for Car powered
//   SET.isDC          CALCULATE  Boolean value for DC powered
//   SET.itemNo        CALCULATE  A record of the Index of this item (for sort)
//   SET.make          SPECIFIED  Manufacturer
//   SET.model         SPECIFIED  Model name(s) associated with set
//   SET.notes         SPECIFIED  Additional notes
//   SET.pic           SPECIFIED  Picture - if in a sequence: nnnnnnn(x).jpg where x is last
//   SET.power         SPECIFIED  Example: AC/DC:250V / B:90V+B:1V5 / Car:12V -ve earth
//   SET.price         CALCULATE  The price in metric
//   SET.price_psd     SPECIFIED  The price in £.s.d.
//   SET.references    SPECIFIED  String list of References
//   SET.referencesNo  CALCULATE  Number of references
//   SET.size          SPECIFIED  Size in inches: H,W,D
//   SET.serials       SPECIFIED  Serial numbers of any known examples of this set
//
// Methods of SET objects:
//   SET()                        Constructor class for object
//   SET.popup()                  Popup window with set details
//   SET.listDevices(device)      Returns html string of devices highlighted
//   SET.showSet(device)          Returns html set table entry for a set
//   SET.exportSet()              Returns JavaScript set array entry

function SET(make, model, references, date, price_psd, bands, IF, gram, devices, power, notes, deck, size, pic, serials) {
  this.itemNo=count.sets;
  this.make       = make;         this.model     = model;
  this.date       = date;         this.price_psd = price_psd;
  this.bands      = bands;        this.IF        = IF;
  this.gram       = gram;         this.devices   = devices;
  this.power      = power;        this.notes     = notes;
  this.gramDeck   = deck;         this.size      = size;
  this.pic        = pic;          this.serials   = serials;

  this.hasFM      = false;        this.hasGram = false;
  this.hasTI      = false;        this.hasCL   = false;
  this.isAC       = false;        this.isBA    = false;
  this.isCA       = false;        this.isDC    = false;
  this.gramSpeed  = "";           this.gramType= "";
  count.sets++;

// If not expanding references (like before an export)
// this.references = references ; count.setReferences+=references.split(",").length

// else:

  if (references) {
    if (references.split(",").length>0) {
      this.references =		references;
      this.referencesNo =	references.split(",").length;
      count.setReferences+=	this.referencesNo;
    }
  }
  else {
    this.references =		"";
    this.referencesNo =		"0";
  }


//---------------------------------------
// Get device statistics and log devices
//---------------------------------------
  if (!devices[0]) {					// If there are no devices for set,
    this.deviceCount=0;					// Set device count to zero
    count.setsNoDevices++;				// Add to stats
    this.devices=[];					// Clear the array
  }
  else if (typeof(devices[0])=="number") {		// Number of devices given, not the devices themselves.
    this.deviceCount=devices[0];			// Extract the number of devices given.
    count.setsNoDevices++;				// Total sets no devices
    this.devices=[];					// Clear the array.
  }
  else {
    var deviceCount=0;					// Temporary counter for device enumeration.
    var deviceName;					// Device name with brackets removed if a substitute.
    for (var i=0; i < this.devices.length; i++) {	// Loop through all devices for this set
      if (this.devices[i].charAt(0)!="(") {		// Device is NOT a substitute.
        deviceCount++;					// Count devices (no subs).
        deviceName=this.devices[i];			// Remember the name for later
        if (!top.Device[deviceName])			// If Device not in deviceName list
          Device[deviceName] = new DEVICE(deviceName,[],[],[],"","","","",0,0,"");
        Device[deviceName].count++;			// Increment devices's count
      }   
      else {						// This is a substitute
        deviceName=this.devices[i].replace(/\(|\)/g,"");// Remove brackets
        if (!top.Device[deviceName])			// If Device not in deviceName list
          Device[deviceName] = new DEVICE(deviceName,[],[],[],"","","","",0,0,"");
        Device[deviceName].countSubs++;			// Increment devices's subs count
      }							// Create new Device entry.

      // Don't add a set twice to list or chronology chart:
      if (Device[deviceName].set[Device[deviceName].set.length-1] != this.itemNo) {
        Device[deviceName].set[Device[deviceName].set.length]=this.itemNo // Add this set to end of list
        var year=parseInt(this.date);			// Read set date
        if (!isNaN(year)) {				// If we have a valid date
          if (!Device[deviceName].history[year])	// This is a new date for the device
            Device[deviceName].history[year]=1;		// Add new date to device chronology
          else
            Device[deviceName].history[year]++;		// Otherwise increment count for this date
        }
        else						// Date unknown for this device
          Device[deviceName].noDate++;			// So add it to the "don't knows"
      }
    }							// End of device loop
    
    this.deviceCount=deviceCount			// Remember total devices for set
    count.devices +=this.devices.length			// Add device count to stats
    count.devicesNoSubs+=deviceCount			// Add device subs count to stats
  }							// End of device checks
  if (this.pic)
    count.hasPIC++
  //---------------------------------------
  // Get set icons and features
  //---------------------------------------
  // These are loaded into an array BACKWARDS so that any training spacer images
  // can be left off - important because Netscape struggles if you have too many
  // images on a page at once.   The array is reversed before concatenation.

  var icons=new Array()					// Array to hold icons for listing
  var iconpad=false					// true when padding images needed
  var n=0						// Array counter

  // Gramophone:
  if (gram) {						// Does set have a gram?
    // 9th item on icon list is gram speed:
    if (this.gram.slice(1,2)) {				// Do we know how many speeds?
      this.gramSpeed=this.gram.slice(1,2);		// Yes, set gramSpeed=value
      icons[n++]="<small>"+this.gramSpeed+"</small>";	// Add to icons
    }
    // 8th item on list is gram type
    if (this.gram.slice(0,1)=="A") {			// Is gram auto?
      this.gramType="A";				// Yes, set gramType="A"
      count.hasAG++;					// Update stats
      icons[n++]=IMG_AG;				// Add AG to icons
      iconpad=true;					// Enable padding for further items
    }
    if (this.gram.slice(0,1)=="M") {			// Is gram manual?
      this.gramType="M";				// Yes, set gramType="M"
      count.hasMG++;					// Update stats
      icons[n++]=IMG_MG;				// Add MG to icons
      iconpad=true;					// Enable padding for further items
    }
  }							// Never pad last item

  // 7th item on list is Clock:
  if ((/clock/i).test(model)) {				// Does set have a clock?
    this.hasCL=true;					// Yes, set flag
    count.hasCL++;					// Update stats
    icons[n++]=IMG_CL;					// Add CL to icons
    iconpad=true;					// Enable padding for further items
  }
  else if (iconpad) {					// Else add gap to icons if padding
    icons[n++]=IMG_0CL;
  }

  // 6th item on list is Tuning Indicator:
  if (RegExpTI.test(this.devices.join())) {		// Does set have a tuning indicator?
    this.hasTI=true;					// Yes, set flag
    count.hasTI++;					// Update stats
    icons[n++]=IMG_TI;					// Add TI to icons
    iconpad=true;					// Enable padding for further items
  }
  else if (iconpad) {					// Else add gap to icons if padding
    icons[n++]=IMG_0TI;
  }

  // 5th item on list is FM Band:
  if ((/FM/).test(bands.join(""))) {			// Does set have FM?
    this.hasFM=true;					// Yes, set flag
    count.hasFM++;					// Update stats
    icons[n++]=IMG_FM;					// Add FM to icons
    iconpad=true;					// Enable padding for further items
  }
  else if (iconpad) {					// Else add gap to icons if padding
    icons[n++]=IMG_0FM;
  }

  // 4th-1st items are Power Supply:
  if (this.power=="") {					// Is power blank?
    count.setsNoPower++;				// Yes, update stats
    icons[n++]=IMG_0AC+IMG_0DC+IMG_0BA+IMG_0CA;}	// first icon = 1-4 padding
  else {						// Otherwise, test it

  // 4th item is Car Radio:
    if ((/Car:/).test(power)) {				// Is it a car radio?
      this.isCA=true;					// Yes, set flag
      count.setsCar++;					// Update stats
      icons[n++]=IMG_CA;				// Add CA to icons
      iconpad=true;					// Enable padding for further items
    }
    else if (iconpad) {					// Else add gap to icons if padding
      icons[n++]=IMG_0CA;
    }

  // 3rd item is Battery Powered:
    if ((/B:/).test(power)) {				// Is it battery powered?
      this.isBA=true;					// Yes, set flag
      count.setsB++;					// Update stats
      icons[n++]=IMG_BA;				// Add BA to icons
      iconpad=true;					// Enable padding for further items
    }
    else if (iconpad) {					// Else add gap to icons if padding
      icons[n++]=IMG_0BA;
    }

  // 2nd item is DC Powered:
    if ((/DC/).test(power)) {				// Is it DC powered?
      this.isDC=true;					// Yes, set flag
      count.setsDC++;					// Update stats
      icons[n++]=IMG_DC;				// Add DC to icons
      iconpad=true;					// Enable padding for further items
    }
    else if (iconpad) {					// Else add gap to icons if padding
      icons[n++]=IMG_0DC;
    }

  // 1st item is AC Powered:
    if ((/AC/).test(power)) {				// Is it AC powered?
      this.isAC=true;					// Yes, set flag
      count.setsAC++;					// Update stats
      icons[n++]=IMG_AC;				// Add AC to icons
    }
    else if (iconpad) {					// Else add gap to icons if padding
      icons[n++]=IMG_0AC;
    }
  }
  // Now we have array filled, reverse it and assign to object
  this.icons = icons.reverse().join("");


//---------------------------------------
// Convert price to metric for sorting
//---------------------------------------

//  var RegExpPSD =	/\£([0-9]+)\.([0-9]+)s\.([0-9]+)d/   // For splitting prices in £.s.d
//  var RegExpGN  =	/([0-9]+)GN/                         // For splitting prices in GN



// Acceptable variants:  "£21.0s.0d", "£21.0s.0d+T", "15GN","15GN+T"
  if (RegExpPSD.test(this.price_psd)) {
    var priceArray =	this.price_psd.match(RegExpPSD);
    this.price =	((priceArray[1]*240)+(priceArray[2]*20)+(priceArray[3]*1));
  }
  else if (RegExpGN.test(this.price_psd)) {
    var priceArray =	this.price_psd.match(RegExpGN);
    this.price =	(priceArray[1]*260);
  }
  else this.price =	0;
 

//---------------------------------------
// Check if manufacturer is in our list
//---------------------------------------
  if (!(RegExpMakers.test(this.make+"#"))) {		// If maker is new to our list, add it.
    makerArray[makerArray.length] = this.make+"#";	// Add new maker, with "#" as item delimiter
    RegExpMakers = new RegExp(makerArray.join("|"));	// Update regular expression
    count.makers++;					// Increment Makers count
  }
}




// ************************************
// * SET.popup()                      *
// ************************************
SET.prototype.popup =	function() {
  var width =		450;
  var height =		380;
  var RegExp_Dev =	/([^(),]+)/g;
  var devicesFind=	" &nbsp; <a href='javascript: "+
			"window.opener.search.allSets();"+
			"window.opener.search.document.criteria.device.value=\""+
			this.devices.join("+")+
			"\";window.opener.search.getSets();"+
			"this.close()'\">"+
			"<img src='but_find_similar.gif' width='53' height='14' align='bottom' "+
			"alt='Find other sets with these devices' border='0'></a>";

  var DevLink =		"<a class='a' href='javascript:void window.opener.Device[\"$1\"].popup()'>$1</a>";
  var devicesList =	this.devices.join().replace(RegExp_Dev,DevLink).replace(/,/g,", ")+devicesFind;

  Details =		window.open('','Details', 'width='+width+',height='+height+',resizable=1,menubar=0,location=0,scrollbars=1,toolbar=0');
  centerPopup(Details,width,height);
  var out =		new Array();
  var n =		0;
  out[n++] =	"<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Frameset//EN\">"
  out[n++] =	"<html>\n<head>\n";
  out[n++] =	"<META http-equiv=\"Content-Type\" content=\"text/html; charset=windows-1252 (Western Europe)\">"
  out[n++] =	"<title>British Wireless Details</title>\n";
  out[n++] =	"<STYLE TYPE='text/css'>\n";
  out[n++] =	"  input      { font-family: Arial, sans-serif; font-size: 8pt }\n";
  out[n++] =	"  table      { border-width: 2px ; border-color: Black}\n";
  out[n++] =	"  td.heading { font-size: 12pt; font-weight: bold;\n";
  out[n++] =	"               text-align: center; padding-left: 6px; padding-right: 6px;\n";
  out[n++] =	"               border-top-width: 1px; border-bottom-width: 1px; border-style: solid }\n";
  out[n++] =	"  td.r       { text-align: right}\n";
  out[n++] =	"  td.spacer  { border-top-width: 1px}\n";
  out[n++] =	"  td.category{ font-size: 9pt; font-weight: bold; text-align: left;padding-left: 6px}\n";
  out[n++] =	"  td.graph   { padding-left: 0; padding-right: 0;}\n";
  out[n++] =	"  td         { background-color: rgb(255,255,200); font-family: Arial; font-size: 8pt;\n";
  out[n++] =	"               vertical-align: top; text-align: 'left'; border-bottom-width:0; border-top-width: 0;\n";
  out[n++] =	"               border-left-width: 0;border-right-width: 0; padding-top: 0;padding-bottom: 0;\n";
  out[n++] =	"               padding-left: 6px; padding-right:6px; border-style: solid; border-color: Black;}\n";
  out[n++] =	"</STYLE>\n</head>\n\n";
  out[n++] =	"<body BGCOLOR='#e0ffe0' background='wallpaper.gif' topmargin='5'>\n";
  out[n++] =	"<table border='1' cellspacing='0' cellpadding='1' width='400'>\n";
  out[n++] =	"  <tr><td class='heading' colspan='3'><u>Set Details</u></td></tr>\n";
  out[n++] =	"  <tr><td class='category' colspan='2'>Make:</td>\n";
  out[n++] =	"      <td>"+this.make+"</td></tr>\n";
  out[n++] =	"  <tr><td class='category' colspan='2'>Model:</td>\n";
  out[n++] =	"      <td>"+this.model+"</td></tr>\n";

  if (this.icons) {
    out[n++] =	"  <tr><td class='category' colspan='2'><b>Features:</b></td>\n";
    out[n++] =	"      <td>"+this.icons.replace(/<IMG SRC='spacer.gif'[^>]+>/g,"")+"</td></tr>\n";
  }

  if (this.date) {
    out[n++] =	"  <tr><td class='category' colspan='2'><b>Date:</b></td>\n";
    out[n++] =	"      <td>"+this.date+"</td></tr>\n";
  }

  if (this.price_psd) {
    out[n++] =		"  <tr><td class='category' colspan='2'><b>Price:</b></td>\n";
    var decimal =	Math.round(this.price*100/240)/100;
    var pounds =	parseInt(decimal);
    var pence =		pad(Math.round((decimal-pounds)*100),2);
    out[n++] =		"      <td>"+this.price_psd+"<br>(Metric equivalent: £"+pounds+"."+pence;
    if (this.price_psd.match(/\+T/)) {
      out[n++] =	" excluding tax.";
    }
    out[n++] =		")</td></tr>\n";
  }

  if (this.size) {
    var size_h=parseFloat(this.size)
    var size_w=parseFloat(this.size.substr(this.size.indexOf("x")+1))
    var size_d=parseFloat(this.size.substr(this.size.lastIndexOf("x")+1))
    if (this.size.match("in")!=null) {
      var size_h_in=size_h; var size_w_in=size_w; var size_d_in=size_d
      var size_h_cm=Math.round(size_h*25.4)/10		// Convert Height
      var size_w_cm=Math.round(size_w*25.4)/10		// Convert Width
      var size_d_cm=Math.round(size_d*25.4)/10		// Convert Width
    }
    else {
      var size_h_cm=size_h; var size_w_cm=size_w; var size_d_cm=size_d
      var size_h_in=Math.round(size_h/0.254)/10		// Convert Height
      var size_w_in=Math.round(size_w/0.254)/10		// Convert Width
      var size_d_in=Math.round(size_d/0.254)/10		// Convert Width
    }
    out[n++] =		"  <tr><td class='category' colspan='2'><b>Size:</b></td>\n";
    out[n++] =		"  <td>"+size_h_cm+"x"+size_w_cm+"x"+size_d_cm+"cm / ";
    out[n++] =		size_h_in+"x"+size_w_in+"x"+size_d_in+" inches (H,W,D).</td></tr>\n"
  }

  if (this.pic) {
    if ((/\([0-9]\)/).test(this.pic)) {
      var pic_qty=parseInt(this.pic.match(/\([0-9]\)/).join().replace(/\(|\)/g,""));
    }
    else {
      var pic_qty=1;
    }
    out[n++] =		"  <tr><td class='category' colspan='2'><b>Photograph:</b><br><small><i>(Click to enlarge)</i></small></td>\n      <td>"
    if (pic_qty==1) {
      out[n++] =	"<a href='../sets/"+this.pic+"' target='new'><img src='../sets_thm/"+this.pic+"' border='0'></a>";
    }
    else {
      var pic =		this.pic.match(/[^\(]+/).join();
      for (var i=1; i<=pic_qty; i++) {
        out[n++] =	"<a href='../sets/"+pic+"("+i+").jpg' target='new'><img src='../sets_thm/"+pic+"("+i+").jpg' border='0'></a> ";
      }
    }
    out[n++] =		"</td></tr>\n";
  }

  if (this.serials) {
    out[n++] =		"  <tr><td class='category' colspan='2'><b>Known Serial(s):</b></td>\n";
    out[n++] =		"      <td>"+this.serials+"</td></tr>\n";
  }

  if (this.references) {
    out[n++] =		"  <tr><td class='spacer' colspan='3'><img src='spacer.gif' height='1'></td>\n";
    out[n++] =		"  <tr><td class='category' colspan='2'>References:</td>\n";
    out[n++] =		"      <td>"+this.references+" &nbsp; ";
    out[n++] =		"<a href='javascript:void window.opener.references();'>";
    out[n++] =		"<img src='but_references_2.gif' width='53' height='14' ";
    out[n++] =		"alt='Decode the reference codes given' border='0'></a>";
    out[n++] =		"</td></tr>\n";
  }

  if (this.bands.length) {
    out[n++] =		"  <tr><td class='spacer' colspan='3'><img src='spacer.gif' height='1'></td>\n";
    out[n++] =		"  <tr><td class='category' colspan='2'>Wavebands:</td>\n";
    out[n++] =		"      <td>"+this.bands.join('<br>')+"</td></tr>\n";
  }

  if (this.IF) {
    out[n++] =		"  <tr><td class='spacer' colspan='3'><img src='spacer.gif' height='1'></td>\n";
    out[n++] =		"  <tr><td class='category' colspan='2'>IF Freq:</td>\n";
    out[n++] =		"      <td>"+this.IF+"</td></tr>\n";
  }

  if (this.gramType) {
    out[n++] =		"  <tr><td class='spacer' colspan='3'><img src='spacer.gif' height='1'></td>\n";
    out[n++] =		"  <tr><td class='category' colspan='2'>Gramophone:</td>\n";
    out[n++] =		"      <td>";
    if (this.gramType=="A") {
      out[n++] =	"Auto Radio Gram";
    }
    if (this.gramType=="M") {
      out[n++] =	"Manual Radio Gram";
    }
    if (this.gramSpeed) {
      out[n++] =	" ("+this.gramSpeed+" speed)";
    }
    if (this.deck) {
      out[n++] =	"<br>Deck: "+this.gramDeck;
    }
    out[n++] =		"</td></tr>\n";
  }

  if (this.devices) {
    out[n++] =		"  <tr><td class='spacer' colspan='3'><img src='spacer.gif' height='1'></td>\n";
    out[n++] =		"  <tr><td class='category' colspan='2'><b>Devices:</b></td>\n";
    out[n++] =		"      <td>"+devicesList+"</td></tr>\n";
  }

  if (this.hasTI) {
    var TIString=this.devices.join("").match(RegExpTI);
    out[n++] =		"  <tr><td class='category' colspan='2'>Tuning Eye:</td>\n";
    out[n++] =		"      <td>"+TIString+"</td></tr>\n";
  }

  if (this.power) {
    out[n++] =		"  <tr><td class='category' colspan='2'><b>Power:</b></td>\n";
    out[n++] =		"      <td>"+this.power+"</td></tr>\n";
  }

  out[n++] =		"  <tr><td class='spacer' colspan='3'><img src='spacer.gif' height='1'></td>\n";

  if (this.notes) {
    out[n++] =		"  <tr><td class='category' colspan='2'><b>Notes:</b></td>\n";
    out[n++] =		"      <td>"+this.notes+"</td></tr>\n";
  }

  out[n++] =		"  <tr><td class='heading' colspan='3'><img src='spacer.gif' height='3'><br>\n";
  out[n++] =		"        <a href='javascript:window.close()'><img\n";
  out[n++] =		"         src='but_close.gif' width='40' height='21' border='0' alt='Close'></a>\n";
  out[n++] =		"      </td></tr>\n";
  out[n++] =		"</table>\n";
  out[n++] =		"</body>\n</html>";
  Details.focus();
  Details.document.write(out.join(""));
  Details.document.close();
}
               

// ********************
// * Set Devices List *
// ********************
SET.prototype.listDevices = function(device) {
  var RegExp_Dev =	/([^(),]+)/g;
  var DevLink =		"<a class='a' href='javascript:top.Device[\"$1\"].popup()'>$1</a>";

  var devicesList =	this.devices.join().replace(RegExp_Dev,DevLink).replace(/,/g,", ");
  if (devicesList=="") {
    devicesList =	"&nbsp;";
  }
  if (device != "") {
    devicesList =	devicesList.replace(RegExpDeviceHtmlMatch,"\>\<b\>\<font color='#ff2020'\>$1\<\/font\>\<\/b\>\<");
  }
  return devicesList;
}


// ************************************
// * setColumns()                     *
// ************************************
function setColumns(columns) {
  var cols = new Object();
  cols["make"] =	"\\n  <TD class='a'>\"+this.make+\"</TD>";
  cols["model"] =	"\\n  <TD class='b'><a href='javascript:top.Item[\"+this.itemNo+\"].popup()\'>\"+this.model+\"</a></TD>";
  cols["date"] =	"\\n  <TD class='b'>\"+(this.date		? '<nobr>'+this.date+'</nobr>':	'&nbsp;')+\"</TD>";
  cols["refs"] =	"\\n  <TD class='b'>\"+(this.references		? this.references:	'&nbsp;')+\"</TD>";
  cols["refNo"] =	"\\n  <TD class='b'>\"+(this.referencesNo	? this.referencesNo:	'&nbsp;')+\"</TD>";
  cols["price"] =	"\\n  <TD class='b'>\"+(this.price_psd		? this.price_psd:	'&nbsp;')+\"</TD>";
  cols["bands"] =	"\\n  <TD class='b'>\"+(this.bands.length	? this.bands.join(', '):'&nbsp;')+\"</TD>";
  cols["bandNo"] =	"\\n  <TD class='c'>\"+(this.bands.length	? this.bands.length:	'&nbsp;')+\"</TD>";
  cols["IF"] =		"\\n  <TD class='b'>\"+(this.IF			? this.IF:		'&nbsp;')+\"</TD>";
  cols["devices"] =	"\\n  <TD class='b'>\"+(this.listDevices(device))+\"</TD>";
  cols["deviceNo"] =	"\\n  <TD class='i'>\"+(this.deviceCount	? this.deviceCount:	'&nbsp;')+\"</TD>";
  cols["power"] =	"\\n  <TD class='i'>\"+(this.power		? this.power:		'&nbsp;')+\"</TD>";
  cols["notes"] =	"\\n  <TD class='b'>\"+(this.notes		? this.notes:		'&nbsp;')+\"</TD>";
  cols["deck"] =	"\\n  <TD class='b'>\"+(this.gramDeck		? this.gramDeck:	'&nbsp;')+\"</TD>";
  cols["size"] =	"\\n  <TD class='b'>\"+(this.size		? this.size:		'&nbsp;')+\"</TD>";
  cols["serials"] =	"\\n  <TD class='b'>\"+(this.serials		? this.serials:		'&nbsp;')+\"</TD>";
  cols["icons"] =	"\\n  <TD class='z'><nobr>\"+this.icons+\"</nobr></TD>";
  cols["pic"] =		"\\n  <TD class='b'>\"+(this.pic		? '<a target=blank href=../sets/'+this.pic+'>'+IMG_PIC+'</a>':'&nbsp;')+\"</TD>";

  SET.prototype.showSet = new Function("device","return \""+
     "\\n<TR>"+
     (columns.match(/make/)		? cols.make:"")+
     (columns.match(/model/)		? cols.model:"")+
     (columns.match(/date/)		? cols.date:"")+
     (columns.match(/refs/)		? cols.refs:"")+
     (columns.match(/refNo/)		? cols.refNo:"")+
     (columns.match(/price/)		? cols.price:"")+
     (columns.match(/bands/)		? cols.bands:"")+
     (columns.match(/bandNo/)		? cols.bandNo:"")+
     (columns.match(/IF/)		? cols.IF:"")+
     (columns.match(/devices/)		? cols.devices:"")+
     (columns.match(/deviceNo/)		? cols.deviceNo:"")+
     (columns.match(/power/)		? cols.power:"")+
     (columns.match(/notes/)		? cols.notes:"")+
     (columns.match(/deck/)		? cols.deck:"")+
     (columns.match(/size/)		? cols.size:"")+
     (columns.match(/serials/)		? cols.serials:"")+
     (columns.match(/icons/)		? cols.icons:"")+
     (columns.match(/pic/)		? cols.pic:"")+
     "\\n</TR>\"");
  selectedColumns = columns;
}

setColumns(selectedColumns);


// ************************************
// * listSetsTop()                    *
// ************************************
// Operation:
// 1) Create and write out[n] array containing search details as html
// 2) Write headings for table
// ----------------------------------------------------------------

function listSetsTop(chosenMaker,chosenModel,chosenDevice,chosenGram,chosenFM,chosenTI,chosenPower,chosenCL) {
  var sortMsg =	"onmouseover='window.status=\"Sort by this column\"; return true' onmouseout='window.status=\"\"; return true'"
  var sortCall ='top.sortSets("'+chosenMaker+'","'+chosenModel+'","'+chosenDevice+'","'+chosenGram+'","'+chosenFM+'","'+chosenTI+'","'+chosenPower+'","'+chosenCL+'")';

  var out =	new Array();
  var n =	0;
  out[n++] =	"<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Frameset//EN\">"
  out[n++] =	"<html>\n<head>\n";
  out[n++] =	"<META http-equiv=\"Content-Type\" content=\"text/html; charset=windows-1252 (Western Europe)\">"
  out[n++] =	"<title>Results for List Radios</title>\n\n";
  out[n++] =	"<map name='key'>";
  out[n++] =	"<area shape='rect' coords='0,1,12,70'    href='javascript:void top.sortingSets(\"AC mains sets first.<br>\",top.setsByAC);"+sortCall+"'>";
  out[n++] =	"<area shape='rect' coords='13,1,25,70'   href='javascript:void top.sortingSets(\"DC mains sets first.<br>\",top.setsByDC);"+sortCall+"'>";
  out[n++] =	"<area shape='rect' coords='26,1,47,70'   href='javascript:void top.sortingSets(\"Battery sets first.<br>\",top.setsByBA);"+sortCall+"'>";
  out[n++] =	"<area shape='rect' coords='48,1,66,70'   href='javascript:void top.sortingSets(\"Car Radios first.<br>\",top.setsByCA);"+sortCall+"'>";
  out[n++] =	"<area shape='rect' coords='67,1,79,70'   href='javascript:void top.sortingSets(\"FM \/ VHF sets first.<br>\",top.setsByFM);"+sortCall+"'>";
  out[n++] =	"<area shape='rect' coords='80,1,92,70'   href='javascript:void top.sortingSets(\"Tuning Eye sets first.<br>\",top.setsByTI);"+sortCall+"'>";
  out[n++] =	"<area shape='rect' coords='93,1,105,70'  href='javascript:void top.sortingSets(\"Clock Radios first.<br>\",top.setsByCL);"+sortCall+"'>";
  out[n++] =	"<area shape='rect' coords='106,1,129,70' href='javascript:void top.sortingSets(\"Gram Type \/ Speed.<br>\",top.setsByGR);"+sortCall+"'>";
  out[n++] =	"</map>";
  out[n++] =	"<STYLE TYPE='text/css'>\n";
  out[n++] =	"  BODY { font-family: Arial, sans-serif;font-size: 12pt}\n";
  out[n++] =	"  a.a  { text-decoration: none;color: rgb(0,0,0) }\n";
  out[n++] =	"  th.s { background-color: rgb(192,192,192);border-left: 1px solid rgb(255,255,255);\n";
  out[n++] =	"         border-right: 1px solid rgb(128,128,128);border-top: 1px solid rgb(255,255,255);\n";
  out[n++] =	"         border-bottom: 1px solid rgb(128,128,128); }\n";
  out[n++] =	"  th   { font-family: Arial;font-size: 10pt;padding-left: 1px;padding-right:1px;\n";
  out[n++] =	"         background-color: rgb(255,255,200);border-style: solid;border-bottom-width: 1px;\n";
  out[n++] =	"         border-top-width: 1;}\n";
  out[n++] =	"  td.a { text-align: left; font-weight: bold; border-left-width: 1px}\n";
  out[n++] =	"  td.b { text-align: left}\n";
  out[n++] =	"  td.c { text-align: center}\n";
  out[n++] =	"  td.i { text-align: left;font-style: italic;color:  rgb(104,51,51)}\n";
  out[n++] =	"  td.z { text-align: left; border-right-width: 1px; border-left-width:1px;}\n";
  out[n++] =	"  td   { vertical-align: top;border-left-width: 0;border-right-width: 0;font-family: Arial;\n";
  out[n++] =	"         font-size: 8pt; padding-left: 1px;padding-right:1px;background-color: rgb(255,255,200);\n";
  out[n++] =	"         border-style: solid;border-bottom-width: 1px;border-top-width: 0;}\n";
  out[n++] =	"</STYLE>\n</head>\n\n";

  out[n++] =	"<body onload='top.window.status=\";Radio list complete.\";return true'";
  out[n++] =	"background='wallpaper.gif'>\n";
  out[n++] =	"<p><font color='#797900'><big><b><u>British Wireless Database</u></b><br>";
  out[n++] =	"Results for List Radios:</big></font><br><font color='#ff0000'><small>\n";

  if (chosenMaker != "(ALL)")	out[n++] = "<b>Maker:</b> "+chosenMaker+"<br>";
  if (chosenModel)		out[n++] = "<b>Model:</b> "+chosenModel+"<br>";
  if (chosenDevice)		out[n++] = "<b>Device:</b> "+chosenDevice+"<br>";
  if (chosenPower) {
    out[n++] =			"<b>Power type:</b> ";
    if (chosenPower=="AC")	out[n++] = "AC Mains";
    if (chosenPower=="DC")	out[n++] = "DC Mains";
    if (chosenPower=="B:")	out[n++] = "Battery";
    if (chosenPower=="Car:")	out[n++] = "Car";
    out[n++]="<br>";
  }
  if (chosenFM != "-")		out[n++] ="<b>FM Band:</b> "+chosenFM+"<br>";
  if (chosenGram != "-")	out[n++]="<b>Gramophone:</b> "+chosenGram+"<br>";
  if (chosenTI != "-")		out[n++]="<b>Tuning Indicator:</b> "+chosenTI+"<br>";
  if (chosenCL != "-")		out[n++]="<b>Built-in Clock:</b> "+chosenCL+"<br>";

  out[n++] =		"</small></font>\n<p align='center'><TABLE border='1' cellpadding='0' cellspacing='0' >";
  out[n++] =		"\n  <TR>";
  if (selectedColumns.match(/make/))
    out[n++] =		"\n    <TH class='s' valign='bottom'><a "+sortMsg+" href='javascript:void top.sortingSets(\"Maker.\",top.setsByMake);"+sortCall+"'>Make:</a></TH>";
  if (selectedColumns.match(/model/))
    out[n++] =		"\n    <TH class='s' valign='bottom'><a "+sortMsg+" href='javascript:void top.sortingSets(\"Model.\",top.setsByModel);"+sortCall+"'>Model:</a></TH>";
  if (selectedColumns.match(/date/))
    out[n++] =		"\n    <TH class='s' valign='bottom'><a "+sortMsg+" href='javascript:void top.sortingSets(\"Date.\",top.setsByDate);"+sortCall+"'>Date:</a></TH>";
  if (selectedColumns.match(/refs/))
    out[n++] =		"\n    <TH class='s' valign='bottom'>References:</TH>";
  if (selectedColumns.match(/refNo/))
    out[n++] =		"\n    <TH class='s' valign='bottom'><a "+sortMsg+" href='javascript:void top.sortingSets(\"References.\",top.setsByRefNo);"+sortCall+"'>Refs:</a></TH>";
  if (selectedColumns.match(/price/))
    out[n++] =		"\n    <TH class='s' valign='bottom'><a "+sortMsg+" href='javascript:void top.sortingSets(\"Price.\",top.setsByPrice);"+sortCall+"'>Price:</a></TH>";
  if (selectedColumns.match(/bands/))
    out[n++] =		"\n    <TH class='s' valign='bottom'>Waveband<br>Coverage:</TH>";
  if (selectedColumns.match(/bandNo/))
    out[n++] =		"\n    <TH class='s' valign='bottom'><a "+sortMsg+" href='javascript:void top.sortingSets(\"Wavebands.\",top.setsByBands);"+sortCall+"'><IMG SRC='bands.gif' WIDTH='12' HEIGHT='43' BORDER='0' ALT='Bands:'></TH>";
  if (selectedColumns.match(/IF/))
    out[n++] =		"\n    <TH class='s' valign='bottom'><a "+sortMsg+" href='javascript:void top.sortingSets(\"IF.\",top.setsByIF);"+sortCall+"'>IF:</TH>";
  if (selectedColumns.match(/devices/)) {
    out[n++] =		"\n    <TH class='s' valign='bottom'>Devices (click for details)";
    if (chosenDevice) {
      out[n++] =	"<small><br>Exact references to <u>"+chosenDevice+"</u> are <font color='#ff0000'><u>highlighted</u></font>.</small>";
    }
  }
  if (selectedColumns.match(/deviceNo/))
    out[n++] =		"</TH>\n    <TH class='s' valign='bottom'><a "+sortMsg+" href='javascript:void top.sortingSets(\"Number of Devices\",top.setsByDeviceCount);"+sortCall+"'><IMG SRC='devices.gif' WIDTH='12' HEIGHT='80' BORDER='0' ALT='Number of Devices:'></a>";
  if (selectedColumns.match(/power/))
    out[n++] =		"</TH>\n    <TH class='s' valign='bottom'>Power:";
  if (selectedColumns.match(/notes/))
    out[n++] =		"</TH>\n    <TH class='s' valign='bottom'><a "+sortMsg+" href='javascript:void top.sortingSets(\"Notes\",top.setsByNotes);"+sortCall+"'>Notes:</a>";
  if (selectedColumns.match(/deck/))
    out[n++] =		"</TH>\n    <TH class='s' valign='bottom'><a "+sortMsg+" href='javascript:void top.sortingSets(\"Record Deck\",top.setsByDeck);"+sortCall+"'>Record Deck:</a>";
  if (selectedColumns.match(/size/))
    out[n++] =		"</TH>\n    <TH class='s' valign='bottom'>Size (H,W,D inches):";
  if (selectedColumns.match(/serials/))
    out[n++] =		"</TH>\n    <TH class='s' valign='bottom'><a "+sortMsg+" href='javascript:void top.sortingSets(\"Serial Numbers<br>\",top.setsBySerials);"+sortCall+"'>Serial(s)</a>";
  if (selectedColumns.match(/icons/))
    out[n++] =		"\n    <TH class='s' valign='bottom'><IMG src='key.gif' "+sortMsg+" usemap='#key' border='0' width='130' height='70' alt='Sort by this column'></TH>";
  if (selectedColumns.match(/pic/))
    out[n++] =		"\n    <TH class='s' valign='bottom'><a "+sortMsg+" href='javascript:void top.sortingSets(\"Sets with Picture.\",top.setsByPic);"+sortCall+"'>"+IMG_PIC+"</a></TH>";
  out[n++] =		"\n  </TR>"

  return out.join("");
}


// ************************************
// * setQuery()                       *
// ************************************
function setQuery(chosenMaker,chosenModel,chosenDevice,chosenGram,chosenFM,chosenTI,chosenPower,chosenCL) {
  var Query =		new Object();
  Query["make"] =	"if (chosenMaker==Item[setNumber].make)\n";
  Query["model"] =	"if (RegExpModel.test(Item[setNumber].model))\n";
  Query["power"] =	"if (RegExpPower.test(Item[setNumber].power))\n";
  Query["FM_Yes"] =	"if (Item[setNumber].hasFM)\n";
  Query["FM_No"] =	"if (!Item[setNumber].hasFM)\n";
  Query["Gram_Yes"] =	"if (Item[setNumber].gramType!=\"\")\n";
  Query["Gram_No"] =	"if (Item[setNumber].gramType==\"\")\n";
  Query["TI_Yes"] =	"if (Item[setNumber].hasTI)\n";
  Query["TI_No"] =	"if (!Item[setNumber].hasTI)\n";
  Query["CL_Yes"] =	"if (Item[setNumber].hasCL)\n";
  Query["CL_No"] =	"if (!Item[setNumber].hasCL)\n";
  Query["PIC_Yes"] =	"if (Item[setNumber].pic!=\"\")\n";
  Query["Device"] =	"if (RegExpDevice.test(Item[setNumber].devices))\n";
  Query["DeviceAnd"] =	"if (RegExpDevice.test(Item[setNumber].devices.join().split(\",\").sort().join()))\n";

  QUERY=new Function("chosenMaker","chosenModel","chosenDevice","chosenGram","chosenFM","chosenTI",
            "chosenPower","chosenCL","number","for (var setNumber=0; setNumber < number; setNumber++)\n"+
//     Query.PIC_Yes+
     (chosenMaker!="(ALL)"            ? Query.make:"")+
     (chosenModel!=""                 ? Query.model:"")+
     (chosenPower!=""                 ? Query.power:"")+
     (chosenFM=="Y"                   ? Query.FM_Yes:"")+
     (chosenFM=="N"                   ? Query.FM_No:"")+
     (chosenGram=="Y"                 ? Query.Gram_Yes:"")+
     (chosenGram=="N"                 ? Query.Gram_No:"")+
     (chosenTI=="Y"                   ? Query.TI_Yes:"")+
     (chosenTI=="N"                   ? Query.TI_No:"")+
     (chosenCL=="Y"                   ? Query.CL_Yes:"")+
     (chosenCL=="N"                   ? Query.CL_No:"")+
     (chosenDevice!=""&&chosenDevice.match(/\+/)==null ? Query.Device:"")+
     (chosenDevice!=""&&chosenDevice.match(/\+/)!=null ? Query.DeviceAnd:"")+
     "{ ItemsMatched[ItemsMatched.length]=Item[setNumber];\n"+
     "  out[l++]=Item[setNumber].showSet(chosenDevice); }\n");
}



// ************************************
// * listSets()                       *
// ************************************
function listSets(chosenMaker,chosenModel,chosenDevice,chosenGram,chosenFM,chosenTI,chosenPower,chosenCL) {
  var timeStart = new Date();				// For timing of search routine
  out = new Array();					// Holds entire output string in chunks joined later
  l = 0;						// Don't use n here as index
  ItemsMatched =	new Array();			// Create an array to hold the matched records
  var chosenDeviceMod =	buildRegExp(chosenDevice);
  RegExpDevice =	new RegExp(chosenDeviceMod,"i");
  if (chosenDevice) {
    RegExpDeviceHtmlMatch = new RegExp(">\("+chosenDeviceMod.replace(/\.\+/g,"|")+"\)<","ig");
    // Thanks to David Thomas, 15 May 2001
  }
  RegExpModel =		new RegExp(buildRegExp(chosenModel),"i");
  RegExpPower =		new RegExp(chosenPower,"i");

  out[l++] =		listSetsTop(chosenMaker,chosenModel,chosenDevice,chosenGram,chosenFM,chosenTI,chosenPower,chosenCL);
  setQuery(chosenMaker,chosenModel,chosenDevice,chosenGram,chosenFM,chosenTI,chosenPower,chosenCL)
  QUERY(chosenMaker,chosenModel,chosenDevice,chosenGram,chosenFM,chosenTI,chosenPower,chosenCL,count.sets)

  if (ItemsMatched.length==0)
    out[l++]="<TR><TD class='z' colspan='12'>No records matched criteria given.</TD></TR>"

  timeElapsed=Math.round((((new Date())-timeStart)/100)/10).toString()
  out[l++]="\n</TABLE><br>"
  out[l++]=barGraph(((Math.round((ItemsMatched.length*1000) / count.sets))/10),200,12)	// value in %, x width, y width
  out[l++]=" <font color='#0000ff'> (Matched " + ItemsMatched.length + " of " + count.sets + " records in " + timeElapsed
  out[l++]=" seconds)<br>"
  if (debugMode) {
    out[l++]="<br><a href=\"javascript: void top.exportJS()\">Export JavaScript for Sets</a>";
    out[l++]="<br><a href=\"javascript: void top.exportSQLSet()\">Export SQL for Sets</a>"
    out[l++]="<br><a href=\"javascript: void top.exportSQLBand()\">Export SQL for Bands</a>"
  }
  out[l++]="</font>\n</body></html>"
  frames.results.document.open()
  frames.results.document.write(out.join(""))
  frames.results.document.close()
}

function sortSets(chosenMaker,chosenModel,chosenDevice,chosenGram,chosenFM,chosenTI,chosenPower,chosenCL) {
  if (top.ItemsMatched){
    var out = new Array();
    var l = 0;   // holds entire output string in chunks joined later
    out[l++] = listSetsTop(chosenMaker,chosenModel,chosenDevice,chosenGram,chosenFM,chosenTI,chosenPower,chosenCL);
    for (var setNumber=0; setNumber < ItemsMatched.length; setNumber++)
      out[l++]=ItemsMatched[setNumber].showSet(chosenDevice);
    if (ItemsMatched.length==0)
      out[l++]="<TR><TD class='z' colspan='12'>No records matched criteria given.</TD></TR>";

    out[l++]="\n</TABLE><br>";
    out[l++]=barGraph(((Math.round((ItemsMatched.length*1000) / count.sets))/10),200,12);	// value in %, x width, y width
    out[l++]=" <font color='#0000ff'> (Matched " + ItemsMatched.length + " of " + count.sets + " records)"
    if (debugMode) {
      out[l++]="<br><a href=\"javascript: void top.exportJS()\">Export JavaScript for Sets</a>";
      out[l++]="<br><a href=\"javascript: void top.exportSQLSet()\">Export SQL for Sets</a>"
      out[l++]="<br><a href=\"javascript: void top.exportSQLBand()\">Export SQL for Bands</a>"
    }
    out[l++]="</font>\n</body></html>"
    frames.results.document.open();
    frames.results.document.write(out.join(""));
    frames.results.document.close();
    Wait2.window.close(); }
  else
    alert("ERROR\nAfter 'Refreshing' this window (by pressing F5 on Internet Explorer),\nthe results list cannot be sorted until you execute the search again.\n\nPlease try your search once again before attempting to sort the list.");
}


// ----------------------------------------------------------------

Loading.document.write("#");

