// Some Variables
var message_box_fade_timeout_id = -1;

// END some variables

// php port
function empty( mixed_var ) {
    // http://kevin.vanzonneveld.net
    // +   original by: Philippe Baumann
    // +      input by: Onno Marsman
    // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +      input by: LH
    // +   improved by: Onno Marsman
    // +   improved by: Francesco
    // *     example 1: empty(null);
    // *     returns 1: true
    // *     example 2: empty(undefined);
    // *     returns 2: true
    // *     example 3: empty([]);
    // *     returns 3: true
    // *     example 4: empty({});
    // *     returns 4: true

    var key;

    if (mixed_var === ""
        || mixed_var === 0
        || mixed_var === "0"
        || mixed_var === null
        || mixed_var === false
        || mixed_var === undefined
    ){
        return true;
    }
    if (typeof mixed_var == 'object') {
        for (key in mixed_var) {
            if (typeof mixed_var[key] !== 'function' ) {
              return false;
            }
        }
        return true;
    }
    return false;
}

//php port
 function isset(  ) {
    // http://kevin.vanzonneveld.net
    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: FremyCompany
    // *     example 1: isset( undefined, true);
    // *     returns 1: false
    // *     example 2: isset( 'Kevin van Zonneveld' );
    // *     returns 2: true

    var a=arguments; var l=a.length; var i=0;

    while ( i!=l ) {
        if (typeof(a[i])=='undefined') {
            return false;
        } else {
            i++;
        }
    }

    return true;
}
// port of php function
function trim (str, charlist) {
    // http://kevin.vanzonneveld.net
    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: mdsjack (http://www.mdsjack.bo.it)
    // +   improved by: Alexander Ermolaev (http://snippets.dzone.com/user/AlexanderErmolaev)
    // +      input by: Erkekjetter
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +      input by: DxGx
    // +   improved by: Steven Levithan (http://blog.stevenlevithan.com)
    // +    tweaked by: Jack
    // +   bugfixed by: Onno Marsman
    // *     example 1: trim('    Kevin van Zonneveld    ');
    // *     returns 1: 'Kevin van Zonneveld'
    // *     example 2: trim('Hello World', 'Hdle');
    // *     returns 2: 'o Wor'
    // *     example 3: trim(16, 1);
    // *     returns 3: 6

    var whitespace, l = 0, i = 0;
    str += '';

    if (!charlist) {
        // default list
        whitespace = " \n\r\t\f\x0b\xa0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000";
    } else {
        // preg_quote custom list
        charlist += '';
        whitespace = charlist.replace(/([\[\]\(\)\.\?\/\*\{\}\+\$\^\:])/g, '\$1');
    }

    l = str.length;
    for (i = 0; i < l; i++) {
        if (whitespace.indexOf(str.charAt(i)) === -1) {
            str = str.substring(i);
            break;
        }
    }

    l = str.length;
    for (i = l - 1; i >= 0; i--) {
        if (whitespace.indexOf(str.charAt(i)) === -1) {
            str = str.substring(0, i + 1);
            break;
        }
    }

    return whitespace.indexOf(str.charAt(0)) === -1 ? str : '';
}
// port of php function
function strpos( haystack, needle, offset){
    // http://kevin.vanzonneveld.net
    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // *     example 1: strpos('Kevin van Zonneveld', 'e', 5);
    // *     returns 1: 14

    var i = haystack.indexOf( needle, offset ); // returns -1
    return i >= 0 ? i : false;
}

// port of php function
 function in_array(needle, haystack, strict) {
    // http://kevin.vanzonneveld.net
    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // *     example 1: in_array('van', ['Kevin', 'van', 'Zonneveld']);
    // *     returns 1: true

    var found = false, key, strict = !!strict;

    for (key in haystack) {
        if ((strict && haystack[key] === needle) || (!strict && haystack[key] == needle)) {
            found = true;
            break;
        }
    }

    return found;
}

function validate_form(form_id){
    valmessage = '';
    masterform = $(form_id);
    for(ff=0; ff<masterform.elements.length; ff++)
    {
        currelem = masterform.elements[ff];
        switch(currelem.type)
        {
            case 'select' :
            case 'select-one' :
                tmp = validateTypes(currelem, currelem.options[currelem.selectedIndex].value);
                if(tmp)
                {
                    valmessage = valmessage + tmp+"\n";
                }
            break;
            case 'text':
                tmp = validateTypes(currelem, currelem.value);
                if(tmp)
                {
                    valmessage = valmessage + tmp+"\n";
                }
            break;
            case 'file':
                tmp = validateTypes(currelem, currelem.value);
                if(tmp)
                {
                    valmessage = valmessage + tmp+"\n";
                }
            break;
            case 'hidden':
                tmp = validateTypes(currelem, currelem.value);
                if(tmp)
                {
                    valmessage = valmessage + tmp+"\n";
                }
            break;
            case 'password':
                tmp = validateTypes(currelem, currelem.value);
                if(tmp)
                {
                    valmessage = valmessage + tmp+"\n";
                }
            break;
            case 'radio':
                tmp = validateTypes(currelem, currelem.value);
                if(tmp && strpos(valmessage, tmp) === false)
                {
                    valmessage = valmessage + tmp+"\n";
                }
            break;
            case 'textarea':
                tmp = validateTypes(currelem, currelem.value);
                if(tmp)
                {
                    valmessage = valmessage + tmp+"\n";
                }
            break;
        }

    }
    if(valmessage!="")
    {
        alert("Please complete the below fields\n\n"+valmessage);
        return false;
    } else {
        return true;
    }
}

function validateTypes(fieldObj, theValue)
{
    if (!fieldObj.attributes['validate']) {  return false; }
    if(fieldObj.attributes['validate'].value)
    {
        vTypes = fieldObj.attributes['validate'].value.split('|'); //  we have a problem here with element ids having pipes in them
    } else {
        return false;
    }
    if(vTypes.length == 1)
    {
        return false;
    }
    errors=0;

    for(vt=1; vt<vTypes.length; vt++)
    {
        realTypes = vTypes[vt].split(':');
        switch(realTypes[0])
        {
            case 'OPTIONAL':
                if(theValue == "")
                {
                    return false;
                }
            break;
            case 'NUM':
                if(!theValue.match(/\b\d+\b/))
                {
                    errors++;
                }
            break;
            case 'POSITIVEINT':
                if(!theValue.match(/\b\d+\b/))
                {
                    errors++;
                } else {
                    if (!(theValue > 0))
                    {
                        errors++;
                    }
                }
            break;
            case 'LENGTH':
                if(theValue.length != parseInt(realTypes[1]))
                {
                    errors++;
                }
            break;
            case 'MAXLENGTH':
                if(theValue.length > parseInt(realTypes[1]))
                {
                    errors++;
                }
            break;
            case 'MINLENGTH':
                if(theValue.length < parseInt(realTypes[1]))
                {
                    errors++;
                }
            break;
            case 'SAMEAS':
                if(theValue != $(realTypes[1]).value)
                {
                    errors++;
                }
            break;
            case 'GREATERTHAN': // must reference another elements by id after the :
                if(!(theValue > $(realTypes[1]).value))
                {
                    errors++;
                }
            break;
            case 'FILEEXTENSION': // after : should contain a commadelimited list of extensions
                extensions = realTypes[1].split(',');
                extension = theValue.split(".").pop();
                if (!in_array(extension.toLowerCase(), extensions) && theValue != '')
                {
                    errors++;
                }
            break;
            case 'EMAIL':
                if (trim(theValue) != "" && !theValue.match(/\b[A-Z0-9._%-]+@[A-Z0-9._%-]+\.[A-Z]{2,4}\b/i))
                {
                    errors++;
                }
            break;
            case 'DATE': // checks if the value is in the form yyyy-mm-dd
                var validformat=/^\d{4}-\d{2}-\d{2}$/; //Basic check for format validity
                if (!validformat.test(theValue)) { errors++; break;}

                var monthfield=theValue.split("-")[1];
                var dayfield=theValue.split("-")[2];
                var yearfield=theValue.split("-")[0];
                var dayobj = new Date(yearfield, monthfield-1, dayfield);
                if ((dayobj.getMonth()+1!=monthfield)||(dayobj.getDate()!=dayfield)||(dayobj.getFullYear()!=yearfield)) { errors++; }

            break;
            case 'DATEGREATEROREQUALTO': // checks if the value is in the form yyyy-mm-dd and is greater than the date held in another element referenced by its ID
                var validformat=/^\d{4}-\d{2}-\d{2}$/; //Basic check for format validity of this date
                if (!validformat.test(theValue)) { errors++; break;}

                var monthfield=theValue.split("-")[1];
                var dayfield=theValue.split("-")[2];
                var yearfield=theValue.split("-")[0];
                var dayobj = new Date(yearfield, monthfield-1, dayfield);
                if ((dayobj.getMonth()+1!=monthfield)||(dayobj.getDate()!=dayfield)||(dayobj.getFullYear()!=yearfield)) { errors++; break;}

                var validformat=/^\d{4}-\d{2}-\d{2}$/; //Basic check for format validity of the other date
                if (!validformat.test($(realTypes[1]).value)) { errors++; break;}

                var monthfield=$(realTypes[1]).value.split("-")[1];
                var dayfield=$(realTypes[1]).value.split("-")[2];
                var yearfield=$(realTypes[1]).value.split("-")[0];
                var other_obj = new Date(yearfield, monthfield-1, dayfield);
                if ((other_obj.getMonth()+1!=monthfield)||(other_obj.getDate()!=dayfield)||(other_obj.getFullYear()!=yearfield)) { errors++; break;}

                // now we compare the dates
                if (dayobj < other_obj)
                {
                    errors++; break;
                }
            break;
            case 'NOTEMPTY':
                if(theValue == "")
                {
                    errors++;
                }
            break;
            case 'NOTEMPTYIFEMPTY': // this value may not be empty if all the other fields specified are empty
                var found_non_empty_field = false;
                for(var i = 1; i < realTypes.length; i++) // i = 1 cos we skip the first element because that is the operator
                {
                    if ($(realTypes[i]).value.length)
                    {
                        found_non_empty_field = true;
                    }
                }
                if (!found_non_empty_field && theValue == "")
                {
                    errors++;
                }
            break;
            case 'FUNCTION': // we need to run the specified function to see if there is a problem
                var eval_string = "var ret_val = "+realTypes[1]+"(fieldObj);";
                eval(eval_string);
                if(!ret_val)
                {
                    errors++;
                }
            break;
            case 'POSITIVE':
                if(parseInt(theValue) < 0 || theValue == "")
                {
                    errors++;
                }
            break;
            default:
                //alert( vTypes[vt] + 'not recognized');
            break;
        }
    }
    if(errors > 0)
    {
        return 	"- "+vTypes[0];
    }
}

function crud(action_name, class_name, id_object ,post_perameters, after_success)
{
  new Ajax.Request('http://www.hothousemedia.com/mm/global_includes/scripts/crud.php?class='+class_name+'&action='+action_name+"&id="+id_object,
  {
        method: 'post',
        parameters: post_perameters,
    onSuccess: function(response){
            var perameter_array = new Array();
            if (after_success != "")
            {
                resp = response.responseText;
                resp_array = resp.split("|");
                resp_code = resp_array[0];
                resp_text = resp_array[1];
                if (resp_code > 0)
                {
                    eval(after_success);
                } else {
                    alert(resp);
                }
            } else {
                if (post_perameters.indexOf("&") > 0)
                {
                    perameter_array = post_perameters.split("&");
                } else {
                    perameter_array[0] = post_perameters;
                }
                for (var x = 0; x < perameter_array.size(); x++)
                {
                    sub_array = perameter_array[x].split("=");
                    if($(sub_array[0]))
                    {
                        $(sub_array[0]).value = sub_array[1];
                        $(sub_array[0]).innerHTML = sub_array[1];
                    } else if (id_object+"_"+$(sub_array[0])) {
                        $(id_object+"_"+sub_array[0]).value = sub_array[1];
                        $(id_object+"_"+sub_array[0]).innerHTML = sub_array[1];
                    }
                }
            }
    },
        onFailure: function()
            {
                alert('Error in CRUD.');
            }
  });
}

function store_center_div_pos(dv)
{
    store_session_variable("center_div_top", $(dv).style.top,"store_session_variable('center_div_left', $(dv).style.left);");
}

function store_session_variable(variable, value, after_success)
{
    ajax_request("global_includes/scripts/save_session_variable.php", "variable="+variable+"&value="+value, after_success);
}

// fills the centre div with a page of content and makes it appear
function populate_div(url_string, _parameters,left,top)
{
  // create div
  var newDiv = document.createElement("DIV");
  newDiv.className = "center_div";

  /*var*/ newId = trim(Math.random()+" ");
  newId = '_' + newId.replace('.','_');

  newDiv.id = newId;
  //$('dv_array').value += (";"+newId);

    document.body.appendChild(newDiv);

  // adding the handle_id to the parameters string
  if (_parameters == "")
    _parameters = "handle_id="+newId+"_handle"+"&centre_div_id="+newId;
  else
    _parameters = _parameters + "&handle_id="+newId+"_handle"+"&centre_div_id="+newId;

  new Ajax.Updater(newId, url_string, {
        method: 'post',
        parameters: _parameters,
        evalScripts: true,
        onFailure: function ()
        {
            alert('Error Encountered.');
        },
        onSuccess: function ()
        {
            $(newId).setStyle({display: 'block' });

            // if positions are sent through then we position the div rather than centering
            if (!empty(left))
            {
                $(newId).style.top = top;
                $(newId).style.left = left;
            } else {
                setTimeout("Effect.Center($(newId),-50);",1);
            }
            //setTimeout("new Draggable(newId, {handle: '"+newId+"_handle'});", 1); // make the centre div draggable by the header bar

            //store_session_variable("center_div_url_string", url_string,"store_session_variable('center_div_parameters', '"+urlencode(_parameters)+"');");
        }
    }
    );
}
// hides the center div
function hide_center_div(centre_div_id)
{
  $(centre_div_id).remove();
    //store_session_variable("center_div_url_string", "");
}

// fills a element.innerHTML with a page
function _populate(element_id, url_string, parameters, after_success, after_failure)
{
     new Ajax.Updater(element_id, url_string, {
        method: 'post',
        parameters: parameters,
        evalScripts: true,
        onFailure: function ()
            {
                alert("Error encountered.");
                eval(after_failure);
            },
        onSuccess: function ()
            {
                eval(after_success);
            }
        }
    );
}

// like _populate, but replaces the entire element rather than filling the innerHTML
function _replace(element_id, url_string, parameters, after_success, after_failure)
{
    new Ajax.Request(url_string, {
        method: 'post',
        parameters: parameters,
        evalScripts: true,
        onSuccess: function (response)
            {
                resp = response.responseText;
                Element.replace(element_id,resp);
                eval(after_success);
            },
        onFailure: function()
            {
                alert("Error encountered.");
                eval(after_failure);
            }
        }
    );
     new Ajax.Updater(element_id, url_string, {
        method: 'post',
        parameters: parameters,
        evalScripts: true,
        onFailure: function ()
            {
                alert("Error encountered.");
                eval(after_failure);
            },
        onSuccess: function ()
            {
                eval(after_success);
            }
        }
    );
}

// same as message_box - but for a second message box
function message_2(message_content)
{
    // if the message_box element exists we use it, if not we just alert the text
    if ($('message_box_2'))
    {
//		if (message_box_fade_timeout_id_2) { clearTimeout(message_box_fade_timeout_id_2); }
        $('message_box_2').morph("background:#FFF9D7 none repeat scroll 0%;border:1px solid #E2C822;");
        $('message_box_2').style.display = "none";
        $('message_box_2').innerHTML = message_content;
        setTimeout ( "Effect.Appear('message_box_2');", 500 );
        Effect.Appear('message_box_2');
//		message_box_fade_timeout_id_2 = setTimeout ( "$('message_box_2').morph('background:#F0F0FA none repeat scroll 0%;border:1px solid #CCCCCC;')", 3000 );
    } else {
        alert(message_content);
    }
}

function getScrollY() {
  var scrOfX = 0, scrOfY = 0;
  if( typeof( window.pageYOffset ) == 'number' ) {
    //Netscape compliant
    scrOfY = window.pageYOffset;
    scrOfX = window.pageXOffset;
  } else if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) {
    //DOM compliant
    scrOfY = document.body.scrollTop;
    scrOfX = document.body.scrollLeft;
  } else if( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) {
    //IE6 standards compliant mode
    scrOfY = document.documentElement.scrollTop;
    scrOfX = document.documentElement.scrollLeft;
  }
//  return [ scrOfX, scrOfY ];
        return scrOfY;
}
function getScrollX() {
  var scrOfX = 0, scrOfY = 0;
  if( typeof( window.pageYOffset ) == 'number' ) {
    //Netscape compliant
    scrOfY = window.pageYOffset;
    scrOfX = window.pageXOffset;
  } else if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) {
    //DOM compliant
    scrOfY = document.body.scrollTop;
    scrOfX = document.body.scrollLeft;
  } else if( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) {
    //IE6 standards compliant mode
    scrOfY = document.documentElement.scrollTop;
    scrOfX = document.documentElement.scrollLeft;
  }
//  return [ scrOfX, scrOfY ];
        return scrOfX;
}


// loads a class's variable into an element
// element_id  => The ID of the element that will have the input field inserted
// class_name  => The name of the class that the input field belongs to
// object_id   => the id of the class object to be loaded
// input_field => the field that will be loaded
// replace		 => if set to something then the replace method will be called instead of populate
function load_object_variable(element_id, class_name, object_id, variable, replace)
{
    parameters = "class="+class_name+"&id="+object_id+"&variable="+variable;
    //$(element_id).innerHTML = '<table><tr><td>Loading...</td><td><img src="images/website/ajax-loaderGray.gif"></td></tr></table>';
    //$(element_id).style.display = "none";

    if (!empty(replace))
    {
        _replace(element_id, "global_includes/scripts/load_object_variable.php", parameters);
    } else {
        _populate(element_id, "global_includes/scripts/load_object_variable.php", parameters);
    }

    Effect.Appear(element_id);

}

function object_method(class_name, object_id, method, after_success, arg1)
{
    ajax_request("global_includes/scripts/object_method.php", "class="+class_name+"&id="+object_id+"&method="+method+"&arg1="+arg1, after_success);
}

// loads a class's input field into an element
// element_id  => The ID of the element that will have the input field inserted
// class_name  => The name of the class that the input field belongs to
// object_id   => the id of the class object to be loaded
// input_field => the field that will be loaded
// replace		 => if set to something then the replace method will be called instead of populate
function load_object_input_field(element_id, class_name, object_id, input_field, replace, after_success)
{
    parameters = "class="+class_name+"&id="+object_id+"&input_field="+input_field;
    //$(element_id).innerHTML = '<table><tr><td>Loading...</td><td><img src="images/website/ajax-loaderGray.gif"></td></tr></table>';
    //$(element_id).style.display = "none";

    if (!empty(replace))
    {
        _replace(element_id, "global_includes/scripts/load_object_input_field.php", parameters, after_success);
    } else {
        _populate(element_id, "global_includes/scripts/load_object_input_field.php", parameters, after_success);
    }
  Effect.Appear(element_id);
}


// makes an ajax request
function ajax_request(url, parameters, after_success, ignore_fail, after_completion)
{
    new Ajax.Request(url, {
        method: 'post',
        parameters: parameters,
        evalScripts: true,
        onSuccess: function (response)
            {
                // only if the response status is something must we do anything
                // if its 0 then no response was recieved - I hope this doesnt cause bugs!
                if (parseInt(response.status) > 0)
                {
                    resp = response.responseText;
                    resp_array = resp.split("|");
                    resp_code = resp_array.shift();
                    resp_text = implode('|',resp_array);
                    if (!resp_code) { alert("ERROR: No Code in resp: "+resp); }
                    if (resp_code > 0)
                    {
                        eval(after_success);
                    } else {
                        alert(resp);
                    }
                }
            },
        onFailure: function()
            {
                if (isset(ignore_fail))
                {

                } else {
                    alert('Ajax Request Failed.');
                }
            },
        onComplete: function(response)
            {
                if (eval(after_completion)){
                    eval(after_completion);
                }
            }
        }
    );
    return true;
}

// makes an ajax updater request
function ajax_updater(url, parameters, update_element_id, after_success, ignore_fail, after_completion)
{
    new Ajax.Updater(update_element_id, url, {
        method: 'post',
        parameters: parameters,
        evalScripts: true,
        onSuccess: function (response)
            {
                eval(after_success);
            },
        onFailure: function()
            {
                if (isset(ignore_fail))
                {

                } else {
                    alert('Ajax Updater Failed.');
                }
            },
        onComplete: function(response)
            {
                if (after_completion){
                    eval(after_completion);
                }
            }
        }
    );
    return true;
}

// makes an ajax updater request
function ajax_periodical_updater(url, parameters, update_element_id, period, after_success)
{
    new Ajax.PeriodicalUpdater(update_element_id, url, {
        method: 'post',
        parameters: parameters,
        evalScripts: true,
        frequency: period,
        decay: 1,
        onSuccess: function (response)
            {
                eval(after_success);
            },
        onFailure: function()
            {
                alert('Ajax Updater Failed.');
            }
        }
    );
    return true;
}


// submits a form via ajax
function submit_form(form_id,success_action)
{
    if (!$(form_id)) { alert('Form: '+form_id+' does not exist'); return false; }
    // validate the form, if it fails dont go further
    if (!validate_form(form_id)) { return false; }

    // now that we know that the form submission is valid
    // we toggle the loading image on if it exists
    toggle_image_load('on');

    parameters = "";

    elements = $(form_id).elements
    for(var i = 0; i < elements.length; i++)
    {
        type = elements[i].type;
        name = elements[i].name;
        value = elements[i].value;
        if (type == "button")
        {

        } else if (type == "checkbox") {
            if (elements[i].checked)
            {
                if (parameters == "")
                {
                    parameters = name+"="+value;
                } else {
                    parameters = parameters + "&"+name+"="+value;
                }
            }
        } else {
            if (parameters == "")
            {
                parameters = name+"="+value;
            } else {
                parameters = parameters + "&"+name+"="+value;
            }
        }
    }
    new Ajax.Request($(form_id).action, {
        method: 'post',
        parameters: parameters,
        onSuccess: function (response)
            {
                // we set up some response values - the full response, and the code and text part (if they exist)
                resp = response.responseText;
                resp_array = resp.split("|");
                resp_code = resp_array[0];
                resp_text = resp_array[1];
                if (!resp_text) { resp_text = "Error Encountered"; }

                // toggles the loading image off if it exists
                // we do this before evaluating the success_action in case the success action includes some image toggling (in which case this would interfere)
                toggle_image_load('off');

                eval(success_action);

            },
        onFailure: function()
            {
                alert('Form Submission Failed\nForm ID:'+$(form_id).id+'\nForm Action:'+$(form_id).action);
                // toggles the loading image off if it exists
                toggle_image_load('off');
            }
        }
    );
    return true;
}

// submits a form via ajax
function submit_form_old(form_id,success_action)
{
    if (!$(form_id)) { alert('Form: '+form_id+' does not exist'); return false; }
    // validate the form, if it fails dont go further
    if (!validate_form(form_id)) { return false; }

    // now that we know that the form submission is valid
    // we toggle the loading image on if it exists
    toggle_image_load('on');

    parameters = "";

    elements = $(form_id).elements
    for(var i = 0; i < elements.length; i++)
    {
        type = elements[i].type;
        name = elements[i].name;
        value = elements[i].value;
        if (type == "button")
        {

        } else if (type == "checkbox") {
            if (elements[i].checked)
            {
                if (parameters == "")
                {
                    parameters = name+"="+value;
                } else {
                    parameters = parameters + "&"+name+"="+value;
                }
            }
        } else {
            if (parameters == "")
            {
                parameters = name+"="+value;
            } else {
                parameters = parameters + "&"+name+"="+value;
            }
        }
    }
    new Ajax.Request($(form_id).action, {
        method: 'post',
        parameters: parameters,
        onSuccess: function (response)
            {
                // we set up some response values - the full response, and the code and text part (if they exist)
                resp = response.responseText;
                resp_array = resp.split("|");
                resp_code = resp_array[0];
                resp_text = resp_array[1];
                if (!resp_text) { resp_text = "Error Encountered"; }

                // toggles the loading image off if it exists
                // we do this before evaluating the success_action in case the success action includes some image toggling (in which case this would interfere)
                toggle_image_load('off');

                eval(success_action);

            },
        onFailure: function()
            {
                alert('Form Submission Failed\nForm ID:'+$(form_id).id+'\nForm Action:'+$(form_id).action);
                // toggles the loading image off if it exists
                toggle_image_load('off');
            }
        }
    );
    return true;
}
// unhides an element that has display:none
function unhide(element_id)
{
    $(element_id).style.display="block";
}

// cancels the propagation of javascript events
// need to make this function properly cross browser
function stopPropagation(evt)
{
    if (window.event)
    {
        window.event.cancelBubble = true; // IE
    } else {
        evt.stopPropagation();
    }
}

// function called from an onkeypress - if the event was the ENTER key then the evalcode will be run
// to use this add the following to an input field in any form: onKeyPress="return on_enter('alert(resp)',event)"
function on_enter(evalcode,e)
{
    var keycode;
    if (window.event) keycode = window.event.keyCode;
    else if (e) keycode = e.which;
    else return true;

    if (keycode == 13)
  {
    eval(evalcode);
    return false;
  } else {
    return true;
    }
}
// sets the focus on first element in the first form on the page
// usually called from the body tag: onload="first_element_focus()"
function first_element_focus()
{
    if (document.forms[0] && document.forms[0].elements[0])
    {
        document.forms[0].elements[0].focus()
    }
    return true;
}
// slides an element up or down based on its style.display
function toggle_slide(element_id)
{
    if ($(element_id).style.display == "none")
    {
        Effect.SlideDown(element_id,{duration:0.3});
    } else {
        Effect.SlideUp(element_id,{duration:0.3});
    }
}
// flips an elements baground colour between the two parameters
function toggle_bg_color(element, colour1, colour2)
{
    current_bg_colour = element.style.backgroundColor;
    if (current_bg_colour.compareColor(colour1) || current_bg_colour == "")
    {
        element.style.backgroundColor = colour2;
    } else {
        element.style.backgroundColor = colour1;
    }
}

// flips an elements class between the two parameters
function toggle_class(element, class1, class2)
{
    current_class = element.className;
    if (current_class == class1 || current_class == "")
    {
        element.className = class2;
    } else {
        element.className = class1;
    }
}

// two new functions below can be applied to colours to compare them
// the first function makes use of the second function.  Currently this function is used
// by the toggle_bg_colour function to switch an element between two background colours
String.prototype.compareColor = function(){
    if((this.indexOf("#") != -1 && arguments[0].indexOf("#") != -1) ||
      (this.indexOf("rgb") != -1 && arguments[0].indexOf("rgb") != -1)){
      return this.toLowerCase() == arguments[0].toLowerCase()
    }
    else{
      xCol_1 = this;
      xCol_2 = arguments[0];
      if(xCol_1.indexOf("#") != -1)xCol_1 = xCol_1.toRGBcolor();
      if(xCol_2.indexOf("#") != -1)xCol_2 = xCol_2.toRGBcolor();
      return xCol_1.toLowerCase() == xCol_2.toLowerCase()
    }
  }


  String.prototype.toRGBcolor = function(){
    varR = parseInt(this.substring(1,3), 16);
    varG = parseInt(this.substring(3,5), 16);
    varB = parseInt(this.substring(5,7), 16);
    return "rgb(" + varR + ", " + varG + ", " +  varB + ")";
  }

 // function takes a number of seconds and returns a human readable time length.  EG: 1 Hour 15 Min 6 Sec
function seconds_to_human_time(num_seconds) {

    seconds = num_seconds%60;
    minutes = (num_seconds/60)%60;
    hours = Math.floor(num_seconds/3600);

    return_value = "";
    if (hours > 0)
    {
        if (hours == 1)
        {
            return_value = hours + " Hour ";
        } else {
            return_value = hours + " Hours ";
        }
    }
    if (minutes > 0)
    {
        if (minutes == 1)
        {
            return_value = return_value+ minutes + " Min ";
        } else {
            return_value = return_value + minutes + " Min ";
        }

    }
    if (seconds > 0)
    {
        if (seconds == 1)
        {
            return_value = return_value+ seconds + " Sec ";
        } else {
            return_value = return_value + seconds + " Sec ";
        }

    }
    return return_value;
}

 // submits a form to an associated invisible iframe
 // button_id is the id of the submit button
 // callback_before_code will run after the form is validated but before it is submitted
function _submit_form(form_id, button_id, callback_before_code)
{
    if (!$(form_id)) { alert('Form: '+form_id+' does not exist'); return false; }
    // validate the form, if it fails dont go further
    if (!validate_form(form_id)) { return false; }

    //if a button_id is sent through then we remove its onclick - this is to prevent forms from being submit twice when a user hits a button twice
    if (isset(button_id) && button_id != '')
    {
        $(button_id).onclick = "return false;";
    }

    if (isset(callback_before_code))
    {
        eval(callback_before_code);
    }
    // now that we know that the form submission is valid
    // we toggle the loading image on if it exists
    toggle_image_load('on');
    $(form_id).submit();
}

function _form_response(resp, resp_function)
{
    resp_array = resp.split("|");
    resp_code = resp_array[0];
    resp_text = resp_array[1];
    resp_id = resp_array[2];

    // if the resp function has a ( in it then it is an actual function call so we just run it
    if (strpos(resp_function,"(") > 0)
    {
        eval(resp_function);
    } else if (!resp_text) {
        alert("Error: Form did not return a valid response.");
    } else {

        eval_text = resp_function+"('"+resp_code+"','"+resp_text+"','"+resp_id+"');";
        eval(eval_text);
    }

}

// toggles the loading image display (if it exists)
// we also change the cursor to an hourglass
function toggle_image_load(_switch)
{
    if ($('image_load'))
    {
        if (_switch == "on")
        {

            $('body_tag').style.cursor = "wait";
            $('image_load').style.display = "table-cell";
        } else {
            $('body_tag').style.cursor = "";
            $('image_load').style.display = "none";
        }
    }
}
function implode( glue, pieces ) {
    // http://kevin.vanzonneveld.net
    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: _argos
    // *     example 1: implode(' ', ['Kevin', 'van', 'Zonneveld']);
    // *     returns 1: 'Kevin van Zonneveld'

    return ( ( pieces instanceof Array ) ? pieces.join ( glue ) : pieces );
}

// generic callback function for submitted forms, it refreshes the page
function generic_add(resp_code, resp_text)
{
    if (resp_code > 0)
    {
        window.location.reload();
    } else {
        alert("Error with CRUD.");
    }
}

function is_array( mixed_var ) {
    // http://kevin.vanzonneveld.net
    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: Legaev Andrey
    // +   bugfixed by: Cord
    // *     example 1: is_array(['Kevin', 'van', 'Zonneveld']);
    // *     returns 1: true
    // *     example 2: is_array('Kevin van Zonneveld');
    // *     returns 2: false

    return ( mixed_var instanceof Array );
}

 function str_replace(search, replace, subject) {
    // http://kevin.vanzonneveld.net
    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: Gabriel Paderni
    // +   improved by: Philip Peterson
    // +   improved by: Simon Willison (http://simonwillison.net)
    // +    revised by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
    // -    depends on: is_array
    // *     example 1: str_replace(' ', '.', 'Kevin van Zonneveld');
    // *     returns 1: 'Kevin.van.Zonneveld'
    // *     example 2: str_replace(['{name}', 'l'], ['hello', 'm'], '{name}, lars');
    // *     returns 2: 'hemmo, mars'

    var f = search, r = replace, s = subject;
    var ra = is_array(r), sa = is_array(s), f = [].concat(f), r = [].concat(r), i = (s = [].concat(s)).length;

    while (j = 0, i--) {
        while (s[i] = s[i].split(f[j]).join(ra ? r[j] || "" : r[0]), ++j in f){};
    };

    return sa ? s : s[0];
}

// this function is called by the default autocompleter input field
 function autocompleter_response(autocomplete_field, list_element)
 {
    // only if the li has an id, else we ignore it when it is clicked
    if (list_element.attributes['id'])
    {
        autocomplete_field.value = list_element.innerHTML;
        id_field = str_replace('_autocompleter', '', autocomplete_field.attributes['id'].value);
        $(id_field).value = list_element.attributes['id'].value;		// Populating hidden tariff ID field
        return true;
    } else {
        autocomplete_field.value = ""; // clearing the input box, if the li had no id - likely it is No matches
    }

 }

 // returns an array of the width and height
function get_page_size() {

         var xScroll, yScroll;

        if (window.innerHeight && window.scrollMaxY) {
            xScroll = window.innerWidth + window.scrollMaxX;
            yScroll = window.innerHeight + window.scrollMaxY;
        } else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
            xScroll = document.body.scrollWidth;
            yScroll = document.body.scrollHeight;
        } else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
            xScroll = document.body.offsetWidth;
            yScroll = document.body.offsetHeight;
        }

        var windowWidth, windowHeight;

        if (self.innerHeight) {	// all except Explorer
            if(document.documentElement.clientWidth){
                windowWidth = document.documentElement.clientWidth;
            } else {
                windowWidth = self.innerWidth;
            }
            windowHeight = self.innerHeight;
        } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
            windowWidth = document.documentElement.clientWidth;
            windowHeight = document.documentElement.clientHeight;
        } else if (document.body) { // other Explorers
            windowWidth = document.body.clientWidth;
            windowHeight = document.body.clientHeight;
        }

        // for small pages with total height less then height of the viewport
        if(yScroll < windowHeight){
            pageHeight = windowHeight;
        } else {
            pageHeight = yScroll;
        }

        // for small pages with total width less then width of the viewport
        if(xScroll < windowWidth){
            pageWidth = xScroll;
        } else {
            pageWidth = windowWidth;
        }

        return [pageWidth,pageHeight];
    }

// returns unix timestamp
function unix_timestamp()
{
    return Math.round(new Date().getTime()/1000.0);
}

// php port
function strpos( haystack, needle, offset){
    // http://kevin.vanzonneveld.net
    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: Onno Marsman
    // *     example 1: strpos('Kevin van Zonneveld', 'e', 5);
    // *     returns 1: 14

    var i = (haystack+'').indexOf( needle, offset );
    return i===-1 ? false : i;
}

// php port
function str_replace(search, replace, subject) {
    // http://kevin.vanzonneveld.net
    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: Gabriel Paderni
    // +   improved by: Philip Peterson
    // +   improved by: Simon Willison (http://simonwillison.net)
    // +    revised by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
    // +   bugfixed by: Anton Ongson
    // +      input by: Onno Marsman
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +    tweaked by: Onno Marsman
    // *     example 1: str_replace(' ', '.', 'Kevin van Zonneveld');
    // *     returns 1: 'Kevin.van.Zonneveld'
    // *     example 2: str_replace(['{name}', 'l'], ['hello', 'm'], '{name}, lars');
    // *     returns 2: 'hemmo, mars'

    var f = search, r = replace, s = subject;
    var ra = r instanceof Array, sa = s instanceof Array, f = [].concat(f), r = [].concat(r), i = (s = [].concat(s)).length;

    while (j = 0, i--) {
        if (s[i]) {
            while (s[i] = s[i].split(f[j]).join(ra ? r[j] || "" : r[0]), ++j in f){};
        }
    };

    return sa ? s : s[0];
}

// takes a div ID and an input ID and creates a date picker
function date_picker(div_id, input_id)
{
    _populate(div_id, 'global_includes/helpers/datepicker/date_picker.php', 'div_id='+div_id+'&input_id='+input_id,'','');
}

// loads a class's input field into an element
// element_id  => The ID of the element that will have the input field inserted
// class_name  => The name of the class that the input field belongs to
// object_id   => the id of the class object to be loaded
// input_field => the field that will be loaded
// replace		 => if set to something then the replace method will be called instead of populate
function load_object_input_field(element_id, class_name, object_id, input_field, replace)
{
    parameters = "class="+class_name+"&id="+object_id+"&input_field="+input_field;
    //$(element_id).innerHTML = '<table><tr><td>Loading...</td><td><img src="images/website/ajax-loaderGray.gif"></td></tr></table>';
    //$(element_id).style.display = "none";

    if (!empty(replace))
    {
        _replace(element_id, "global_includes/scripts/load_object_input_field.php", parameters);
    } else {
        _populate(element_id, "global_includes/scripts/load_object_input_field.php", parameters);
    }

    Effect.Appear(element_id);

}

// loads a class's variable into an element
// element_id  => The ID of the element that will have the input field inserted
// class_name  => The name of the class that the input field belongs to
// object_id   => the id of the class object to be loaded
// input_field => the field that will be loaded
// replace		 => if set to something then the replace method will be called instead of populate
function load_object_variable(element_id, class_name, object_id, variable, replace)
{

    parameters = "class="+class_name+"&id="+object_id+"&variable="+variable;
    //$(element_id).innerHTML = '<table><tr><td>Loading...</td><td><img src="images/website/ajax-loaderGray.gif"></td></tr></table>';
    //$(element_id).style.display = "none";

    if (!empty(replace))
    {
        _replace(element_id, "global_includes/scripts/load_object_variable.php", parameters);
    } else {
        _populate(element_id, "global_includes/scripts/load_object_variable.php", parameters);
    }

    Effect.Appear(element_id);

}

function object_method(class_name, object_id, method, after_success, method_parameters, element_to_be_updated, after_completion)
{
    if (element_to_be_updated){
        ajax_updater("http://www.hothousemedia.com/mm/global_includes/scripts/object_method.php", "request_type=updater&class="+class_name+"&id="+object_id+"&method="+method+"&method_parameters="+urlencode(method_parameters), element_to_be_updated, after_success, false, after_completion);
    }
    else{
        ajax_request("http://www.hothousemedia.com/mm/global_includes/scripts/object_method.php", "class="+class_name+"&id="+object_id+"&method="+method+"&method_parameters="+urlencode(method_parameters), after_success, after_completion);
    }
}




// php port
function empty( mixed_var ) {
    // http://kevin.vanzonneveld.net
    // +   original by: Philippe Baumann
    // +      input by: Onno Marsman
    // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +      input by: LH
    // +   improved by: Onno Marsman
    // +   improved by: Francesco
    // *     example 1: empty(null);
    // *     returns 1: true
    // *     example 2: empty(undefined);
    // *     returns 2: true
    // *     example 3: empty([]);
    // *     returns 3: true
    // *     example 4: empty({});
    // *     returns 4: true

    var key;

    if (mixed_var === ""
        || mixed_var === 0
        || mixed_var === "0"
        || mixed_var === null
        || mixed_var === false
        || mixed_var === undefined
    ){
        return true;
    }
    if (typeof mixed_var == 'object') {
        for (key in mixed_var) {
            if (typeof mixed_var[key] !== 'function' ) {
              return false;
            }
        }
        return true;
    }
    return false;
}

// php port
function urldecode (str) {
    // http://kevin.vanzonneveld.net
    // +   original by: Philip Peterson
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +      input by: AJ
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // +      input by: travc
    // +      input by: Brett Zamir (http://brett-zamir.me)
    // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: Lars Fischer
    // +      input by: Ratheous
    // +   improved by: Orlando
    // +      reimplemented by: Brett Zamir (http://brett-zamir.me)
    // +      bugfixed by: Rob
    // %        note 1: info on what encoding functions to use from: http://xkr.us/articles/javascript/encode-compare/
    // %        note 2: Please be aware that this function expects to decode from UTF-8 encoded strings, as found on
    // %        note 2: pages served as UTF-8
    // *     example 1: urldecode('Kevin+van+Zonneveld%21');
    // *     returns 1: 'Kevin van Zonneveld!'
    // *     example 2: urldecode('http%3A%2F%2Fkevin.vanzonneveld.net%2F');
    // *     returns 2: 'http://kevin.vanzonneveld.net/'
    // *     example 3: urldecode('http%3A%2F%2Fwww.google.nl%2Fsearch%3Fq%3Dphp.js%26ie%3Dutf-8%26oe%3Dutf-8%26aq%3Dt%26rls%3Dcom.ubuntu%3Aen-US%3Aunofficial%26client%3Dfirefox-a');
    // *     returns 3: 'http://www.google.nl/search?q=php.js&ie=utf-8&oe=utf-8&aq=t&rls=com.ubuntu:en-US:unofficial&client=firefox-a'

    return decodeURIComponent(str.replace(/\+/g, '%20'));
}

// creates a form and appends it to the document.  Parameters are split and created as hidden fields in the form
function generate_form(action, parameters)
{
    var submitForm = document.createElement("FORM");
    document.body.appendChild(submitForm);
    submitForm.method = "POST";
    submitForm.action = action;

    param_array = parameters.split("&");
    for (var index = 0; index < param_array.length; ++index)
    {
        if(param_array[index])
        {
            param_pair = param_array[index].split("=");
            create_form_element(submitForm, param_pair[0], param_pair[1]);
        }
    }
    return submitForm;
}

// takes a form object and adds a new hidden form element to it
function create_form_element(inputForm, elementName, elementValue){
 var newElement = document.createElement("input");
 newElement.setAttribute("name", elementName);
 newElement.setAttribute("value", elementValue);
 newElement.setAttribute("type", "hidden");
 inputForm.appendChild(newElement);
}

//php port
function rand( min, max ) {
    // http://kevin.vanzonneveld.net
    // +   original by: Leslie Hoare
    // +   bugfixed by: Onno Marsman
    // *     example 1: rand(1, 1);
    // *     returns 1: 1
    var argc = arguments.length;
    if (argc == 0) {
        min = 0;
        max = 2147483647;
    } else if (argc == 1) {
        throw new Error('Warning: rand() expects exactly 2 parameters, 1 given');
    }
    return Math.floor(Math.random() * (max - min + 1)) + min;
}

//php port
function date ( format, timestamp ) {
    // http://kevin.vanzonneveld.net
    // +   original by: Carlos R. L. Rodrigues (http://www.jsfromhell.com)
    // +      parts by: Peter-Paul Koch (http://www.quirksmode.org/js/beat.html)
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: MeEtc (http://yass.meetcweb.com)
    // +   improved by: Brad Touesnard
    // +   improved by: Tim Wiel
    // +   improved by: Bryan Elliott
    // +   improved by: Brett Zamir (http://brettz9.blogspot.com)
    // +   improved by: David Randall
    // +      input by: Brett Zamir (http://brettz9.blogspot.com)
    // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: Brett Zamir (http://brettz9.blogspot.com)
    // +   improved by: Brett Zamir (http://brettz9.blogspot.com)
    // +   derived from: gettimeofday
    // %        note 1: Uses global: php_js to store the default timezone
    // *     example 1: date('H:m:s \\m \\i\\s \\m\\o\\n\\t\\h', 1062402400);
    // *     returns 1: '09:09:40 m is month'
    // *     example 2: date('F j, Y, g:i a', 1062462400);
    // *     returns 2: 'September 2, 2003, 2:26 am'
    // *     example 3: date('Y W o', 1062462400);
    // *     returns 3: '2003 36 2003'
    // *     example 4: x = date('Y m d', (new Date()).getTime()/1000); // 2009 01 09
    // *     example 4: (x+'').length == 10
    // *     returns 4: true

    var jsdate=(
        (typeof(timestamp) == 'undefined') ? new Date() : // Not provided
        (typeof(timestamp) == 'number') ? new Date(timestamp*1000) : // UNIX timestamp
        new Date(timestamp) // Javascript Date()
    ); // , tal=[]
    var pad = function(n, c){
        if( (n = n + "").length < c ) {
            return new Array(++c - n.length).join("0") + n;
        } else {
            return n;
        }
    };
    var _dst = function (t) {
        // Calculate Daylight Saving Time (derived from gettimeofday() code)
        var dst=0;
        var jan1 = new Date(t.getFullYear(), 0, 1, 0, 0, 0, 0);  // jan 1st
        var june1 = new Date(t.getFullYear(), 6, 1, 0, 0, 0, 0); // june 1st
        var temp = jan1.toUTCString();
        var jan2 = new Date(temp.slice(0, temp.lastIndexOf(' ')-1));
        temp = june1.toUTCString();
        var june2 = new Date(temp.slice(0, temp.lastIndexOf(' ')-1));
        var std_time_offset = (jan1 - jan2) / (1000 * 60 * 60);
        var daylight_time_offset = (june1 - june2) / (1000 * 60 * 60);

        if (std_time_offset === daylight_time_offset) {
            dst = 0; // daylight savings time is NOT observed
        }
        else {
            // positive is southern, negative is northern hemisphere
            var hemisphere = std_time_offset - daylight_time_offset;
            if (hemisphere >= 0) {
                std_time_offset = daylight_time_offset;
            }
            dst = 1; // daylight savings time is observed
        }
        return dst;
    };
    var ret = '';
    var txt_weekdays = ["Sunday","Monday","Tuesday","Wednesday",
        "Thursday","Friday","Saturday"];
    var txt_ordin = {1:"st",2:"nd",3:"rd",21:"st",22:"nd",23:"rd",31:"st"};
    var txt_months =  ["", "January", "February", "March", "April",
        "May", "June", "July", "August", "September", "October", "November",
        "December"];

    var f = {
        // Day
            d: function(){
                return pad(f.j(), 2);
            },
            D: function(){
                var t = f.l();
                return t.substr(0,3);
            },
            j: function(){
                return jsdate.getDate();
            },
            l: function(){
                return txt_weekdays[f.w()];
            },
            N: function(){
                return f.w() + 1;
            },
            S: function(){
                return txt_ordin[f.j()] ? txt_ordin[f.j()] : 'th';
            },
            w: function(){
                return jsdate.getDay();
            },
            z: function(){
                return (jsdate - new Date(jsdate.getFullYear() + "/1/1")) / 864e5 >> 0;
            },

        // Week
            W: function(){
                var a = f.z(), b = 364 + f.L() - a;
                var nd2, nd = (new Date(jsdate.getFullYear() + "/1/1").getDay() || 7) - 1;

                if(b <= 2 && ((jsdate.getDay() || 7) - 1) <= 2 - b){
                    return 1;
                }
                if(a <= 2 && nd >= 4 && a >= (6 - nd)){
                    nd2 = new Date(jsdate.getFullYear() - 1 + "/12/31");
                    return date("W", Math.round(nd2.getTime()/1000));
                }
                return (1 + (nd <= 3 ? ((a + nd) / 7) : (a - (7 - nd)) / 7) >> 0);
            },

        // Month
            F: function(){
                return txt_months[f.n()];
            },
            m: function(){
                return pad(f.n(), 2);
            },
            M: function(){
                var t = f.F();
                return t.substr(0,3);
            },
            n: function(){
                return jsdate.getMonth() + 1;
            },
            t: function(){
                var n;
                if( (n = jsdate.getMonth() + 1) == 2 ){
                    return 28 + f.L();
                }
                if( n & 1 && n < 8 || !(n & 1) && n > 7 ){
                    return 31;
                }
                return 30;
            },

        // Year
            L: function(){
                var y = f.Y();
                return (!(y & 3) && (y % 1e2 || !(y % 4e2))) ? 1 : 0;
            },
            o: function(){
                if (f.n() === 12 && f.W() === 1) {
                    return jsdate.getFullYear()+1;
                }
                if (f.n() === 1 && f.W() >= 52) {
                    return jsdate.getFullYear()-1;
                }
                return jsdate.getFullYear();
            },
            Y: function(){
                return jsdate.getFullYear();
            },
            y: function(){
                return (jsdate.getFullYear() + "").slice(2);
            },

        // Time
            a: function(){
                return jsdate.getHours() > 11 ? "pm" : "am";
            },
            A: function(){
                return f.a().toUpperCase();
            },
            B: function(){
                // peter paul koch:
                var off = (jsdate.getTimezoneOffset() + 60)*60;
                var theSeconds = (jsdate.getHours() * 3600) +
                                 (jsdate.getMinutes() * 60) +
                                  jsdate.getSeconds() + off;
                var beat = Math.floor(theSeconds/86.4);
                if (beat > 1000) {
                    beat -= 1000;
                }
                if (beat < 0) {
                    beat += 1000;
                }
                if ((String(beat)).length == 1) {
                    beat = "00"+beat;
                }
                if ((String(beat)).length == 2) {
                    beat = "0"+beat;
                }
                return beat;
            },
            g: function(){
                return jsdate.getHours() % 12 || 12;
            },
            G: function(){
                return jsdate.getHours();
            },
            h: function(){
                return pad(f.g(), 2);
            },
            H: function(){
                return pad(jsdate.getHours(), 2);
            },
            i: function(){
                return pad(jsdate.getMinutes(), 2);
            },
            s: function(){
                return pad(jsdate.getSeconds(), 2);
            },
            u: function(){
                return pad(jsdate.getMilliseconds()*1000, 6);
            },

        // Timezone
            e: function () {
/*                var abbr='', i=0;
                if (this.php_js && this.php_js.default_timezone) {
                    return this.php_js.default_timezone;
                }
                if (!tal.length) {
                    tal = timezone_abbreviations_list();
                }
                for (abbr in tal) {
                    for (i=0; i < tal[abbr].length; i++) {
                        if (tal[abbr][i].offset === -jsdate.getTimezoneOffset()*60) {
                            return tal[abbr][i].timezone_id;
                        }
                    }
                }
*/
                return 'UTC';
            },
            I: function(){
                return _dst(jsdate);
            },
            O: function(){
               var t = pad(Math.abs(jsdate.getTimezoneOffset()/60*100), 4);
               t = (jsdate.getTimezoneOffset() > 0) ? "-"+t : "+"+t;
               return t;
            },
            P: function(){
                var O = f.O();
                return (O.substr(0, 3) + ":" + O.substr(3, 2));
            },
            T: function () {
/*                var abbr='', i=0;
                if (!tal.length) {
                    tal = timezone_abbreviations_list();
                }
                if (this.php_js && this.php_js.default_timezone) {
                    for (abbr in tal) {
                        for (i=0; i < tal[abbr].length; i++) {
                            if (tal[abbr][i].timezone_id === this.php_js.default_timezone) {
                                return abbr.toUpperCase();
                            }
                        }
                    }
                }
                for (abbr in tal) {
                    for (i=0; i < tal[abbr].length; i++) {
                        if (tal[abbr][i].offset === -jsdate.getTimezoneOffset()*60) {
                            return abbr.toUpperCase();
                        }
                    }
                }
*/
                return 'UTC';
            },
            Z: function(){
               return -jsdate.getTimezoneOffset()*60;
            },

        // Full Date/Time
            c: function(){
                return f.Y() + "-" + f.m() + "-" + f.d() + "T" + f.h() + ":" + f.i() + ":" + f.s() + f.P();
            },
            r: function(){
                return f.D()+', '+f.d()+' '+f.M()+' '+f.Y()+' '+f.H()+':'+f.i()+':'+f.s()+' '+f.O();
            },
            U: function(){
                return Math.round(jsdate.getTime()/1000);
            }
    };

    return format.replace(/[\\]?([a-zA-Z])/g, function(t, s){
        if( t!=s ){
            // escaped
            ret = s;
        } else if( f[s] ){
            // a date function exists
            ret = f[s]();
        } else{
            // nothing special
            ret = s;
        }
        return ret;
    });
}
//phpport
function urlencode( str ) {
    // http://kevin.vanzonneveld.net
    // +   original by: Philip Peterson
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +      input by: AJ
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: Brett Zamir (http://brettz9.blogspot.com)
    // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +      input by: travc
    // +      input by: Brett Zamir (http://brettz9.blogspot.com)
    // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: Lars Fischer
    // %          note 1: info on what encoding functions to use from: http://xkr.us/articles/javascript/encode-compare/
    // *     example 1: urlencode('Kevin van Zonneveld!');
    // *     returns 1: 'Kevin+van+Zonneveld%21'
    // *     example 2: urlencode('http://kevin.vanzonneveld.net/');
    // *     returns 2: 'http%3A%2F%2Fkevin.vanzonneveld.net%2F'
    // *     example 3: urlencode('http://www.google.nl/search?q=php.js&ie=utf-8&oe=utf-8&aq=t&rls=com.ubuntu:en-US:unofficial&client=firefox-a');
    // *     returns 3: 'http%3A%2F%2Fwww.google.nl%2Fsearch%3Fq%3Dphp.js%26ie%3Dutf-8%26oe%3Dutf-8%26aq%3Dt%26rls%3Dcom.ubuntu%3Aen-US%3Aunofficial%26client%3Dfirefox-a'

    var histogram = {}, unicodeStr='', hexEscStr='';
    var ret = (str+'').toString();

    var replacer = function(search, replace, str) {
        var tmp_arr = [];
        tmp_arr = str.split(search);
        return tmp_arr.join(replace);
    };

    // The histogram is identical to the one in urldecode.
    histogram["'"]   = '%27';
    histogram['(']   = '%28';
    histogram[')']   = '%29';
    histogram['*']   = '%2A';
    histogram['~']   = '%7E';
    histogram['!']   = '%21';
    histogram['%20'] = '+';
    histogram['\u00DC'] = '%DC';
    histogram['\u00FC'] = '%FC';
    histogram['\u00C4'] = '%D4';
    histogram['\u00E4'] = '%E4';
    histogram['\u00D6'] = '%D6';
    histogram['\u00F6'] = '%F6';
    histogram['\u00DF'] = '%DF';
    histogram['\u20AC'] = '%80';
    histogram['\u0081'] = '%81';
    histogram['\u201A'] = '%82';
    histogram['\u0192'] = '%83';
    histogram['\u201E'] = '%84';
    histogram['\u2026'] = '%85';
    histogram['\u2020'] = '%86';
    histogram['\u2021'] = '%87';
    histogram['\u02C6'] = '%88';
    histogram['\u2030'] = '%89';
    histogram['\u0160'] = '%8A';
    histogram['\u2039'] = '%8B';
    histogram['\u0152'] = '%8C';
    histogram['\u008D'] = '%8D';
    histogram['\u017D'] = '%8E';
    histogram['\u008F'] = '%8F';
    histogram['\u0090'] = '%90';
    histogram['\u2018'] = '%91';
    histogram['\u2019'] = '%92';
    histogram['\u201C'] = '%93';
    histogram['\u201D'] = '%94';
    histogram['\u2022'] = '%95';
    histogram['\u2013'] = '%96';
    histogram['\u2014'] = '%97';
    histogram['\u02DC'] = '%98';
    histogram['\u2122'] = '%99';
    histogram['\u0161'] = '%9A';
    histogram['\u203A'] = '%9B';
    histogram['\u0153'] = '%9C';
    histogram['\u009D'] = '%9D';
    histogram['\u017E'] = '%9E';
    histogram['\u0178'] = '%9F';

    // Begin with encodeURIComponent, which most resembles PHP's encoding functions
    ret = encodeURIComponent(ret);

    for (unicodeStr in histogram) {
        hexEscStr = histogram[unicodeStr];
        ret = replacer(unicodeStr, hexEscStr, ret); // Custom replace. No regexing
    }

    // Uppercase for full PHP compatibility
    return ret.replace(/(\%([a-z0-9]{2}))/g, function(full, m1, m2) {
        return "%"+m2.toUpperCase();
    });
}

function json_encode(mixed_val) {
    // http://kevin.vanzonneveld.net
    // +      original by: Public Domain (http://www.json.org/json2.js)
    // + reimplemented by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // *     example 1: json_encode(['e', {pluribus: 'unum'}]);
    // *     returns 1: '[\n    "e",\n    {\n    "pluribus": "unum"\n}\n]'

    /*
        http://www.JSON.org/json2.js
        2008-11-19
        Public Domain.
        NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
        See http://www.JSON.org/js.html
    */

    var value = mixed_val;

    var quote = function (string) {
        var escapable = /[\\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
        var meta = {    // table of character substitutions
            '\b': '\\b',
            '\t': '\\t',
            '\n': '\\n',
            '\f': '\\f',
            '\r': '\\r',
            '"' : '\\"',
            '\\': '\\\\'
        };

        escapable.lastIndex = 0;
        return escapable.test(string) ?
        '"' + string.replace(escapable, function (a) {
            var c = meta[a];
            return typeof c === 'string' ? c :
            '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
        }) + '"' :
        '"' + string + '"';
    };

    var str = function(key, holder) {
        var gap = '';
        var indent = '    ';
        var i = 0;          // The loop counter.
        var k = '';          // The member key.
        var v = '';          // The member value.
        var length = 0;
        var mind = gap;
        var partial = [];
        var value = holder[key];

        // If the value has a toJSON method, call it to obtain a replacement value.
        if (value && typeof value === 'object' &&
            typeof value.toJSON === 'function') {
            value = value.toJSON(key);
        }

        // What happens next depends on the value's type.
        switch (typeof value) {
            case 'string':
                return quote(value);

            case 'number':
                // JSON numbers must be finite. Encode non-finite numbers as null.
                return isFinite(value) ? String(value) : 'null';

            case 'boolean':
            case 'null':
                // If the value is a boolean or null, convert it to a string. Note:
                // typeof null does not produce 'null'. The case is included here in
                // the remote chance that this gets fixed someday.

                return String(value);

            case 'object':
                // If the type is 'object', we might be dealing with an object or an array or
                // null.
                // Due to a specification blunder in ECMAScript, typeof null is 'object',
                // so watch out for that case.
                if (!value) {
                    return 'null';
                }

                // Make an array to hold the partial results of stringifying this object value.
                gap += indent;
                partial = [];

                // Is the value an array?
                if (Object.prototype.toString.apply(value) === '[object Array]') {
                    // The value is an array. Stringify every element. Use null as a placeholder
                    // for non-JSON values.

                    length = value.length;
                    for (i = 0; i < length; i += 1) {
                        partial[i] = str(i, value) || 'null';
                    }

                    // Join all of the elements together, separated with commas, and wrap them in
                    // brackets.
                    v = partial.length === 0 ? '[]' :
                    gap ? '[\n' + gap +
                    partial.join(',\n' + gap) + '\n' +
                    mind + ']' :
                    '[' + partial.join(',') + ']';
                    gap = mind;
                    return v;
                }

                // Iterate through all of the keys in the object.
                for (k in value) {
                    if (Object.hasOwnProperty.call(value, k)) {
                        v = str(k, value);
                        if (v) {
                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
                        }
                    }
                }

                // Join all of the member texts together, separated with commas,
                // and wrap them in braces.
                v = partial.length === 0 ? '{}' :
                gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
                mind + '}' : '{' + partial.join(',') + '}';
                gap = mind;
                return v;
        }
    };

    // Make a fake root object containing our value under the key of ''.
    // Return the result of stringifying the value.
    return str('', {
        '': value
    });
}
function strtotime(str, now) {
    // http://kevin.vanzonneveld.net
    // +   original by: Caio Ariede (http://caioariede.com)
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +      input by: David
    // +   improved by: Caio Ariede (http://caioariede.com)
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // +   bugfixed by: Wagner B. Soares
    // %        note 1: Examples all have a fixed timestamp to prevent tests to fail because of variable time(zones)
    // *     example 1: strtotime('+1 day', 1129633200);
    // *     returns 1: 1129719600
    // *     example 2: strtotime('+1 week 2 days 4 hours 2 seconds', 1129633200);
    // *     returns 2: 1130425202
    // *     example 3: strtotime('last month', 1129633200);
    // *     returns 3: 1127041200
    // *     example 4: strtotime('2009-05-04 08:30:00');
    // *     returns 4: 1241418600

    var i, match, s, strTmp = '', parse = '';

    strTmp = str;
    strTmp = strTmp.replace(/\s{2,}|^\s|\s$/g, ' '); // unecessary spaces
    strTmp = strTmp.replace(/[\t\r\n]/g, ''); // unecessary chars

    if (strTmp == 'now') {
        return (new Date()).getTime()/1000; // Return seconds, not milli-seconds
    } else if (!isNaN(parse = Date.parse(strTmp))) {
        return (parse/1000);
    } else if (now) {
        now = new Date(now*1000); // Accept PHP-style seconds
    } else {
        now = new Date();
    }

    strTmp = strTmp.toLowerCase();

    var __is =
    {
        day:
        {
            'sun': 0,
            'mon': 1,
            'tue': 2,
            'wed': 3,
            'thu': 4,
            'fri': 5,
            'sat': 6
        },
        mon:
        {
            'jan': 0,
            'feb': 1,
            'mar': 2,
            'apr': 3,
            'may': 4,
            'jun': 5,
            'jul': 6,
            'aug': 7,
            'sep': 8,
            'oct': 9,
            'nov': 10,
            'dec': 11
        }
    };

    var process = function (m) {
        var ago = (m[2] && m[2] == 'ago');
        var num = (num = m[0] == 'last' ? -1 : 1) * (ago ? -1 : 1);

        switch (m[0]) {
            case 'last':
            case 'next':
                switch (m[1].substring(0, 3)) {
                    case 'yea':
                        now.setFullYear(now.getFullYear() + num);
                        break;
                    case 'mon':
                        now.setMonth(now.getMonth() + num);
                        break;
                    case 'wee':
                        now.setDate(now.getDate() + (num * 7));
                        break;
                    case 'day':
                        now.setDate(now.getDate() + num);
                        break;
                    case 'hou':
                        now.setHours(now.getHours() + num);
                        break;
                    case 'min':
                        now.setMinutes(now.getMinutes() + num);
                        break;
                    case 'sec':
                        now.setSeconds(now.getSeconds() + num);
                        break;
                    default:
                        var day;
                        if (typeof (day = __is.day[m[1].substring(0, 3)]) != 'undefined') {
                            var diff = day - now.getDay();
                            if (diff == 0) {
                                diff = 7 * num;
                            } else if (diff > 0) {
                                if (m[0] == 'last') {diff -= 7;}
                            } else {
                                if (m[0] == 'next') {diff += 7;}
                            }
                            now.setDate(now.getDate() + diff);
                        }
                }
                break;

            default:
                if (/\d+/.test(m[0])) {
                    num *= parseInt(m[0], 10);

                    switch (m[1].substring(0, 3)) {
                        case 'yea':
                            now.setFullYear(now.getFullYear() + num);
                            break;
                        case 'mon':
                            now.setMonth(now.getMonth() + num);
                            break;
                        case 'wee':
                            now.setDate(now.getDate() + (num * 7));
                            break;
                        case 'day':
                            now.setDate(now.getDate() + num);
                            break;
                        case 'hou':
                            now.setHours(now.getHours() + num);
                            break;
                        case 'min':
                            now.setMinutes(now.getMinutes() + num);
                            break;
                        case 'sec':
                            now.setSeconds(now.getSeconds() + num);
                            break;
                    }
                } else {
                    return false;
                }
                break;
        }
        return true;
    };

    match = strTmp.match(/^(\d{2,4}-\d{2}-\d{2})(?:\s(\d{1,2}:\d{2}(:\d{2})?)?(?:\.(\d+))?)?$/);
    if (match != null) {
        if (!match[2]) {
            match[2] = '00:00:00';
        } else if (!match[3]) {
            match[2] += ':00';
        }

        s = match[1].split(/-/g);

        for (i in __is.mon) {
            if (__is.mon[i] == s[1] - 1) {
                s[1] = i;
            }
        }
        s[0] = parseInt(s[0], 10);

        s[0] = (s[0] >= 0 && s[0] <= 69) ? '20'+(s[0] < 10 ? '0'+s[0] : s[0]+'') : (s[0] >= 70 && s[0] <= 99) ? '19'+s[0] : s[0]+'';
        return parseInt(this.strtotime(s[2] + ' ' + s[1] + ' ' + s[0] + ' ' + match[2])+(match[4] ? match[4]/1000 : ''), 10);
    }

    var regex = '([+-]?\\d+\\s'+
        '(years?|months?|weeks?|days?|hours?|min|minutes?|sec|seconds?'+
        '|sun\.?|sunday|mon\.?|monday|tue\.?|tuesday|wed\.?|wednesday'+
        '|thu\.?|thursday|fri\.?|friday|sat\.?|saturday)'+
        '|(last|next)\\s'+
        '(years?|months?|weeks?|days?|hours?|min|minutes?|sec|seconds?'+
        '|sun\.?|sunday|mon\.?|monday|tue\.?|tuesday|wed\.?|wednesday'+
        '|thu\.?|thursday|fri\.?|friday|sat\.?|saturday))'+
        '(\\sago)?';

    match = strTmp.match(new RegExp(regex, 'g'));
    if (match == null) {
        return false;
    }

    for (i in match) {
        if (!process(match[i].split(' '))) {
            return false;
        }
    }

    return (now.getTime()/1000);
}

// phpport
function sleep(seconds) {
    // http://kevin.vanzonneveld.net
    // +   original by: Christian Doebler
    // %          note: For study purposes. Current implementation could lock up the user's browser.
    // %          note: Consider using setTimeout() instead.
    // *     example 1: sleep(1);
    // *     returns 1: 0

    seconds *= 1000;
    var start = new Date().getTime();
    while (new Date().getTime() < start + seconds);

    return 0;
}

function populate_loading(container_id)
{
  $(container_id).innerHTML = '<table id="ajax_loading_sub" cellpadding="0" cellspacing="0" border="0" class="content"><tr><td><img src="images/ajax-loader.gif"></td><td style="padding-left:10px;">Loading... </td></tr></table>';
}

function shortenText(text, length, suffix) {
    if (text.length <= length) {
        return text;
    } else {
        return text.substr(0, length) + suffix;
    }
}
