
// function to preload dojo requirements so that future pages can benefit
// anything in this function should ALSO be loaded prior to use, but placing
// it here gives us an opportunity to grab it in advance and cache it.
function preloadDojoRequire()
{
  dojo.require("dijit.form.Button");
  dojo.require("dijit.form.CheckBox");
  dojo.require("dojo.data.ItemFileReadStore");
  dojo.require("dijit.form.Textarea");
  dojo.require("dijit.form.TextBox");
  dojo.require("dijit.form.ComboBox");
}

dojo.require("dijit.form.Form");

// anything that is needed training-wide can be placed here.
// These should be minimal, because while they are loading, nothing will be visible.
dojo.require("dojo.parser");
dojo.require("dijit.Dialog");

// TODO: Is it possible to get the right result using only markup and CSS?
// This isn't a priority change, because the dialog depends on the layout
// code, so removing this doesn't affect the load time.
dojo.require("dijit.layout.ContentPane");
dojo.require("dijit.layout.LayoutContainer");
dojo.require("dijit.layout.BorderContainer");
dojo.require("dijit.layout.SplitContainer");

//dojo.require("dijit.TitlePane"); // not used at the moment
// dojo.require("dojo.back"); // not used at the moment
//dojo.require("dijit.layout.AccordionContainer"); // not used at the moment
//dojo.require("dojox.widget.FisheyeLite"); // not used at the moment
//dojo.require("dojox.fx"); // not used at the moment
//dojo.require("dijit.Toolbar"); // not used at the moment

    
// We never want the server to automatically sign people out, so we have
// to make sure it knows that the person is still there. We do this by
// making a nominal request every 5 minutes. The server should continue
// to recognize the session, and keep it alive.
setInterval ( "keepsessionalive()", 5*60*1000 );
function keepsessionalive()
{
  dojo.xhrPost({
      url: "keepsessionalive.php",
      content: {},
      load: function(responseObject, ioArgs){
        return responseObject;
      },
      error: function(response, ioArgs){
        return response;
      }
    });
}

dojo.addOnLoad(function()
{
//  // make the fisheyelite class work
//  dojo.query("fisheyelite").instantiate(dojox.widget.FisheyeLite,{});

//  // make the navigation classes work
//  dojo.query("nav_part").instantiate(dojox.widget.FisheyeLite,{});
//  dojo.query("nav_chapter").instantiate(dojox.widget.FisheyeLite,{});
//  dojo.query("nav_section").instantiate(dojox.widget.FisheyeLite,{});

  dojo.query(".droplist input[type='text']").addClass("droplistinput").forEach("item.readOnly = true;");
  
  // We need to track when the popup is open for printing purposes.
  // This function will allow us to do that by adding/removing a
  // class from the center pane and dialog to indicate when it is
  // open. This will allow us to do the rest in our print stylesheet.
  var dlg = dijit.byId('popupnavdialog');
  var dialogcleanup = dojo.hitch(dlg, function()
  {
      dojo.removeClass('centercontentpane', 'popupnavopen');
      dojo.removeClass('popupnavdialog', 'popupnavopen');
      dojo.addClass('centercontentpane', 'popupnavclosed');
      dojo.addClass('popupnavdialog', 'popupnavclosed');
  });
  // NOTE: We are technically NOT supposed to override onCancel, but
  // right now it has nothing in it, so it isn't a big deal. Watch out
  // for this to change.
  dojo.connect(dlg,"onCancel",dialogcleanup);
  // default state is closed
  dojo.addClass('centercontentpane', 'popupnavclosed');
  dojo.addClass('popupnavdialog', 'popupnavclosed');
  
  // Handle the case where a popup of sorts was requested
  if (__querystring['popup'])
  {
	  if (__querystring['popup'] == 'downloaderror')
	  {
	      DownloadErrorPopup();
	  }
      else if (__querystring['popup'] == 'error')
      {
          ErrorPopup();
      }
  }
});

// generic function for popups to handle errors.
function ErrorPopup()
{
  if (__querystring['errorcode'] && __querystring['errorcode'] != 'success')
  {
    ModalError('Error', __querystring['errormsg']);
  }
}

// specialized error popup used for downloads
function DownloadErrorPopup()
{
  if (__querystring['errorcode'] == 'updateinprogress')
  {
    // We handle this case specially, because 
    ModalError('eBook Update In Progress', '<p>The online training system was recently updated, and the newest eBook is not yet available for your selected training tools. It will be ready soon.</p><p>Support has been notified of your request. You will be contacted personally when your eBook is ready. Thank you for your patience as we work to bring you the very latest training information.</p>');
  }
  else
  {
    ErrorPopup();
  }
}

function DoLogin(data)
{
  dojo.xhrPost({
      url: "login.php",
      content: data,
      load: function(responseObject, ioArgs){
        //The responseObject parameter is a JavaScript object
        //that Dojo has converted from the text pulled from
        //the remote file. It did this because the 'handleAs'
        //parameter to the xhrGet function is set to 'json'
        
        var textBuffer = ["The data returned is:"];
        for(var i = 0; i < responseObject.length; i++){
          textBuffer.push("errorcode:"+responseObject[i].errorcode
           + ", errormsg:"+responseObject[i].errormsg);
        }
        
        
        dojo.byId("toBeReplaced").innerHTML = textBuffer.join("<br/>");
        
        //Dojo recommends that you always return(response); 
        //to propagate the response to other callback 
        //handlers. Otherwise, the error 
        //callbacks may be called in the success case.
        return responseObject;
      },
      error: function(response, ioArgs){
        dojo.byId("toBeReplaced").innerHTML = 
          "An error occurred, with response: " + response;
        return response;
      },
      handleAs: "json"
    });
    /*
  dojo.xhrPost({
      url: "login.php",
      content: data,
      load: function(responseObject, ioArgs){
        //The responseObject parameter is a JavaScript object
        //that Dojo has converted from the text pulled from
        //the remote file. It did this because the 'handleAs'
        //parameter to the xhrGet function is set to 'json'
        
        var textBuffer = "The data returned is:"+responseObject;
        
        dojo.byId("toBeReplaced").innerHTML = textBuffer;
        
        //Dojo recommends that you always return(response); 
        //to propagate the response to other callback 
        //handlers. Otherwise, the error 
        //callbacks may be called in the success case.
        return responseObject;
      },
      error: function(response, ioArgs){
        dojo.byId("toBeReplaced").innerHTML = 
          "An error occurred, with response: " + response;
        return response;
      },
    });
    */
}

function QuickDestroyChildren(parentid)
{
  NodeDestroyChildren(dojo.byId(parentid));
//  children = document.getElementById(parentid).childNodes;
//  for (var a = 0; a <children.length; a++)
//  {
//    children[a].destroy();
//  }
//  dojo.query('#' + parentid + ' *[id]').forEach(function(n) {
//      if(dijit.byId(n.id)) {
//          dijit.byId(n.id).destroy();
//      }
//  });
}

function NodeDestroyChildren(node)
{
  for (var a = 0; a <node.childNodes.length; a++)
  {
    if (node.childNodes[a] == undefined)
    {
    }
    else
    {
      if(dijit.byId(node.childNodes[a].id)){
         dijit.byId(node.childNodes[a].id).destroy();
      }
      else if (node.childNodes[a].hasChildNodes())
      {
        NodeDestroyChildren(node.childNodes[a]);
      }
    }
  }
}

lastinternalnav = "";
function InternalNav(url, scrollto)
{
  lastinternalnav = url;
  dojo.xhrGet({
      url: url,
      load: function(responseObject, ioArgs)
      {
        try
        {
	      responseObject = dojo.fromJson(responseObject);
	      QuickDestroyChildren("popupnavhtml");
	      dojo.byId("popupnavhtml").innerHTML = responseObject[0].errormsg;
	      try
	      {
            dojo.parser.parse(dojo.byId("popupnavhtml"));
          }
          catch(err2)
          {
            dojo.byId("popupnavhtml").innerHTML += "error: "+err2;
          }
          dojo.addClass('centercontentpane', 'popupnavopen');
          dojo.addClass('popupnavdialog', 'popupnavopen');
	      dojo.removeClass('centercontentpane', 'popupnavclosed');
	      dojo.removeClass('popupnavdialog', 'popupnavclosed');
	      dijit.byId('popupnavdialog').show();
          // the timeout is a TERRIBLE nasty hack. We shouldn't have to use this
          // to get the right result, but for some silly reason focus isn't totally
          // set yet, and the dialog will go to the first anchor instead of the
          // location we specify unless we use a timeout to make this code execute
          // after the scroll for focus.
          if (scrollto != '' && scrollto != null)
          {
            setTimeout("shell = dojo.byId('popupnavhtmlshell'); shell.scrollTop = Math.min((dojo.byId('"+scrollto+"').offsetTop - 30), shell.scrollHeight);", 200);
          }
          else
          {
            shell = dojo.byId('popupnavhtmlshell'); shell.scrollTop = 0;
            setTimeout("shell = dojo.byId('popupnavhtmlshell'); shell.scrollTop = 0;", 200);
          }
	    }
	    catch(err)
	    {
          QuickDestroyChildren("popupnavhtml");
          dojo.byId("popupnavhtml").innerHTML = responseObject;
          dojo.parser.parse(dojo.byId("popupnavhtml"));
          dojo.addClass('centercontentpane', 'popupnavopen');
          dojo.addClass('popupnavdialog', 'popupnavopen');
          dojo.removeClass('centercontentpane', 'popupnavclosed');
          dojo.removeClass('popupnavdialog', 'popupnavclosed');
          dijit.byId('popupnavdialog').show();
	    }
        return responseObject;
      },
      error: function(response, ioArgs){
        QuickDestroyChildren("popupnavhtml");
        dojo.byId("popupnavhtml").innerHTML = response;
        dojo.parser.parse(dojo.byId("popupnavhtml"));
        dojo.addClass('centercontentpane', 'popupnavopen');
        dojo.addClass('popupnavdialog', 'popupnavopen');
        dojo.removeClass('centercontentpane', 'popupnavclosed');
        dojo.removeClass('popupnavdialog', 'popupnavclosed');
        dijit.byId('popupnavdialog').show();
        return response;
      }
    });
/*
  dojo.xhrGet({
      url: url,
      load: function(responseObject, ioArgs){
        dojo.byId("popupnavhtml").innerHTML = responseObject[0].errormsg;
        dojo.parser.parse(dojo.byId("popupnavhtml"));
        dijit.byId('popupnavdialog').show();
        return responseObject;
      },
      error: function(response, ioArgs){
        dojo.byId("popupnavhtml").innerHTML = response;
        dojo.parser.parse(dojo.byId("popupnavhtml"));
        dijit.byId('popupnavdialog').show()
        return response;
      },
      handleAs: "json"
    });
    */
}

function ModalError(title, message, okbutton)
{
  if (okbutton == null)
  {
    okbutton = true;
  }
  // The old code used the main nav dialog, but that was REALLY ugly
  // since that dialog is styled specifically for navigation, not for
  // short messages. It wa fine for debugging, but now we're starting
  // to use this function for REAL code, so we need to create the new
  // dialog on the fly.
//  QuickDestroyChildren("popupnavhtml");
//  dojo.byId("popupnavhtml").innerHTML = title+message;
//  dojo.parser.parse(dojo.byId("popupnavhtml"));
//  dijit.byId('popupnavdialog').show();

  // add the button to the message if needed
  var button = '';
  if (okbutton)
  {
	  button = '<div><center><button dojoType="dijit.form.Button" type="submit">OK</button></center></div>'
  }

    var dlg = new dijit.Dialog({ title: title,
      execute: function(formContents) {}
    });
    dojo.addClass(dlg.domNode, 'messageboxpopup');
    dojo.body().appendChild(dlg.domNode);
    // make sure we can handle the controls we are about to use...
    dlg.setContent(message+button);
    dlg.startup();
    // the reshow popup nav stuff is needed because inputs have trouble
    // with backspace, delete, arrows, and enter when more than one dialog
    // is visible. Until this is fixed, we have to hide any spares.
    var reshowpopupnav = dijit.byId('popupnavdialog').open;
    var dialogcleanup = dojo.hitch(dlg, function()
    {
        // cleanup
        this.destroyDescendants();
        this.destroy();
        if (reshowpopupnav)
        {
            dijit.byId('popupnavdialog').show();
        }
    });
    // NOTE: We are technically NOT supposed to override onCancel, but
    // right now it has nothing in it, so it isn't a big deal. Watch out
    // for this to change.
    //
    // WARNING: If you switch this to connect to the hide function, you
    // will destroy the form in the dialog before the contents can be
    // submitted.
    dojo.connect(dlg,"onCancel",dialogcleanup);
    if (reshowpopupnav)
    {
        dijit.byId('popupnavdialog').hide();
    }
    dlg.show();
}

// if sync is true, the code will wait for the post to complete
// the return value is a dojo.Deferred object
//
// if sync is true, you can check for the error condition with
// Deferred.fired. fired will be 0 on success, 1 on error. If
// sync is false, fired will be -1 until the operation is done.
//
// The Deferred object will also have the results, if any, in
// the results object.
function SubmitForm(formid, url, onsuccess, sync)
{
  if (!url)
  {
    url = dojo.byId(formid).getAttribute('action');
  }
  if (dijit.byId(formid))
  {
    if (!dijit.byId(formid).validate())
    {
      alert('The form was not properly filled out.');
      return false;
    }
  }
  if (!onsuccess)
  {
    onsuccess = function(){}; // do nothing
  }
  var ret = dojo.xhrPost({
      url: url,
      form: formid,
      sync: sync,
      load: function(responseObject, ioArgs)
      {
        try
        {
          responseObject = dojo.fromJson(responseObject);
          if (responseObject[0].errorcode == 'success')
          {
            onsuccess();
          }
          else
          {
            // we had a problem
            ModalError("Problem Saving Worksheet", responseObject[0].errormsg);
          }
        }
        catch(err)
        {
          ModalError("Unknown Error Saving Worksheet", responseObject);
        }
        return responseObject;
      },
      error: function(response, ioArgs){
        ModalError("Unknown Error Saving Worksheet", response);
        return response;
      }
    });
    return ret;
}

function fixPostContent(content, key, pdata)
{
  if (typeof(content) == 'object')
  {
    for (k in content)
    {
      if (!key)
      {
        fixPostContent(content[k], k, pdata);
      }
      else
      {
        fixPostContent(content[k], key + '[' + k +']', pdata);
      }
    }
  }
  else if (key)
  {
    pdata[key] = content;
  }
}
// arbitrary function to send data to a specific URL. The function specified
// by onsuccess will be called when the send completes.
function SendData(url, data, onsuccess, onerror, sync)
{
  var fixed_data = {};
  fixPostContent(data, null, fixed_data);
  if (!onsuccess)
  {
    onsuccess = function(){}; // do nothing
  }
  var ret = dojo.xhrPost({
      url: url,
      content: fixed_data,
      sync: sync,
      load: function(responseObject, ioArgs)
      {
        try
        {
          responseObject = dojo.fromJson(responseObject);
          if (responseObject[0].errorcode == 'success')
          {
            onsuccess(responseObject);
          }
          else
          {
            // we had a problem
	        if (!onerror)
	        {
                ModalError("Problem Sending Data", responseObject[0].errormsg);
	        }
	        else
	        {
	           onerror(responseObject[0].errormsg);
	        }
          }
        }
        catch(err)
        {
          if (!onerror)
          {
	          ModalError("Unknown Error Sending Data", responseObject);
          }
          else
          {
             onerror(responseObject);
          }
        }
        return responseObject;
      },
      error: function(response, ioArgs){
		if (!onerror)
		{
	        ModalError("Unknown Error Sending Data", response);
	        return response;
	    }
	    else
	    {
	       onerror(response);
	    }
      }
    });
    return ret;
}

function UpdateTrainingSectionAndNavigate(trainingid, section, completed, timespent, currentservertime, navigateto)
{
  SendData("updatetrainingsection.php", 
           {
             trainingid: trainingid,
             section: section,
             timespent: timespent,
             extratimestart: currentservertime, // time between this and the time the server gets the request is added to time spent. 
             lastviewed: currentservertime,
             completed: completed
           },
             function(){
               window.location.href = navigateto;
             }
           );
}
/*
function SubmitStressorWorksheet(id, onsuccess)
{
  dojo.xhrPost({
      url: "updatestressors.php",
      form: id,
      load: function(responseObject, ioArgs)
      {
        try
        {
          responseObject = dojo.fromJson(responseObject);
          if (responseObject[0].errorcode == 'success')
          {
            onsuccess();
          }
          else
          {
            // we had a problem
            ModalError("Problem Saving Worksheet", responseObject[0].errormsg);
          }
        }
        catch(err)
        {
          ModalError("Unknown Error Saving Worksheet", responseObject);
        }
        return responseObject;
      },
      error: function(response, ioArgs){
        return response;
      },
    });
}
*/

function updatetotalvalue(totalfieldid, partsquery)
{
    // count the total
    dojo.byId(totalfieldid).value = gettotalvalue(totalfieldid, partsquery);
}

function gettotalvalue(totalfieldid, partsquery)
{
  // count the total
  var total = 0;
  var itemlist = dojo.query(partsquery);
  var a;
  for (a = 0; a < itemlist.length; a++)
  {
    var item = itemlist[a];
    if (isNaN(parseInt(item.value)))
    {
      continue;
    }
    total = total + parseInt(item.value);
  }
  return total;
}

function updatedollarsperhour(dollarsperhourid, annualincomeid, totalhoursid, totalhoursbase)
{
  var hours = parseInt(dojo.byId(totalhoursid).value);
  if (isNaN(hours) || hours == 0)
  {
    hours = totalhoursbase
  }
  if (hours == 0)
  {
    var value = 0;
  }
  else
  {
    var value = parseInt(dojo.byId(annualincomeid).value) / 12 / 4.33 / hours;
  }
  if (isNaN(value))
  {
    dojo.byId(dollarsperhourid).value = 0;
  }
  else
  {
    // use the value, rounded to two decimals
    dojo.byId(dollarsperhourid).value = Math.round(value * 100)/100;
  }
}

// Get the value of the selected radio button in the group with the given name
function getCheckedValue(form, name) {
    var radioObj = document.forms[form].elements[name];
    if(!radioObj)
        return "";
    var radioLength = radioObj.length;
    if(radioLength == undefined)
        if(radioObj.checked)
            return radioObj.value;
        else
            return "";
    for(var i = 0; i < radioLength; i++) {
        if(radioObj[i].checked) {
            return radioObj[i].value;
        }
    }
    return "";
}

// select the radio button with the given value
function setCheckedValue(form, name, newValue) {
    var radioObj = document.forms[form].elements[name];
    if(!radioObj)
        return;
    var radioLength = radioObj.length;
    if(radioLength == undefined) {
        radioObj.checked = (radioObj.value == newValue.toString());
        return;
    }
    for(var i = 0; i < radioLength; i++) {
        radioObj[i].checked = false;
        if(radioObj[i].value == newValue.toString()) {
            radioObj[i].checked = true;
        }
    }
}

function CreditApplyToTraining(userid, creditid, trainingid)
{
  SendData("updatetraining.php", 
           {
             actiontype: 'update',
             userid: userid,
             creditid: creditid,
             trainingid: trainingid
           },
          function(){DoRefresh();}, // reload the page if it worked
          function(errormsg){ModalError('Error', errormsg);}
           );
}

function CreditReportsToDialog(creditid, oldvalue)
{
    if (creditid == '')
    {
        ModalError('Selection Required', 'Please select a training credit first');
        return;
    }
	var dlg = new dijit.Dialog({ title: "Reports To",
	  execute: function(formContents)
	  {
          SendData("updatecredit.php", formContents,
          function(){DoRefresh(); dialogcleanup()},
          function(errormsg){ModalError('Error', errormsg); dialogcleanup();});
	  }
	});
	dojo.body().appendChild(dlg.domNode);
	// make sure we can handle the controls we are about to use...
	dojo.require("dijit.form.Button");
	dojo.require("dijit.form.TextBox");
    dlg.setContent(
      '<p style="max-width: 350px;">Specify a person to receive progress reports. When this person logs in using the email address indicated, they will be able to see information about the training this credit is applied to.</p>'+
      '<label for="reportto_username">Email: </label>'+
      '<input dojoType="dijit.form.TextBox" type="hidden" id="reporttodlg_creditid" name="creditid" value="'+creditid+'" />'+
      '<input dojoType="dijit.form.TextBox" type="hidden" id="reporttodlg_action" name="actiontype" value="update" />'+
      '<input dojoType="dijit.form.TextBox" type="text" id="reporttodlg_reportto_username" name="reportto" value="'+oldvalue+'"/>'+
      '<button dojoType="dijit.form.Button" type="submit">OK</button>'
    );
	dlg.startup();
	// the reshow popup nav stuff is needed because inputs have trouble
	// with backspace, delete, arrows, and enter when more than one dialog
	// is visible. Until this is fixed, we have to hide any spares.
    var reshowpopupnav = dijit.byId('popupnavdialog').open;
    var dialogcleanup = dojo.hitch(dlg, function()
    {
        // cleanup
        this.destroyDescendants();
        this.destroy();
        if (reshowpopupnav)
        {
            dijit.byId('popupnavdialog').show();
        }
    });
    // NOTE: We are technically NOT supposed to override onCancel, but
    // right now it has nothing in it, so it isn't a big deal. Watch out
    // for this to change.
    //
    // WARNING: If you switch this to connect to the hide function, you
    // will destroy the form in the dialog before the contents can be
    // submitted.
    dojo.connect(dlg,"onCancel",dialogcleanup);
    if (reshowpopupnav)
    {
        dijit.byId('popupnavdialog').hide();
    }
	dlg.show();
}

function CreditSendToDialog(creditid, oldvalue)
{
    if (creditid == '')
    {
        ModalError('Selection Required', 'Please select a training credit first');
        return;
    }
    var dlg = new dijit.Dialog({ title: "Send To",
      execute: function(formContents)
      {
          SendData("updatecredit.php", formContents,
          function(){DoRefresh(); dialogcleanup();},
          function(errormsg){ModalError('Error', errormsg); dialogcleanup();});
      }
    });
    dojo.body().appendChild(dlg.domNode);
    // make sure we can handle the controls we are about to use...
    dojo.require("dijit.form.Button");
    dojo.require("dijit.form.TextBox");
    dojo.require("dijit.form.CheckBox");
    dlg.setContent(
      '<p style="max-width: 450px;">Specify another person who may use this credit. When this person logs in using the email address indicated, they will have the option of applying this credit to any training.</p>'+
      '<label for="sendto_username">Email: </label>'+
      '<input dojoType="dijit.form.TextBox" type="hidden" id="sendtodlg_creditid" name="creditid" value="'+creditid+'" />'+
      '<input dojoType="dijit.form.TextBox" type="hidden" id="sendtodlg_action" name="actiontype" value="update" />'+
      '<input dojoType="dijit.form.TextBox" type="text" id="sendtodlg_sendto_username" name="sendto" value="'+oldvalue+'"/>'+
      '<input dojoType="dijit.form.CheckBox" type="checkbox" id="sendtodlg_sendto_sendemail" name="sendtosendemail" value="on"/>'+
      '<label for="sendtodlg_sendto_sendemail">Send an email</label>'+
      '<button dojoType="dijit.form.Button" type="submit">OK</button>'
    );
    dlg.startup();
    // the reshow popup nav stuff is needed because inputs have trouble
    // with backspace, delete, arrows, and enter when more than one dialog
    // is visible. Until this is fixed, we have to hide any spares.
    //
    // TODO: Replace this whole thing with a TooltipDialog. We can't do this
    // until the two dialog issue is resolved, becuase TooltipDialogs inside
    // of regular dialogs ALSO have the same problem.
    var reshowpopupnav = dijit.byId('popupnavdialog').open;
    var dialogcleanup = dojo.hitch(dlg, function()
    {
        // cleanup
        this.destroyDescendants();
        this.destroy();
        if (reshowpopupnav)
        {
	        dijit.byId('popupnavdialog').show();
	    }
    });
    // NOTE: We are technically NOT supposed to override onCancel, but
    // right now it has nothing in it, so it isn't a big deal. Watch out
    // for this to change.
    //
    // WARNING: If you switch this to connect to the hide function, you
    // will destroy the form in the dialog before the contents can be
    // submitted.
    dojo.connect(dlg,"onCancel",dialogcleanup);
    if (reshowpopupnav)
    {
        dijit.byId('popupnavdialog').hide();
    }
    dlg.show();
}

// refresh function that is aware of navigation attempts within
// the popup as well as the main app. It will reload the popup
// if there is one, otherwise it will reload the page.
function DoRefresh()
{
    if (dijit.byId('popupnavdialog').open)
    {
    	InternalNav(lastinternalnav);
    }
    else
    {
        location.reload(true);
    }
}

function DoPrint()
{
    window.print();
}

function ValidateAndSubmit(form)
{
  // if there is no onsubmit handler, or the handler returned true...
  if ((!form.onsubmit) || form.onsubmit())
  {
    form.submit();
  }
}

function IsEnter(e)
{
	e = e || window.event;
	var code = e.keyCode || e.which;
	if(code == 13)
	{
	  return true;
    }
    return false;
}

function GridSort(gridinfo, fields)
{
  gridinfo.sorts = fields;
  RefreshGrid(gridinfo);
}

function GridCollapse(gridinfo, collapse)
{
  if (gridinfo.collapsed != collapse)
  {
    if (gridinfo.collapsed)
    {
      gridinfo.expanding = true; // normally the grid isn't fully loaded on ajax requests, but this lets us skip that
    }
    gridinfo.collapsed = collapse;
    RefreshGrid(gridinfo);
  }
}

function UpdatePageLen(gridinfo)
{
    c = dojo.byId(gridinfo.id+'_grid_pagelen');
    if (c != null)
    {
	    len = c.value;
	    // Change the page so that with the new length, the current top
	    // record will be on the same page after the refresh
	    gridinfo.page = Math.floor((gridinfo.pagelen * gridinfo.page) / len);
	    gridinfo.pagelen = len;
    }
}

function UpdateFilter(gridinfo)
{
    // Set the filter to the filter inputs
    gridinfo.filters = new Array;
    for (var a = 0; a < gridinfo.filterinputs.length; a++)
    {
      c = dojo.byId(gridinfo.filterinputs[a].id);
      if (c != null)
      {
        if (c.value != '')
        {
          gridinfo.filters[gridinfo.filterinputs[a].field] = new Array;
          gridinfo.filters[gridinfo.filterinputs[a].field][gridinfo.filterinputs[a].op] = dojo.byId(gridinfo.filterinputs[a].id).value;
        }
      }
    }
}

function SubmitFilter(gridinfo)
{
    // RefreshGrid will grab the filter information
    RefreshGrid(gridinfo);
}

function ResetFilter(gridinfo)
{
    gridinfo.filters = new Array;
    // clear the filter fields too
    for (var a = 0; a < gridinfo.filterinputs.length; a++)
    {
      c = dojo.byId(gridinfo.filterinputs[a].id);
      if (c != null)
      {
        c.value = '';
      }
    }
    gridinfo.sorts = new Array;
    // clear the page length
    c = dojo.byId(gridinfo.id+'_grid_pagelen');
    if (c != null)
    {
      c.value = '';
    }
    gridinfo.pagelen = '';
    RefreshGrid(gridinfo);
}

function GridSetPage(gridinfo, page)
{
    gridinfo.page = page;
    if (gridinfo.page < 0)
    {
      gridinfo.page = 0;
    }
    else if (gridinfo.page > gridinfo.pagelast)
    {
      gridinfo.page = gridinfo.pagelast;
    }
    RefreshGrid(gridinfo);
}

function GridFirstPage(gridinfo){GridSetPage(gridinfo, 0);}
function GridPrevPage(gridinfo){GridSetPage(gridinfo, gridinfo.page - 1);}
function GridLastPage(gridinfo){GridSetPage(gridinfo, gridinfo.pagelast);}
function GridNextPage(gridinfo){GridSetPage(gridinfo, gridinfo.page + 1);}

function RefreshGrid(gridinfo)
{
    dojo.addClass(gridinfo.id, 'grid_loading');
    
    try
    {
	    // grab any user information
		UpdatePageLen(gridinfo);
		UpdateFilter(gridinfo);
	
	    SendData("ajaxgrid.php", gridinfo,
	    function(responseObject)
	    {
	      try
	      {
		      var ctl = dojo.byId(gridinfo.id);
		      NodeDestroyChildren(ctl);
		//      ctl.destroyDescendants();
		//      ctl.destroy();
		      ctl.innerHTML = responseObject[0]['errormsg'];
		      dojo.parser.parse(ctl);
		      var scripts = ctl.getElementsByTagName("script");
		      for (var a = 0; a < scripts.length; a++)
		      {
		        var script = scripts[a];
		        eval(script.text);
		      }
	        dojo.removeClass(gridinfo.id, 'grid_loading');
	        drawChart(); //to add the sparkline if there is any...
	      }
	      catch(e)
	      {
	        dojo.removeClass(gridinfo.id, 'grid_loading');
	        ModalError('Error', e);
	      }
	    },
	    function(errormsg)
	    {
          if (errormsg == undefined)
          {
            dojo.removeClass(gridinfo.id, 'grid_loading');
            ModalError('Error', 'Unknown error');
          }
	      else if (errormsg[0] == undefined || errormsg[0]['errormsg'] == undefined)
	      {
	        dojo.removeClass(gridinfo.id, 'grid_loading');
	        ModalError('Error', errormsg);
	      }
	      else
	      {
	        dojo.removeClass(gridinfo.id, 'grid_loading');
	        ModalError('Error', errormsg[0]['errormsg']);
	      }
	    });
  }
  catch(e)
  {
    dojo.removeClass(gridinfo.id, 'grid_loading');
    ModalError('Error', e);
  }
  gridinfo.expanding = false; // if set, it is only good for one pass
}

/***********************************************
* AnyLink Drop Down Menu- © Dynamic Drive (www.dynamicdrive.com)
* This notice MUST stay intact for legal use
* Visit http://www.dynamicdrive.com/ for full source code
***********************************************/

var menuwidth='165px' //default menu width
var menubgcolor='lightyellow'  //menu bgcolor
var disappeardelay=250  //menu disappear speed onMouseout (in miliseconds)
var hidemenu_onclick="yes" //hide menu when user clicks within menu?

/////No further editting needed

var ie4=document.all
var ns6=document.getElementById&&!document.all

if (ie4||ns6)
document.write('<div id="dropmenudiv" style="visibility:hidden;width:'+menuwidth+';background-color:'+menubgcolor+'" onMouseover="clearhidemenu()" onMouseout="dynamichide(event)"></div>')

function getposOffset(what, offsettype){
var totaloffset=(offsettype=="left")? what.offsetLeft : what.offsetTop;
var parentEl=what.offsetParent;
while (parentEl!=null){
totaloffset=(offsettype=="left")? totaloffset+parentEl.offsetLeft : totaloffset+parentEl.offsetTop;
parentEl=parentEl.offsetParent;
}
return totaloffset;
}


function showhide(obj, e, visible, hidden, menuwidth){
if (ie4||ns6)
dropmenuobj.style.left=dropmenuobj.style.top="-500px"
if (menuwidth!=""){
dropmenuobj.widthobj=dropmenuobj.style
dropmenuobj.widthobj.width=menuwidth
}
if (e.type=="click" && obj.visibility==hidden || e.type=="mouseover")
obj.visibility=visible
else if (e.type=="click")
obj.visibility=hidden
}

function iecompattest(){
return (document.compatMode && document.compatMode!="BackCompat")? document.documentElement : document.body
}

function clearbrowseredge(obj, whichedge){
var edgeoffset=0
if (whichedge=="rightedge"){
var windowedge=ie4 && !window.opera? iecompattest().scrollLeft+iecompattest().clientWidth-15 : window.pageXOffset+window.innerWidth-15
dropmenuobj.contentmeasure=dropmenuobj.offsetWidth
if (windowedge-dropmenuobj.x < dropmenuobj.contentmeasure)
edgeoffset=dropmenuobj.contentmeasure-obj.offsetWidth
}
else{
var topedge=ie4 && !window.opera? iecompattest().scrollTop : window.pageYOffset
var windowedge=ie4 && !window.opera? iecompattest().scrollTop+iecompattest().clientHeight-15 : window.pageYOffset+window.innerHeight-18
dropmenuobj.contentmeasure=dropmenuobj.offsetHeight
if (windowedge-dropmenuobj.y < dropmenuobj.contentmeasure){ //move up?
edgeoffset=dropmenuobj.contentmeasure+obj.offsetHeight
if ((dropmenuobj.y-topedge)<dropmenuobj.contentmeasure) //up no good either?
edgeoffset=dropmenuobj.y+obj.offsetHeight-topedge
}
}
return edgeoffset
}

function populatemenu(what){
if (ie4||ns6)
dropmenuobj.innerHTML=what.join("")
}


function dropdownmenu(obj, e, menucontents, menuwidth){
if (window.event) event.cancelBubble=true
else if (e.stopPropagation) e.stopPropagation()
clearhidemenu()
dropmenuobj=document.getElementById? document.getElementById("dropmenudiv") : dropmenudiv
populatemenu(menucontents)

if (ie4||ns6){
showhide(dropmenuobj.style, e, "visible", "hidden", menuwidth)
dropmenuobj.x=getposOffset(obj, "left")
dropmenuobj.y=getposOffset(obj, "top")
dropmenuobj.style.left=dropmenuobj.x-clearbrowseredge(obj, "rightedge")+"px"
dropmenuobj.style.top=dropmenuobj.y-clearbrowseredge(obj, "bottomedge")+obj.offsetHeight+"px"
}

return clickreturnvalue()
}

function clickreturnvalue(){
if (ie4||ns6) return false
else return true
}

function contains_ns6(a, b) {
while (b.parentNode)
if ((b = b.parentNode) == a)
return true;
return false;
}

function dynamichide(e){
if (ie4&&!dropmenuobj.contains(e.toElement))
delayhidemenu()
else if (ns6&&e.currentTarget!= e.relatedTarget&& !contains_ns6(e.currentTarget, e.relatedTarget))
delayhidemenu()
}

function hidemenu(e){
if (typeof dropmenuobj!="undefined"){
if (ie4||ns6)
dropmenuobj.style.visibility="hidden"
}
}

function delayhidemenu(){
if (ie4||ns6)
delayhide=setTimeout("hidemenu()",disappeardelay)
}

function clearhidemenu(){
if (typeof delayhide!="undefined")
clearTimeout(delayhide)
}

if (hidemenu_onclick=="yes")
document.onclick=hidemenu

//***************************************
// End drop menu code
//***************************************