
/* ------------------------------------------------------------------------------------------------------------------ */
/*                                                                                                                    */
/* ALL FUNCTIONS (c) Jamie Jones unless stated otherwise, and NOT to be used without giving full credit.              */
/*                    ---  This means YOU !                                                                           */
/*                    ---  jamie@bishopston net - http://phpbbmods.bishopston.net/                                    */
/*                                                                                                                    */
/*  Last Updated: 29th September 2009.                                                                                 */
/*                                                                                                                    */
/* ------------------------------------------------------------------------------------------------------------------ */
/*                                                                                                                    */
/* For debugging, use a scheme similar to this:                                                                       */
/*                                                                                                                    */
/*       if (navigator.platform.indexOf('FreeBSD') !=-1)                                                              */
/*          alert (...);                                                                                              */
/*                                                                                                                    */
/* ------------------------------------------------------------------------------------------------------------------ */
function catflap_debug(what, value)
  {
    document.getElementById("catflap_menu_td").innerHTML += "<pre style=\"text-align:left\">" + what + " = " + value + "</pre>\n";
  }

/* ------------------------------------------------------------------------------------------------------------------ */
function catflap_sleep(sleeptime)
  {
    var date_now = new Date();
    var cur_time = date_now.getTime();
    var return_time = cur_time + sleeptime;

    while (cur_time < return_time)
      {
        date_now = new Date(); 
        cur_time = date_now.getTime();
      }
  }

/* ------------------------------------------------------------------------------------------------------------------ */
function catflap_toggle_spoiler(linkobject, spoilerobject, opentext, closetext)
  {
    var visibleobject = spoilerobject.childNodes[1].firstChild.firstChild;
    var hiddenobject  = spoilerobject.childNodes[2].firstChild.firstChild;

    if (hiddenobject)
      if ( hiddenobject.style.display != 'block' )
        {
          hiddenobject.style.display = 'block';
          if (visibleobject) visibleobject.style.display = 'none';
          if (linkobject)    linkobject.nodeValue = 'Click here to ' + closetext;
        }
       else
        {
          hiddenobject.style.display = 'none';
          if (visibleobject) visibleobject.style.display = 'block';
          if (linkobject)    linkobject.nodeValue = 'Click here to ' + opentext;
        }
  }

/* ------------------------------------------------------------------------------------------------------------------ */

  // <object width="640" height="480">
  // <param name="movie" value="jw-mediaplayer-3.16.swf"/>
  // <param name="flashvars" value="file=john_smiths.flv&autostart=false&width=640&height=480&showvolume=true&image=john_smiths2.jpg&overstretch=false&showdigits=true&enablejs=false"/>
  // <embed src="jw-mediaplayer-3.16.swf" flashvars="FILL IN HERE" type="application/x-shockwave-flash" width="640" height="480"></embed>
  // </object>

/* ------------------------------------------------------------------------------------------------------------------ */
function catflap_toggle_flash(videoobject, linkobject, objectid, what, action)
  {
    if (action=="load")
      {
        videoobject.catflap_video_unloadedhtml=videoobject.innerHTML.replace(/flash_red\.jpg/, "flash_blue.jpg")
        videoobject.catflap_link_unloadedhtml=linkobject.innerHTML;

        if (what=="youtube")
          {
            var youtubewidth=642;
            var youtubeheight=385;

            // Next, get the colors for the video borders:
           if (typeof catflap_youtube_color=="undefined")
             {
               // The following two aren't proceeded with 'var' as we want them to remain global
	       catflap_youtube_color="";

               var the_elements = document.styleSheets[0].cssRules;
               var count = the_elements.length;
               var loop;

               for (loop=0; loop < count; loop++)
                 if (the_elements[loop].selectorText)
                   if (the_elements[loop].selectorText == ".catflap_youtube_color") catflap_youtube_color = new catflap_RGBColor (the_elements[loop].style.backgroundColor);
              }

	    var colortext = "";

	    if (catflap_youtube_color.ok) colortext = "&color1=" + catflap_youtube_color.toHex() + "&color2=" + catflap_youtube_color.toHex();

            var url = "http://www.youtube.com/v/" + objectid + "&hl=en&rel=0&border=0" + colortext + "&fs=1&autoplay=1";

            videoobject.innerHTML="<object width=\"" + youtubewidth + "\" height=\"" + youtubeheight + "\"><param name=\"movie\" value=\"" + url + "\"/><param name=\"allowFullScreen\" value=\"true\"/><embed src=\"" + url + "\" type=\"application/x-shockwave-flash\" allowfullscreen=\"true\" width=\"" + youtubewidth + "\" height=\"" + youtubeheight + "\"></embed></object>";

            linkobject.innerHTML="<a onMouseOver=\"window.status='Stop Video Clip'; this.style.cursor='pointer'; return false\" onMouseOut=\"window.status=''; return false;\" onClick=\"catflap_toggle_flash(parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.childNodes[1].firstChild.firstChild, parentNode, '{VIDEO_ID}', 'youtube', 'unload'); return false;\">Click here to unload video</a>";
          }
         else if (what=="flash")
          {
            videoobject.innerHTML="<object width=\"700\" height=\"500\"><param name=\"movie\" value=\"" + objectid + "\"/><param name=\"width\" value=\"700\"/><param name=\"height\" value=\"500\"/><param name=\"loop\" value=\"false\"/><param name=\"quality\" value=\"high\"/><param name=\"allowScriptAccess\" value=\"never\"/><embed src=\"" + objectid + "\" type=\"application/x-shockwave-flash\" width=\"700\" height=\"500\" loop=\"false\" quality=\"high\" allowScriptAccess=\"never\"></embed></object>";

            linkobject.innerHTML="<a onMouseOver=\"window.status='Stop Flash Clip'; this.style.cursor='pointer'; return false\" onMouseOut=\"window.status=''; return false;\" onClick=\"catflap_toggle_flash(parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.childNodes[1].firstChild.firstChild, parentNode, '{URL}', 'flash', 'unload'); return false;\">Click here to stop</a>";
          }
      }
     else
      if (action=="close")
        {
          videoobject.catflap_video_openhtml=videoobject.innerHTML;
          videoobject.catflap_link_openhtml=linkobject.innerHTML;

          videoobject.innerHTML="";

          if (what=="youtube") linkobject.innerHTML="<span style=\"float: left\"><a class=\"catflap_options\" onMouseOver=\"window.status='Options'; this.style.cursor='pointer'; return false\" onMouseOut=\"window.status=''; return false;\" href=\"/profile.php?mode=profil&amp;sub=profile_prefer&amp;mod=1&amp;msub=7\" target=\"_blank\" title=\"Options\">Options</a></span><span style=\"float: right;\"><a style=\"cursor: pointer;\" onmouseover=\"window.status='Open'; this.style.cursor='pointer'; return false\" onmouseout=\"window.status=''; return false;\" onclick=\"catflap_toggle_flash(parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.childNodes[1].firstChild.firstChild, parentNode.parentNode, '{VIDEO_ID}', 'youtube', 'open'); return false;\">Open</a></span>";
           else if (what=="flash") linkobject.innerHTML="<span style=\"float: right;\"><a style=\"cursor: pointer;\" onmouseover=\"window.status='Open'; this.style.cursor='pointer'; return false\" onmouseout=\"window.status=''; return false;\" onclick=\"catflap_toggle_flash(parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.childNodes[1].firstChild.firstChild, parentNode.parentNode, '{URL}', 'flash', 'open'); return false;\">Open</a></span>";
        }
       else
        if (action=="open")
          {
            videoobject.innerHTML=videoobject.catflap_video_openhtml;
            linkobject.innerHTML=videoobject.catflap_link_openhtml;
          }
         else
           if (action=="unload")
            {
              videoobject.innerHTML=videoobject.catflap_video_unloadedhtml;
              linkobject.innerHTML=videoobject.catflap_link_unloadedhtml;
            }
  }

/* ------------------------------------------------------------------------------------------------------------------ */
/*
  name - name of the desired cookie
  return string containing value of specified cookie or null
  if cookie does not exist.
  This function from http://www.webreference.com/js/column8/functions.html
*/

function catflap_getCookie(name) {
  var dc = document.cookie;
  var prefix = name + "=";
  var begin = dc.indexOf("; " + prefix);
  if (begin == -1) {
    begin = dc.indexOf(prefix);
    if (begin != 0) return null;
  } else
    begin += 2;
  var end = document.cookie.indexOf(";", begin);
  if (end == -1)
    end = dc.length;
  return unescape(dc.substring(begin + prefix.length, end));
}

/* ------------------------------------------------------------------------------------------------------------------ */
function catflap_setcookie (cookie_name, cookie_value)
  {
    var the_date = new Date();

    // For registered users, the cookie only needs to last until any page on the forum
    // is loaded, after which point, the information is stored in the users profile, and
    // the cookie then reset. So, choose a cookie max age of 28 days, which should be
    // plenty. -- If they don't login for 28 days, they don't deserve to have the option
    // set !! - In fact, they'll probably not remember setting the option.
    // Anonymous users will simply have to suffer resetting the cookie every 28 days, as
    // the information is not stored online in such cases.
    the_date.setTime(the_date.getTime() + 2419200000);

    /* document.cookie = cookie_name + '=; path=/; expires=Thu, 01-Jan-1970 00:00:01 GMT'; */

    // Update or create cookie:
    document.cookie = cookie_name + '=' + cookie_value + '; path=/; expires=' + the_date.toGMTString();
  }

/* ------------------------------------------------------------------------------------------------------------------ */

/* flags variable holds 2-bit pairs for the default state of the section. Each section has a unique pair of bits.

   0 00 System/users profile default -- This value is set when the server syncs the users profile with their cookie
   1 01 Window closed
   2 10 Window minimised
   3 11 Window maximised

   Allocated unique section IDs and their corresponding html ID:

    0 whoisonline
    1 gallery
    2 latesttopics
    3 forumlistings
    4 ratings
    5 funtrivia
    6 misc
    7 weblinks
    8 sidebar
    9 forumquiz
*/

function catflap_section_return_shift (section_html_id)
  {
    // Basically, the number of positions to bitwise-'shift' the flags is 2 multiplied
    // by a unique number allocated to each section.

    var ret=-1;

    if (section_html_id == "whoisonline")   ret = 0;
    if (section_html_id == "gallery")       ret = 1;
    if (section_html_id == "latesttopics")  ret = 2;
    if (section_html_id == "forumlistings") ret = 3;
    if (section_html_id == "ratings")       ret = 4;
    if (section_html_id == "funtrivia")     ret = 5;
    if (section_html_id == "misc")          ret = 6;
    if (section_html_id == "weblinks")      ret = 7;
    if (section_html_id == "sidebar")       ret = 8;
    if (section_html_id == "forumquiz")     ret = 9;

    return (ret*2);
  }

function catflap_section_default (section_html_id)
  {
    var the_cookie_value = catflap_getCookie ('catflap_fps');
    var open_state = "block";
    var minimised_state = "none";
    var section_default_state = 0;
    
    if (the_cookie_value) section_default_state = (the_cookie_value>>>catflap_section_return_shift(section_html_id) & 3);

    if (section_default_state == 1)
      {
        open_state = "none";
        minimised_state = "none";
      }
      else if (section_default_state == 2)
        {
          open_state = "none";
          minimised_state = "block";
        }

    if (section_default_state != 0)
      {
        document.getElementById(section_html_id + '_section_open').style.display = open_state;
        document.getElementById(section_html_id + '_section_minimised').style.display = minimised_state;
      }
   }

function catflap_section_change (change_type, section_html_id)
  {
    var the_cookie_value = catflap_getCookie ('catflap_fps');
    var open_state = "block";
    var minimised_state = "none";
    var section_default_state = 3;
    var section_shift = catflap_section_return_shift(section_html_id);

    if (change_type == "close")
      {
        open_state = "none";
        minimised_state = "none";
        section_default_state = 1;
      }

    if (change_type == "minimise")
      {
        open_state = "none";
        minimised_state = "block";
        section_default_state = 2;
      }

    document.getElementById(section_html_id + '_section_open').style.display = open_state;
    document.getElementById(section_html_id + '_section_minimised').style.display = minimised_state; 

    // Get new value for cookie:
    if (!the_cookie_value) the_cookie_value=0;

    // Here we XOR the relevent 2 bits in the cookie data with themselves, hence resetting them to zero.
    // Then we OR in place the new bits.
    new_cookie_value = the_cookie_value ^ (the_cookie_value>>>section_shift & 3)<<section_shift | (section_default_state<<section_shift);

    // Update or create cookie:
    catflap_setcookie ("catflap_fps", new_cookie_value);
  }

function catflap_section_show_all ()
  {
    var the_divs = document.getElementsByTagName("div");
    var count = the_divs.length;
    var new_cookie_value = 0;
    var loop;

    for (loop=0; loop < count; loop++)
      {
        // if (the_divs[loop].hasAttribute("id")) --- "hasAttribute" doesn't work on IE :-(
        if (the_divs[loop].id)
          {
            if ((the_divs[loop].getAttribute("id").match(/_section_open$/)) || (the_divs[loop].getAttribute("id").match(/_section_minimised$/)))
              {
                section_html_id = the_divs[loop].getAttribute("id").replace(/_section_open$/, "").replace(/_section_minimised$/, "");

                if (document.getElementById(section_html_id + '_section_open'))      document.getElementById(section_html_id + '_section_open').style.display = "block";
                if (document.getElementById(section_html_id + '_section_minimised')) document.getElementById(section_html_id + '_section_minimised').style.display = "none";

                // Here we OR in place the 2 '1' bits relevent to this entry.
                new_cookie_value = new_cookie_value  | (3<<catflap_section_return_shift(section_html_id));
              }
          }
      }

    // Update or create cookie:
    catflap_setcookie ("catflap_fps", new_cookie_value);
  }

/* ------------------------------------------------------------------------------------------------------------------ */

// Based on info from: http://www.quirksmode.org/viewport/compatibility.html
// --- "Inner Width"
// --- The inner dimensions of the window or frame.
function catflap_viewport_size()
  {
    var x = 0;
    var y = 0;

    if (self.innerWidth) x = self.innerWidth;
      else if (document.documentElement && document.documentElement.clientWidth) x = document.documentElement.clientWidth;
        else if (document.body) x = document.body.clientWidth;

    if (self.innerHeight) y = self.innerHeight;
      else if (document.documentElement && document.documentElement.clientHeight) y = document.documentElement.clientHeight;
        else if (document.body) y = document.body.clientHeight;
    
    return (x + " X " + y);
  }

/* ------------------------------------------------------------------------------------------------------------------ */
function catflap_move_box(block_id)
  {
    var catflap_open      = document.getElementById(block_id + '_block_open');
    var catflap_minimised = document.getElementById(block_id + '_block_minimised');

    var catflap_open_object  = new getObj(block_id + '_block_open');
    if (catflap_open_object.obj.captureEvents) catflap_open.obj.captureEvents(Event.MOUSEUP)
    if (catflap_open_object.obj.captureEvents) catflap_open.obj.captureEvents(Event.MOUSEDOWN)

    var e = catflap_open.event; 
    alert (e.clientX);
    document.getElementById(block_id + '_block_open').style.position = 'absolute';
    document.getElementById(block_id + '_block_minimised').style.position = 'absolute';
    document.getElementById(block_id + '_block_open').style.left = this.clientX + 'px';
    document.getElementById(block_id + '_block_open').style.top = this.clientY + 'px';
    document.getElementById(block_id + '_block_minimised').style.left = this.clientX + 'px';
    document.getElementById(block_id + '_block_minimised').style.top = this.clientY + 'px';
    alert (ee.clientX + " " + ee.clientY);
  }

function catflap_stopmove_box(block_id)
  {
    document.getElementById(block_id + '_block_open').style.position = 'relative';
    document.getElementById(block_id + '_block_minimised').style.position = 'relative';
  }

/* ------------------------------------------------------------------------------------------------------------------ */
// From http://www.quirksmode.org/js/events_properties.html
function catflap_doSomething(e)
{
        var posx = 0;
        var posy = 0;
        if (!e) var e = window.event;
        if (e.pageX || e.pageY)
        {
                posx = e.pageX;
                posy = e.pageY;
        }
        else if (e.clientX || e.clientY)
        {
                posx = e.clientX + document.body.scrollLeft;
                posy = e.clientY + document.body.scrollTop;
        }
        // posx and posy contain the mouse position relative to the document.
        // Do something with this information!
}

/* ------------------------------------------------------------------------------------------------------------------ */
function smeg (sdf)
{
 alert (sdf.parentNode.nodeName);
}

function catflap_resize_image (imageref)
  {
  }

function catflap_resize_image_DISABLED (imageref)
  {
    var winwidth = 0;
    var size_available = 500;

    imageref.onload = null;
    if (self.innerWidth) winwidth = self.innerWidth;
      else if (document.documentElement && document.documentElement.clientWidth) winwidth = document.documentElement.clientWidth;
        else if (document.body) winwidth = document.body.clientWidth;

    size_available = winwidth - document.getElementById('catflap_messagebox').offsetLeft - 110;

    var tmp=imageref.style.display;

    var parent_element=imageref.parentNode;
    // MAYBE HERE ALL WE NEED IS TO CHECK THAT THE PARENT_ELEMENT IS BLOCK, NOT INLINE?
    // MAYBE HERE ALL WE NEED IS TO CHECK THAT THE PARENT_ELEMENT IS BLOCK, NOT INLINE?
    // MAYBE HERE ALL WE NEED IS TO CHECK THAT THE PARENT_ELEMENT IS BLOCK, NOT INLINE?
    // MAYBE HERE ALL WE NEED IS TO CHECK THAT THE PARENT_ELEMENT IS BLOCK, NOT INLINE?
    // MAYBE HERE ALL WE NEED IS TO CHECK THAT THE PARENT_ELEMENT IS BLOCK, NOT INLINE?
    // MAYBE HERE ALL WE NEED IS TO CHECK THAT THE PARENT_ELEMENT IS BLOCK, NOT INLINE?
    // MAYBE HERE ALL WE NEED IS TO CHECK THAT THE PARENT_ELEMENT IS BLOCK, NOT INLINE?
    // MAYBE HERE ALL WE NEED IS TO CHECK THAT THE PARENT_ELEMENT IS BLOCK, NOT INLINE?
    // MAYBE HERE ALL WE NEED IS TO CHECK THAT THE PARENT_ELEMENT IS BLOCK, NOT INLINE?
    // MAYBE HERE ALL WE NEED IS TO CHECK THAT THE PARENT_ELEMENT IS BLOCK, NOT INLINE?
    // MAYBE HERE ALL WE NEED IS TO CHECK THAT THE PARENT_ELEMENT IS BLOCK, NOT INLINE?
    // MAYBE HERE ALL WE NEED IS TO CHECK THAT THE PARENT_ELEMENT IS BLOCK, NOT INLINE?
    // MAYBE HERE ALL WE NEED IS TO CHECK THAT THE PARENT_ELEMENT IS BLOCK, NOT INLINE?
    // MAYBE HERE ALL WE NEED IS TO CHECK THAT THE PARENT_ELEMENT IS BLOCK, NOT INLINE?
    while (parent_element.nodeName != "TD" && parent_element.nodeName != "UL")
      parent_element=parent_element.parentNode;

    smeg1= (imageref.offsetWidth);
    imageref.style.display="none";
    smeg2= (parent_element.offsetWidth);
    size_available = parent_element.offsetWidth;
    imageref.style.display=tmp;
    smeg3= (imageref.offsetWidth);
    // alert (smeg1 + " " + smeg2 + " " + smeg3);

    // if (navigator.platform.indexOf('FreeBSD') !=-1) alert (imageref.width + " " + size_available);
    if (imageref.width > size_available)
      {
        var pc = Math.round (size_available / imageref.width * 10000) / 100;
        // if (navigator.platform.indexOf('FreeBSD') !=-1) alert (imageref.width);
        imageref.catflap_original_width=imageref.width;
        imageref.catflap_shrunk_width=size_available;
        imageref.catflap_shrunk_pc=pc;
        imageref.catflap_shrunk_status=1;
        imageref.style.width=size_available + 'px';
        if (imageref.previousSibling)
          {
            imageref.previousSibling.style.width=size_available + 'px';
            imageref.previousSibling.firstChild.nodeValue="Image reduced to " + pc + "% of its original size. Click this bar to restore to full size.";
            imageref.previousSibling.style.display = 'block';
          }
      }
  }

function catflap_toggle_image_size (imageref)
  {
    if (imageref.nextSibling)
      {
        if (imageref.nextSibling.catflap_shrunk_status == 1)
          {
            imageref.firstChild.nodeValue="Image at full-size. Click this bar to fit to window.";
            imageref.style.width=imageref.nextSibling.catflap_original_width + 'px';
            imageref.nextSibling.style.width=imageref.nextSibling.catflap_original_width + 'px';
            imageref.nextSibling.catflap_shrunk_status=0;
            imageref.style.display = 'block';
          }
         else
          {
            imageref.firstChild.nodeValue="Image reduced to " + imageref.nextSibling.catflap_shrunk_pc + "% of its original size. Click this bar to restore to full size.";
            imageref.style.width=imageref.nextSibling.catflap_shrunk_width + 'px';
            imageref.nextSibling.style.width=imageref.nextSibling.catflap_shrunk_width + 'px';
            imageref.nextSibling.catflap_shrunk_status=1;
            imageref.style.display = 'block';
          }
      }
  }

/* ------------------------------------------------------------------------------------------------------------------ */
function catflap_convert_to_entity()
  {
    var inpstring = escape (document.myform.inputbox.value);
    var inplen = inpstring.length;
    var outstringhex="";
    var outstringbinary="";
    var loop=0;

    // Convert CF/LF pairs to just LF
    inpstring = inpstring.replace (/%0D%0A/g, "%0A");

    while (loop < inplen)
      {
        if (inpstring.charAt(loop) == "%")
          {
            if (inpstring.charAt(++loop) == "u")
              {
                singlechar = inpstring.charAt(++loop) + inpstring.charAt(++loop) + inpstring.charAt(++loop) + inpstring.charAt(++loop);
                outstringhex += "&#x" + singlechar + ";";
                outstringbinary += "&#" + parseInt (singlechar, 16) + ";";
              }
             else
              {
                singlechar = inpstring.charAt(loop) + inpstring.charAt(++loop);
                if ( (singlechar == "09") || (singlechar == "0A") || (singlechar.search(/^[2-7].$/) != -1) && (singlechar != "6F") && (singlechar != "26") )
                  {
                    outstringhex += unescape ("%" + singlechar);
                    outstringbinary += unescape ("%" + singlechar);
                  }
                 else
                  {
                    outstringhex += "&#x" + singlechar + ";";
                    outstringbinary += "&#" + parseInt (singlechar, 16) + ";";
                  }
              }
            loop++;
          }
        else
          {
            outstringhex += inpstring.charAt(loop);
            outstringbinary += inpstring.charAt(loop++);
          }
      }

    document.myform.outputboxhex.value = outstringhex;
    document.myform.outputboxbinary.value = outstringbinary;

  }

/* ------------------------------------------------------------------------------------------------------------------ */
function catflap_topic_mark_set_latestposts_class (node, highlight, title, row1_value, row2_value)
  {
    var the_trs = document.getElementsByTagName("tr");
    var count = the_trs.length;
    var loop;
    var thistopic_id = node.parentNode.parentNode.id;

    thistopic_id_re = new RegExp ("^" + thistopic_id.replace (/_[1-9][0-9]*$/, "") + "_");
    for (loop=0; loop < count; loop++)
      {
        // if (the_trs[loop].hasAttribute("id")) --- "hasAttribute" doesn't work on IE :-(
        if (the_trs[loop].id)
          {
            if (the_trs[loop].getAttribute("id").match(thistopic_id_re))
              {
                the_trs[loop].childNodes[0].className=row1_value;
                the_trs[loop].childNodes[1].className=row2_value;
                the_trs[loop].childNodes[1].firstChild.src=highlight;
                the_trs[loop].childNodes[1].firstChild.alt=title;
                the_trs[loop].childNodes[1].firstChild.title=title;
                the_trs[loop].childNodes[2].className=row1_value;
                the_trs[loop].childNodes[3].className=row2_value;
                the_trs[loop].childNodes[4].className=row2_value;
                the_trs[loop].childNodes[5].className=row1_value;
                the_trs[loop].childNodes[6].className=row2_value;
                the_trs[loop].childNodes[7].className=row1_value;
                the_trs[loop].childNodes[8].className=row2_value;
                the_trs[loop].childNodes[9].className=row2_value;
              }
          }
      }
  }

function catflap_topic_mark_set_latesttopics_class (node, row1_value, row2_value)
  {
    node.parentNode.previousSibling.className=row1_value;
    node.parentNode.className=row2_value;
    node.parentNode.nextSibling.className=row1_value;
    node.parentNode.nextSibling.nextSibling.className=row2_value;
    node.parentNode.nextSibling.nextSibling.nextSibling.className=row1_value;
    node.parentNode.nextSibling.nextSibling.nextSibling.nextSibling.className=row2_value;
    node.parentNode.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.className=row2_value;
    node.parentNode.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.className=row1_value;
    node.parentNode.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.className=row2_value;
  }

function catflap_topic_mark_set_viewforum_class (node, row1_value, row2_value, row3_value)
  {
    node.parentNode.previousSibling.className=row1_value;
    node.parentNode.className=row2_value;
    node.parentNode.nextSibling.className=row1_value;
    node.parentNode.nextSibling.nextSibling.className=row1_value;
    node.parentNode.nextSibling.nextSibling.nextSibling.className=row2_value;
    node.parentNode.nextSibling.nextSibling.nextSibling.nextSibling.className=row1_value;
    node.parentNode.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.className=row2_value;
    node.parentNode.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.className=row2_value;
    node.parentNode.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.className=row2_value;
    node.parentNode.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.className=row3_value;
  }

function catflap_topic_mark_change(node, forum_id, topic_id, page, unsubscribe_allowed, highlightrow)
  {
    var normal      = "http://media.forums.bishopston.net/images/templates/subSilver/catflap_topic_normal.gif";
    var highlight   = "http://media.forums.bishopston.net/images/templates/subSilver/catflap_topic_highlighted.gif";
    var normal2     = "http://media.forums.bishopston.net/images/templates/subSilver/catflap_topic_normal2.gif";
    var unsubscribe = "http://media.forums.bishopston.net/images/templates/subSilver/catflap_topic_unsubscribed.gif";

    var the_cookie_value = catflap_getCookie ('catflap_marked_topics');
    var cookie_flag="";

    if (!the_cookie_value) the_cookie_value = "";

    if (page == "viewtopic")
      {
        node = document.getElementById("catflap_topic_mark_button_top");

        normal      = "http://media.forums.bishopston.net/images/templates/subSilver/icon_catflap_topic_normal.gif";
        highlight   = "http://media.forums.bishopston.net/images/templates/subSilver/icon_catflap_topic_highlighted.gif";
        normal2     = "http://media.forums.bishopston.net/images/templates/subSilver/icon_catflap_topic_normal2.gif";
        unsubscribe = "http://media.forums.bishopston.net/images/templates/subSilver/icon_catflap_topic_unsubscribed.gif";
      }

    if (node.src == normal)
      {
        node.src=highlight;
        node.title="Topic highlighted. Click to change.";
        node.alt=node.title;

        if (highlightrow == "1")
          {
            if (page == "latestposts") catflap_topic_mark_set_latestposts_class (node, node.src, node.title, "row3", "row3");
              else if (page == "latesttopics") catflap_topic_mark_set_latesttopics_class (node, "row3", "row3");
                else if (page == "viewforum") catflap_topic_mark_set_viewforum_class (node, "row3", "row3", "row3");
          }
         else
          {
            if (page == "latestposts") catflap_topic_mark_set_latestposts_class (node, node.src, node.title, "row1", "row2");
              else if (page == "latesttopics") catflap_topic_mark_set_latesttopics_class (node, "row1", "row2");
                else if (page == "viewforum") catflap_topic_mark_set_viewforum_class (node, "row1", "row2", "row3");
          }

         cookie_flag="h";
       }
      else if ( (node.src == highlight) || (node.src == unsubscribe) )
        {
          if ( (node.src == highlight) && (unsubscribe_allowed == "allow-unsubscribe") ) node.src=normal2;
            else node.src=normal;

          node.alt="Normal topic. Click to change.";
          node.title="Normal topic. Click to change.";

          if (page == "latestposts") catflap_topic_mark_set_latestposts_class (node, node.src, node.title, "row1", "row2");
            else if (page == "latesttopics") catflap_topic_mark_set_latesttopics_class (node, "row1", "row2");
              else if (page == "viewforum") catflap_topic_mark_set_viewforum_class (node, "row1", "row2", "row3");

          cookie_flag="n";
        }
        else if (node.src == normal2)
          {
            node.src=unsubscribe;
            node.alt="Topic unsubscribed. Click to change.";
            node.title="Topic unsubscribed. Click to change.";

            if (page == "latestposts") catflap_topic_mark_set_latestposts_class (node, node.src, node.title, "catflap_deleted", "catflap_deleted");
              else if (page == "latesttopics") catflap_topic_mark_set_latesttopics_class (node, "catflap_deleted", "catflap_deleted");
                else if (page == "viewforum") catflap_topic_mark_set_viewforum_class (node, "catflap_deleted", "catflap_deleted", "catflap_deleted");

            cookie_flag="u";
          }

    if (page == "viewtopic")
      {
        var node_bottom = document.getElementById("catflap_topic_mark_button_bottom");
        node_bottom.src=node.src;
        node_bottom.title=node.title;
        node_bottom.alt=node.alt;
      }

    if (cookie_flag)
      {
        // Update or create cookie:
        var search_text = new RegExp (",[1-9][0-9]*:" + topic_id + "[nuh]", "g");
        catflap_setcookie ("catflap_marked_topics", the_cookie_value.replace (search_text, "") + "," + forum_id + ":" + topic_id + cookie_flag);
      }
  }

/* ------------------------------------------------------------------------------------------------------------------ */
function catflap_set_topic_summary_coords(e)
  {

    mouse_y = 0;

    if (typeof (e) == "undefined") var e = window.event;
    if (!e) var e = window.event;
    if (e.pageY) mouse_y = e.pageY;
     else if (e.clientY) mouse_y = e.clientY + document.body.scrollTop;
  }

function catflap_show_topic_summary(node, bgcol, topicinfo)
  {
    catflap_show_topic_or_post_summary (node, bgcol, topicinfo, "Topic");
  }

function catflap_show_post_summary(node, bgcol, topicinfo)
  {
    catflap_show_topic_or_post_summary (node, bgcol, topicinfo, "Post");
    node.nextSibling.style.backgroundColor="#" + bgcol;
  }

function catflap_show_topic_or_post_summary(node, bgcol, topicinfo, what)
  {
    var preview_box = document.getElementById("catflap_preview_box");
    var height=0;

    if (self.innerHeight) height = self.innerHeight;
      else if (document.documentElement && document.documentElement.clientHeight) height = document.documentElement.clientHeight;
        else if (document.body) height = document.body.clientHeight;

    // In case this function is called before the page has completed loading, and therefore before the event has been initialised:
    if (typeof (mouse_y) == "undefined") mouse_y=0;

    // Stop box displaying off the bottom of the window:
    if (mouse_y+140 > height+document.body.scrollTop ) mouse_y = height-140+document.body.scrollTop;

    preview_box.style.right=120;
    preview_box.style.top=mouse_y;

    preview_box.style.display="block";
    preview_box.innerHTML="<b>" + what + " Summary:</b> " + unescape (topicinfo);
    node.style.backgroundColor="#" + bgcol;
  }

function catflap_hide_topic_summary(node)
  {
    var preview_box = document.getElementById("catflap_preview_box");

    preview_box.style.display="none";
    preview_box.innerHTML="";

    // The following removes the background colour override of the topic-subject TD, thus
    // reverting it to the colour specified by the class assigned to the element:
    node.style.backgroundColor='';
  }

function catflap_hide_post_summary(node)
  {
    var preview_box = document.getElementById("catflap_preview_box");

    preview_box.style.display="none";
    preview_box.innerHTML="";

    // The following removes the background colour override of the topic-subject and post-subject TD's, thus
    // reverting it to the colour specified by the class assigned to the element:
    node.style.backgroundColor='';
    node.nextSibling.style.backgroundColor='';
  }

/* ------------------------------------------------------------------------------------------------------------------ */
function catflap_get_offsetleft(node)
  {
    // YET ANOTHER IE KLUDGE: It appears that IE Won't return the value for offsetLeft unless the element contains
    // some valid display data :-( So, we purposely add a bogus character to the end, grab the offset then take the
    // bogus character off again :-( :-(  Grrrrrrrrr - this one took a while to debug :-(   -- Jamie 7th November 2006

    var ie_is_crap = node.innerHTML;
    var offset_left;

    node.innerHTML += "&nbsp;";
    offset_left = node.offsetLeft;
    if (!offset_left) offset_left=0;
    node.innerHTML = ie_is_crap;
    return (offset_left);
  }

/* ------------------------------------------------------------------------------------------------------------------ */
function catflap_process_bbcode_aligns()
  {
    var the_spans = document.getElementsByTagName("span");
    var count = the_spans.length;
    var max_lengths = new Array();
    var loop;
    var loop2;
    var tab_index;
    var class_name;
    var line_offset_left;
    var bbcode_align_padding = 30;
    var bcode_align_content;
    var word_padding_needed;

    //
    // This first section cycles through all the lines of all messages on the page, and for each line that contains
    // an align-tag, it determins the 'tab stop' position for each 'align group'. I.E. It finds the horizontal pixel
    // offset of the longest line up to an align, in each align group, i.e. the maximum value.
    // It also 'removes' the 'text box alert' which exists for those browsers without javascript.
    //
    for (loop=0; loop < count; loop++)
      {
        // Gotta love browser incompatabilities :-( - if (the_spans[loop].hasAttribute("class")) --- "hasAttribute" doesn't work on IE :-(
        class_name = the_spans[loop].getAttribute("class");
        // IE NEEDS className here!:
        if (!class_name) class_name = the_spans[loop].getAttribute("className");
  
        if (class_name)
          {
            // Firstly, hide all the formatting warning boxes displayed for people not running javascript:
            if (class_name == "catflap_halign_nojs") the_spans[loop].style.display="none";

            if (class_name.match(/^catflap_bbcode_align_[0-9]{1,2}_[0-9]{1,2}$/))
              {
                tab_index = class_name.replace(/^catflap_bbcode_align_/, "");
                if (typeof (max_lengths[tab_index]) == "undefined") max_lengths[tab_index] = 0;
                line_offset_left = catflap_get_offsetleft(the_spans[loop]);
                if (line_offset_left > max_lengths[tab_index]) max_lengths[tab_index] = line_offset_left;
              }
          }
      }
  
    //
    // Now, start at the beginning again, and loop through each line again, this time padding each line in an align-group
    // with the appropriate number of pixels to align it.
    //
    for (loop=0; loop < count; loop++)
      {
        // Gotta love browser incompatabilities :-( - if (the_spans[loop].hasAttribute("class")) --- "hasAttribute" doesn't work on IE :-(
        class_name = the_spans[loop].getAttribute("class");
        // IE NEEDS className here!:
        if (!class_name) class_name = the_spans[loop].getAttribute("className");
  
        if (class_name)
          if ( class_name.match(/^catflap_bbcode_align_[0-9]{1,2}_[0-9]{1,2}$/) || class_name.match(/^catflap_bbcode_align_after_tag_[0-9]{1,2}_[0-9]{1,2}$/) )
            {
              if (class_name.match(/^catflap_bbcode_align_[0-9]{1,2}_[0-9]{1,2}$/))
                {
                  tab_index = class_name.replace(/^catflap_bbcode_align_/, "");
                  line_offset_left = catflap_get_offsetleft(the_spans[loop]);
                  the_spans[loop].style.paddingLeft=(max_lengths[tab_index] + bbcode_align_padding - line_offset_left) + "px";
                }
  
              //
              // Now we've just aligned the line, the end of the line may be wrapping onto the next line. If this is the case,
              // we need to pad these new, wrapped lines also.
              // To do this we go through every remaining word on the line, looking to see if it has wrapped, and if so, dealing with it appropriately.
              //
              bbcode_align_content = the_spans[loop].childNodes;
              for (loop2=0; loop2 < bbcode_align_content.length; loop2++)
                if (bbcode_align_content[loop2].nodeName=="SPAN")
                {
                  // Gotta love browser incompatabilities :-(
                  class_name = bbcode_align_content[loop2].getAttribute("class");
                  if (!class_name) class_name = bbcode_align_content[loop2].getAttribute("className");
  
                  if (class_name)
                    if (class_name == "catflap_bbcode_align_word")
                      {
                        // (max_lengths[tab_index] + bbcode_align_padding) is the horizontal pixel position of our align-point,
                        // which must be greater than the OffsetLeft of the current word, otherwise word wrapping has occured, and
                        // so the word needs to be padded to fit the alignment.
                        // I.E. "If ((max_lengths[tab_index] + bbcode_align_padding - catflap_get_offsetleft(bbcode_align_content[loop2])"
                        // is greater than zero, pad to this value, to realign it.
                        word_padding_needed = max_lengths[tab_index] + bbcode_align_padding - catflap_get_offsetleft(bbcode_align_content[loop2]);
                        if ( word_padding_needed > 0 ) bbcode_align_content[loop2].style.paddingLeft = word_padding_needed + "px";
                      }
                }
            }
      }
  }

/* ------------------------------------------------------------------------------------------------------------------ */
function catflap_size_menu_nicely(what)
  {
    var menuref=document.getElementById("catflap_menu_td");

    if (what=="start")
      {
        catflap_space_width=document.getElementById("catflap_space_width").clientWidth;
        catflap_max_width=menuref.clientWidth - (catflap_space_width * 3);
      }

    var the_spans = document.getElementsByTagName("span");
    var count = the_spans.length;
    var total_menu_items=0;
    var lines_needed=1;
    var this_line_width=catflap_space_width + catflap_space_width;
    var menu_spans = new Array();
    var loop;

    for (loop=0; loop < count; loop++)
      {
        // if (the_spans[loop].hasAttribute("class")) --- "hasAttribute" doesn't work on IE :-(
        if (the_spans[loop].className)
          {
            // IE NEEDS className here!:
            if (the_spans[loop].getAttribute("class") == "catflap_menu_nowrap")
              {
                span_width = the_spans[loop].clientWidth + catflap_space_width;
                menu_spans[total_menu_items++] = span_width;
                this_line_width += span_width;
                if (this_line_width > catflap_max_width)
                  {
                    this_line_width=span_width+catflap_space_width;
                    lines_needed++;
                  }
              }
          }
       }

   // For testing, set innerHTML to (lines_needed + "<br>");
   // if (navigator.platform.indexOf('FreeBSD') !=-1) alert (total_menu_items + " : " + total_menu_width + " : " + catflap_max_width + " : " + menuref.clientWidth);
   if (catflap_max_width > 150)
   {
     menuref.style.width=catflap_max_width - 100 + 'px';
     // document.getElementsByTagName("form")[1].innerHTML=catflap_max_width;
   }
  }

/* ------------------------------------------------------------------------------------------------------------------ */
function catflap_set_foreground_colour_default()
  {
    if (document.getElementById('foreground_colorused').bgColor)
      {
        colour = document.getElementById('foreground_colorused').bgColor;
        if (confirm ("OK to change default foreground colour to: " + colour +  " ?")==true)
          catflap_setcookie ("catflap_foreground_colour_default", colour.substring(1).toLowerCase());
       }
     else alert ("You need to first select a colour on the bar to the left");
  }

function catflap_set_background_colour_default()
  {
    if (document.getElementById('background_colorused').bgColor)
      {
        colour = document.getElementById('background_colorused').bgColor;
        if (confirm ("OK to change default background colour to: " + colour +  " ?")==true)
          catflap_setcookie ("catflap_background_colour_default", colour.substring(1).toLowerCase());
      }
     else alert ("You need to first select a colour on the bar to the left");
  }

function catflap_reset_colour_defaults()
  {
    if (confirm ("OK to change default posting colours to the system defaults ?")==true)
      {
        catflap_setcookie ("catflap_foreground_colour_default", "-1");
        catflap_setcookie ("catflap_background_colour_default", "-1");
      }
  }

/* ------------------------------------------------------------------------------------------------------------------ */
// The following functions are from the mod_calendar mod by Ptirhiik:
// catflap_hdr_ref, catflap_hdr_expand, catflap_hdr_contract, catflap_hdr_toggle:

function catflap_hdr_ref(object)
{
        if (document.getElementById)
        {
                return document.getElementById(object);
        }
        else if (document.all)
        {
                return eval('document.all.' + object);
        }
        else
        {
                return false;
        }
}

function catflap_hdr_expand(object)
{
        var object = catflap_hdr_ref(object);

        if( !object.style )
        {
                return false;
        }
        else
        {
                object.style.display = '';
        }

        if (window.event)
        {
                window.event.cancelBubble = true;
        }
}

function catflap_hdr_contract(object)
{
        var object = catflap_hdr_ref(object);

        if( !object.style )
        {
                return false;
        }
        else
        {
                object.style.display = 'none';
        }

        if (window.event)
        {
                window.event.cancelBubble = true;
        }
}

function catflap_hdr_toggle(object, open_close, open_icon, close_icon)
{
        var object = catflap_hdr_ref(object);
        var icone = catflap_hdr_ref(open_close);

        if( !object.style )
        {
                return false;
        }

        if( object.style.display == 'none' )
        {
                object.style.display = '';
                icone.src = close_icon;
                document.cookie = 'calendar_state=open; path=/';
        }
        else
        {
                object.style.display = 'none';
                icone.src = open_icon;
                document.cookie = 'calendar_state=closed; path=/';
        }
}

/*
   Set the open/closed state of the calendar box based on the value of the
   cookie. If the cookie isn't set, use the normal users default.

   -- Written by Jamie Jones <jamie@bishopston.net>
*/
function catflap_hdr_cookie_set(object, open_close, open_icon, close_icon, default_state)
  {
    var object = catflap_hdr_ref(object);
    var icone = catflap_hdr_ref(open_close);

    if (!object.style) return false;

    the_cookie_value = catflap_getCookie ('calendar_state');

    // If cookie is set to "open", make calendar box open.
    // If cookie is set to "close", make calendar box closed.
    // If cookie is unset, use board defaults.

    if (!the_cookie_value) 
      {
        if (default_state == "none") the_cookie_value = "closed";
          else the_cookie_value = "open";
      }
    if (the_cookie_value == "open") 
      {
        object.style.display = '';
        icone.src = close_icon;
      }

    if (the_cookie_value == "closed") 
      {
        object.style.display = 'none';
        icone.src = open_icon;
      }
   }

/* ------------------------------------------------------------------------------------------------------------------ */
// The following function is from the mod_arcade system:

var win = null;
function catflap_Gk_PopTart(mypage,myname,w,h,scroll)
{
  LeftPosition = (screen.width) ? (screen.width-w)/2 : 0;
  TopPosition = (screen.height) ? (screen.height-h)/2 : 0;
  settings = 'height='+h+',width='+w+',top='+TopPosition+',left='+LeftPosition+',scrollbars='+scroll+',resizable=yes';
  win = window.open(mypage,myname,settings);
}

/* ------------------------------------------------------------------------------------------------------------------ */
// The following function is by Stoyan Stefanov:

/**
 * A class to parse color values
 * @author Stoyan Stefanov <sstoo@gmail.com>
 * @link   http://www.phpied.com/rgb-color-parser-in-javascript/
 * @license Use it if you like it
 */
function catflap_RGBColor(color_string)
{
    this.ok = false;

    // strip any leading #
    if (color_string.charAt(0) == '#') { // remove # if any
        color_string = color_string.substr(1,6);
    }

    color_string = color_string.replace(/ /g,'');
    color_string = color_string.toLowerCase();

    // before getting into regexps, try simple matches
    // and overwrite the input
    var simple_colors = {
        aliceblue: 'f0f8ff',
        antiquewhite: 'faebd7',
        aqua: '00ffff',
        aquamarine: '7fffd4',
        azure: 'f0ffff',
        beige: 'f5f5dc',
        bisque: 'ffe4c4',
        black: '000000',
        blanchedalmond: 'ffebcd',
        blue: '0000ff',
        blueviolet: '8a2be2',
        brown: 'a52a2a',
        burlywood: 'deb887',
        cadetblue: '5f9ea0',
        chartreuse: '7fff00',
        chocolate: 'd2691e',
        coral: 'ff7f50',
        cornflowerblue: '6495ed',
        cornsilk: 'fff8dc',
        crimson: 'dc143c',
        cyan: '00ffff',
        darkblue: '00008b',
        darkcyan: '008b8b',
        darkgoldenrod: 'b8860b',
        darkgray: 'a9a9a9',
        darkgreen: '006400',
        darkkhaki: 'bdb76b',
        darkmagenta: '8b008b',
        darkolivegreen: '556b2f',
        darkorange: 'ff8c00',
        darkorchid: '9932cc',
        darkred: '8b0000',
        darksalmon: 'e9967a',
        darkseagreen: '8fbc8f',
        darkslateblue: '483d8b',
        darkslategray: '2f4f4f',
        darkturquoise: '00ced1',
        darkviolet: '9400d3',
        deeppink: 'ff1493',
        deepskyblue: '00bfff',
        dimgray: '696969',
        dodgerblue: '1e90ff',
        feldspar: 'd19275',
        firebrick: 'b22222',
        floralwhite: 'fffaf0',
        forestgreen: '228b22',
        fuchsia: 'ff00ff',
        gainsboro: 'dcdcdc',
        ghostwhite: 'f8f8ff',
        gold: 'ffd700',
        goldenrod: 'daa520',
        gray: '808080',
        green: '008000',
        greenyellow: 'adff2f',
        honeydew: 'f0fff0',
        hotpink: 'ff69b4',
        indianred : 'cd5c5c',
        indigo : '4b0082',
        ivory: 'fffff0',
        khaki: 'f0e68c',
        lavender: 'e6e6fa',
        lavenderblush: 'fff0f5',
        lawngreen: '7cfc00',
        lemonchiffon: 'fffacd',
        lightblue: 'add8e6',
        lightcoral: 'f08080',
        lightcyan: 'e0ffff',
        lightgoldenrodyellow: 'fafad2',
        lightgrey: 'd3d3d3',
        lightgreen: '90ee90',
        lightpink: 'ffb6c1',
        lightsalmon: 'ffa07a',
        lightseagreen: '20b2aa',
        lightskyblue: '87cefa',
        lightslateblue: '8470ff',
        lightslategray: '778899',
        lightsteelblue: 'b0c4de',
        lightyellow: 'ffffe0',
        lime: '00ff00',
        limegreen: '32cd32',
        linen: 'faf0e6',
        magenta: 'ff00ff',
        maroon: '800000',
        mediumaquamarine: '66cdaa',
        mediumblue: '0000cd',
        mediumorchid: 'ba55d3',
        mediumpurple: '9370d8',
        mediumseagreen: '3cb371',
        mediumslateblue: '7b68ee',
        mediumspringgreen: '00fa9a',
        mediumturquoise: '48d1cc',
        mediumvioletred: 'c71585',
        midnightblue: '191970',
        mintcream: 'f5fffa',
        mistyrose: 'ffe4e1',
        moccasin: 'ffe4b5',
        navajowhite: 'ffdead',
        navy: '000080',
        oldlace: 'fdf5e6',
        olive: '808000',
        olivedrab: '6b8e23',
        orange: 'ffa500',
        orangered: 'ff4500',
        orchid: 'da70d6',
        palegoldenrod: 'eee8aa',
        palegreen: '98fb98',
        paleturquoise: 'afeeee',
        palevioletred: 'd87093',
        papayawhip: 'ffefd5',
        peachpuff: 'ffdab9',
        peru: 'cd853f',
        pink: 'ffc0cb',
        plum: 'dda0dd',
        powderblue: 'b0e0e6',
        purple: '800080',
        red: 'ff0000',
        rosybrown: 'bc8f8f',
        royalblue: '4169e1',
        saddlebrown: '8b4513',
        salmon: 'fa8072',
        sandybrown: 'f4a460',
        seagreen: '2e8b57',
        seashell: 'fff5ee',
        sienna: 'a0522d',
        silver: 'c0c0c0',
        skyblue: '87ceeb',
        slateblue: '6a5acd',
        slategray: '708090',
        snow: 'fffafa',
        springgreen: '00ff7f',
        steelblue: '4682b4',
        tan: 'd2b48c',
        teal: '008080',
        thistle: 'd8bfd8',
        tomato: 'ff6347',
        turquoise: '40e0d0',
        violet: 'ee82ee',
        violetred: 'd02090',
        wheat: 'f5deb3',
        white: 'ffffff',
        whitesmoke: 'f5f5f5',
        yellow: 'ffff00',
        yellowgreen: '9acd32'
    };
    for (var key in simple_colors) {
        if (color_string == key) {
            color_string = simple_colors[key];
        }
    }
    // emd of simple type-in colors

    // array of color definition objects
    var color_defs = [
        {
            re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,
            example: ['rgb(123, 234, 45)', 'rgb(255,234,245)'],
            process: function (bits){
                return [
                    parseInt(bits[1]),
                    parseInt(bits[2]),
                    parseInt(bits[3])
                ];
            }
        },
        {
            re: /^(\w{2})(\w{2})(\w{2})$/,
            example: ['#00ff00', '336699'],
            process: function (bits){
                return [
                    parseInt(bits[1], 16),
                    parseInt(bits[2], 16),
                    parseInt(bits[3], 16)
                ];
            }
        },
        {
            re: /^(\w{1})(\w{1})(\w{1})$/,
            example: ['#fb0', 'f0f'],
            process: function (bits){
                return [
                    parseInt(bits[1] + bits[1], 16),
                    parseInt(bits[2] + bits[2], 16),
                    parseInt(bits[3] + bits[3], 16)
                ];
            }
        }
    ];

    // search through the definitions to find a match
    for (var i = 0; i < color_defs.length; i++) {
        var re = color_defs[i].re;
        var processor = color_defs[i].process;
        var bits = re.exec(color_string);
        if (bits) {
            channels = processor(bits);
            this.r = channels[0];
            this.g = channels[1];
            this.b = channels[2];
            this.ok = true;
        }

    }

    // validate/cleanup values
    this.r = (this.r < 0 || isNaN(this.r)) ? 0 : ((this.r > 255) ? 255 : this.r);
    this.g = (this.g < 0 || isNaN(this.g)) ? 0 : ((this.g > 255) ? 255 : this.g);
    this.b = (this.b < 0 || isNaN(this.b)) ? 0 : ((this.b > 255) ? 255 : this.b);

    // some getters
    this.toRGB = function () {
        return 'rgb(' + this.r + ', ' + this.g + ', ' + this.b + ')';
    }
    this.toHex = function () {
        var r = this.r.toString(16);
        var g = this.g.toString(16);
        var b = this.b.toString(16);
        if (r.length == 1) r = '0' + r;
        if (g.length == 1) g = '0' + g;
        if (b.length == 1) b = '0' + b;
        return r + g + b;
    }

    // help
    this.getHelpXML = function () {

        var examples = new Array();
        // add regexps
        for (var i = 0; i < color_defs.length; i++) {
            var example = color_defs[i].example;
            for (var j = 0; j < example.length; j++) {
                examples[examples.length] = example[j];
            }
        }
        // add type-in colors
        for (var sc in simple_colors) {
            examples[examples.length] = sc;
        }

        var xml = document.createElement('ul');
        xml.setAttribute('id', 'rgbcolor-examples');
        for (var i = 0; i < examples.length; i++) {
            try {
                var list_item = document.createElement('li');
                var list_color = new RGBColor(examples[i]);
                var example_div = document.createElement('div');
                example_div.style.cssText =
                        'margin: 3px; '
                        + 'border: 1px solid black; '
                        + 'background:' + list_color.toHex() + '; '
                        + 'color:' + list_color.toHex()
                ;
                example_div.appendChild(document.createTextNode('test'));
                var list_item_value = document.createTextNode(
                    ' ' + examples[i] + ' -> ' + list_color.toRGB() + ' -> ' + list_color.toHex()
                );
                list_item.appendChild(example_div);
                list_item.appendChild(list_item_value);
                xml.appendChild(list_item);

            } catch(e){}
        }
        return xml;

    }

}

