/*****************************************************
    Various dhtml functions for VolunteerSolutions

    Included in this library:
    - html dom util procs 
        (see tcl/core/ajax-dhtml, tcl/core/ajax-toggable.tcl)
    - rsh helper procs (see tcl/core/ajax-rsh.tcl)

 We minify this Javascript for increased speed. The version
 we deliver is lib-mini.js  You can minify using the Google
 performance tool for Firebug, which minifies scripts for you.
 *****************************************************/

var mousePosX;
var mousePosY;

/**
 * Dynamically loads a javascript file. If the file has been loaded before (same filename),
 * then does nothing.
 */
function vs_load_script(fullPath, filename) {
    var loaded_scripts = document.getElementsByTagName('script');
    if ( loaded_scripts ) {
        for(var i = 0; i < loaded_scripts.length; i++) {
            if ( loaded_scripts[i]
                && loaded_scripts[i].src
                && loaded_scripts[i].src.search(filename) != -1
            ) {
                // means this file has been loaded before
                return;
            }
        }
    }

    var head = document.getElementsByTagName('head')[0];
    var script = document.createElement('script');
    script.type= 'text/javascript';
    script.src= fullPath;
    head.appendChild(script);
}

function isMicrosoftBrowser() {
  if (navigator.appName.indexOf("Microsoft") == -1) {
    return false;
  }
  return true;
}
  
function captureMousePosition(event) {
    if (isMicrosoftBrowser()) {
      event = window.event;
    }
    mousePosX = event.screenX;
    mousePosY = event.screenY;
}

/**
 * Prepends the specified base path onto the specified url if necessary.
 * This is required to support mouseovers.
 *
 * @pre pBasePath must be of the form http://www.foo.com/bar/
 *      and pRoot must be of the form http://www.foo.com/
 **/
function swtmMaybePrependBasePath(pURL,pBasePath,pRoot) {
  // Check the beginning for the following cases: http:// or // or /
  // If it is none of these cases, then prepend the base path.

  // If pURL start with a single / then pURL is relative to the
  // root of pBasePath.
  if (pURL.charAt(0) == "/" && 
      (pURL.length==1 || pURL.charAt(1) != "/")) {
      return pRoot + pURL.substring(1, pURL.length);
  }
  // If pURL starts with http:// or // then just return it
  if (pURL.indexOf("http://")==0 || pURL.indexOf("https://")==0 || pURL.indexOf("//")==0) {
      return pURL;
  }
  // The URL is relative to the base path
  return pBasePath + pURL;
}


/**
 * Somewhat browser independent way of retrieving elements
 **/
function _getElement(strID) {
    var el = null;
    if (document.getElementById) {
        el = document.getElementById(strID);  
    } else if (document.all) {
        el = document.all[strID];  
    }
    return el;
}

/**
 * Pops up a window
 **/
function openWindow(pURL,pHeight,pWidth) {
  var win = window.open(pURL,'popup','menubar=no,toolbar=no,location=no,directories=no,status=no,scrollbars=yes,resizable=yes,width='+pWidth+',height='+pHeight);
  win.focus();
}

/**
 * Pops open a window, attempting to position it next to the current mouse position
 **/
function openWindowNextToMouse(pURL,pHeight,pWidth) {
  if (mousePosX - pWidth < 0) {
    mousePosX = pWidth;
  }
  if (mousePosY + pHeight > screen.height) {
    mousePosY -= (mousePosY + pHeight + 50) - screen.height;
  }
  mousePosX -= pWidth;
  mousePosY += 10;

  var win = window.open(pURL,'popup','screenX=' + mousePosX + ',left=' + mousePosX + 'screenY=' + mousePosY + ',top=' + mousePosY + 'menubar=no,toolbar=no,location=no,directories=no,status=no,scrollbars=yes,resizable=yes,width='+pWidth+',height='+pHeight);
  win.focus();
  win.moveTo(mousePosX, mousePosY);
}

/**
 * Removes the leading and trailing spaces from a string
 * 
 * @see http://www.voy.com/1888/58.html
 **/ 
function trim(st) {
    var len = st.length
    var begin = 0, end = len - 1;
    while (st.charAt(begin) == " " && begin < len) {
        begin++;
    }
    while (st.charAt(end) == " " && begin < end) {
        end--;
    }
    return st.substring(begin, end+1);
}


/**
 * Format US phone numbers to look like (xxx) yyy-zzzz. Ignores any
 * phone number that does not have exactly 10 digits.
 * 
 * @see https://ssl.salesforce.com/js/functions.js
 * @see http://www.js-x.com/example/?ex=980&mode=1&COLOR_OFF=YES
 **/
function formatPhone (field) {
    field.value = trim(field.value);    

    var ov = field.value;
    var v = "";
    var x = -1;

    // is this phone number 'escaped' by a leading plus?
    if (0 < ov.length && '+' != ov.charAt(0)) { // format it
        // count number of digits
        var n = 0;
        if ('1' == ov.charAt(0)) {  // skip it
            ov = ov.substring(1, ov.length);
        }

        for (i = 0; i < ov.length; i++) {
            var ch = ov.charAt(i);

            // build up formatted number
            if (ch >= '0' && ch <= '9') {
                if (n == 0) v += "(";
                else if (n == 3) v += ") ";
                else if (n == 6) v += "-";
                v += ch;
                n++;
            }
            // check for extension type section;
            // are spaces, dots, dashes and parentheses the only valid non-digits in a phone number?
            if (! (ch >= '0' && ch <= '9') && ch != ' ' && ch != '-' && ch != '.' && ch != '(' && ch != ')') {
                x = i;
                break;
            }
        }
        // add the extension
        if (x >= 0) v += " " + ov.substring(x, ov.length);

        // if we recognize the number, then format it
        if (n == 10 && v.length <= 40) field.value = v;
    }
    return true;
}

/**
 * Sets the selected option in a <select> element.
 * 
 * @param optionValue The value of the option that we are looking for.
 **/ 
function vsSetDropDownSelected(pSelectWidget, optionValue) {
    for ( var i = 0; i < pSelectWidget.options.length; i++ ) {
        if ( pSelectWidget.options[i].value == optionValue )
            pSelectWidget.options[i].selected = true;
        else
            pSelectWidget.options[i].selected = false;
    }
}

/**
 * Used to set the page number while paginating through a table.
 * We prefer this to using a form as it allows us to avoid
 * nesting forms.
 * 
 * @param pTargetURL The URL to which to go redirect the user
 * @param pURLVars URL Vars to pass along. Should include everything 
 *                 except for this widget's field name.
 * @param askForConfirmation If true, then we ask the user for confirmation
 *        before proceeding.
 **/ 
function adTableRedirect(pSelectWidget, pFieldName, pTargetURL, pURLVars, askForConfirmation) {
    if (askForConfirmation
        && !confirm("Are you sure you want to proceed? (All information you provided on this page will be lost)")
    ) {
        // Try to revert to the initial selected option
        var initial_select = pSelectWidget.getAttribute('selected');
        if ( initial_select ) {
            vsSetDropDownSelected(pSelectWidget, initial_select);
        }
        return false;
    }

    var value = pSelectWidget.options[pSelectWidget.selectedIndex].value;
    var url = pTargetURL + '?';
    if (pURLVars.length > 0) {
        url += pURLVars + '&';
    }
    url += pFieldName + '=' + value;
    window.location.href = url;

    return true;
}


/**
 * Check all input fields (e.g. all checkboxes)
 * 
 * @param pFieldName The input field to check
 * @param pTrueFalse The value to which to set the checkboxes
 **/ 
function checkAll(pFieldName, pTrueFalse) {
  var inputFields = null;
  if (document.getElementsByTagName) {
     inputFields = document.getElementsByTagName("input");
  } else if (document.all) {
    inputFields = document.all.tags("input");
  } else {
    // no input fields could be found - just return
    return;
  }

  var fld, thisType, thisName;
  for (var i = 0; i < inputFields.length; i++) {
    fld = inputFields[i];
    if (! fld.type || fld.type != "checkbox" ) {
      continue;
    }
    if (! fld.name || fld.name != pFieldName ) {
      continue;
    }

    fld.checked = pTrueFalse;
  }
}

/**
 * Toggles the diplay attributes of our simple category menu
 **/
function toggleCategoryDisplay(strID, imgID) {
    var el = _getElement(strID);
    var img = _getElement(imgID);
    if (el.style.display != "none") {
        el.style.display = "none";
        img.src = "/images/util/plus-box.gif";
    } else {
        el.style.display = "block";
        img.src = "/images/util/minus-box.gif";
    }
}

/**
 * Toggles the diplay attributes of our simple category menu
 **/
function displayIfSelected(strID) {
    var el = _getElement(strID);
    if (el.style.display != "none") {
        el.style.display = "none";
    } else {
        el.style.display = "block";
    }
}


/**
 * Set display to none of all elements that begin with strPrefix
 **/
function setDisplayToNoneByPrefix(strPrefix) {
  var inputFields = null;
  if (document.getElementsByTagName) {
     inputFields = document.getElementsByTagName("div");
  } else if (document.all) {
    inputFields = document.all.tags("div");
  } else {
    // no input fields could be found - just return
    return;
  }
  // alert("setDisplayToNoneByPrefix: " +strPrefix + "-== " + inputFields);

  var fld, thisType, thisName;
  for (var i = 0; i < inputFields.length; i++) {
    fld = inputFields[i];
    if (fld.id && strPrefix == fld.id.substring(0, strPrefix.length) ) {
      fld.style.display = 'none';
    }
  }
}


/**
 * Set the diplay attribute of the element with the specified ID
 **/
function setDisplay(strID, strDisplay) {
    var elements = strID.split("|");
    var i = 0;
    while (i < elements.length) {
      var el = _getElement(elements[i]);
      if ( el != null ) {
        if (el.style.display != strDisplay) {
            el.style.display = strDisplay;
        }
      }
      i += 1;
    }
}

// Store the last field to allow the user to immediately correct what
// we auto-capitalize
var lastCapitalizedField = null;

/**
 * Capitalizes the specified word
 **/
function capitalizeWord(strWord) {
  return strWord.substring(0,1).toUpperCase() + strWord.substring(1, strWord.length);
}

/**
 * Replaces the innerHTML property of the specified document element
 **/
function updateInnerHtml(strFieldName, strText) {
    var theTarget = _getElement(strFieldName);
    if (theTarget != null) {
        theTarget.innerHTML = strText;
    }
}

/**
 * Replaces the style property of the specified document element
 **/
function updateStyleDisplay(strFieldName, strStyle) {
    var theTarget = _getElement(strFieldName);
    if (theTarget != null) {
        theTarget.style.display = strStyle;
    }
}

/**
 * Capitalizes the first letter in each word (space separated). 
 * Does not touch any other characters.
 **/
function capitalizeWords(strID) {
  if (lastCapitalizedField != null && strID == lastCapitalizedField) {
    return;
  }
  lastCapitalizedField = strID;
  var el = _getElement(strID);
  var current = el.value;
  if (current != null) {
    var newValue;
    var words = current.split(' ');
    if (words.length == 0) {
      newValue = capitalizeWord(current);
    } else {
      newValue = '';
      for (var i=0; i < words.length; i++) {
        if (i > 0) {
          newValue += ' ';
        }
        newValue += capitalizeWord(words[i]);
      }
    }
  }
  el.value = newValue;
}

function postFormByName(form) {
  form.submit();
}

/**
 * Enables/disables all the form elements with the given name prefix.
 * 
 * @param theForm The form object that the element belongs to. Usually, you could just do: 
 *                  toggleDisableFields(this.form, 'name');
 * @param input_name_prefix The prefix name of the input/fields to disable
 *
 */
function toggleDisableFields(theForm, input_name_prefix) {
    var element;
    for(i = 0; i < theForm.elements.length; i++) {
        element = theForm.elements[i];
        if ( element.name.match("^" + input_name_prefix) ) {
            element.disabled = !element.disabled;
        }
    }
}

function setFocus(field_name) {
    if ( document.getElementsByName(field_name) ) {
        if ( document.getElementsByName(field_name).length ) {
            document.getElementsByName(field_name)[0].focus();
        } else {
            document.getElementsByName(field_name).focus();
        }
    }
}

/**
 * Gets all elements with the given prefix and updates receiver with the sum amount.
 * Revised to exclude hours with 'deny' checkbox checked (if param checkDeny is true). The
 * 'Deny' checkbox is retrieved by checking for a checkbox with a 'target' attribute
 * with value equal to the name of the element of the textbox.
 *
 * Note: Prototype.js is required
 *
 * @param prefix String The regexp prefix of the name of the inputs to include in the sum.
 * @param receiver String The id of the element that will receive the sum.
 * @param checkDeny If true, then a 'Deny' checkbox is searched and skips the elements
 *                  if checked.
 *
 * Example: <input type=textbox id=sum_hours onchange="this.value = vs_getSumWithDeny('hours_', 'sum_hours', true);">
 */
function vs_getSum(prefix, receiver, checkDeny) {
    var sum = 0.0;
    var elems;
    var rec_elem = $(receiver);

    elems = $$('input[name*="' + prefix + '"][type="text"]');

    // Loop through each element with name matching prefix
    elems.each(function(elem) {
        var hasDeny = false;
        var deny_cbx = $$('input[target="' + elem.name + '"][type="checkbox"]');
        if ( deny_cbx && deny_cbx.length > 0 ) {
            hasDeny = deny_cbx[0].checked;
        }
        // Check if the value is a number and if there is no deny element that is checked

        if ( !elem.disabled && !isNaN(elem.value) && !hasDeny ) {
            sum += parseFloat(elem.value);
        }
    });

    if ( rec_elem ) {
        if ( rec_elem.value == null ) {
            rec_elem.update(sum);
        } else {
            rec_elem.value = sum;
        }
    }
    return sum;
}

/**
 * Disables a textbox if a checkbox is checked.
 *
 * Note: Prototype.js is required for appending the vs_disabled class
 *
 * @param cbx The checkbox element.
 * @param elemToDisable The html element (textbox or whatever) to disable if the checkbox is checked.
 *
 * Example:
 *      <input type=text id=sum_hour value=12 />
 *      <input type=checkbox id=deny_hour onclick="vs_disableIfChecked(this, 'sum_hour');" />
 */
function vs_disableIfChecked(cbx, elemToDisable) {
    var elem = $(elemToDisable);
    if ( ! elem || ! cbx ) {
        return;
    }

    if ( cbx.checked ) {
        elem.disabled = true;
        elem.addClassName('vs_disabled');
    } else {
        elem.disabled = true;
        elem.removeClassName('vs_disabled');
    }
}

/**
 * Toggles the style->display property 
 * (if it's display: block, then it'll set it to display: none, and vice versa).
 * 
 * @param id String The id of the element to toggle the display.
 * @param isInline Boolean Optional parameter to check if the visible value of display is
 *        inline. Otherwise, it's block.
 */
function vs_toggleDisplay(id, isInline) {
    var element = _getElement(id);
    var visibleValue = (isInline)?"inline":"block";
    if ( element ) {
        if ( element.style.display.toLowerCase() == visibleValue) {
            element.style.display = "none";
        } else {
            element.style.display = visibleValue;
        }
    }
}

/**
 * Sets the style->display property to none.
 * 
 * @param id String The id of the element to toggle the display.
 */
function vs_hideDisplay(id) {
    var element = _getElement(id);
    if ( element ) {
        element.style.display = "none";
    }
}

/**
 * Sets the style->display property to inline.
 * 
 * @param id String The id of the element to toggle the display.
 */
function vs_showDisplayInline(id) {
    var element = _getElement(id);
    if ( element ) {
        element.style.display = "inline";
    }
}

/**
 * Sets the style->display property to block.
 * 
 * @param id String The id of the element to toggle the display.
 */
function vs_showDisplay(id) {
    var element = _getElement(id);
    if ( element ) {
        element.style.display = "block";
    }
}

/**
 * Toggles the image displayed from one image src to another.
 * 
 * @param id String The id of the element to toggle the display.
 */
function vs_toggleImageSrc(id, imageSrc1, imageSrc2) {
    var element = document.getElementById(id);
    if ( element && element.src ) {
        if ( element.src.toLowerCase().indexOf(imageSrc1.toLowerCase()) > -1 ) {
            element.src = imageSrc2;
        } else {
            element.src = imageSrc1;
        }
    }
}

/**
 * Sets the content of the given element to a spinner image.
 * 
 * @param id String The id of the element to change content.
 * @param message String The message to add after the spinner image. If no value is passed,
 *                message defaults to 'Loading...'
 */
function vs_setContentToLoadingMessage(id, message, imgSize) {
    var sizeProperty = "";
    var element = document.getElementById(id);
    if ( !element )
        return;

    if ( message == null ) {
        message = "Loading...";
    }

    if ( imgSize != null ) {
        sizeProperty = " width=\"" + imgSize + "\" height=\"" + imgSize + "\" ";
    }

    element.innerHTML = "<img src=\"/images/util/spinner.gif\" " + sizeProperty + " />" + message;
}

/**
 * Sets the value of the input element.
 * 
 * @param id String The id of the element.
 * @param value String The value to set for the element.
 */
function vs_setElementValue(id, value) {
    var element = document.getElementById(id);
    if ( element == null ) {
        element = document.getElementsByName(id);
        if ( element.length == 1 )
            element = element[0];
    }

    if ( !element || element.value == "undefined" ) {
        return "";
    }

    element.value = value;
}

/**
 * Gets the value of the element with the given id. If the element is a 
 * checkbox/radio, then this will return a space separated list of all
 * the values of the element.
 * 
 * @param id String The id of the element.
 * @param delimiter String The delimiter to use on elements with more 
 *        than one value (checkboxes). Defaults to " ".
 */
function vs_getElementValue(id, delimiter) {
    var element = document.getElementById(id);

    // Hack for IE's bug that getElementById retrieves elements with name = id
    if ( isMicrosoftBrowser() ) {
        
        named_elements = getElementsByName_iefix("input", id);
        if ( named_elements.length && named_elements.length > 1 ) {
            element = named_elements;
        }

    // If element is null, let's try element names
    } else if ( element == null ) {
        element = document.getElementsByName(id);
        if ( element.length == 1 )
            element = element[0];
    }

    if ( !element ) {
        return "";
    }

    if ( delimiter == null )
        delimiter = " ";

    if ( element.length ) {
        // If radio list
        if ( element.options ) {
            var strResult = "";
            for ( var i = 0; i < element.options.length; i++ ) {
                if ( element.options[i].value && (element.options[i].selected || element.options[i].checked) ) {
                    if ( strResult != "" )
                        strResult += delimiter;
                    strResult += element.options[i].value;
                }
            }
            return strResult;

        // If checkboxes or selects
        } else {
            var strResult = "";
            for ( var i = 0; i < element.length; i++ ) {
                // Select
                if ( element[i].options && element[i].options.length ) {
                    for( var j = 0; j < element[i].options.length; j++ ) {
                        if ( element[i].options[j].value 
                            && (element[i].options[j].selected 
                            || element[i].options[j].checked) 
                        ) {
                            if ( strResult != "" )
                                strResult += delimiter;
                            strResult += element[i].options[j].value;
                        }
                    }

                // Checkbox
                } else if ( element[i].checked || element[i].selected ) {
                    if ( strResult != "" )
                        strResult += delimiter;
                    strResult += element[i].value;
                }
            }

            return strResult;
        }

    } else if ( element.value 
        // If this is a single checkbox, check first if it' checked
        && (element.getAttribute("type") != "checkbox" || element.checked) 
    ) {
        return element.value;
    } else {
        return "";
    }

}

/**
 * Gets the content of the element with the given id.
 * 
 * @param id String The id of the element.
 */
function vs_getContent(id) {
    var element = _getElement(id);
    if ( !element ) {
        return "";
    }

    return element.innerHTML;
}

/**
 * Generates a url dynamically by getting the values of all fields given.
 * 
 * @param url String The url to append the parameters.
 * @param fieldNamesList String Space separated list of field names
 *
 *        Example: var url = vs_generateDynamicUrl("/volunteer/search-2?", "keywords us_state city zip"});
 */
function vs_generateDynamicUrl(url, fieldNamesList) {
    if ( url.indexOf("?") == -1 )
        url += "?1=1";
    var fieldNames = fieldNamesList.split(" ");

    for(var i = 0; i < fieldNames.length; i++ ) {
        var elementValue = vs_getElementValue(fieldNames[i], "|");
        if ( elementValue != null && elementValue != "" ) {
            // If this is a checkbox, then the value would be "val1|val2|val3"
            var valueArray = elementValue.split("|");
            if ( valueArray.length > 1 ) {
                for( var j = 0; j < valueArray.length; j++ )
                    url += "&" + fieldNames[i] + "=" + escape(valueArray[j]);
            } else {
                url += "&" + fieldNames[i] + "=" + escape(elementValue);
            }
        }
    }
    return url;
}

/**
 * Gets all the values from the given fieldNamesList and returns a 
 * concatenated string in names=values{delimiter} format.
 * 
 * @param fieldNamesList String Space separated list of field names
 * @param delimiter String The delimiter String appended between 
 *        each name=value pair.
 * @param alsoCheckSpans If true, also checks the innerHTML of span
 *        elements. Defaults to false.
 *
 *        Example: var vars = vs_getFieldNamesAndValues("keywords us_state city zip", "|");
 *
 *  NOTE: Problem in IE for alsoCheckSpans = true
 */
function vs_getFieldNamesAndValues(fieldNamesList, delimiter, alsoCheckSpans) {
    var fieldNames = fieldNamesList.split(" ");
    var returnValue = "";

    for(var i = 0; i < fieldNames.length; i++ ) {
        var elementValue = vs_getElementValue(fieldNames[i], "|");
        if ( alsoCheckSpans && elementValue == "" ) {
            var elemObject = _getElement(fieldNames[i]);

            if ( elemObject && elemObject.constructor && elemObject.constructor.toString().match(/span/i) ) {
                elementValue = vs_getContent(fieldNames[i]);
            }
        }
        if ( elementValue != null && elementValue != "" ) {
            // If this is a checkbox, then the value would be "val1|val2|val3"
            var valueArray = elementValue.split("|");
            if ( valueArray.length > 1 ) {
                for( var j = 0; j < valueArray.length; j++ ) {
                    if ( returnValue != "" )
                        returnValue += delimiter;
                    returnValue += fieldNames[i] + "=" + valueArray[j];
                }
            } else {
                if ( returnValue != "" )
                    returnValue += delimiter;
                returnValue += fieldNames[i] + "=" + elementValue;
            }
        }
    }

    return returnValue;
}

/**
 * Causes a given element to call the 'click' event.
 * 
 * @param anchorId String[] This is the ID of the anchor 
 *        element to click.
 */
function vs_simulateClicks(anchorIds) {
    if ( !isArray(anchorIds) ) {
        var anchorElem = _getElement(anchorIds);
        if ( anchorElem && anchorElem.onclick ) {
            anchorElem.onclick();
        }

    } else {
        for ( var i = 0; i < anchorIds.length; i++) {
            var anchorElem = _getElement(anchorIds[i]);
            if ( anchorElem ) {
                if ( anchorElem.onclick ) {
                    anchorElem.onclick();
                } else if ( anchorElem.onClick ) {
                    anchorElem.onClick();
                }
            }
        }

    }
}

/**
 * Encodes html strings to its equivalent.
 * 
 * @param htmlStr String The string to encode.
 */
function htmlEncode(htmlStr) {
    var encoded = htmlStr.replace(/&/g,"&amp;");
    encoded = encoded.replace(/</g,"&lt;");
    encoded = encoded.replace(/>/g,"&gt;");
    return encoded;
}

/**
 * Decodes html strings to its equivalent.
 * 
 * @param htmlStr String The string to decode.
 */
function htmlDecode(htmlStr) {
    var encoded = htmlStr.replace(/&amp;/g,"&");
    encoded = encoded.replace(/&lt;/g,"<");
    encoded = encoded.replace(/&gt;/g,">");
    encoded = encoded.replace(/&quot;/g,"\"");
    return encoded;
}

/**
 * Code that is called when a i18n form locale checkbox list
 * is checked.
 * 
 * @see vs::form::add_i18n_selector_to_form
 */
function vs_i18n_form_check(isDisableToggleSkipped) {
    $$(".vs_i18n_widget").each(function(elem) {
        elem.setStyle({display: "none"});
        if ( !isDisableToggleSkipped ) {
            elem.select("input").each(function(field) {
                field.disabled = true;
            });
            elem.select("textarea").each(function(field) {
                field.disabled = true;
            });
        }
    });

    var values = vs_getElementValue("i18n_selector", " ").split(" ");
    var hasChecked = false;
    for(var i = 0; i < values.length; i++) {
        if ( values[i].replace(/(^\s+)|(\s+$)/g, "") == "" ) {
            continue;
        }

        $$(".vs_i18n_" + values[i]).each(function(elem) {
            elem.setStyle({display: "block"});
            if ( !isDisableToggleSkipped ) {
                elem.select("input").each(function(field) {
                    field.disabled = false;
                });
                elem.select("textarea").each(function(field) {
                    field.disabled = false;
                });
            }
        });
        hasChecked = true;
    }

    $$(".vs_i18n_widget_container").each(function(elem) {
        if ( hasChecked ) {
            elem.addClassName("vs_i18n_widget_container_sel");
        } else {
            elem.removeClassName("vs_i18n_widget_container_sel");
        }
    });
}

/**
 * Changes a form field to a hidden element with the same name/id and value, and
 * creates a span element with its innerHTML as the form field's value.
 *
 * Note: Prototype.js is required.
 *
 * @see vs_update_form_fields
 */
function vs_field_to_span( elementId, newValue, skipIfHiddenField ) {
    var elem = $(elementId);
    if ( elem ) {
        if ( skipIfHiddenField
            && elem.readAttribute("type") == "hidden"
            && elem.readAttribute("spanned") != "true"
        ) {
            return;
        }
        var valueToUse = ( newValue != null )?newValue:elem.value;
        // If this is a previously spanned element, then use the existing span
        var span = null;
        if ( elem.readAttribute("spanned") == "true" )
            span = $('span_' + elementId);
        // Otherwise, create a new one
        if ( !span )
            span = new Element('span', {'class': 'vs_fieldspan', 'id': 'span_' + elementId});

        span.update(valueToUse);

        // 1. Change textfield to hidden
        //elem.writeAttribute("type", "hidden");
        elem.setStyle({"display": "none"});
        elem.writeAttribute("spanned", "true");
        elem.writeAttribute("value", valueToUse);

        // 2. Create span with innerhtml = value
        elem.up().insert({top: span});
    }
}

/**
 * Reverse of vs_field_to_span. Changes a <span> element and a hidden input to
 * an input text field.
 *
 * Note: Prototype.js is required.
 *
 * @param elementId Either the element ID of a single element or an array of
 *        string of element IDs.
 *
 * @see vs_update_form_fields
 */
function vs_span_to_field( elementId ) {
    var elementIds = null;
    if ( elementId.each ) {
        elementIds = elementId;
    } else {
        elementIds = [elementId];
    }
    elementIds.each( function(id) {
        var elem = $(id);
        var span = $('span_' + id);

        if ( elem && span ) {
            var valueToUse = elem.value;

            // 1. Change hidden to textfield
            //elem.type = "text";
            elem.setStyle({"display": "block"});
            elem.value = valueToUse;

            // 2. Remove span
            span.remove();
        }
    });
}

/**
 * Updates all form fields with the given values.
 * Called by /user/events/user-id
 *
 * Note: Prototype.js is required
 *
 * @param fieldData json A JSON object with field ids as its keys and the field
 *        values as its values. Example:
 *        vs_update_form_fields( {'screen_name': 'levy', 'user_id': 12345} );
 *         ^ This will update the form field with ID=screen_name and ID=user_id
 *           with the values 'levy', and 12345 respectively.
 *
 * @param hideFields If true, then we change all fields that are not hidden type
 *        to hidden and then create a span element containing the values in its
 *        place.
 */
function vs_update_form_fields( fieldData, hideFields ) {
    for(var key in fieldData) {
        var elem = $(key);
        if ( elem ) {
            //alert(key + ": " + fieldData[key]);
            elem.value = fieldData[key];
            // If hideFields is true and the element is not a hidden element 
            // (or a previously spanned element), then convert this element to a SPAN
            if ( hideFields &&
                (elem.readAttribute("type") != "hidden" || elem.readAttribute("spanned") == "true")
            ) {
                vs_field_to_span(key, fieldData[key]);
            }
        }
    }
}

/**
 * Helper proc that creates a label with a 'remove' link.
 * Called by /user/events/user-id
 *
 * @see vs_update_form_fields
 */
function vs_create_remove_link( fullName, containerId, fieldIdsArr ) {
    var elem = $(containerId);
    if ( elem ) {
        var fieldData = {};
        for ( var i = 0; i < fieldIdsArr.length; i++ ) {
            fieldData[fieldIdsArr[i]] = "";
        }

        var a = new Element('a', {
            'class': 'actionLink vs_close_button',
            href: 'javascript:void(0);'
        }).update("x");
        a.observe('click', function(event) {
            vs_update_form_fields(fieldData);
            vs_span_to_field(fieldIdsArr);
            elem.update("").hide();
        });
        elem.update("<span class='vs_user_icon'>" + fullName + "</span>").insert(a);
        elem.show();
    }
}

/**************************************
  Helper procs for
    vs_table_single_cell_layout
 **************************************/

function set_values_to_all_duplicates(ddl, ddl_name) {
    var all_ddl = document.getElementsByName(ddl_name);

    if ( all_ddl.length > 1 ) {
        for( i=0; i < all_ddl.length; i++) {
            all_ddl[i].value = ddl.value;
        }
    }
}

function get_final_sort_value() {
    var hidden = document.getElementsByName('orderby');
    var column = document.getElementsByName('sort_select_column');
    var order = document.getElementsByName('sort_select_order');

    if ( hidden.length > 1 ) {
        for( i=0; i < hidden.length; i++ ) {
            hidden[i].value = column[0].value + order[0].value;
        }
    }
    else {
        hidden.value = column.value + order.value;
    }
    return true;
}

/**************************************
  RSH Helper functions
  @DEPRECATED
  @see /web/vs/www/style/vsSearch.js
 **************************************/

/**
 * Returns a properly formatted url string with parameters based 
 * from the fieldList field of the historyData object. This is used 
 * on the rsh api. See tcl/core/ajax-rsh.tcl
 * 
 * @param historyData Object This is the parameter of the history 
 *        handler of the rsh api.
 */
function vs_getParamFromHistoryData(url, historyData) {
    if ( url.indexOf("?") == -1 )
        url += "?1=1";

    if ( historyData && historyData.paramElementId) {
        //var params = historyData.fieldList.replace(/\|/g, "&");
        //var params = htmlDecode(vs_getContent(historyData.paramElementId));
        var params = htmlDecode(historyData.fieldList);
        return url + "&" + params;
    }
    return url;
}

/**
 * Checks the current url and if it contains extra params 
 * (eg. /volunteer/search-2#submitkeyword=food), then it will call
 * the passed functionToCall.
 * 
 * @param urlToken String The token prefix. 
 *        (eg. 'submit' on '/volunteer/search-2#submitkeyword=food)
 *
 * @param functionToCall Function This is the function that will
 *        be called if the current url has rsh history parameters.
 *        This function must have a single String parameter which
 *        will store the parameter name/value pairs.
 *
 * example: <body onload="vs_callFunctionIfRshPage(function(params) {
                    ajaxRequest('/volunteer/search-2?' + params, 'vs_main')
                });">
 */
function vs_callFunctionIfRshPage(urlToken, functionToCall) {
    var currentUrl = document.location.toString();
    var extraParamsIdx = currentUrl.indexOf("#" + urlToken);
    var paramList = "";

    if ( extraParamsIdx > -1 ) {
        extraParamsIdx += ("#" + urlToken).length;
        paramList = "&" + currentUrl.substring(extraParamsIdx).replace(/\|/g,"&");
        functionToCall(paramList);
    }
}

/**
 * Helper proc for dhtmlHistory.add. This is needed so that we
 * can store a variable isLoadedToVS to dhtmlHistory. This var
 * will help us determine if the page is actually a first loaded
 * page, or if the page is loaded, then added history, then 
 * "Back" event.
 *
 * @see tcl/core/ajax-rsh.tcl
 */
function vs_history_add(newLocation, historyData) {
    window.dhtmlHistory.isLoadedToVS = true;
    dhtmlHistory.add(newLocation,historyData);
}

/**
 * Helper proc that will add a default event to call when
 * the page first loads.
 *
 * @see tcl/core/ajax-rsh.tcl
 */
function vs_history_add_default_event(functionToCall) {
    if ( window.dhtmlHistory ) {
        // If we have default events already, append the new function to it.
        if ( window.dhtmlHistory.vsDefaultEvents ) {
            var ctr = window.dhtmlHistory.vsDefaultEvents.length;
            window.dhtmlHistory.vsDefaultEvents[ctr] = functionToCall;
        } else {
            window.dhtmlHistory.vsDefaultEvents = new Array(functionToCall);
        }
    }
}

/**
 * History handler proc that will be called on a refresh,
 * back, or forward event.
 *
 * @see tcl/core/ajax-rsh.tcl
 */
function vs_history_handler(newLocation, historyData) {

    if ( historyData ) {

        if ( historyData.type == "function" ) {
            historyData.data(newLocation,historyData);

        } else if ( historyData.type == "element" ) {
            eval(vs_getContent(historyData.data));
        }

    // Lets check if this page is first loaded OR the user clicks 
    // on back up until the first page load.
    } else if (window.dhtmlHistory.isLoadedToVS) {
        // If we have default events set, call them
        if ( window.dhtmlHistory.vsDefaultEvents && window.dhtmlHistory.vsDefaultEvents.length ) {
            for( var i = 0; i < window.dhtmlHistory.vsDefaultEvents.length; i++ ) {
                window.dhtmlHistory.vsDefaultEvents[i]();
            }
        }
    }
}

/**************************************
 Autor: Jonas Raoni Soares Silva
 Site: http://www.joninhas.ath.cx:666
**************************************/

function fmtMoney( n, c, d, t ) {
    var m = ( c = Math.abs( c ) + 1 ? c : 2, d = d || ",", t = t || ".", /(\d+)(?:(\.\d+)|)/.exec( n + "" ) ), x = m[1].length % 3;
    return ( x ? m[1].substr( 0, x ) + t : "" ) + m[1].substr( x ).replace( /(\d{3})(?=\d)/g, "$1" + t ) + ( c ? d + ( +m[2] ).toFixed( c ).substr( 2 ) : "" );
};

/**
 * Returns true if the object is an array.
 * http://www.bram.us/2008/02/01/javascript-isarray-check-if-an-elementobject-is-an-array/
 */
function isArray(obj) {
    return obj.constructor == Array;
}

/**
 * Adds the given url to the client's favorites.
 * 
 * http://labnol.blogspot.com/2006/01/add-to-favorites-ie-bookmark-firefox.html
 */

function vs_createBookmark(url,title){
    if (window.sidebar) { // Mozilla Firefox Bookmark
        window.sidebar.addPanel(title, url,"");

    } else if( window.external ) { // IE Favorite
        window.external.AddFavorite( url, title);

    } else if(window.opera && window.print) { // Opera Hotlist
        alert("Press CTRL-D (Netscape) or CTRL-T (Opera) to bookmark");
        return true; 
    }

}

/**
 * Hack script to fix IE's problem with getElementsByName proc
 * 
 * http://www.dreamincode.net/code/snippet293.htm
 */
function getElementsByName_iefix(tag, name) {
     
     var elem = document.getElementsByTagName(tag);
     var arr = new Array();
     for(i = 0,iarr = 0; i < elem.length; i++) {
          att = elem[i].getAttribute("name");
          if(att == name) {
               arr[iarr] = elem[i];
               iarr++;
          }
     }
     return arr;
}

/**
 * Returns the user's timezone in GMT offset.
 * http://www.webmasterworld.com/forum13/3922.htm
 */
function vs_getUsersTimezone() {
    var tzo=(new Date().getTimezoneOffset()/60)*(-1);
    return vs_convertDecimalToTZOffset(tzo);
}

/**
 * Returns the number of milliseconds since 1970.
 */
function vs_getCurrentMilliseconds() {
    var d = new Date();
    return Date.UTC(d.getYear(),d.getMonth(),d.getDate(),d.getHours(),d.getMinutes(),d.getSeconds(),d.getMilliseconds());
}

/**
 * Returns the current date in YYYY-MM-DD format
 */
function vs_getCurrentDate() {
    var d = new Date();
    return d.getFullYear() + "-" + (d.getMonth() + 1) + "-" + d.getDate();
}

/**
 * Returns the current time in HH:MI format
 */
function vs_getCurrentTime() {
    var d = new Date();
    return d.getHours() + ":" + d.getMinutes();
}


function vs_convertDecimalToTZOffset(dec) {
    var decStr = (dec + "");
    if ( dec == null ) {
        return "00:00"
    }

    var op = "+";
    if ( decStr.indexOf("-") > -1 ) {
        op = "-";
        decStr = decStr.replace("-", "");
    } else if (decStr.indexOf("+") > -1) {
        decStr = decStr.replace("+", "");
    }

    // Has decimal
    if ( decStr.indexOf(".") > -1 ) {
        var numdata = decStr.split(".");
        var wnum = numdata[0];
        var decimal = numdata[1];

        // Make sure whole num is two digits
        if ( !wnum.match(/\d\d/) )
            wnum = "0" + wnum;

        // Make sure decimal is two digits
        if ( decimal.length < 2 )
            decimal += "0";

        return op + wnum + ":" + (parseFloat(decimal) / 100 * 60);
    } else {
        if ( !decStr.match(/\d\d/) ) {
            decStr = "0" + decStr;
        }
        return op + decStr + ":00";
    }
}
