//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 '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('|');
    } 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 (!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 '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('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));$(newId).setStyle({visibility: 'visible' });",500);
            }
            setTimeout("new Draggable(newId, {handle: '"+newId+"_handle', onEnd: store_center_div_pos(newId) });", 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;
}

// makes an ajax request
function ajax_request(url, parameters, after_success, ignore_fail)
{
    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.');
                }
            }
        }
    );
    return true;
}

// makes an ajax updater request
function ajax_updater(url, parameters, update_element_id, after_success, ignore_fail, blankContentsReplacement)
{
    new Ajax.Updater(update_element_id, url, {
        method: 'post',
        parameters: parameters,
        evalScripts: true,
        onComplete: function (response)
            {
                if (response.responseText == '' || response.status != 200) {
                    $(update_element_id).innerHTML = blankContentsReplacement;
                }
                eval(after_success);
            },
        onFailure: function()
            {
                if (isset(ignore_fail))
                {

                } else {
                    if (response.responseText == '') {
                        $(update_element_id).innerHTML = blankContentsReplacement;
                    }
                }
            }
        }
    );

    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")
        {
            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];

    // 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+"');";
        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)
{
    ajax_request("global_includes/scripts/object_method.php", "class="+class_name+"&id="+object_id+"&method="+method+"&method_parameters="+urlencode(method_parameters), after_success);
}

// 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 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)
    // %          note: 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 = {}, histogram_r = {}, code = 0, tmp_arr = [];
    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['!']   = '%21';
    histogram['%20'] = '+';

    // Begin with encodeURIComponent, which most resembles PHP's encoding functions
    ret = encodeURIComponent(ret);

    for (search in histogram) {
        replace = histogram[search];
        ret = replacer(search, replace, 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();
    });

    return ret;
}


// 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 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://brett-zamir.me)
    // +   improved by: David Randall
    // +      input by: Brett Zamir (http://brett-zamir.me)
    // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // +   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;
    });
}

var php_js_shared;

// php port
function file_get_contents( url, flags, context, offset, maxLen ) {
    // Read the entire file into a string
    //
    // version: 906.111
    // discuss at: http://phpjs.org/functions/file_get_contents
    // +   original by: Legaev Andrey
    // +      input by: Jani Hartikainen
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // +   input by: Raphael (Ao) RUDLER
    // +   bugfixed by: Brett Zamir (http://brett-zamir.me)
    // %        note 1: This function uses XmlHttpRequest and cannot retrieve resource from different domain.
    // %        note 2: Synchronous by default (as in PHP) so may lock up browser. Can
    // %        note 2: get async by setting a custom "phpjs.async" property to true and "notification" for an
    // %        note 2: optional callback (both as context params, with responseText, and other JS-specific
    // %        note 2: request properties available via 'this'). Note that file_get_contents() will not return the text
    // %        note 2: in such a case (use this.responseText within the callback). Or, consider using
    // %        note 2: jQuery's: $('#divId').load('http://url') instead.
    // %        note 3: The context argument is only implemented for http, and only partially (see below for
    // %        note 3: "Presently unimplemented HTTP context options"); also the arguments passed to
    // %        note 3: notification are incomplete
    // *     example 1: file_get_contents('http://kevin.vanzonneveld.net/pj_test_supportfile_1.htm');
    // *     returns 1: '123'
    // Note: could also be made to optionally add to global $http_response_header as per http://php.net/manual/en/reserved.variables.httpresponseheader.php

    var tmp, headers = [], newTmp = [], k=0, i=0, href = '', pathPos = -1, flagNames = '', content = null;
    var func = function (value) { return value.substring(1) !== ''; };

    // BEGIN REDUNDANT
    this.php_js = this.php_js || {};
    this.php_js.ini = this.php_js.ini || {};
    // END REDUNDANT
    context = context || this.php_js.default_streams_context || null;

    if (!flags) {flags = 0;}
    var OPTS = {
        PHP_FILE_USE_INCLUDE_PATH : 1,
        PHP_FILE_TEXT : 32,
        PHP_FILE_BINARY : 64
    };
    if (typeof flags === 'number') { // Allow for a single string or an array of string flags
        flagNames = flags;
    }
    else {
        flags = [].concat(flags);
        for (i=0; i < flags.length; i++) {
            if (OPTS[flags[i]]) {
                flagNames = flagNames | OPTS[flags[i]];
            }
        }
    }
    if ((flagNames & OPTS.PHP_FILE_USE_INCLUDE_PATH) && this.php_js.ini.include_path &&
            this.php_js.ini.include_path.local_value) {
        var slash = this.php_js.ini.include_path.local_value.indexOf('/') !== -1 ? '/' : '\\';
        url = this.php_js.ini.include_path.local_value+slash+url;
    }
    else if (!/^(https?|file):/.test(url)) { // Allow references within or below the same directory (should fix to allow other relative references or root reference; could make dependent on parse_url())
        href = this.window.location.href;
        pathPos = url.indexOf('/') === 0 ? href.indexOf('/', 8)-1 : href.lastIndexOf('/');
        url = href.slice(0, pathPos+1)+url;
    }

    if (context) {
        var http_options = context.stream_options && context.stream_options.http;
        var http_stream = !!http_options;
    }

    if (!context || http_stream) {
        var req = this.window.ActiveXObject ? new ActiveXObject('Microsoft.XMLHTTP') : new XMLHttpRequest();
        if (!req) {throw new Error('XMLHttpRequest not supported');}

        var method = http_stream ? http_options.method : 'GET';
        var async = !!(context && context.stream_params && context.stream_params['phpjs.async']);
        req.open(method, url, async);
        if (async) {
            var notification = context.stream_params.notification;
            if (typeof notification === 'function') {
                req.onreadystatechange = function (aEvt) { // aEvt has stopPropagation(), preventDefault(); see https://developer.mozilla.org/en/NsIDOMEvent

// Other XMLHttpRequest properties: multipart, responseXML, status, statusText, upload, withCredentials; overrideMimeType()
/*
PHP Constants:
STREAM_NOTIFY_RESOLVE   1     A remote address required for this stream has been resolved, or the resolution failed. See severity  for an indication of which happened.
STREAM_NOTIFY_CONNECT   2   A connection with an external resource has been established.
STREAM_NOTIFY_AUTH_REQUIRED 3   Additional authorization is required to access the specified resource. Typical issued with severity level of STREAM_NOTIFY_SEVERITY_ERR.
STREAM_NOTIFY_MIME_TYPE_IS  4   The mime-type of resource has been identified, refer to message for a description of the discovered type.
STREAM_NOTIFY_FILE_SIZE_IS  5   The size of the resource has been discovered.
STREAM_NOTIFY_REDIRECTED    6   The external resource has redirected the stream to an alternate location. Refer to message .
STREAM_NOTIFY_PROGRESS  7   Indicates current progress of the stream transfer in bytes_transferred and possibly bytes_max as well.
STREAM_NOTIFY_COMPLETED 8   There is no more data available on the stream.
STREAM_NOTIFY_FAILURE   9   A generic error occurred on the stream, consult message and message_code for details.
STREAM_NOTIFY_AUTH_RESULT   10   Authorization has been completed (with or without success).

STREAM_NOTIFY_SEVERITY_INFO 0   Normal, non-error related, notification.
STREAM_NOTIFY_SEVERITY_WARN 1   Non critical error condition. Processing may continue.
STREAM_NOTIFY_SEVERITY_ERR  2   A critical error occurred. Processing cannot continue.
*/

                    var objContext = {}; // properties are not available in PHP, but offered on notification via 'this' for convenience
                    objContext.responseText = req.responseText;
                    objContext.responseXML = req.responseXML;
                    objContext.status = req.status;
                    objContext.statusText = req.statusText;
                    objContext.readyState = req.readyState;
                    objContext.evt = aEvt;

                    // notification args: notification_code, severity, message, message_code, bytes_transferred, bytes_max (all int's except string 'message')
                    // Need to add message, etc.
                    var bytes_transferred;
                    switch(req.readyState) {
                        case 0: //   UNINITIALIZED   open() has not been called yet.
                            notification.call(objContext, 0, 0, '', 0, 0, 0);
                            break;
                        case 1: //   LOADING   send() has not been called yet.
                            notification.call(objContext, 0, 0, '', 0, 0, 0);
                            break;
                        case 2: //   LOADED   send() has been called, and headers and status are available.
                            notification.call(objContext, 0, 0, '', 0, 0, 0);
                            break;
                        case 3: //   INTERACTIVE   Downloading; responseText holds partial data.
                            bytes_transferred = Math.floor(req.responseText.length/2); // Two characters for each byte
                            notification.call(objContext, 7, 0, '', 0, bytes_transferred, 0);
                            break;
                        case 4: //   COMPLETED   The operation is complete.
                            if (req.status >= 200 && req.status < 400) {
                                bytes_transferred = Math.floor(req.responseText.length/2); // Two characters for each byte
                                notification.call(objContext, 8, 0, '', req.status, bytes_transferred, 0);
                            }
                            else if (req.status === 403) { // Fix: These two are finished except for message
                                notification.call(objContext, 10, 2, '', req.status, 0, 0);
                            }
                            else { // Errors
                                notification.call(objContext, 9, 2, '', req.status, 0, 0);
                            }
                            break;
                        default:
                            throw 'Unrecognized ready state for file_get_contents()';
                    }
                }
            }
        }

        if (http_stream) {
            var sendHeaders = http_options.header && http_options.header.split(/\r?\n/);
            var userAgentSent = false;
            for (i=0; i < sendHeaders.length; i++) {
                var sendHeader = sendHeaders[i];
                var breakPos = sendHeader.search(/:\s*/);
                var sendHeaderName = sendHeader.substring(0, breakPos);
                req.setRequestHeader(sendHeaderName, sendHeader.substring(breakPos+1));
                if (sendHeaderName === 'User-Agent') {
                    userAgentSent = true;
                }
            }
            if (!userAgentSent) {
                var user_agent = http_options.user_agent ||
                                                                    (this.php_js.ini.user_agent && this.php_js.ini.user_agent.local_value);
                if (user_agent) {
                    req.setRequestHeader('User-Agent', user_agent);
                }
            }
            content = http_options.content || null;
            /*
            // Presently unimplemented HTTP context options
            var request_fulluri = http_options.request_fulluri || false; // When set to TRUE, the entire URI will be used when constructing the request. (i.e. GET http://www.example.com/path/to/file.html HTTP/1.0). While this is a non-standard request format, some proxy servers require it.
            var max_redirects = http_options.max_redirects || 20; // The max number of redirects to follow. Value 1 or less means that no redirects are followed.
            var protocol_version = http_options.protocol_version || 1.0; // HTTP protocol version
            var timeout = http_options.timeout || (this.php_js.ini.default_socket_timeout && this.php_js.ini.default_socket_timeout.local_value); // Read timeout in seconds, specified by a float
            var ignore_errors = http_options.ignore_errors || false; // Fetch the content even on failure status codes.
            */
        }
        // We should probably change to an || "or", in order to have binary as the default (as it is in PHP), but this method might not be well-supported; check for its existence instead or will this be to much trouble?
        if (flagNames & OPTS.PHP_FILE_BINARY && !(flagNames & OPTS.PHP_FILE_TEXT)) { // These flags shouldn't be together
            req.sendAsBinary(content); // In Firefox, only available FF3+
        }
        else {
            req.send(content);
        }

        tmp = req.getAllResponseHeaders();
        if (tmp) {
            tmp = tmp.split('\n');
            for (k=0; k < tmp.length; k++) {
                if (func(tmp[k])) {
                    newTmp.push(tmp[k]);
                }
            }
            tmp = newTmp;
            for (i=0; i < tmp.length; i++) {
                headers[i] = tmp[i];
            }
            this.$http_response_header = headers; // see http://php.net/manual/en/reserved.variables.httpresponseheader.php
        }

        if (offset || maxLen) {
            if (maxLen) {
                return req.responseText.substr(offset || 0, maxLen);
            }
            return req.responseText.substr(offset);
        }
        return req.responseText;
    }
    return false;
}

// php port
function require( filename ) {
    // http://kevin.vanzonneveld.net
    // +   original by: Michael White (http://getsprink.com)
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +      input by: Brett Zamir (http://brett-zamir.me)
    // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // %        note 1: Force Javascript execution to pause until the file is loaded. Usually causes failure if the file never loads. ( Use sparingly! )
    // %        note 2: Uses global: php_js to keep track of included files
    // -    depends on: file_get_contents
    // *     example 1: require('http://www.phpjs.org/js/phpjs/_supporters/pj_test_supportfile_2.js');
    // *     returns 1: 2

    var d = this.window.document;
    var js_code = this.file_get_contents(filename);
    var script_block = d.createElementNS ? d.createElementNS('http://www.w3.org/1999/xhtml', 'script') : d.createElement('script');
    script_block.type = 'text/javascript';
    var client_pc = navigator.userAgent.toLowerCase();
    if((client_pc.indexOf("msie") != -1) && (client_pc.indexOf("opera") == -1)) {
        script_block.text = js_code;
    } else {
        script_block.appendChild(d.createTextNode(js_code));
    }

    if (typeof(script_block) != "undefined") {
        d.getElementsByTagName('head')[0].appendChild(script_block);

        // save include state for reference by include_once and require_once()
        var cur_file = {};
        cur_file[this.window.location.href] = 1;

        // BEGIN REDUNDANT
        this.php_js = this.php_js || {};
        // END REDUNDANT

        if (!this.php_js.includes) {
            this.php_js.includes = cur_file;
        }

        if (!this.php_js.includes[filename]) {
            this.php_js.includes[filename] = 1;
            return 1;
        } else {
            return ++this.php_js.includes[filename];
        }
    }
    return 0;
}

// phpport
function require_once(filename) {
    // http://kevin.vanzonneveld.net
    // +   original by: Michael White (http://getsprink.com)
    // +      input by: Brett Zamir (http://brett-zamir.me)
    // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // %        note 1: Uses global: php_js to keep track of included files
    // -    depends on: require
    // *     example 1: require_once('http://www.phpjs.org/js/phpjs/_supporters/pj_test_supportfile_2.js');
    // *     returns 1: true

    var cur_file = {};
    cur_file[this.window.location.href] = 1;

    // save include state for reference by include_once and require_once()
    // BEGIN REDUNDANT
    php_js_shared = php_js_shared || {}; // We use a non-namespaced global here since we wish to share across all instances
    // END REDUNDANT

    if (!php_js_shared.includes) {
        php_js_shared.includes = cur_file;
    }
    if (!php_js_shared.includes[filename]) {
        if (this.require(filename)) {
            return true;
        }
    } else {
        return true;
    }
    return false;
}
