//=============================================================================
//
// select.js   | For making a div behave as a select box
//
//

//-----------------------------------------------------------------------------
// COPYRIGHT 2003 DELCAM PLC., BIRMINGHAM, ENGLAND. 
//-----------------------------------------------------------------------------
//
// History.
// Who When     What   
// --- -------- ---------------------------------------------------------------
// tpb 21/05/03 Written
// tpb 03/07/03 Enabled double click events to do the same thing as mouse down
// tpb/pah 30/03/04 Set font colour if vbit-able in Entry level
// tpb 11/05/04 Fix a bug that occurs in Jewelsmith due to pages loading other
//              pages and leaving the OnResize override out of scope.
// ejp 03/02/06 Reverted to the original form as was hijacking the 
//              resize message entirely so the body was not reacting.
// sgc 23/11/06 Fixed error message appearing if NaN was passed to select_SetSelectedIndex
//-----------------------------------------------------------------------------


// TODO: Page up and page down *could* be done doing proper pages.
//       letters, jumping down the list?
//       Use timer interval for auto scrolling?
//       We could do, it's already running... how do we get the mouse position?


// The default path to the shared images is set here
var select_DefaultSharedImagePath = artcam.HtmlRootDir + "../SharedImages/";


//=== PromoteDivToSelect ==============================================
//
// This function acts like the constructor for a new style select
// It transforms a div into a select control
// The third argument is a path to the shared images.
// It defaults to "../../SharedImages/" but you might not be
// in the right place so you can override this if you pass a path string in.
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------
// tpb 21/05/03 Written
//-----------------------------------------------------------------------

function PromoteDivToSelect(select, sharedImagePath)
{
   // We check to see if the shared image path was passed in
   if( typeof(sharedImagePath) == "undefined" )
      sharedImagePath = select_DefaultSharedImagePath;

   // Setup the styles in the select
   select.style.border = "3px window-inset";

   if (select.basecolour == null)
      select.basecolour = "window";

   if (select.textcolour == null)
      select.textcolour = "windowtext";

   if (select.highlighttextcolour == null)
      select.highlighttextcolour = "highlighttext";

   if (select.highlightcolour == null)
      select.highlightcolour = "highlight";

   if (select.disabledcolour == null)
      select.disabledcolour = "buttonface";

   if (select.disabledtextcolour == null)
      select.disabledtextcolour = "graytext";

   // Build up the innerHTML
   var fixheight = select.fixheight == null ? "20px": select.fixheight + "px";
   select.innerHTML = 
      "<table id='"+select.id+"Table' cellspacing=0 cellpadding=0 border=0 width=100% onmousedown='" + select.id + "._ShowPopup()' ondblclick='" + select.id + "._ShowPopup()'><tr>" +
      "  <td style='background-color:" + select.basecolour + ";' width=100%>" +
      "  <div id='"+select.id+"Display' tabindex=0" +
      "     style='width:100%;overflow:hidden;height:"+fixheight+"'" +
      "     onkeydown='"+select.id+"._OnKeyDown()'" +
      "     onfocus='"+select.id+"._OnFocus()'" +
      "     onblur='"+select.id+"._OnBlur()'" +
      "  ></div></td>" +
      "  <td style='background-color:buttonface;' id='"+select.id+"Button'><div style='border:2px outset;height:"+fixheight+"'><img align='absmiddle' src='"+sharedImagePath+"downarrow.gif'></div></td>" +
      "</tr></table>";

   // Now setup the member variables

   // PRIVATE members
   select._popup = null;
   select._rows = new Array();
   select._display = eval(select.id + "Display");
   select._displayTable = eval(select.id + "Table");
   select._displayButton = eval(select.id + "Button");
   select._selectedIndex = -1; // Nothing selected to begin with

   // PRIVATE events
   select.onresize           = select_OnResize;

   // PRIVATE functions
   select._OnPopupSelect     = select_OnPopupSelect;
   select._CreatePopup       = select_CreatePopup;
   select._OnMouseOver       = select_OnMouseOver; 
   select._ShowPopup         = select_ShowPopup;
   select._OnKeyDown         = select_OnKeyDown;
   select._OnFocus           = select_OnFocus;
   select._OnBlur            = select_OnBlur;
   select._OpenIntervalCheck = select_OpenIntervalCheck;
   select._FireOnSelect      = select_FireOnSelect;
   select._FireOnSelectEval  = select_FireOnSelectEval;

   // PUBLIC functions.
   select.AddRow           = select_AddRow;           // (html, data) Adds a row to the row list. html is displayed, data can store whatever you like
   select.PreLoad          = select_PreLoad;          // ()
   select.GetSelectedIndex = select_GetSelectedIndex; // ()           returns selected index
   select.SetSelectedIndex = select_SetSelectedIndex; // (idx)        set the selected index
   select.GetRowCount      = select_GetRowCount;      // ()           returns number of rows
   select.GetRow           = select_GetRow;           // (idx)        returns the row object with .html and .data members
   select.Empty            = select_Empty;            // ()           removes all the rows
   select.IsOpen           = select_IsOpen;           // ()           returns whether the popup is open
   select.SetDisabled      = select_SetDisabled;      // (bool)       sets the disabled state and updates the display colors
   select.Refresh          = select_Refresh;          // ()           for refreshing the control when it is shown

   select.GetSelectedRow   = select_GetSelectedRow;   // ()           returns the selected row
   select.GetSelectedData  = select_GetSelectedData;  // ()           returns the selected row.data
   select.GetSelectedHTML  = select_GetSelectedHTML;  // ()           returns the selected row.html
   select.GetSelectedTitle = select_GetSelectedTitle; // ()           returns the selected row.title

   select.FindIndexWithData = select_FindIndexWithData;  // (data)     returns an index to the item with matching data
   select.FindIndexWithTitle = select_FindIndexWithTitle;// (title)    returns an index to the item with matching title
}




//=== select_AddRow ==============================================
//
// For adding in a row to the menus html and an data marker
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------
// tpb 21/05/03 Written
//-----------------------------------------------------------------------

function select_AddRow(html, data, title)
{
   // Put the information into a new object
   var obj  = new Object();
   if( this.nobr != null )
      obj.html = "<nobr>" + html + "</nobr>";
   else
      obj.html = html;
   obj.data = data;
   if( title != null )
      obj.title = title;

   // Store the object in the rows array
   this._rows.push(obj);

   // Now set the popup state to null if we already have one, to force it to be re created
   if( this._popup != null )
   {
      // If the popup is showing, hide it
      if( this._popup.isOpen )
         this._popup.hide();
      this._popup = null;
   }

   // We make this the currently selected row so we call OnPopupSelect
   // Not doing this at the moment.
   //this.SetSelectedIndex(this._rows.length - 1);
}


//=== select_CreatePopup ==============================================
//
// 
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------
// tpb 21/05/03 Written
//-----------------------------------------------------------------------

function select_CreatePopup()
{
   this._popup = window.createPopup();
   this._popup.document.ondragstart   = function() {return false}; // Make sure we can't drag
   this._popup.document.onselectstart = function() {return false}; // or select anything

   // Store the popup window in our object and set a _select object
   // on it for the popup's events to refer to.
   this._popupWindow = this._popup.document.parentWindow;
   this._popupWindow._select = this;

   // Build up the Popup body
   var html = new Array();
   html.push("<div id='popupdiv' style='CURSOR:default; overflow:auto; height:100%; border:solid 1px; background-color:" + this.basecolour + ";'>" +
             "<table id='popuptable' border=0 width=100% cellspacing=0 cellpadding=0>");
   for(var idx=0; idx<this._rows.length; idx++)
      html.push("<tr><td onmouseover='_select._OnMouseOver("+idx+")' onclick='_select._OnPopupSelect("+idx+")'>" + this._rows[idx].html + "</td></tr>");
   html.push("</table></div>");

   // Now set this as the document body
   this._popup.document.body.innerHTML = html.join("\n");

   // Now figure out it's dimensions for when we show it
   // We have to show and hide it once with a zero height to get it to render so we can retrieve the rendered dimensions
   this._popup.show(0, this.offsetHeight, this.offsetWidth, 0, this); // Create popup with zero height
   this._popupWidth  = this._popupWindow.popupdiv.offsetWidth;        // Grab the html width from the popup table
   this._popupHeight = this._popupWindow.popuptable.offsetHeight + 2; // Grab the html height from the popup table
   if( this._popupHeight > screen.height/3 ) // Limit against screen height
      this._popupHeight = screen.height/3;   // This will force a scrollbar to appear
   this._popup.hide();
}



//=== select_ShowPopup ==============================================
//
// 
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------
// tpb 21/05/03 Written
//-----------------------------------------------------------------------

function select_ShowPopup()
{
   // If we are diabled, go no further
   if( this.disabled )
      return;

   // If the popup has never been created, create it.
   if( this._popup == null )
      this._CreatePopup();

   // If the popup is open, hide it. Otherwise we show it.
   if( this.IsOpen() )
      this._popup.hide();
   else
   {
      // Show the popup. The width and height are worked out in the CreatePopup function
      var w = this._popupWidth > this.offsetWidth ? this._popupWidth : this.offsetWidth; // Allow it to get bigger if the main drop box has resized
      this._popup.show(0, this.offsetHeight, w, this._popupHeight, this);

      // Ensure the current selection is selected in the popup, using the OnMouseOver function.
      this._OnMouseOver(this._selectedIndex);

      // Start the monitoring interval so we can have a close event.
      // There seems to be no other way around this as I can't catch a close event
      // on the window. IsOpen checks whether this interval is still running
      this._popupOpenInterval = setInterval(this.id+"._OpenIntervalCheck()", 100);
   }
}


//=== select_OpenIntervalCheck ==============================================
//
// 
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------
// tpb 23/05/03 Written
//-----------------------------------------------------------------------

function select_OpenIntervalCheck()
{
   if(!this._popup || !this._popup.isOpen)
   {
      clearInterval(this._popupOpenInterval);
      this._popupOpenInterval = null;
   }
}


//=== select_IsOpen ==============================================
//
// This function overrides the default isOpen on _popup to get around
// a problem we have when we click the drop box while the popup is open.
// The popup loses focus, dissappears and then we get a mousedown to
// the drop box which would see that the popup was closed and open it again!
// So this function relies on the monitoring interval to tell us when it
// has closed. We only think we have closed once the monitoring interval
// has seen it. This interval is also used for auto scrolling.
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------
// tpb 23/05/03 Written
//-----------------------------------------------------------------------

function select_IsOpen()
{
   if( this._popup == null )
      return false;
   if( this._popupOpenInterval != null ) // If our popup open interval is running still, we assume we are open
      return true;
   return this._popup.isOpen;
}



//=== select_OnMouseOver ==============================================
//
// 
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------
// tpb 21/05/03 Written
// ejp 18/12/03 Check that the lastSelected is not > number of rows 
//              This can happen if the content of the select is being changed
//              dynamically.
//-----------------------------------------------------------------------

function select_OnMouseOver(idx)
{
   // Normalise the index
   if( idx >= this._rows.length )
      idx = this._rows.length - 1;
   else if( idx < 0 )
      idx = 0;

   // If there is a last selected index, unhighlight it
   if( this._lastSelected != null && this._lastSelected < this._rows.length)
   {
      var tr = this._popupWindow.popuptable.rows(this._lastSelected);
      tr.style.backgroundColor = this.basecolour;
      tr.style.color = this.textcolour;
   }

   // And highlight the new index
   var tr = this._popupWindow.popuptable.rows(idx);
   tr.style.backgroundColor = this.highlightcolour;
   tr.style.color = this.highlighttextcolour;

   // Work out whether we need to scroll or not
   var trTop = tr.offsetTop;
   var trBottom = trTop + tr.offsetHeight;
   var clientHeight = this._popupWindow.popupdiv.clientHeight;
   var scrollTop = this._popupWindow.popupdiv.scrollTop;
   var scrollBottom = scrollTop + clientHeight;

   // Now scroll it if neccessary into position
   if( trTop < scrollTop )
      this._popupWindow.popupdiv.scrollTop = trTop;
   if( trBottom > scrollBottom )
      this._popupWindow.popupdiv.scrollTop = trBottom - clientHeight;

   // Remember this as the last selected index
   this._lastSelected = idx;
}



//=== select_OnPopupSelect ==============================================
//
// Called when a row from the popup has been selected
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------
// tpb 21/05/03 Written
//-----------------------------------------------------------------------

function select_OnPopupSelect(idx)
{
   this._popup.hide();

   this.SetSelectedIndex(idx);

   // Set the focus to the display
   this._display.focus();

   // Inform the callback if one has been specified
   this._FireOnSelect();
}




//=== select_PreLoad ==============================================
//
// This will cause the popup to preload by actually creating it and trying to open it briefly.
// This is used as a speedup for fuller lists and is performed in the background on a timeout
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------
// tpb 21/05/03 Written
//-----------------------------------------------------------------------

function select_PreLoad()
{
   if( this._PreloadTimeout == null )
   {
      // Call the preload after an instant timeout
      this._PreloadTimeout = setTimeout(this.id + ".PreLoad()", 0);
   }
   else
   {
      this._PreloadTimeout = null;
      this._CreatePopup();
      this._popup.show(0, 0, 0, 0);
      this._popup.hide();

      // Now put the focus on the document body
      document.body.focus();
   }
}


//=== select_GetSelectedIndex ==============================================
//
// 
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------
// tpb 22/05/03 Written
//-----------------------------------------------------------------------

function select_GetSelectedIndex()
{
   return this._selectedIndex;
}


//=== select_SetSelectedIndex ==============================================
//
// 
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------
// tpb 22/05/03 Written
// sgc 22/11/06 Fixed script error if NaN is passed in as idx
//-----------------------------------------------------------------------

function select_SetSelectedIndex(idx)
{
   // Normalise the index
   if( idx >= this._rows.length )
      idx = this._rows.length - 1;
   else if( idx < -1 )
      idx = -1;

   // Set the display div to zero pixels to allow the table to shrink, we need to measure a few sizes
   this._display.style.width = "0px";

   // If this is a -1 index, we leave the display blank.
   // Otherwise we set the display to the currently selected row

   if(isNaN(idx))
   {
      // NaN here causes a script error so just return
      return;
   }

   this._selectedIndex = idx;
   if( idx != -1 )
   {
      this._display.innerHTML = this._rows[idx].html;
      if( this._rows[idx].title != null )
         this._display.title = this._rows[idx].title;
      else
         this._display.title = this._display.innerText;
      this._display.style.width = this._displayTable.offsetWidth - this._displayButton.offsetWidth; // Force the width to depend on the table
   }
}



//=== select_OnResize ==============================================
//
// 
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------
// tpb 28/05/03 Written
// tpb 20/10/06 Fixed a nasty recursion issue
//-----------------------------------------------------------------------

function select_OnResize()
{
   // BEFORE YOU FEEL TEMPTED TO CHANGE THIS FUNCTION: READ THIS!
   // This function is called when a resize event occurs.
   // The SetSelectedIndex part below allows the control to resize itself nicely for a given size.
   // During this process it sets the width twice and generates two more resize events on the queue,
   // which in turn call this function. Originally we used to catch the body onresize event in a 
   // chain instead, so that we only responded to body size events. This was fine until in JewelSmith
   // parts of the body got rewritten and window.onresize would end up pointing to a non existant function.
   // 
   // So now we have this. We catch the event on the object itself. In order to stop recursion
   // we temporarily set this objects event handler to null to prevent further calls.
   // Then we restore this function after a timeout of zero. A timeout of zero will put the
   // operation AFTER any generated resize events that may be on the queue.
   //
   // When we didn't do this on a time out, the onresize handler would be restored after the first generated event,
   // and the second generated event would start it all off again. This is now safe to handle any number of
   // generated events.
   //
   // Still tempted?
   
   // Protect against recursion. Ignore calls to this function until further notice.
   this.onresize = null;

   // Just set the selected index again. It will sort the sizing issues out
   this.SetSelectedIndex(this._selectedIndex); // Reset the index   
   
   // Restore the resize handler after any resize events have been ignored.
   setTimeout(this.id + ".onresize = select_OnResize", 0);
}




//=== select_GetRow ==============================================
//
// 
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------
// tpb 22/05/03 Written
//-----------------------------------------------------------------------

function select_GetRow(idx)
{
   // if we are out of range, return null
   if( idx < 0 || idx >= this._rows.length )
      return null;

   // Now return the row object
   return this._rows[idx];
}

//=== select_GetRowCount ==============================================
//
// 
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------
// tpb 22/05/03 Written
//-----------------------------------------------------------------------

function select_GetRowCount()
{
   return this._rows.length;
}


//=== select_Empty ==============================================
//
// 
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------
// tpb 22/05/03 Written
//-----------------------------------------------------------------------

function select_Empty()
{
   // Set the popup state to null if we already have one, to force it to be re created
   if( this._popup != null )
   {
      // If the popup is showing, hide it
      if( this._popup.isOpen )
         this._popup.hide();
      this._popup = null;
   }

   // Remove the old rows by creating a new array
   this._rows = new Array();
   this.SetSelectedIndex(-1); 
}


//=== select_FindIndexWithData ==============================================
//
// 
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------
// tpb 22/05/03 Written
//-----------------------------------------------------------------------

function select_FindIndexWithData(data)
{
   for(var idx=0; idx<this._rows.length; idx++)
      if(this._rows[idx].data == data)
         return idx;
   return -1;
}



//=== select_OnKeyPress ==============================================
//
// 
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------
// tpb 23/05/03 Written
//-----------------------------------------------------------------------

function select_OnKeyDown()
{
   // Different things occur, depending on whether the popup is open or not
   switch(event.keyCode)
   {
   case 13: // Enter
   case 32: // Space
      if( this.IsOpen() )
         this._OnPopupSelect(this._lastSelected); // Make the selection with the current row
      else
         this._ShowPopup(); // Otherwise just show the popup
      break;

   case 33: // PgUp
   case 36: // Home - Select the first
      if( this.IsOpen() )
      {
         if(this._lastSelected == 0)
            break;
         this.SetSelectedIndex(0); 
         this._OnMouseOver(0);
      }
      else
      {
         if(this._selectedIndex == 0)
            break;
         this.SetSelectedIndex(0); 
         this._FireOnSelect();
      }
      break;

   case 34: // PgDown
   case 35: // End    - Select the last
      if( this.IsOpen() )
      {
         if(this._lastSelected == this._rows.length-1)
            break;
         this.SetSelectedIndex(this._rows.length-1); 
         this._OnMouseOver(this._rows.length-1);
      }
      else
      {
         if(this._selectedIndex == this._rows.length-1)
            break;
         this.SetSelectedIndex(this._rows.length-1); 
         this._FireOnSelect();
      }
      break;

   case 38: // Up - Select the previous
      if( this.IsOpen() )
      {
         if(this._lastSelected == 0)
            break;
         this.SetSelectedIndex(this._lastSelected-1); 
         this._OnMouseOver(this._lastSelected-1);
      }
      else
      {
         if(this._selectedIndex == 0)
            break;
         this.SetSelectedIndex(this._selectedIndex-1); 
         this._FireOnSelect();
      }
      break;

   case 40: // Down - Select the next
      if( this.IsOpen() )
      {
         if(this._lastSelected == this._rows.length-1)
            break;
         this.SetSelectedIndex(this._lastSelected+1); 
         this._OnMouseOver(this._lastSelected+1);
      }
      else
      {
         if(this._selectedIndex == this._rows.length-1)
            break;
         this.SetSelectedIndex(this._selectedIndex+1); 
         this._FireOnSelect();
      }
      break;
   }

   // We need to stop this event continuing down the page
   event.returnValue = false;
   return false;
}



//=== select_OnFocus ==============================================
//
// 
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------
// tpb 23/05/03 Written
//-----------------------------------------------------------------------

function select_OnFocus()
{
   this._display.style.color = this.highlighttextcolour;
   this._display.style.backgroundColor = this.highlightcolour;
}


//=== select_OnBlur ==============================================
//
// 
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------
// tpb 23/05/03 Written
//-----------------------------------------------------------------------

function select_OnBlur()
{
   this._display.style.color = this.textcolour;
   this._display.style.backgroundColor = this.basecolour;
}



//=== select_FireOnSelect ==============================================
//
// 
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------
// tpb 23/05/03 Written
//-----------------------------------------------------------------------

function select_FireOnSelect()
{
   if(this.onselect == null)
      return; // Nothing to fire

   if( this._FireOnSelectTimeout == null )
   {
      // Fire the onselect event after an instant timeout
      // This allows the page to update and other events to pass through first
      // It also means that we don't fire one on top of another.
      // If the timeout already exists, we don't make another call.
      this._FireOnSelectTimeout  = setTimeout(this.id + "._FireOnSelectEval()", 0);
   }
}



//=== select_FireOnSelectEval ==============================================
//
// 
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------
// tpb 23/05/03 Written
//-----------------------------------------------------------------------

function select_FireOnSelectEval()
{
   if(this.onselect == null)
      return; // Nothing to fire
   this._FireOnSelectTimeout = null; // Cancel this timeout, it will allow another to fire
   eval(this.onselect);
}



//=== select_SetDisabled ==============================================
//
// sets the disabled state and updates the display colors
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------
// tpb 26/09/03 Written
// tpb 26/01/04 Added extra .disabled state to stop redraw bug
//-----------------------------------------------------------------------

function select_SetDisabled(state)
{
   this.disabled = state;
   this._display.disabled = state;
   if( state )
   {
      // Change colors
      this._display.style.color = this.disabledtextcolour;
      this._display.style.backgroundColor = this.disabledcolour;
   }
   else
   {
      this._display.style.color = this.textcolour;
      this._display.style.backgroundColor = this.basecolour;
   }
}


//=== select_Refresh ==============================================
//
// for refreshing the control when it is shown
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------
// tpb 26/09/03 Written
//-----------------------------------------------------------------------

function select_Refresh()
{
   // This will cause a resize of everything and refresh the control
   this.SetSelectedIndex(this.GetSelectedIndex());
}


//=== select_GetSelected...==============================================
//
// Series of direct return functions for the currently selected object
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------
// ejp 18/12/03 Written
//-----------------------------------------------------------------------

function select_GetSelectedRow()
{
   return this.GetRow(this.GetSelectedIndex());
}

function select_GetSelectedData()
{
   return this.GetRow(this.GetSelectedIndex()).data
}

function select_GetSelectedHTML()
{
   return this.GetRow(this.GetSelectedIndex()).html;
}

function select_GetSelectedTitle()
{
   return this.GetRow(this.GetSelectedIndex()).title;
}


//=== select_FindIndexWithTitle ==============================================
//
// Returns the index of the item in the list with the passed title else
// returns -1.
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------
// ejp 03/09/04 Written
//-----------------------------------------------------------------------

function select_FindIndexWithTitle(title)
{
   for(var idx=0; idx<this._rows.length; idx++)
      if(this._rows[idx].title == title)
         return idx;
   return -1;
}





//============================================================================
// S P E C I A L   S E L E C T   B O X E S
//============================================================================


//=== PromoteDivToFontSelect ==============================================
//
// Makes the passed in div a font select box, used on a few pages
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------
// tpb 28/05/03 Written
// tpb/pah 30/03/04 Set font colour if vbit-able in Entry level
//-----------------------------------------------------------------------

function PromoteDivToFontSelect(select, sharedImagePath)
{
   // We check to see if the shared image path was passed in
   if( typeof(sharedImagePath) == "undefined" )
      sharedImagePath = select_DefaultSharedImagePath;

   // We set this up as a normal select but with a certain height and font settings within it
   // Make sure the height is fixed at and that this is a nobr control
   select.fixheight = 22;
   select.nobr = true;

   // No promote this to a normal select
   PromoteDivToSelect(select, sharedImagePath);

   // Get our paths for the images to represent fonts
   var truetypeFont = "<img src='"+sharedImagePath+"truetype.gif' align='absmiddle'>&nbsp;";
   var artcamFont   = "<img src='"+sharedImagePath+"artfont.gif'  align='absmiddle'>&nbsp;";

   // We use these regexps for detecting the different kinds of fonts in the list
   var artRegEx = /^\(AFN\) /;  // Allow the regexp's to be compiled
   var symRegEx = /\[S\]$/;
   var atRegEx  = /^\@/;

   var simpleFontSelect = artcam.RetrieveInt("Text Editing", "SimpleFontSelect", 0);

   // Now we add in all the fonts
   // Load up the font list by calling GetNextFontNameDetailed until it returns an empty font name
   for( var fontName = artcam.Font.GetNextFontNameDetailed();
        fontName.length != 0;
        fontName = artcam.Font.GetNextFontNameDetailed() )
   {
      // The actual font name without details
      var shortName = fontName;
      if( shortName.match(symRegEx) )
         shortName = fontName.replace(symRegEx, "");

      // We add this font to the select list and move onto next font
      // We need to make the font face display optional as slower computers might have problems
      if(simpleFontSelect)
      {
         if( fontName.match(artRegEx) )
            select.AddRow(artcamFont + "<font style='font-size:12pt;'>" + fontName.replace(artRegEx, "") + "</font>", fontName);
         else if(fontName.match(atRegEx) )
            select.AddRow("<font style='font-size:12pt;'>" + fontName.replace(atRegEx, "@ ") + "</font>", fontName);
         else if(fontName.match(symRegEx) )
            select.AddRow(truetypeFont + "<font style='font-size:12pt;'>" + shortName + "</font>", shortName, shortName);
         else
            select.AddRow(truetypeFont + "<font style='font-size:12pt;'>"+fontName+"</font>", fontName);
      }
      else
      {
         if( fontName.match(artRegEx) )
         {
            var color_str = "background-color=white;";

            // Try to find a preview if we can for ArtCAM fonts
            var preview_img = artcam.Font.FindFontPreviewImage(shortName);
            if(preview_img.length)
               select.AddRow(artcamFont + "<img src='" + preview_img + "' align=absmiddle style='margin:1px;"+color_str+"'>", fontName, fontName.replace(artRegEx, ""));
            else
               select.AddRow(artcamFont + "<font style='font-size:12pt;'>" + fontName.replace(artRegEx, "") + "</font>", fontName);
         }
         else if(fontName.match(atRegEx) )
            select.AddRow("<font style='font-size:12pt;'>" + fontName.replace(atRegEx, "@ ") + "</font>", fontName);
         else if(fontName.match(symRegEx) )
            select.AddRow(truetypeFont + "(" + shortName + ")<font size=+1 face='"+shortName+"'>" + shortName + "</font>", shortName, shortName);
         else
            select.AddRow(truetypeFont + "<font size=+1 face='"+fontName+"'>"+fontName+"</font>", fontName);
      }
   }

   // Preload it - creates the popup on a timeout as it can take a while when there are lots of fonts
   select.PreLoad();

   // Need an option on the options page to allow plain text
}


// NOTE!! DON'T ADD FUNCTIONS HERE, unless they are special select box constructors
// Add them above this 'Special Select Boxes' section. For tidy's sake.