/*----------------------------------------------------------------------
$Header: std_libs.jsc  Revision:1.41  den 3 mars 2005 10:36:24  pk $
--------------------------------------------------------------------- */

/* ---------------------------------------------------------------------
   Global constants (no strings, strings should be defined in text.js)
--------------------------------------------------------------------- */

// A day in milliseconds
var dayinms = 1000 * 60 * 60 * 24;

/* ---------------------------------------------------------------------
   Java support
--------------------------------------------------------------------- */

/*===================================================================================
  Detetcts Java support and displays an error message if Java is not supported.
  Returns:  True if Java is supported, otherwise false
  
  2002-12-06 PK
====================================================================================*/
function detectJavaSupport()
{
  if(!navigator.javaEnabled())
  {
    alert(strconstJavaNotSupported);
  }

  return navigator.javaEnabled();
}

/* ---------------------------------------------------------------------
   Form handling routines
--------------------------------------------------------------------- */

/*===================================================================================
  Sets focus to first appropriate field.
  
  2004-11-19 AA   Changed forms(0). -> forms[0]
                  elementCollection(counter)  -> elementCollection[counter]
  2002-12-17 PK   Added try blocks to catch exceptions
  2002-11-12 PK
====================================================================================*/
function cursorAtTop()
{
  var elementCollection = document.forms[0].elements;

  for(var counter=0; counter < elementCollection.length; counter++)
  {
    var tagName = elementCollection[counter].tagName.toLowerCase();

    if(tagName == "textarea")
    {
      try
      {
        elementCollection[counter].focus();
        break;
      }
      catch(e)
      {
        // Do nothing...
      }
    }

    if(tagName == "input")
    {
      var type = elementCollection[counter].type.toLowerCase();
      if(type == "text")
      {
        try
        {
          elementCollection[counter].focus();
          break;
        }
        catch(e)
        {
          // Do nothing...
        }
      }
    }
  }
}

/*===================================================================================
  Tests if an element can gain focus
  Params:  element - the element to test
  Returns:  True if element can gain focus, otherwise false
  
  2003-06-23 PK
====================================================================================*/
function canFocus(element)
{
  // Booleans to test obstacles, add more obstacles when needed...
  var readOnly = element.readOnly;
  var hiddenInput = (element.tagName=="INPUT")&&(element.type=="HIDDEN");

  // Any obstacles?
  if(readOnly||hiddenInput)
  {
    return false;
  }
  else // Otherwise it can gain focus
  {
    return true;
  }
}

/*===================================================================================
  Moves the focus to the next element in the tab order that can gain focus.
  If none is found the focus is removed.
  
  2003-06-23 PK
====================================================================================*/
function nextInTabOrder()
{
  var element = document.activeElement;

  if(element)
  {
    var form = element.form;
  }

  if(form)
  {
    var counter = 0;

    // Find current elements index
    while((element!=form.elements[counter]) && (counter < form.elements.length))
    {
      counter++;
    }

    // Find next valid elements index
    counter++;
    while((!canFocus(form.elements[counter])) && (counter < form.elements.length))
    {
      counter++;
    }

    if(counter < form.elements.length)
    {
      form.elements[counter].focus();
    }
    else
    {
      element.blur();
    }
  }
}

/*===================================================================================
  Gets all paramters send in the search string of the form.
  Returns:  An array with the form parameters. Each parameter is represented by a
  string at the form paramname=paramvalue.
  
  2003-01-10 PK
====================================================================================*/
function getFormParameters()
{
  var search = location.search;
  search = search.replace(/^\?/, "");
  var paramArray = search.split("&");

  return paramArray;
}

/*===================================================================================
  Gets all paramters send in the search string of the form.
  Params:  paramName - the name of the param to get the value of
  Returns:  The value of the param
  
  2003-01-10 PK
====================================================================================*/
function getFormParameter(paramName)
{
  paramName = paramName.toLowerCase();
  var paramArray = getFormParameters();

  for(var counter=0; counter<paramArray.length; counter++)
  {
    var name = paramArray[counter].split("=")[0];

    if(name.toLowerCase() == paramName)
    {
      var value = paramArray[counter].substring(name.length+1);

      return value;
    }
  }

  return "";
}

/*===================================================================================
  Fires the named event of the field. This function is called when you want to to
  trigger an event on the field. The function gives no error if the event does not
  exist.
  Params:
  fieldname - the name of the field
  eventname - the name of the event
  
  2002-11-01 PK
====================================================================================*/
function fireEvent(fieldname, eventname)
{
  field = document.getElementById(fieldname);
  eventname = eventname.toLowerCase();

  // If event is defined for field
  if(eval("field." + eventname))
  {
    // Fire event
    eval("field." + eventname + "()");
  }
}

/*===================================================================================
  Fires "the usual" events of the field. This function should be used when the value
  of the field is changed "programatically" to allow the field to handle the change
  as usual.
  Params:  fieldname - the name of the field
  
  2002-11-01 PK
====================================================================================*/
function fireEvents(fieldname)
{
  fireEvent(fieldname, "onchange");
  fireEvent(fieldname, "onblur");
  // Add more events when needed...
}

/*===================================================================================
  When an mail form is expanded In C reloads the form.
  This function called from onLoad will scroll down to the newly expanded mail form.
  
  2002-10-18 PK
====================================================================================*/
function scrollToMailFormAnchor()
{
  // Last expanded mail form is by In C marked by an anchor named pos. Redirect to this anchor, if not found we end up at top of form as usual
  location.href="#pos";
}

/*===================================================================================
  Funktionen byter ut HTML-koden i de två celler som används för
  epostfunktionaliteten. När man klickar på "Ångra"-knappen körs funktionen nedan.
  Params: fieldNo - Fältnummret på den epost som ska förändras.
          buttonValue - valfri inparameter som sätter value (texten) på knappen.
    buttonStyle - valfri inparameter som tar CSS-kod för att sätta stylen på
  Example: removeEmailFields("10", "Aktivera e-post", "width:95px;");
  Returns: nothing.
  
  2005-03-02 MH - Tillägg för stöd av "Sök" i knappar vid Ångra.
  2004-04-20 ML - Tillägg för att det ska fungera på kvittens
  2004-04-14 MH - Tillägg för att fungera även med sök/visa fält och knapp för rollfät
  2003-10-09 ML - Netscape anpassning (.search i stället för .indexOf & extractTextElements() i stället för .innerText).
  2003-10-02 ML - Tillägg av andra och tredje inparametern.
  2003-10-01 ML
====================================================================================*/

function removeEmailFields(fieldNo, buttonValue, buttonStyle) {
  // Leta upp cellen med de aktuella Epostfälten.
  var cell = document.getElementById("tdF"+fieldNo);

  if(cell) {
    var selectEndTagLength = 9;
    // Kollar om det kommer med en inparameter, annars sätt namnet till Epost.
    if(!buttonValue) {
      buttonValue = "Epost";
    }
    // Om inparametern buttonStyle så fixa ihop den med HTML koden annars sätt den till inget.
    if(buttonStyle) {
      buttonStyle = " STYLE='" + buttonStyle + "'";
    } else {
      buttonStyle = "";
    }

    // Letar i koden efter strängen "</SELECT>" och räknar antalet tecken till OCH MED ordet (därav +selectEndTagLength).
    var endValue = 0;
    // Om det fins en Visa knapp
    var visaPos = cell.innerHTML.indexOf("Visa");
    if(visaPos==-1)
      visaPos = cell.innerHTML.indexOf("Sök");
    if(visaPos==-1)
      visaPos = cell.innerHTML.indexOf("S&ouml;k");
    if(visaPos != -1) {
      var foundEnd = false;
      while(!foundEnd && visaPos<cell.innerHTML.length) {
        if(cell.innerHTML.substr(visaPos,1)==">") {
          foundEnd = true;
          visaPos++; 
        } else {
          visaPos++; 
        }
      }
      endValue = visaPos;
    // Annars om det fins en </SELECT> tagg
    } else if(cell.innerHTML.indexOf("</SELECT>") != -1) {
      endValue = cell.innerHTML.search(/<\/SELECT>/i) + selectEndTagLength;
    // Annars så ta innehållet i cellen till näsa tagg börjar "<"
    } else {
      endValue = cell.innerHTML.search(/</i);
    }

    // Hämta ut HTML-koden och spara det i variabeln.
    var HTMLToKeep = cell.innerHTML.substring(0, endValue);
    // Lägg tillbaka den ursprungliga HTML-koden (Rullmenyn och Email-knappen).
    var newHTML = HTMLToKeep + "\n<INPUT TYPE='submit' NAME='AddEMailFields_" + fieldNo + "' VALUE='" + buttonValue + "'" + buttonStyle + ">"
    newHTML += "\n</TD>\n          <TD WIDTH='305' ALIGN='left' VALIGN='top' CLASS='text' COLSPAN='2'>&nbsp;</TD>\n        </TR>"
    // Lägg HTML-koden i cellen.
    cell.innerHTML = newHTML;

    // Leta upp och ta bort taggara runt innehållet i rubriken.
    var cell2 = document.getElementById("tdL"+fieldNo);
    if(cell2) {
      cell2.innerHTML = extractTextElements(cell2);
    }
  }
}

/*===================================================================================
  Function to confirm or decline "Clear" of form when clicking "Rensa".
  2003-11-09 MH
====================================================================================*/
function confirmClear()
{
  if( confirm(strconstConfirmClear) )
  {
    if ( document.forms[0] ) 
      document.forms[0].reset();
  }
}

/*===================================================================================
  Gets the deviation type from the hidden field if exists
  Params:  rootnode  - the deviation type rootnode used to name the hidden field
  Returns:  The deviation type if accessible, otherwise ""
  
  2003-01-15 PK   Made it OK to give the rootnode with leading "V" as we usually does
  2002-10-11 PK   Changed all element references to cross browser code (no document.all)
  2002-06-03 PK   Handles rootnodes even if the V is not capital
  2002-05-29 PK
====================================================================================*/
function getDeviationType(rootnode)
{
  // Remove all but number, makes the leading "V" optional
  rootnode = extractNumber(rootnode);

  var root = document.getElementById("V" + rootnode);

  //if(!root) root = document.getElementById("v" + rootnode);

  if(root)
    if(root.value) return root.value;

  return "";
}

/*===================================================================================
  Gets the value of a field if defined or the text encapsulated by a tag that  supports innerHtml.
  This work around gives a value even if the field isn't editable.
  Params:  fieldname            - the name of a field from In C
  tagEncapsulatingText - the name of an element ecapsulating the text created by
                         In C as a result of a non-editabled field
  Returns:  The value of the field, the text created as a result of a non-editable field or
  "undefined" if non of the other alternatives is possible.
  Warning:  There is a danger in comparing the text created since in may be altered in the
  client by any administrator.
  
  2002-11-26 PK   Replaced innerText with extractTextElements to skip enclosed elements
  2002-11-14 PK   Strip innerText before assigning it to the result
  2002-10-11 PK   Changed all element references to cross browser code (no document.all)
  2002-09-24 PK
====================================================================================*/
function getFieldValueOrText(fieldname, tagEncapsulatingText)
{
  var result;

  var field = document.getElementById(fieldname);
  //var field = eval("document.all." + fieldname);
  var textTag = document.getElementById(tagEncapsulatingText);
  //var textTag = eval("document.all." + tagEncapsulatingText);

  // Get value wheter show or not
  if(field)
  {
    // Edit, get code type number
    result = field.value;
  }
  else if(textTag)
  {
    // Show, field is not available, get value instead
    result = extractTextElements(textTag);
    result = strip(result);
  }

  return result;
}

/*===================================================================================
  Extracts all text nodes from a html subtree and concatenates all their texts.
  Params:  parent  - the parent node of the html subtree
  Returns:  The concatenation of all the text nodes
  
  2002-11-26 PK
====================================================================================*/
function extractTextElements(parent)
{
  var str = "";

  var children = parent.childNodes;
  for(var counter=0; counter<children.length; counter++)
  {
    switch(children[counter].nodeType)
    {
      case 3 : str += children[counter].nodeValue;            // text node
               break;
      case 1 : str += extractTextElements(children[counter]); // element
               break;
    }
  }
  return str;
}

/*===================================================================================
  Gets a value from a radio group
  Params:  name  - the name of the radio group
  Returns:  The value from the checked option if any, otherwise ""
  
  2002-10-29 PK   Bugfix, getElementById replaced by getElementsByName
  2002-10-11 PK   Changed all element references to cross browser code (no document.all)
  2002-07-11 PK   Added check if radiogroup exists before adressing it
  2002-06-20 PK&POK
====================================================================================*/
function radioGroupValue(name)
{
  var radioGroup = document.getElementsByName(name);

  if(radioGroup)
    for(var i=0; i<radioGroup.length; i++)
    {
      if(radioGroup[i].checked)
      {
        return radioGroup[i].value;
        break;
      }
    }

  return "";
}

/*===================================================================================
  Gets a label (LABELVALUE) from a radio group
  Params:  labelName  - the InC label name of the radio group
  Returns:  The InC label from the checked option if any, otherwise ""
  
  2004-09-22 AA
====================================================================================*/
function radioGroupLabelValue(labelName){

  var inputElements=document.getElementsByTagName('input');			// Hämta alla inputelement
  var nbrOfElements=inputElements.length;					// Hur många var där

  // Loopa igenom all element
  for(iElementCounter=0;iElementCounter<nbrOfElements;iElementCounter++){

    var currentElement=inputElements[iElementCounter];				// current element
    if(currentElement.type){
      var elementTypeLowerCase = currentElement.type.toLowerCase();
    }
    // Om elementet är en radioknapp
    if(elementTypeLowerCase == "radio"){
      // Rätt element är hittat
      if(currentElement.LABELTOP==labelName){
        var sBtnGroup=currentElement.name;
        var oBtnGroup = document.getElementsByName(sBtnGroup);

        for(iButton=0;iButton<oBtnGroup.length;iButton++){
          if(oBtnGroup[iButton].checked){
            return oBtnGroup[iButton].LABELVALUE;				// Returnera label på ikryssad radio
	    break;
          }
        }
      }
    }
  }
  return "";
}

/*===================================================================================
  Checks a radio group for a value
  Params:  name  - the name of the radio group
  Returns:  true if any button is checked, otherwise false
  
  2002-10-29 PK   Bugfix, getElementById replaced by getElementsByName
  2002-10-11 PK   Changed all element references to cross browser code (no document.all)
  2002-07-11 PK   Added check if radiogroup exists before adressing it
  2002-05-21 PK
====================================================================================*/
function radioGroupChecked(name)
{
  var radioGroup = document.getElementsByName(name);

  if(radioGroup)
  {
    for(var i=0; i<radioGroup.length; i++)
    {
      if(radioGroup[i].checked)
      {
        return true;
      }
    }
  }

  return false;
}

/*===================================================================================
  Inits a radio group if no value is set
  Params:  rGroup  - the name of the radio group to init
  	   rButton - the index of the button in the group to select
	   
  2002-10-29 PK   Bugfix, getElementById replaced by getElementsByName
  2002-10-11 PK   Changed all element references to cross browser code (no document.all)
  2002-07-12 PK
====================================================================================*/
function initRadioButton(rGroup, rButton)
{
  var radioGroup = document.getElementsByName(rGroup);

  if(radioGroup)
  {
    if(!radioGroupChecked(rGroup))
    {
      for(var i=0; i<radioGroup.length; i++)
      {
        if(radioGroup[i].value == rButton)
        {
          radioGroup[i].click();
        }
      }
    }
  }
}

/*===================================================================================
  Removes invalid characters from a field
  Params:  field - the field to remove invalid characters from
  	   charstr - a string containing all valid characters
	   
  2003-04-09 PK  Renamed variable from char to character since char is reserved word
  2002-05-16 PK
====================================================================================*/
function validChars(field, charstr)
{
  var counter=0;
  var character;

  // Loop the fields value string
  while(counter <field.value.length)
  {
    character = field.value.charAt(counter);
    //alert(char);
    if(charstr.indexOf(character) == -1)
      // Replace invalid characters with ""
      field.value = field.value.replace(character,"")
    else
        counter++;
  }
}

/*===================================================================================
  Extracts params from a string
  Params:  paramstr  - a string with params separated by a separator character
  Returns:  An array with the params
  
  2002-05-14 PK
====================================================================================*/
function extractParams(paramstr)
{
  // Character that separeates the different params
  var separator = "|";

  return paramstr.split(separator);
}

/*===================================================================================
  Transforms a fieldnumber into a valid fieldname
  Negative numbers are transformed into an codetype, positive to an ordinary field.
  Params:  prefix    - the prefix to add before the fieldnumber
  	   fieldnumber - the number of the field to transform
  Returns:  A "valid" fieldname
  
  2002-05-13 PK
====================================================================================*/
function transformFieldName(prefix, fieldnumber)
{
  var result = "";

  if(fieldnumber < 0)
  {
    // Codetype with negative value
    result = -fieldnumber;
    result = result.toString();

    while(result.length < 5) result = "0" + result;
  }
  else
    // Ordinary field or codetype with five digits
    result = fieldnumber;

  // Add the prefix and return the result
  result = prefix + result;
  return result;
}

/*===================================================================================
  Returns an element given by its id, or if none id is available by the current event.
  Params:  elementId - the id of the element to return. If none (or null) is given the
              element that caused the current event is returned.
  Returns:  A form element
  
  2003-03-21 PK
====================================================================================*/
function getElementByIdOrEvent(elementId)
{
  if(elementId)
  {
    return document.getElementById(elementId);
  }
  else
  {
    return event.srcElement;
  }
}

/* ---------------------------------------------------------------------
   Clear fields
--------------------------------------------------------------------- */

/*===================================================================================
  Clears a radio group
  Params:  name  - the name of the radio group
  
  2002-10-30 PK   Bugfix, getElementById replaced by getElementsByName
  2002-10-11 PK   Changed all element references to cross browser code (no document.all)
  2002-07-12 PK   Added check if radiogroup exists before adressing it
  2002-05-21 PK
====================================================================================*/
function clearRadioGroup(name)
{
  var radioGroup = document.getElementsByName(name);

  if(radioGroup)
  {
    for(var i=0; i<radioGroup.length; i++)
    {
      if(radioGroup[i].name == name)
      {
        radioGroup[i].checked = false;
      }
    }
  }
}

/*===================================================================================
  Clears a group of VFields.
  Params:  paramstr  - an string with the fieldnumbers of the field to enable/disable
          separated by a separator character
	  
  2002-05-13 PK
====================================================================================*/
function clearVFields(paramstr){

  fields = extractParams(paramstr);

  for(var i=0; i<fields.length; i++){
    clearVField(fields[i]);
  }
}

/*===================================================================================
  Clear a VField.
  Params:  field - the fieldnumber of the field to clear
  
  2002-10-11 PK   Changed all element references to cross browser code (no document.all)
  2002-05-13 PK
====================================================================================*/
function clearVField(field)
{
  var expandedFieldName = document.getElementById(transformFieldName("v", field));
  //var expandedFieldName = "document.forms[0]." + transformFieldName("v", field);

  // Only existing field will be processed
    if(eval(expandedFieldName))
  {
    switch(eval(expandedFieldName).type)
    {
      case "checkbox" : eval(expandedFieldName).checked = false;
                break;
      // Just add more types when needed!
    }
  }
}

/* ---------------------------------------------------------------------
   Required, see also reqiuredField.js and requiredClass.js
--------------------------------------------------------------------- */

/*===================================================================================
  Sets/clears the "required property" of the field
  Params:  fieldname - the name of the field
  	   required  - a boolean, true means that the property is set, false that it is cleared
	   
  2002-12-10 PK Most of the code moved to the more generic new function setRequired.
  2002-10-29 PK Bugfix in "make unrequired", added left part of assign
  2002-10-11 PK Changed all element references to cross browser code (no document.all)
  2002-07-09 PK Added support for multiple classes
  2002-07-04 PK
====================================================================================*/
function makeRequired(fieldname, required){

  field = document.getElementById(fieldname);
  setRequired(field, required);
}

/*===================================================================================
  Sets/clears the "required property" of a radio group.
  Params:  radioName - the name of the radio group
           required  - a boolean, true means that the property is set, false that it is cleared
	   
  2002-12-10 PK
====================================================================================*/
function requireRadio(radioName, required){
  var fields = document.getElementsByName(radioName);

  for(var counter=0; counter<fields.length; counter++){
    setRequired(fields[counter], required);
  }
}

/*===================================================================================
  Sets/clears the "required property" of an element.
  Params: field - the element
          required  - a boolean, true means that the property is set, false that it is cleared
	  
  2004-06-10 MLU Added check to se if "required" is in the class  
  2004-03-15 AA Function now removes backgrouncolor when an element is "unrequired"
  2004-03-08 AA Added check to see if the object already has classname 'required'
  2002-12-10 PK
====================================================================================*/
function setRequired(field, required){
  if(field){
    if(required){
      if(field.className.indexOf("required") == -1){	// Finns inte required sedan innan så..
        field.className = field.className + ' required';
      }
    }
    else{
      if(field.className.indexOf("required") != -1){   // 2004-06-09 ML Finns required så...
        // Three versions to get rid of unnecessary spaces
        field.className = field.className.replace(" required", "");
        field.className = field.className.replace("required ", "");
        field.className = field.className.replace("required", "");
        field.style.backgroundColor="";	// Removes background color AA 040315 
      }     
    }
  }
}

/* ---------------------------------------------------------------------
   Disabled
--------------------------------------------------------------------- */

/*===================================================================================
  Sets/clears the "disabled property" of the field
  Params: fieldname - the name of the field
          disabled  - a boolean, true means that the property is set, false that it is cleared
	  
  2003-04-10 PK Added support for button/submit/reset
  2002-12-16 PK Changed LABEL to special case and changed DEFAULT behaviour
  2002-10-11 PK Changed all element references to cross browser code (no document.all)
  2002-07-05 PK Don't set disabled checkboxes class to disabled,
                disabled colors are managed by the system
  2002-07-04 PK
====================================================================================*/
function makeDisabled(fieldname, disabled)
{
  field = document.getElementById(fieldname);
  //field = eval("document.all." + fieldname);

  if(field)
  {
    if(disabled)
    {
      switch(field.nodeName)
      {
        case "INPUT" :    switch(field.type)
                          {
                            case "checkbox" : field.disabled=true;
                                              break;

                            case "button" :
                            case "submit" :
                            case "reset" :    field.disabled=true;
                                              field.className="disabled";
                                              break;
                            default :         field.disabled=true;
                                              field.className="disabled";
                                              field.value='';
                                              break;
                          }
                          break;
        case "LABEL" :    field.disabled=true;
                          field.className="disabled";
                          field.style.backgroundColor = getStylesheetRule("BODY").style.backgroundColor;
                          break;
        default :         // textarea...
                          field.disabled=true;
                          field.className="disabled";
      }
    }
    else // !disabled
    {
      if(field.className=="disabled") field.className="";
      field.disabled=false;
    }
  }
}

/*===================================================================================
  Sets/clears the "disabled property" of all fields belonging to a specific class
  Params:  classname - the name of the class
           disabled  - a boolean, true means that the property is set, false that it is cleared
	   
  2002-10-11 PK   Changed all element references to cross browser code (no document.all)
  2002-07-09 PK
====================================================================================*/
function disableClass(classname, disable)
{
  for(var counter = 0; counter < document.forms[0].elements.length; counter++)
  {
    field = document.forms[0].elements[counter];

    if(field.className == classname)
    {
      // Disable field
      if(field.name)
        makeDisabled(field.name, disable);
      else if(field.id)
        makeDisabled(field.id, disable);

      // Find label belonging to field
      label = document.getElementById("l" + field.name.substring(1));
      //label = eval("document.all.l" + field.name.substring(1));

      // Disable label if found
      if(label)
      {
        if(label.name)
          makeDisabled(label.name, disable);
        else if(label.id)
          makeDisabled(label.id, disable);
      }
    }
  }
}

/*===================================================================================
  Enables/disables a single radio button
  Params:  name  - the name of the radio group
           value - the value of the radio button
           enable  - true to enable/disable
	   
  2002-10-30 PK   Bugfix, getElementById replaced by getElementsByName
  2002-10-11 PK Changed all element references to cross browser code (no document.all)
  2002-07-11 PK Added check if exists
  2001-05-21 PK
====================================================================================*/
function enableRadioButton(name, value, enable)
{
  var radioGroup = document.getElementsByName(name);

  if(radioGroup)
  {
    for(var i=0; i<radioGroup.length; i++)
    {
      if((radioGroup[i].name == name) && (radioGroup[i].value == value))
      {
        radioGroup[i].disabled = !enable;
      }
    }
  }
}

/*===================================================================================
  Enables/disables a radio group
  Params:  name  - the name of the radio group, for instance 'v00358'
           enable  - true to enable/disable
  2002-10-29 PK   Bugfix, getElementById replaced by getElementsByName
  2002-10-11 PK Changed all element references to cross browser code (no document.all)
  2002-07-11 PK Added check if exists
  2002-05-21 PK
====================================================================================*/
function enableRadioGroup(name, enable)
{
  var radioGroup = document.getElementsByName(name);

  if(radioGroup)
  {
    for(var i=0; i<radioGroup.length; i++)
    {
      if(radioGroup[i].name == name)
      {
        radioGroup[i].disabled = !enable;
      }
    }
  }
}

/*===================================================================================
  Enables a single radio button
  Params:  name  - the name of the radio group
           value - the value of the radio button
	   
  2002-10-29 PK   Bugfix, getElementById replaced by getElementsByName
  2002-10-11 PK Changed all element references to cross browser code (no document.all)
  2002-07-11 PK Added check if exists
  2002-05-21 PK
====================================================================================*/
function enableRadioButton(name, value)
{
  var radioGroup = document.getElementsByName(name);

  if(radioGroup)
  {
    for(var i=0; i<radioGroup.length; i++)
    {
      if((radioGroup[i].name == name) && (radioGroup[i].value == value))
      {
        radioGroup[i].checked = false;
      }
    }
  }
}

/*===================================================================================
  Switch a VField.
  Params:  enable  - true to enable fields, false to disable them
           field - the fieldnumber of the field to enable/disable
	   
  2002-10-11 PK   Changed all element references to cross browser code (no document.all)
  2002-05-13 PK
====================================================================================*/
function switchVField(enable, field){
  var expandedFieldName = document.getElementById(transformFieldName("v", field));
  //var expandedFieldName = "document.forms[0]." + transformFieldName("v", field);

  // Only existing field will be processed
  if(eval(expandedFieldName)){
    // Enable/disable field
    eval(expandedFieldName).disabled = !enable;
  }
}

/*===================================================================================
  Enables/disables a group of VFields.
  Params:  enable    - true to enable fields, false to disable them
           paramstr  - an string with the fieldnumbers of the field to enable/disable separated by a separator character
	    
  2002-05-13 PK
====================================================================================*/
function switchVFields(enable, paramstr)
{
  fields = extractParams(paramstr);

  for(var i=0; i<fields.length; i++)
  {
    switchVField(enable, fields[i]);
  }
}

/*===================================================================================
  "User friendly" function to clear and disable a group of VFields.
  Encapsulates clearVFields and switchVFields.
  Params:  paramstr  - an string with the fieldnumbers of the field to enable/disable
          separated by a separator character
	  
  2002-05-13 PK
====================================================================================*/
function disableVFields(paramstr)
{
  clearVFields(paramstr);
  switchVFields(false, paramstr);
}

/*===================================================================================
  "User friendly" function to enable a group of VFields.
  Encapsulates switchVFields.
  Params:  paramstr  - an string with the fieldnumbers of the field to enable/disable
          separated by a separator character
	  
  2002-05-13 PK
====================================================================================*/
function enableVFields(paramstr)
{
  switchVFields(true, paramstr);
}

/*===================================================================================
  Disables the "saveSendButton" button in a form. Optional parameters are a button name/id [1st] and disable true/false [2nd].
  Params:  id - the name of the button element (optional), standard value is "saveSendButton".
           bool - disable/enable (optional), standard value is true.
	   
  2004-06-01 ML
====================================================================================*/
function disableButton(id, bool) {
  // If an id was send to the function
  if(id) {
    var button = document.getElementById(id);// Get button element
  } else {
    var button = document.getElementById("saveSendButton");// If a certain button NOT was defined, get "saveSendButton" element
  }
 
  // If bool was defined
  if(bool == false) {
    bool = false;
  } else {
    bool = true;
  }
 
  // If there is a button element
  if(button && bool) {
    button.disabled = true;  // Disable it
  }
}

/* ---------------------------------------------------------------------
   Span routines
--------------------------------------------------------------------- */

/*===================================================================================
  Returns the HTML code content of a span tag
  Params:  elementname - the name of the span
  Returns:  a string containing the HTML code content of the span, i.e. the innerHTML
  
  2002-07-03 PK
====================================================================================*/
function getSpanCode(elementname){
  var spanElement = document.getElementById(elementname);

  if(spanElement)   return spanElement.innerHTML;
  else  return "";
}

/*===================================================================================
  "Shows" and "hides" the content of a span element
  Params:  elementname - the name of the span
           show        - a boolean, true shows the content, false hides it
           codeStorage - a string containing the content of the span to be showed
  Note: Use this function together with the getSpanCode function. With getSpanCode
        you can save the content of a span in a string variable. This variable can
        later be used as codeStorage for the displaySpan function.
  Returns:  a string containing the HTML code content of the span, i.e. the innerHTML
  
  2002-07-03 PK
====================================================================================*/
function displaySpan(elementname, show, codeStorage)
{
  var spanElement = document.getElementById(elementname);

  if(spanElement)
  {
    if(show)
      spanElement.innerHTML = codeStorage;
    else
      spanElement.innerHTML = "";
  }
}

/* ---------------------------------------------------------------------
   String handling routines
--------------------------------------------------------------------- */

/*=====================================================================================
  Removes all characters except digits from a string.
  Params:  str - the string to remove all but the digits from
  Returns:  A string containing just digits
  
  2002-11-18 PK
=====================================================================================*/
function extractNumber(str)
{
  return str.replace(/[^0-9]/g, "");
}

/*=====================================================================================
  Encodes JavaScript unicode character to HTML charcter entites
  Params:  str - the JavaScript string
  Returns:  A string in HTML format
  
  2002-10-31 PK  Bugfix: made the replaces global
  2002-10-23 PK
=====================================================================================*/
function encodeHTMLEntities(str)
{
  str = str.replace(/\u00C5/g,"&Aring;");  // Å
  str = str.replace(/\u00C4/g,"&Auml;");   // Ä
  str = str.replace(/\u00D6/g,"&Ouml;");   // Ö
  str = str.replace(/\u00E5/g,"&aring;");  // å
  str = str.replace(/\u00E4/g,"&auml;");   // ä
  str = str.replace(/\u00F6/g,"&ouml;");   // ö
  return str;
}

/*=====================================================================================
  Decodes HTML character entities to JavaScript unicode charcters
  Params:  str - the HTML string that might contain HTML entities
  Returns:  A string in JavaScript format
  
  2002-10-31 PK  Bugfix: made the replaces global
  2002-10-23 PK
=====================================================================================*/
function decodeHTMLEntities(str)
{
  str = str.replace(/(&Aring;)/g, "\u00C5");  // Å
  str = str.replace(/(&Auml;)/g, "\u00C4");   // Ä
  str = str.replace(/(&Ouml;)/g, "\u00D6");   // Ö
  str = str.replace(/(&aring;)/g, "\u00E5");  // å
  str = str.replace(/(&auml;)/g, "\u00E4");   // ä
  str = str.replace(/(&ouml;)/g, "\u00F6");   // ö
  return str;
}

/*=====================================================================================
  Fills a string from the left with any chosen char
  Params:  str      - the string to fill
           len      - the length to fill the string to
           fillchar - the character to fill the string with
  Returns:  A string filled with fillchar to the length len
  
  2002-08-19 PK
=====================================================================================*/
function leftFill(str, len, fillchar){
  // Make sure that str is treated as a string
  str = str.toString();

  // Fill str from left
  while(str.length < len){
    str = fillchar + str;
  }
  return str;
}

/*=====================================================================================
  Strips a string from leading and trailing spaces.
  Params:  str      - the string to strip
  
  2002-11-12 PK
=====================================================================================*/
function strip(str){
  while((str > "") && (str.charAt(0) == " ")){
    str = str.substring(1);
  }

  while((str > "") && (str.charAt(str.length-1) == " ")){
    str = str.substring(0, str.length-1);
  }
  return str;
}

/* ---------------------------------------------------------------------
   Date handling routines
--------------------------------------------------------------------- */

/*=====================================================================================
  Function is replaced by replaceRelativeDate(). which it now apsulates. Kept for compatibility reasons only.
  Params:  field - the name of the field to parse
  
  2003-03-21 PK   Function is replaced by replaceRelativeDate().
  2002-10-29 PK
=====================================================================================*/
function parseRelativeDate(field)
{
  var datefield = document.getElementById(field); // Field variable
  replaceRelativeDate(datefield);
}

/*=====================================================================================
  Parses relative dates. A relative date is a '+' or a '-' followed by an integer. The value should be
  added/subtracted to/from todys date.
  Params:  datefield - the field to work with
  
  2003-03-21 PK   The main part of pareseRelativeDate() is extracted as this new function
=====================================================================================*/
function replaceRelativeDate(datefield)
{
  // If field is defined
  if(datefield)
  {
    var relativeDateRegExp = /^[\+-][0-9]+$/;

    // If field contains a relative date
    if(relativeDateRegExp.test(datefield.value))
    {
      var modifier = datefield.value.charAt(0);
      // Value without sign
      var modifierValue = Math.abs(datefield.value);

      // Create a new date and set it to "today" modified by the modifier value
      var theDate = new Date();
      eval("theDate.setTime(theDate.getTime()" + modifier + "modifierValue * dayinms);");

      datefield.value = toSwedishDate(theDate);
    }
  }
}

/*=====================================================================================
  Function for test if a datefield is valid. Otherwise an alert is displayed and the
  date is reset to "00-00-00".
  Params:  field - the name of the field to check
  
  2002-10-11 PK Changed all element references to cross browser code (no document.all)
  2002-10-09 PK
=====================================================================================*/
function checkDatefield(field)
{
  // Field variable
  var datefield = document.getElementById(field);

  // If field is defined
  if(datefield)
  {
    if(!isSwedishDate(datefield.value))
    {
      alert(strconstInvalidDate);
      datefield.value = strconstNoDate;
    }
  }
}

/*=====================================================================================
  Encapsulates calls to all date routines that should be called when a datefield is changed.
  Params:  field - the name of the field to check
  
  2003-03-21 PK Rewritten to not require parameter if called from an event handler
  2002-11-26 PK Optimation to get "faster" code
  2002-11-11 PK Added code for reformat to "pretty" swedish date
  2002-10-31 PK Added test for empty date
  2002-10-30 PK
=====================================================================================*/
function datefieldChanged(field)
{
  datefield = getElementByIdOrEvent(field);

  // If field is defined
  if(datefield)
  {
    if(!isEmptyDate(datefield.value))
    {
      replaceRelativeDate(datefield);

      // Reformat swedish date (add - etc)
      var date = parseSwedishDate(datefield.value);
      if(date)
      {
        datefield.value = toSwedishDate(date);
      }
      else
      {
        alert(strconstInvalidDate);
        datefield.value = strconstNoDate;
      }
    }
  }
}

/*=====================================================================================
  Function for test for empty dates ("000000", "00-00-00" or "00/00/00").
  Params:  str - a datestring
  Returns:  true if "empty date", otherwise false
  2004-11-18 AA Fixed bug with four or five zeros
  2002-10-31 PK Added empty string as empty date value
  2002-09-05 PK Made the separartors ("-" or "/") optional
  2002-07-04 PK Moved this function from requiredField.js to this file
  2002-06-25 PK
=====================================================================================*/
function isEmptyDate(str)
{
  var emptyStringRegExp = /^[ ]*$/;			// Empty
  var emptyDateRegExp = /^00[-\/]?00[-\/]?00$/;		// 000000, 00-00-00, 00/00/00
  var emptyDateRegExp2 = /^0000[-\/]?00[-\/]?00$/;	// 00000000, 0000-00-00, 0000/00/00

  return (emptyDateRegExp.test(str)) || (emptyStringRegExp.test(str)) || (emptyDateRegExp2.test(str));
}

/*=====================================================================================
  Function for test for swedish dates.
  Params:  str - a datestring
  Returns:  true if "swedish date", otherwise false

  2002-09-05 PK
=====================================================================================*/
function isSwedishDate(str){
  var dateObject = parseSwedishDate(str);

  if(dateObject)   return true;
  else    return false;
}

/*=====================================================================================
  Compares two swedish dates
  Params:  date1 - a swedish datestring
           date2 - a swedish datestring

  Returns:  ">" if date1 > date2
            "<" if date1 < date2
            "=" if date1 = date2

  2003-04-09 PK  Bugfix: Replaced "=" with "==" in if statement
  2002-10-30 PK
=====================================================================================*/
function compareSwedishDates(date1, date2)
{
  var date1 = parseSwedishDate(date1);
  var date2 = parseSwedishDate(date2);

  if(date1 > date2) return ">";
  if(date1 < date2) return "<";
  if(date1 == date2) return "=";
}

/*===================================================================================
  Convertes a date object to a swedish date string
  Params:  dateobject - the date object to convert
  Returns:  A string containing the date in swedish date format

  2002-12-10 PK  Replaced getYear() with getFullYear()
  2002-09-10 PK  Bug correction, compensated for the JS month bug
  2002-08-19 PK
====================================================================================*/
function toSwedishDate(dateobject){
  var tempstr = dateobject.getFullYear() + "-" + leftFill(dateobject.getMonth() + 1, 2, "0") + "-" + leftFill(dateobject.getDate(), 2, "0");
  return tempstr;
}

/*===================================================================================
  Parses a swedish date string and returns it as a date object.
  Params:  datestring - a swedish datestring
  Returns:  A date object set to the date specified by datestring or null if invalid datestring

  2002-12-10 PK  Replaced getYear() with getFullYear(), added regexp to check format
  2002-11-27 PK  Rewritten with same functionality
  2002-09-05 PK  Added some error handling and null as a possible return value
  2002-05-14 PK
====================================================================================*/
function parseSwedishDate(datestring)
{
  // Right form? Otherwise it is dangerous to use "smart" conversions
  var swedateRegExp = /^[0-9]{2,4}[ -]?[0-9][0-9][ -]?[0-9][0-9]$/;

  if(swedateRegExp.test(datestring))
  {
    // Remove everything but digits
    var newstring = extractNumber(datestring);

    // Make year four digits
    if(newstring.length == 6) newstring = "20" + newstring;
    if(newstring.length == 7) newstring = "2" + newstring;

    var datelength = newstring.length;

    if(datelength == 8)
    {
      // Extract day, month and year
      var theYear = newstring.substring(0, 4);
      var theMonth = newstring.substring(4, 6) - 1; // -1 due to the famous date bug in JavaScript
      var theDay = newstring.substring(6, 8);

      // Create date object
      var theDate = new Date(theYear, theMonth, theDay);

      // Valid date?
      if((theDate.getFullYear() == theYear)&&(theDate.getMonth() == theMonth)&&(theDate.getDate() == theDay))
      {
        return theDate;
      }
    }
  }
  return null;
}

/*===================================================================================
  Parses a swedish date string and returns the day number, i.e. the number of the weekday.
  Params: datestring - a swedish datestring
  Returns:  The day number, i.e. the number of the weekday, specified by the datestring,
  or an empty string if invalid datestring

  2002-09-05 PK  Added some error handling and an empty string as a possible return value
  2002-05-14 PK
====================================================================================*/
function getDayNumber(datestring){
  var dateObject = parseSwedishDate(datestring);

  if(dateObject){
    // Get day number
    var daynumber = dateObject.getDay();
  }
  else daynumber = ""; // The empty string is better to assign to a form field than null

  return daynumber;
}

/*===================================================================================
  Parses a swedish date string and returns the weekday as a string. The string is defined in the global text.js.
  Params:  datestring - a swedish datestring
  Returns:  The weekday as a string defined in text.js or an empty string if invalid datestring

  2002-09-12 PK  Bugfix, (sundays)
  2002-09-05 PK  Added some error handling and an empty string as a possible return value
  2002-05-14 PK
====================================================================================*/
function getWeekday(datestring)
{
  var result = ""; // The empty string is better to assign to a form field than null
  var daynumber = getDayNumber(datestring);

  if((daynumber >= 0) && (daynumber <= 6))  result = strconstWeekdays[daynumber];

  return result;
}

/* ---------------------------------------------------------------------
   Time handling routines
--------------------------------------------------------------------- */

/*=====================================================================================
  Function for test for an empty time ("00:00", "0:00", "0.00" or "00.00").
  Params:  str - a timestring
  Returns:  true if "empty time", otherwise false

  2003-08-18 AA
=====================================================================================*/
function isEmptyTime(str){

  var emptyStringRegExp1 = /^[ ]*$/;
  var emptyStringRegExp2 = /^0?0[.:]?00?$/;

  return (emptyStringRegExp1.test(str)) || (emptyStringRegExp2.test(str));
}

/*=====================================================================================
  Function for test if a timefield is valid. Otherwise an alert is displayed and the time is reset to "00:00".
  Params:  field - the name of the field to check

  2003-03-21 PK Rewritten to not require parameter if called from an event handler
  2002-10-31 PK
=====================================================================================*/
function checkTimefield(field){

  var timefield = getElementByIdOrEvent(field);  // Field variable

  // If field is defined
  if(timefield)  {
    var time = timefield.value;

    // Regular expressions to check time
    var timeRegExp1 = /^[0-1]?[0-9][ .:]?[0-5][0-9]$/; // 00.00-19.59
    var timeRegExp2 = /^2[0-3][ .:]?[0-5][0-9]$/;      // 20.00-23.59

    if(timeRegExp1.test(time) || timeRegExp2.test(time)){
      var minutes = time.substring(time.length-2);
      var possibleSeparator = time.charAt(time.length-3);

      var digit = /^[0-9]$/;
      if(digit.test(possibleSeparator)){ // No separator
        var hours = time.substring(0, time.length-2);
      }
      else{ // Separator
        var hours = time.substring(0, time.length-3);
      }

      leftFill(hours, 2, "0");
      timefield.value = hours + ":" + minutes;
    }
    else{ // Invalid time
      alert(strconstInvalidTime);
      timefield.value = strconstNoTime;
    }
  }
}

/* ---------------------------------------------------------------------
   Array handling routines
--------------------------------------------------------------------- */

/*===================================================================================
  Removes an element from an array without leaving a "hole" as delete would have done
  Params:  array        - the array to delete an element from
           elementindex - the index of the element to delete

  2002-07-09 PK
====================================================================================*/
function removeFromArray(array, elementindex){
  if(elementindex >= 0){
    for(var counter=elementindex+1;counter<array.length;counter++){
      array[counter-1] = array[counter];
    }
    array.length = array.length-1;
  }
}

/* ---------------------------------------------------------------------
   Dialog routines
--------------------------------------------------------------------- */

/*===================================================================================
  Opens a modal dialog with html formated content. Returns a value from the  dialog.
  Params: dialogTitle - the title of the dialog window
          htmlstr     - the html code to display in the dialog window
  Returns:  The value asigned to 'window.returnValue' in the htmlstr

  2002-09-04 PK
====================================================================================*/
function showModal(dialogTitle, htmlstr){
  // Returns the value asigned to 'window.returnValue' in the htmlstr
  
  returnValue = window.showModalDialog('about:<head><title>' + dialogTitle + '</title></head><body onload="document.write(window.dialogArguments);"></body>', htmlstr, 'dialogHeight: 200px; dialogWidth:200px;center=yes;');
  return returnValue;
}

/* ---------------------------------------------------------------------
   CSS routines
--------------------------------------------------------------------- */

/*=====================================================================================
  Gets a stylesheet rule number from styleSheet[0] by it's name
  Params:  rule - the case sensitive class name of the rule
  
  2005-01-18 MH   Enhanced for support of all browsers (cssRules)
  2002-07-09 PK
====================================================================================*/
function getStylesheetRuleIndex(rule){
  var styleSheet = document.styleSheets[0];
  if(styleSheet.rules)
    styleSheet.cssRules = styleSheet.rules;
    
  for(var i=0; i < styleSheet.cssRules.length; i++){
    if(styleSheet.cssRules[i].selectorText == rule){
      return i;
    }
  }
  return null;
}

/*=====================================================================================
  Gets a stylesheet rule from styleSheet[0] by it's name.
  Params:  rule - the case sensitive class name of the rule

  2005-01-18 MH   Enhanced for support of all browsers (cssRules)
  2002-07-05 PK
====================================================================================*/
function getStylesheetRule(rule) {
  var styleSheet = document.styleSheets[0];
  if(styleSheet.rules)
    styleSheet.cssRules = styleSheet.rules;

  for(i=0; i < styleSheet.cssRules.length; i++) {
    if(styleSheet.cssRules[i].selectorText == rule) {
      return styleSheet.cssRules[i];
    }
  }
  return null;
}
