
//****************************************************************************************
// 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, parent, flags)
{
    this.name = name;
    this.id = id;
    this.parent = parent;
    this.flags = flags;
};

this.AllTools = new Array(
 // 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.
    new this.Tool('', '', '', FLAG_TASK | FLAG_CAL | FLAG_MAIL | FLAG_MOBILE)
  , new this.Tool('Android', 'android', '', FLAG_MOBILE)
  , new this.Tool('Blackberry (BB OS 3)', 'blackberry3', '', FLAG_MOBILE)
  , new this.Tool('Blackberry (BB OS 4+)', 'blackberry4', 'blackberry3', FLAG_MOBILE)
  , new this.Tool('Blackberry Storm', 'blackberrystorm', 'blackberry4', FLAG_MOBILE)
  , new this.Tool('Donedesk', 'donedesk', '', FLAG_TASK)
  , new this.Tool('Entourage 2004 (Mac)', 'entourage2004', '', FLAG_TASK | FLAG_CAL | FLAG_MAIL | FLAG_BETA | FLAG_ALPHA)
  , new this.Tool('Entourage 2008 (Mac)', 'entourage2008', 'entourage2004', FLAG_TASK | FLAG_CAL | FLAG_MAIL | FLAG_BETA | FLAG_ALPHA)
  , new this.Tool('GMail', 'gmail', 'webmail', FLAG_MAIL)
  , new this.Tool('Google Calendar', 'gcal', '', FLAG_CAL)
  , new this.Tool('iPad', 'ipad', 'iphone', FLAG_MOBILE)
  , new this.Tool('iPhone', 'iphone', '', FLAG_MOBILE)
  , new this.Tool('iPod Touch', 'itouch', 'iphone', FLAG_MOBILE)
  , new this.Tool('Lightning', 'lightning', '', FLAG_CAL)
  , new this.Tool('Nozbe', 'nozbe', '', FLAG_TASK | FLAG_BETA | FLAG_ALPHA)
  , new this.Tool('Outlook 2003 for Windows', 'outlook2003', '', FLAG_TASK | FLAG_CAL | FLAG_MAIL)
  , new this.Tool('Outlook 2007 for Windows', 'outlook2007', 'outlook2003', FLAG_TASK | FLAG_CAL | FLAG_MAIL)
  , new this.Tool('Outlook 2010 for Windows', 'outlook2010', 'outlook2007', FLAG_TASK | FLAG_CAL | FLAG_MAIL)
  , new this.Tool('Palm (Palm OS, not Windows Mobile)', 'palm', '', FLAG_MOBILE)
  , new this.Tool('Palm webOS', 'palmwebos', 'palm', FLAG_MOBILE)
  , new this.Tool('Paper Calendar', 'paper', '', FLAG_CAL)
  , new this.Tool('Paper Planner', 'planner', '', FLAG_TASK | FLAG_CAL | FLAG_MOBILE)
  , new this.Tool('Paper Printouts', 'paper', '', FLAG_MOBILE)
  , new this.Tool('Pocket PC', 'pocketpc', 'wm5', FLAG_MOBILE)
  , new this.Tool('Remember The Milk', 'rtm', '', FLAG_TASK)
  , new this.Tool('Things (Mac)', 'things', '', FLAG_TASK | FLAG_BETA | FLAG_ALPHA)
  , new this.Tool('Thunderbird', 'tbird', '', FLAG_MAIL)
  , new this.Tool('ToDoList', 'todolist', '', FLAG_TASK)
  , new this.Tool('Toodledo', 'toodledo', '', FLAG_TASK)
  , new this.Tool('Trog Bar with Outlook 2003 for Windows', 'trog2003', 'outlook2003', FLAG_TASK) 
  , new this.Tool('Trog Bar with Outlook 2007 for Windows', 'trog2007', 'outlook2007', FLAG_TASK)
  , new this.Tool('Trog Bar with Outlook 2010 for Windows', 'trog2010', 'outlook2010', FLAG_TASK)
  , new this.Tool('Web Email', 'webmail', '', FLAG_MAIL)
  , new this.Tool('Windows Mobile 5', 'wm5', '', FLAG_MOBILE)
  , new this.Tool('Windows Mobile 6', 'wm6', 'wm5', FLAG_MOBILE)
  , new this.Tool('Windows Mobile 7', 'wm7', 'wm6', FLAG_MOBILE)
  // Other and None go here, None is last
  , new this.Tool('Other Calendar App', 'other', '', FLAG_CAL)
  , new this.Tool('Other Mail Software', 'other', '', FLAG_MAIL)
  , new this.Tool('Other Mobile Device', 'other', '', FLAG_MOBILE)
  , new this.Tool('Other Task Manager App', 'other', '', FLAG_TASK)
  , new this.Tool('None', 'none', '', FLAG_MOBILE)
);


this.Required = function (flag1, id1, flag2, id2, msg)
{
  this.flag1 = flag1;
  this.id1 = id1;
  this.flag2 = flag2;
  this.id2 = id2;
  this.msg = msg;
};

this.AllRequired = new Array(
  // List combinations of tools that must (we recommend) go together
  // If user chooses one of these, we tell them that the other is required.
  // We only display one message at a time
  // "Priacta recommends: (msg)"
    new this.Required(FLAG_TASK, 'planner', FLAG_CAL, 'planner', '"Planner" should be selected for tasklist, calendar, and mobile.')
  , new this.Required(FLAG_TASK, 'planner', FLAG_MOBILE, 'planner', '"Planner" should be selected for tasklist, calendar, and mobile.')
  , new this.Required(FLAG_CAL, 'planner', FLAG_MOBILE, 'planner', '"Planner" should be selected for tasklist, calendar, and mobile.')
);

this.Conflicts = function (flag1, id1, flag2, id2, msg)
{
    this.flag1 = flag1;
    this.id1 = id1;
    this.flag2 = flag2;
    this.id2 = id2;
    this.msg = msg;
};

this.AllConflicts = new Array(
    // List combinations of tools that conflict and should NOT be mixed
    // If user chooses one of these, we tell them that it is not recommened.
    // We only display one message at a time
    // "Priacta recommends: (msg)"
    new this.Conflicts(FLAG_TASK, 'outlook2003', FLAG_CAL, 'outlook2007', 'Do not mix Outlook versions for your tasklist, calendar, and email.')
  , new this.Conflicts(FLAG_TASK, 'outlook2003', FLAG_CAL, 'outlook2010', 'Do not mix Outlook versions for your tasklist, calendar, and email.')
  , new this.Conflicts(FLAG_TASK, 'outlook2007', FLAG_CAL, 'outlook2003', 'Do not mix Outlook versions for your tasklist, calendar, and email.')
  , new this.Conflicts(FLAG_TASK, 'outlook2007', FLAG_CAL, 'outlook2010', 'Do not mix Outlook versions for your tasklist, calendar, and email.')
  , new this.Conflicts(FLAG_TASK, 'outlook2010', FLAG_CAL, 'outlook2003', 'Do not mix Outlook versions for your tasklist, calendar, and email.')
  , new this.Conflicts(FLAG_TASK, 'outlook2010', FLAG_CAL, 'outlook2007', 'Do not mix Outlook versions for your tasklist, calendar, and email.')
  , new this.Conflicts(FLAG_MAIL, 'outlook2003', FLAG_CAL, 'outlook2007', 'Do not mix Outlook versions for your tasklist, calendar, and email.')
  , new this.Conflicts(FLAG_MAIL, 'outlook2003', FLAG_CAL, 'outlook2010', 'Do not mix Outlook versions for your tasklist, calendar, and email.')
  , new this.Conflicts(FLAG_MAIL, 'outlook2007', FLAG_CAL, 'outlook2003', 'Do not mix Outlook versions for your tasklist, calendar, and email.')
  , new this.Conflicts(FLAG_MAIL, 'outlook2007', FLAG_CAL, 'outlook2010', 'Do not mix Outlook versions for your tasklist, calendar, and email.')
  , new this.Conflicts(FLAG_MAIL, 'outlook2010', FLAG_CAL, 'outlook2003', 'Do not mix Outlook versions for your tasklist, calendar, and email.')
  , new this.Conflicts(FLAG_MAIL, 'outlook2010', FLAG_CAL, 'outlook2007', 'Do not mix Outlook versions for your tasklist, calendar, and email.')
  , new this.Conflicts(FLAG_MAIL, 'outlook2003', FLAG_TASK, 'outlook2007', 'Do not mix Outlook versions for your tasklist, calendar, and email.')
  , new this.Conflicts(FLAG_MAIL, 'outlook2003', FLAG_TASK, 'outlook2010', 'Do not mix Outlook versions for your tasklist, calendar, and email.')
  , new this.Conflicts(FLAG_MAIL, 'outlook2007', FLAG_TASK, 'outlook2003', 'Do not mix Outlook versions for your tasklist, calendar, and email.')
  , new this.Conflicts(FLAG_MAIL, 'outlook2007', FLAG_TASK, 'outlook2010', 'Do not mix Outlook versions for your tasklist, calendar, and email.')
  , new this.Conflicts(FLAG_MAIL, 'outlook2010', FLAG_TASK, 'outlook2003', 'Do not mix Outlook versions for your tasklist, calendar, and email.')
  , new this.Conflicts(FLAG_MAIL, 'outlook2010', FLAG_TASK, 'outlook2007', 'Do not mix Outlook versions for your tasklist, calendar, and email.')
  , new this.Conflicts(FLAG_TASK, 'trog2003', FLAG_CAL, 'outlook2007', 'Do not mix Outlook versions for your tasklist, calendar, and email.')
  , new this.Conflicts(FLAG_TASK, 'trog2003', FLAG_CAL, 'outlook2010', 'Do not mix Outlook versions for your tasklist, calendar, and email.')
  , new this.Conflicts(FLAG_TASK, 'trog2007', FLAG_CAL, 'outlook2003', 'Do not mix Outlook versions for your tasklist, calendar, and email.')
  , new this.Conflicts(FLAG_TASK, 'trog2007', FLAG_CAL, 'outlook2010', 'Do not mix Outlook versions for your tasklist, calendar, and email.')
  , new this.Conflicts(FLAG_TASK, 'trog2010', FLAG_CAL, 'outlook2003', 'Do not mix Outlook versions for your tasklist, calendar, and email.')
  , new this.Conflicts(FLAG_TASK, 'trog2010', FLAG_CAL, 'outlook2007', 'Do not mix Outlook versions for your tasklist, calendar, and email.')
  , new this.Conflicts(FLAG_TASK, 'trog2003', FLAG_MAIL, 'outlook2007', 'Do not mix Outlook versions for your tasklist, calendar, and email.')
  , new this.Conflicts(FLAG_TASK, 'trog2003', FLAG_MAIL, 'outlook2010', 'Do not mix Outlook versions for your tasklist, calendar, and email.')
  , new this.Conflicts(FLAG_TASK, 'trog2007', FLAG_MAIL, 'outlook2003', 'Do not mix Outlook versions for your tasklist, calendar, and email.')
  , new this.Conflicts(FLAG_TASK, 'trog2007', FLAG_MAIL, 'outlook2010', 'Do not mix Outlook versions for your tasklist, calendar, and email.')
  , new this.Conflicts(FLAG_TASK, 'trog2010', FLAG_MAIL, 'outlook2003', 'Do not mix Outlook versions for your tasklist, calendar, and email.')
  , new this.Conflicts(FLAG_TASK, 'trog2010', FLAG_MAIL, 'outlook2007', 'Do not mix Outlook versions for your tasklist, calendar, and email.')
  , new this.Conflicts(FLAG_TASK, 'entourage2004', FLAG_CAL, 'entourage2008', 'Do not mix Entourage versions for your tasklist, calendar, and email.')
  , new this.Conflicts(FLAG_MAIL, 'entourage2004', FLAG_CAL, 'entourage2008', 'Do not mix Entourage versions for your tasklist, calendar, and email.')
  , new this.Conflicts(FLAG_MAIL, 'entourage2004', FLAG_TASK, 'entourage2008', 'Do not mix Entourage versions for your tasklist, calendar, and email.')
);

this._SelectTool = function(type, tasklist, calendar, mailclient, mobile) {
    switch (type)
    {
    case FLAG_TASK:
        return tasklist;
    case FLAG_CAL:
        return calendar;
    case FLAG_MAIL:
        return mailclient;
    case FLAG_MOBILE:
        return mobile;
    }
    return null;
};

this.GetRequiredMessages = function(tasklist, calendar, mailclient, mobile) {
    var ret = [];
    for (var a = 0; a < this.AllRequired.length; a++)
    {
        var req = this.AllRequired[a];
        var tool1_match = (req.id1 == this._SelectTool(req.flag1, tasklist, calendar, mailclient, mobile));
        if (tool1_match)
        {
            // see if the requirement was met
            var tool2_match = (req.id2 == this._SelectTool(req.flag2, tasklist, calendar, mailclient, mobile));
            if (!tool2_match)
            {
                ret.push(req.msg);
            }
        }
    }
    return ret;
};

this.GetConflictMessages = function(tasklist, calendar, mailclient, mobile) {
    var ret = [];
    for (var a = 0; a < this.AllConflicts.length; a++)
    {
        var conflict = this.AllConflicts[a];
        var tool1_match = (conflict.id1 == this._SelectTool(conflict.flag1, tasklist, calendar, mailclient, mobile));
        if (tool1_match)
        {
            // see if there is a conflict
            var tool2 = this._SelectTool(conflict.flag2, tasklist, calendar, mailclient, mobile);
            if (tool2)
            {
                var tool2_match = (conflict.id2 == this._SelectTool(conflict.flag2, tasklist, calendar, mailclient, mobile));
                if (tool2_match)
                {
                    ret.push(conflict.msg);
                }
            }
        }
    }
    return ret;
};

// 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,
                                  this.AllTools[a].parent,
                                  (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 in other lists 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 from consideration 
    // if an incompatible tool is already selected in another list.
    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 tasklist = this.GetSelectedTaskList();
    var calendar = this.GetSelectedCalendar();
    var mailclient = this.GetSelectedMailClient();
    var mobile = this.GetSelectedMobile();

    var tools = this.GetCompatibleTools(tasklist,
                                        calendar,
                                        mailclient,
                                        mobile,
                                        !(flags & FLAG_ALPHA),
                                        !(flags & FLAG_BETA));

    // get required and/or conflict messages
    var required_messages = this.GetRequiredMessages(tasklist, calendar, mailclient, mobile);
    var conflict_messages = this.GetConflictMessages(tasklist, calendar, mailclient, mobile);
    
    if (required_messages.length)
    {
        this._ShowMessage(required_messages[0]);
    }
    else if (conflict_messages.length)
    {
        this._ShowMessage(conflict_messages[0]);
    }

    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._ShowMessage = function(message, messageid)
{
    if (messageid)
    {
        $('#'+messageid).text(message ? message : '');
    }
//    if (message)
//    {
//        alert(message);
//    }
}

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, messageid, 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);

    var tasklist = this.GetValueDojo(tasklistvalueid);
    var calendar = this.GetValueDojo(calendarvalueid);
    var mailclient = this.GetValueDojo(mailvalueid);
    var mobile = this.GetValueDojo(mobilevalueid);

    // get the list of allowed tools
    var tools = this.GetCompatibleTools(tasklist,
                                        calendar,
                                        mailclient,
                                        mobile,
                                        stripalpha, stripbeta);

    // get required and/or conflict messages
    var required_messages = this.GetRequiredMessages(tasklist, calendar, mailclient, mobile);
    var conflict_messages = this.GetConflictMessages(tasklist, calendar, mailclient, mobile);

    if (required_messages.length)
    {
        this._ShowMessage(required_messages[0], messageid);
    }
    else if (conflict_messages.length)
    {
        this._ShowMessage(conflict_messages[0], messageid);
    }
    else
    {
        this._ShowMessage(null, messageid);
    }
    
    // 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;
    }
};


}
