
//****************************************************************************************
// trofieldguidewidget.js
//
// (c) 2008 Priacta, Inc.
//
// This file is distributed under the terms of the Creative Commons Attribution-No
// Derivative Works 3.0 United States License.
//
// A summary of this license is available at:
// http://creativecommons.org/licenses/by-nd/3.0/us/
//
// The full terms and conditions are available at:
// http://creativecommons.org/licenses/by-nd/3.0/us/legalcode
//
// For the purposes of attribution in 4b, this copyright section will be considered
// sufficient credit, reasonable for the purposes of this tool.
//****************************************************************************************

//****************************************************************************************
// This file is designed to be minimally disruptive to names. At the global level, only
// one variable, and one function are defined. The variable is used to keep track of
// objects so that this can be fully encapsulated. The function acts like a constructor. 
//****************************************************************************************

//****************************************************************************************
// http://javascriptcompressor.com/ can be used to reduce the size of this code to about a
// third. Be aware that if any lines are missing the ; this will cause a problem, even though
// the code may still execute in the browser. http://www.jslint.com/ can help you track down
// the missing semi-colons. 
//****************************************************************************************

var __g_PriactaFieldGuides = new Array(); // array of all field guide widgets created. This is used when
                                          // referencing the widget in HTML (for mouse events mostly).

// Consructor for the widget. Example usage:
// 
// var widget = new PriactaFieldGuideWidget();
// widget.MakeWidget("widget");
function PriactaFieldGuideWidget(idprefix, cssprefix, autohidetimeout)
{

// parameter defaults
if (idprefix == null){idprefix = 'tro_field_guide_';}
if (cssprefix == null){cssprefix = 'fieldguidewidget_';}
if (autohidetimeout == null){autohidetimeout = 500;}
//if (usecustomdroplist == null){usecustomdroplist = true;}

//PriactaFieldGuide = new Object();
var wnum = __g_PriactaFieldGuides.length;
__g_PriactaFieldGuides[wnum] = this; // add the new widget
this.hidelisttimeout = 0;
this.openlist = '';

// Flags for what a tool can handle
var FLAG_CAL = 0x00000001;
var FLAG_TASK = 0x00000002;
var FLAG_MAIL = 0x00000004;
var FLAG_MOBILE = 0x00000008;
var FLAG_ALPHA = 0x000000010; 
var FLAG_BETA = 0x000000020; // TODO: This is not a good way to do this, since the tool 
                             // may be only PART beta (paper tasklist anyone?) In this case,
                             // the work around is to have two tools, one for the beta parts,
                             // and one for the non beta parts. The tools should have different
                             // IDs (paper_beta).
this.FLAG_CAL = FLAG_CAL;
this.FLAG_TASK = FLAG_TASK;
this.FLAG_MAIL = FLAG_MAIL;
this.FLAG_MOBILE = FLAG_MOBILE;
this.FLAG_ALPHA = FLAG_ALPHA;
this.FLAG_BETA = FLAG_BETA;

this.Tool = function (name, id, flags)
{
    this.name = name;
    this.id = id;
    this.flags = flags;
};

// WARNING!!! The ids AND NAMES must match the list in util/trotools.php EXACTLY!!!
// If they don't match exactly, the tools that don't match won't work right.
this.AllTools = new Array(
                  new this.Tool('', '', FLAG_TASK | FLAG_CAL | FLAG_MAIL | FLAG_MOBILE),
                  new this.Tool('Trog Bar', 'trog', FLAG_TASK), 
                  new this.Tool('Google Calendar', 'gcal', FLAG_CAL),
                  new this.Tool('Google Mail', 'gmail', FLAG_MAIL),
                  new this.Tool('Outlook', 'outlook', FLAG_TASK | FLAG_CAL | FLAG_MAIL),
                  new this.Tool('Remember The Milk', 'rtm', FLAG_TASK),
                  new this.Tool('ToDoList', 'todolist', FLAG_TASK),
                  new this.Tool('Toodledo (beta)', 'toodledo', FLAG_TASK | FLAG_BETA | FLAG_ALPHA),
                  new this.Tool('None', 'none', FLAG_MOBILE),
                  new this.Tool('Paper', 'paper', FLAG_CAL | FLAG_MOBILE),
                  new this.Tool('iPhone/iTouch', 'iphone', FLAG_MOBILE),
                  new this.Tool('Windows Mobile 5/6', 'wm', FLAG_MOBILE),
                  new this.Tool('Blackberry', 'blackberry', FLAG_MOBILE),
                  new this.Tool('Palm (non-WM)', 'palm', FLAG_MOBILE),
                  new this.Tool('Other', 'other', FLAG_MAIL | FLAG_CAL | FLAG_MOBILE),
                  new this.Tool('Thunderbird', 'tbird', FLAG_MAIL)
                  );

// based on a certain combination of tools, GetCompatibleTools will return a
// list of tool options, similar to the AllTools list, but without anything
// that could create an invalid configuration.
//
// if any parameter == '' || == null, it will be considered to be undecided
//
// Most tools should be fully compatible with eachother, however, a few tools
// are actually add-ons, and require certain other tools to be used.
this.GetCompatibleTools = function(tasklist, calendar, mailclient, mobile, stripalpha, stripbeta)
{
    stripalpha = (stripbeta === null ? true : stripalpha);
    stripbeta = (stripbeta === null ? true : stripbeta);
    
    // Javascript can't copy the array correctly on it's own, do it manually
    // at the same time, handle the stripbeta functionality
    var compat = new Array();
    for (var a = 0; a < this.AllTools.length; a++)
    {
        var zapit = (stripalpha && (this.AllTools[a].flags & FLAG_ALPHA)) ||
                    (stripbeta && (this.AllTools[a].flags & FLAG_BETA));  
        compat[a] = new this.Tool(this.AllTools[a].name, 
                                  this.AllTools[a].id, 
                                  (zapit ? 0 : this.AllTools[a].flags));
    }
    // This is a two pass process.
    
    // run the prefilter
    if (typeof(ToolsPreFilter) != "undefined")
    {
	    compat = ToolsPreFilter(compat, tasklist, calendar, mailclient, mobile, stripalpha, stripbeta);
    }
    
    // First, if a given tool is selected, it should
    // remove any tools options that it can't work with.
    if (tasklist == 'trog')
    {
       // Trog calendar must be Outlook or paper, zap the calendar
        // modes for all tools except Outlook or paper
        //for (var a = 0; a < compat.length; a++)
        //{
        //    if (compat[a].id != 'outlook' && compat[a].id != 'paper')
        //    {
        //        compat[a].flags = (compat[a].flags & (~FLAG_CAL));
        //    }
        //}
        // Trog mail client must be Outlook, zap the mail client
        // modes for all tools except Outlook
        //for (var a = 0; a < compat.length; a++)
        //{
        //    if (compat[a].id != 'outlook')
        //    {
        //        compat[a].flags = (compat[a].flags & (~FLAG_MAIL));
        //    }
        //}
    }
    /* iPhone is fine for anybody.
    if (mobile == 'iphone')
    {
        // iPhone tasklist must be RTM, outlook, Trog now
        for (var a = 0; a < compat.length; a++)
        {
            if (compat[a].id != 'rtm' && compat[a].id != 'outlook' && compat[a].id != 'trog')
            {
                compat[a].flags = (compat[a].flags & (~(FLAG_TASK)));
            }
        }
    }
    */

    // Second, a tool should remove itself if an incompatible tool
    // is already selected.
    if (tasklist != '' && tasklist != null)
    {
      /* iPhone is fine for anybody.
      // iPhone mobile requires rtm, outlook, or trog bar
      if (tasklist != 'rtm' && tasklist != 'outlook' && tasklist != 'trog')
        {
            for (var a = 0; a < compat.length; a++)
            {
                if (compat[a].id == 'iphone')
                {
                    compat[a].flags = (compat[a].flags & (~FLAG_MOBILE));
                }
            }
        }
      */
    }
    if (calendar != '' && calendar != null)
    {
      // Trog tasklist requires outlook or paper to be the calendar
	    //if (calendar != 'outlook' && calendar != 'paper')
	    //{
	    //    for (var a = 0; a < compat.length; a++)
	    //    {
	    //        if (compat[a].id == 'trog')
	    //        {
	    //            compat[a].flags = (compat[a].flags & (~FLAG_TASK));
	    //        }
	    //    }
	    //}
  	}
    if (mailclient != '' && mailclient != null)
    {
        // Trog tasklist requires outlook to be the mailclient
        //if (mailclient != 'outlook')
        //{
        //    for (var a = 0; a < compat.length; a++)
        //    {
        //        if (compat[a].id == 'trog')
        //        {
        //            compat[a].flags = (compat[a].flags & (~FLAG_TASK));
        //        }
        //    }
        //}
    }
    return compat;
};

this.GetSelectedTaskList = function()
{
    var e = document.getElementById(idprefix+"tasklist_value");
    if (e != null)
    {
        return e.value;
    }
//    else if (usecustomdroplist == false)
//    {
//        e = document.getElementById(idprefix+"tasklist");
//        if (e != null)
//        {
//            return e.options[e.selectedIndex].value;
//        }
//    }
    return '';
};

this.GetSelectedCalendar = function()
{
    var e = document.getElementById(idprefix+"calendar_value");
    if (e != null)
    {
        return e.value;
    }
//    else if (usecustomdroplist == false)
//    {
//        e = document.getElementById(idprefix+"calendar");
//        if (e != null)
//        {
//            return e.options[e.selectedIndex].value;
//        }
//    }
    return '';
};

this.GetSelectedMailClient = function()
{
    var e = document.getElementById(idprefix+"mailclient_value");
    if (e != null)
    {
        return e.value;
    }
//    else if (usecustomdroplist == false)
//    {
//        e = document.getElementById(idprefix+"mailclient");
//        if (e != null)
//        {
//            return e.options[e.selectedIndex].value;
//        }
//    }
    return '';
};

this.GetSelectedMobile = function()
{
    var e = document.getElementById(idprefix+"mobile_value");
    if (e != null)
    {
        return e.value;
    }
//    else if (usecustomdroplist == false)
//    {
//        e = document.getElementById(idprefix+"mobile");
//        if (e != null)
//        {
//            return e.options[e.selectedIndex].value;
//        }
//    }
    return '';
};

this.HideOpenList = function()
{
    var e = document.getElementById(this.openlist+"_list");
    if (e != null)
    {
        if (e.className == cssprefix+'optionlistshow')
        {
            e.className = cssprefix+'optionlisthide';
        }
    }
    clearTimeout(this.hidelisttimeout);
};


this.OptionCtlAreaClick = function(fldname)
{
    var ctl = document.getElementById(fldname);
    var display = document.getElementById(fldname+"_display");
    var btn = document.getElementById(fldname+"_button");
    var e = document.getElementById(fldname+"_list");
    if (ctl != null && display != null && btn != null && e != null)
    {
        if (e.className == cssprefix+'optionlistshow')
        {
            e.className = cssprefix+'optionlisthide';
        }
        else
        {
            this.HideOpenList(); // hide the open list, if any
            // move the list to the new position
            e.style.position = "absolute";
            // The one pixel below is because the relatively positioned box that the list sits
            // inside actually starts one pixel left of where we want.
            e.style.left = '1px';
            e.bottom = 0;
            // show it
            e.className = cssprefix+'optionlistshow';
            this.openlist = fldname; // remember the currently open list
        }
    }
    
};

this.OptionCtlAreaMouseDown = function(fldname)
{
    // switch the style to represent pressed...
    var e = document.getElementById(fldname+"_ctlarea");
    if (e != null)
    {
        e.className = cssprefix+"optionctlareapressed";
    }
};

this.OptionCtlAreaMouseUp = function(fldname)
{
    // switch the style to represent hover...
    var e = document.getElementById(fldname+"_ctlarea");
    if (e != null)
    {
        e.className = cssprefix+"optionctlareahover";
    }
};

this.OptionCtlAreaMouseOver = function(fldname)
{
    clearTimeout(this.hidelisttimeout);
    // switch the style to represent hover...
    var e = document.getElementById(fldname+"_ctlarea");
    if (e != null)
    {
        e.className = cssprefix+"optionctlareahover";
    }
};

this.OptionCtlAreaMouseOut = function(fldname)
{
    this.hidelisttimeout = setTimeout('__g_PriactaFieldGuides['+wnum+'].HideOpenList();', autohidetimeout);
    // switch the style to represent normal...
    var e = document.getElementById(fldname+"_ctlarea");
    if (e != null)
    {
        e.className = cssprefix+"optionctlarea";
    }
};

this.OptionDisplayClick = function(fldname)
{
    // for now, this is handled by the control area...
};

this.OptionDisplayMouseDown = function(fldname)
{
    // for now, this is handled by the control area...
};

this.OptionDisplayMouseUp = function(fldname)
{
    // for now, this is handled by the control area...
};

this.OptionDisplayMouseOver = function(fldname)
{
    // for now, this is handled by the control area...
};

this.OptionDisplayMouseOut = function(fldname)
{
    // for now, this is handled by the control area...
};

this.OptionButtonClick = function(fldname)
{
    // for now, this is handled by the control area...
};

this.OptionButtonMouseDown = function(fldname)
{
    // for now, this is handled by the control area...
};

this.OptionButtonMouseUp = function(fldname)
{
    // for now, this is handled by the control area...
};

this.OptionButtonMouseOver = function(fldname)
{
    // for now, this is handled by the control area...
};

this.OptionButtonMouseOut = function(fldname)
{
    // for now, this is handled by the control area...
};

this.OptionListMouseOver = function(fldname)
{
    clearTimeout(this.hidelisttimeout);
    // Set the hover class
    var e = document.getElementById(fldname+"_list");
    if (e != null)
    {
	    if (e.className == cssprefix+"optionlistshow")
	    {
	        e.className = cssprefix+"optionlistshowhover";
	    }
    }
};

this.OptionListMouseOut = function(fldname)
{
    this.hidelisttimeout = setTimeout('__g_PriactaFieldGuides['+wnum+'].HideOpenList();', autohidetimeout);
    // clear the hover class
    var e = document.getElementById(fldname+"_list");
    if (e != null)
    {
	    if (e.className == cssprefix+"optionlistshowhover")
	    {
	        e.className = cssprefix+"optionlistshow";
	    }
	}
};

this.OptionListItemClick = function(fldname, toolid, element)
{
    // hide the list
    this.HideOpenList();
    // update the value
    var val = document.getElementById(fldname+"_value");
    if (val != null)
    {
        val.value = toolid;
    }
    // refresh the rest of the widget
    this.UpdateOptions(FLAG_TASK | FLAG_CAL | FLAG_MAIL | FLAG_MOBILE);
};

this.OptionListItemMouseOver = function(fldname, toolid, element)
{
    clearTimeout(this.hidelisttimeout);
    // Set the hover class
    if (element.className == cssprefix+"optionitemselected")
    {
        element.className = cssprefix+"optionitemselectedhover";
    }
    else
    {
        element.className = cssprefix+"optionitemhover";
    }
};

this.OptionListItemMouseOut = function(fldname, toolid, element)
{
    // clear the hover class
    if (element.className == cssprefix+"optionitemselectedhover")
    {
        element.className = cssprefix+"optionitemselected";
    }
    else
    {
        element.className = "";
    }
};

// this creates the guts of the combo box
// assumes that the hidden field for value has already been created
// Wants the final field name (WITH the prefix)
this.ComboBoxInnerHTML = function(tools, fldname, blank, flags, selected)
{
    var ret = "";
    var selectedname = blank;
//    if (usecustomdroplist)
//    {
	    // The wierd div below will take up no space in either IE 7, or Firefox (need to test IE6, Safari, and Opera)
	    // This will allow us to relatively position the droplist without any danger of the position
	    // being wrong if a parent of the widget is relatively positioned.
	    ret += "<div style='position: relative; padding:1px; margin:-1px; border: 0px none; text-indent: 0;'>";
	    ret += "<ul class='"+cssprefix+"optionlisthide' id='"+fldname+"_list'";
	    ret += " onmouseover='__g_PriactaFieldGuides["+wnum+"].OptionListMouseOver(\""+fldname+"\");'";
	    ret += " onmouseout='__g_PriactaFieldGuides["+wnum+"].OptionListMouseOut(\""+fldname+"\");'";
	    ret += ">";
	    ret += "<li onclick='__g_PriactaFieldGuides["+wnum+"].OptionListItemClick(\""+fldname+"\", \"\", this);'";
	    ret += " onmouseover='__g_PriactaFieldGuides["+wnum+"].OptionListItemMouseOver(\""+fldname+"\", \"\", this);'";
	    ret += " onmouseout='__g_PriactaFieldGuides["+wnum+"].OptionListItemMouseOut(\""+fldname+"\", \"\", this);'";
	    if (selected == '')
	    {
	        ret += " class='"+cssprefix+"optionitemselected'";
	    }
	    ret += ">"+blank+"</li>";
	    for (var a = 0; a < tools.length; a++)
	    {
	        if (tools[a].flags & flags)
	        {
			    ret += "<li onclick='__g_PriactaFieldGuides["+wnum+"].OptionListItemClick(\""+fldname+"\", \""+tools[a].id+"\", this);'";
			    ret += " onmouseover='__g_PriactaFieldGuides["+wnum+"].OptionListItemMouseOver(\""+fldname+"\", \""+tools[a].id+"\", this);'";
			    ret += " onmouseout='__g_PriactaFieldGuides["+wnum+"].OptionListItemMouseOut(\""+fldname+"\", \""+tools[a].id+"\", this);'";
	            if (selected == tools[a].id)
	            {
			        ret += " class='"+cssprefix+"optionitemselected'";
			        selectedname = tools[a].name; // remember for later
	            }
	            ret += ">"+tools[a].name+"</li>";
	        }
	    }
	    ret += "</ul>";
	    ret += "</div>";
	    // build the main control area with button and display
	    var ctl = '';
	    ctl += "<div class='"+cssprefix+"optionctlarea' id='"+fldname+"_ctlarea'";
        ctl += " onclick='__g_PriactaFieldGuides["+wnum+"].OptionCtlAreaClick(\""+fldname+"\");'";
        ctl += " onmousedown='__g_PriactaFieldGuides["+wnum+"].OptionCtlAreaMouseDown(\""+fldname+"\");'";
        ctl += " onmouseup='__g_PriactaFieldGuides["+wnum+"].OptionCtlAreaMouseUp(\""+fldname+"\");'";
	    ctl += " onmouseover='__g_PriactaFieldGuides["+wnum+"].OptionCtlAreaMouseOver(\""+fldname+"\");'";
	    ctl += " onmouseout='__g_PriactaFieldGuides["+wnum+"].OptionCtlAreaMouseOut(\""+fldname+"\");'";
	    ctl += " ><div>";
	    ctl += "<div class='"+cssprefix+"optiondisplay' id='"+fldname+"_display'";
        ctl += " onclick='__g_PriactaFieldGuides["+wnum+"].OptionDisplayClick(\""+fldname+"\");'";
        ctl += " onmousedown='__g_PriactaFieldGuides["+wnum+"].OptionDisplayMouseDown(\""+fldname+"\");'";
        ctl += " onmouseup='__g_PriactaFieldGuides["+wnum+"].OptionDisplayMouseUp(\""+fldname+"\");'";
        ctl += " onmouseover='__g_PriactaFieldGuides["+wnum+"].OptionDisplayMouseOver(\""+fldname+"\");'";
        ctl += " onmouseout='__g_PriactaFieldGuides["+wnum+"].OptionDisplayMouseOut(\""+fldname+"\");'";
        ctl += "><div>"+selectedname+"</div></div>";
	    ctl += "<div class='"+cssprefix+"optionbutton' id='"+fldname+"_button'";
        ctl += " onclick='__g_PriactaFieldGuides["+wnum+"].OptionButtonClick(\""+fldname+"\");'";
        ctl += " onmousedown='__g_PriactaFieldGuides["+wnum+"].OptionButtonMouseDown(\""+fldname+"\");'";
        ctl += " onmouseup='__g_PriactaFieldGuides["+wnum+"].OptionButtonMouseUp(\""+fldname+"\");'";
        ctl += " onmouseover='__g_PriactaFieldGuides["+wnum+"].OptionButtonMouseOver(\""+fldname+"\");'";
        ctl += " onmouseout='__g_PriactaFieldGuides["+wnum+"].OptionButtonMouseOut(\""+fldname+"\");'";
        ctl += "><div>&nbsp;</div></div>";
	    ctl += "</div></div>";
	    // put the button and display in front of the list (prepend the string)
	    ret = ctl + ret;
//    }
//    else
//    {
//	    ret += "<option value=''"
//	    if (selected == '')
//	    {
//	        ret += " selected";
//	    }
//	    ret += ">"+blank+"</option>";
//	    for (var a = 0; a < tools.length; a++)
//	    {
//	        if (tools[a].flags & flags)
//	        {
//	            ret += "<option value='"+tools[a].id+"'";
//	            if (selected == tools[a].id)
//	            {
//	                ret += " selected";
//	            }
//	            ret += ">"+tools[a].name+"</option>";
//	        }
//	    }
//    }
    return ret;
};

this.ValueFieldHTML = function(fldname, selected)
{
    return "<hidden id='"+idprefix+fldname+"_value' name='"+fldname+"' value='"+selected+"' \/>";
};

// this creates the control shell with the guts
// Wants the field name WITHOUT the prefix
this.ComboBoxHTML = function(tools, fldname, blank, flags, selected)
{
    var ret = "";
//    if (usecustomdroplist)
//    {
	    ret += this.ValueFieldHTML(fldname, selected); //"<hidden id='"+idprefix+fldname+"_value' name='"+fldname+"' value='"+selected+"' />";
	    ret += "<div class='"+cssprefix+"option' id='"+idprefix+fldname+"'><div>";
	    ret += this.ComboBoxInnerHTML(tools, idprefix+fldname, blank, flags, selected);
	    ret += "</div></div>";
//    }
//    else
//    {
//	    ret += "<select class='"+cssprefix+"select' id='"+idprefix+fldname+"' onchange='__g_PriactaFieldGuides["+wnum+"].UpdateOptions("+(~flags)+")'>";
//	    ret += this.ComboBoxInnerHTML(tools, fldname, blank, flags, selected);
//	    ret += "</select>";
//    }
    return ret;
};

this.TaskListOptionsInnerHTML = function(tools, selected)
{
    return this.ComboBoxInnerHTML(tools, idprefix+"tasklist", "Select a Task List...", FLAG_TASK, selected);
};

this.CalendarOptionsInnerHTML = function(tools, selected)
{
    return this.ComboBoxInnerHTML(tools, idprefix+"calendar", "Select a Calendar...", FLAG_CAL, selected);
};

this.MailClientOptionsInnerHTML = function(tools, selected)
{
    return this.ComboBoxInnerHTML(tools, idprefix+"mailclient", "Select a Mail Client...", FLAG_MAIL, selected);
};

this.MobileOptionsInnerHTML = function(tools, selected)
{
    return this.ComboBoxInnerHTML(tools, idprefix+"mobile", "Select a Mobile Option...", FLAG_MOBILE, selected);
};

this.TaskListOptionsHTML = function(tools, selected)
{
    return this.ComboBoxHTML(tools, "tasklist", "Select a Task List...", FLAG_TASK, selected);
};

this.CalendarOptionsHTML = function(tools, selected)
{
    return this.ComboBoxHTML(tools, "calendar", "Select a Calendar...", FLAG_CAL, selected);
};

this.MailClientOptionsHTML = function(tools, selected)
{
    return this.ComboBoxHTML(tools, "mailclient", "Select a Mail Client...", FLAG_MAIL, selected);
};

this.MobileOptionsHTML = function(tools, selected)
{
    return this.ComboBoxHTML(tools, "mobile", "Select a Mobile Option...", FLAG_MOBILE, selected);
};

this.BeginFormHTML = function()
{
    return "<form action='http://www.priacta.com/fieldguidetest/Priacta_TRO_Manual.php' method='get'>";
};

this.EndFormHTML = function()
{
    return "</form>";
};

this.UpdateOptions = function(flags)
{
    var tools = this.GetCompatibleTools(this.GetSelectedTaskList(),
                                        this.GetSelectedCalendar(),
                                        this.GetSelectedMailClient(),
                                        this.GetSelectedMobile(),
                                        !(flags & FLAG_ALPHA),
                                        !(flags & FLAG_BETA));

    if (flags & FLAG_TASK)
    {
	    var e = document.getElementById(idprefix+"tasklist");
	    if (e != null)
	    {
	        e.innerHTML = this.TaskListOptionsInnerHTML(tools, this.GetSelectedTaskList());
	    }
	}
    
    if (flags & FLAG_CAL)
    {
	    var e = document.getElementById(idprefix+"calendar");
	    if (e != null)
	    {
	        e.innerHTML = this.CalendarOptionsInnerHTML(tools, this.GetSelectedCalendar());
	    }
    }
    
    if (flags & FLAG_MAIL)
    {
	    var e = document.getElementById(idprefix+"mailclient");
	    if (e != null)
	    {
	        e.innerHTML = this.MailClientOptionsInnerHTML(tools, this.GetSelectedMailClient());
	    }
    }
    
    if (flags & FLAG_MOBILE)
    {
	    var e = document.getElementById(idprefix+"mobile");
	    if (e != null)
	    {
	        e.innerHTML = this.MobileOptionsInnerHTML(tools, this.GetSelectedMobile());
	    }
    }
};

this.ToolNameToID = function(name)
{
    var compat = new Array();
    for (var a = 0; a < this.AllTools.length; a++)
    {
        if (this.AllTools[a].name == name)
        {
            return this.AllTools[a].id;
        }
    }
    return '';
}

this.GetValueDojo = function(ctlid)
{
  return dijit.byId(ctlid).value;
};

this.DojoComboUpdateHidden = function(comboid, hiddenid)
{
  var c = dijit.byId(comboid);
  if (c != null)
  {
    var h = dijit.byId(hiddenid);
    if (h != null)
    {
      h.setValue(this.ToolNameToID(c.getValue()));
    }
  }
};

this.UpdateItems = function(combo, tools, flags)
{
	var itemDataStr = "{" +
	"label: 'name'," +
	"identifier: 'name'," +
	"items:" +
	"[";
	var glue = '';
    for (var a = 0; a < tools.length; a++)
    {
        if (tools[a].flags & flags)
        {
			var itemDataStr = itemDataStr + glue + "{ name:'" + tools[a].name + "'}";
			glue = ", ";
        }
    }
	var itemDataStr = itemDataStr +
	"]" +
	"}";
    var itemData = dojo.fromJson(itemDataStr);
    dojo.require("dojo.data.ItemFileReadStore"); // make sure we can use this...
    var itemsStore= new dojo.data.ItemFileReadStore({data: itemData });
	combo.store = itemsStore;
};

this.UpdateOptionsDojo = function(tasklistnameid, tasklistvalueid, calendarnameid, calendarvalueid, mailnameid, mailvalueid, mobilenameid, mobilevalueid, stripalpha, stripbeta)
{
    // update the value from the name, if needed
    this.DojoComboUpdateHidden(tasklistnameid, tasklistvalueid);
    this.DojoComboUpdateHidden(calendarnameid, calendarvalueid);
    this.DojoComboUpdateHidden(mailnameid, mailvalueid);
    this.DojoComboUpdateHidden(mobilenameid, mobilevalueid);
    
    // get the list of allowed tools
    var tools = this.GetCompatibleTools(this.GetValueDojo(tasklistvalueid),
                                        this.GetValueDojo(calendarvalueid),
                                        this.GetValueDojo(mailvalueid),
                                        this.GetValueDojo(mobilevalueid),
                                        stripalpha, stripbeta);

    // update the controls
    var e = dijit.byId(tasklistnameid);
    if (e != null)
    {
        this.UpdateItems(e, tools, FLAG_TASK);
    }

    var e = dijit.byId(calendarnameid);
    if (e != null)
    {
        this.UpdateItems(e, tools, FLAG_CAL);
    }
    
    var e = dijit.byId(mailnameid);
    if (e != null)
    {
        this.UpdateItems(e, tools, FLAG_MAIL);
    }
    
    var e = dijit.byId(mobilenameid);
    if (e != null)
    {
        this.UpdateItems(e, tools, FLAG_MOBILE);
    }
    
    // if we changed the values in the loop, we'll need another hidden field update
    this.DojoComboUpdateHidden(tasklistnameid, tasklistvalueid);
    this.DojoComboUpdateHidden(calendarnameid, calendarvalueid);
    this.DojoComboUpdateHidden(mailnameid, mailvalueid);
    this.DojoComboUpdateHidden(mobilenameid, mobilevalueid);
};

// ConvertToWidget accepts the id of an element, and replaces the contents of that
// element with a very basic form of the widget. This is suitable for cases where
// the widget doesn't need any special customization other than styling.
this.ConvertToWidget = function(id)
{
    var w = document.getElementById("widget");
	var newdiv = document.createElement('div');
	var html = this.BeginFormHTML();
	var tools = this.GetCompatibleTools(this.GetSelectedTaskList(),
	                                    this.GetSelectedCalendar(),
	                                    this.GetSelectedMailClient(),
	                                    this.GetSelectedMobile());
	html += this.TaskListOptionsHTML(tools, this.GetSelectedTaskList());
    html += this.CalendarOptionsHTML(tools, this.GetSelectedCalendar());
    html += this.MailClientOptionsHTML(tools, this.GetSelectedMailClient());
    html += this.MobileOptionsHTML(tools, this.GetSelectedMobile());
	html += this.EndFormHTML();
    newdiv.innerHTML = html; 
	w.appendChild(newdiv);
};

// For more complex control over the widget, use the following functions, which will
// allow you to place the pieces of the widget where you want in the document:

// Use this to start the form for a custom design
this.BeginForm = function()
{
    document.write(this.BeginFormHTML());
};

// Use this to close the form for a custom design
this.EndForm = function()
{
    document.write(this.EndFormHTML());
    // we can't validate the defaults as we write the widget for custom setups, so
    // we have to refresh everything at the end.
    this.UpdateOptions(FLAG_TASK | FLAG_CAL | FLAG_MAIL | FLAG_MOBILE);
};

// Use the following four functions to insert the options controls for a custom design

this.TaskListOptions = function(selected, blank)
{
    if (blank == null){blank = "Select a Task List...";}
    
    document.write(this.ComboBoxHTML(this.AllTools, "tasklist", blank, FLAG_TASK, selected));
//    if (usecustomdroplist)
//    {
	    var e = document.getElementById(idprefix+"tasklist_value");
	    if (e != null)
	    {
	        e.value = selected;
	    }
//	}
};

this.CalendarOptions = function(selected, blank)
{
    if (blank == null){blank = "Select a Calendar...";}
    
    document.write(this.ComboBoxHTML(this.AllTools, "calendar", blank, FLAG_CAL, selected));
//    if (usecustomdroplist)
//    {
	    var e = document.getElementById(idprefix+"calendar_value");
	    if (e != null)
	    {
	        e.value = selected;
	    }
//	}
};

this.MailClientOptions = function(selected, blank)
{
    if (blank == null){blank = "Select a Mail Client...";}
    
    document.write(this.ComboBoxHTML(this.AllTools, "mailclient", blank, FLAG_MAIL, selected));
//    if (usecustomdroplist)
//    {
	    var e = document.getElementById(idprefix+"mailclient_value");
	    if (e != null)
	    {
	        e.value = selected;
	    }
//	}
};

this.MobileOptions = function(selected, blank)
{
    if (blank == null){blank = "Select a Mobile Option...";}
    
    document.write(this.ComboBoxHTML(this.AllTools, "mobile", blank, FLAG_MOBILE, selected));
//    if (usecustomdroplist)
//    {
	    var e = document.getElementById(idprefix+"mobile_value");
	    if (e != null)
	    {
	        e.value = selected;
	    }
//	}
};

// If you want to hard code one or more tools, use one of the following functions in place
// of the option that you want to hard code. Nothing will be visibly displayed, so you may
// want to consider adding some text in the HTML indicating what the setting is.
this.TaskListConstant = function(selected)
{
    document.write(this.ValueFieldHTML("tasklist", selected));
    var e = document.getElementById(idprefix+"tasklist_value");
    if (e != null)
    {
        e.value = selected;
    }
};

this.CalendarConstant = function(selected)
{
    document.write(this.ValueFieldHTML("calendar", selected));
    var e = document.getElementById(idprefix+"calendar_value");
    if (e != null)
    {
        e.value = selected;
    }
};

this.MailClientConstant = function(selected)
{
    document.write(this.ValueFieldHTML("mailclient", selected));
    var e = document.getElementById(idprefix+"mailclient_value");
    if (e != null)
    {
        e.value = selected;
    }
};

this.MobileConstant = function(selected)
{
    document.write(this.ValueFieldHTML("mobile", selected));
    var e = document.getElementById(idprefix+"mobile_value");
    if (e != null)
    {
        e.value = selected;
    }
};


}