function historyChange(newLocation, historyData)
{
	if(historyData) {
		document.backcnt--;
		historyData=historyData.split('|');
		sa(historyData[0], historyData[1],false);
	}
	else {window.location.hash='';window.location.reload(false);}
}

function sa(urlOrForm, obj_id, bSaveBack)
{
    var sal = new salajax();
	sal.Debug = 0;	
    sal.PresendHtml = null;
    sal.OnError = '';
    sal.ErrorHtml == null;
	sal.EvalScripts = true;
	if(typeof (obj_id)== 'function'){
		sal.PassAjaxResponseToFunction(urlOrForm, obj_id);
		}
    else{
		if(obj_id=='canvas' && (bSaveBack==null || bSaveBack==true)) window.dhtmlHistory.add(document.backcnt++,urlOrForm+'|'+obj_id);
		sal.SetInnerHTMLFromAjaxResponse(urlOrForm, obj_id);
		}
}
document.sa=sa;
if (!document.backcnt) document.backcnt=0;

function alert_error(v){
	if(v.length>2) alert(v);
}

function hide_loader(){
	var ajxload= document.getElementById("ajax_loader");
	if (ajxload!=null) {
		ajxload.style.display='none';
	}
	
}
function show_loader(){
	var ajxload= document.getElementById("ajax_loader");
	if (ajxload!=null) {
		ajxload.style.top=getPageSize()[3]/2-32 + getScrollXY()[1];
		ajxload.style.left=getPageSize()[2]/2-32 + getScrollXY()[0];
		ajxload.style.display='block';
	}
	
}

/*
The Salajax Class.
Ajax class that allows use of the back button and bookmarks.
Written by Nigel Liefrink.


| This software is provided "as is", without warranty of any kind, express or |
| implied, including  but not limited  to the warranties of  merchantability, |
| fitness for a particular purpose and noninfringement. In no event shall the |
| authors or  copyright  holders be  liable for any claim,  damages or  other |
| liability, whether  in an  action of  contract, tort  or otherwise, arising |
| from,  out of  or in  connection with  the software or  the  use  or  other |
| dealings in the software.   

14-05-2007 : v2.0 Initial version release.  

Usage:
    //set up the salajax settings.
    var sal = new salajax();
    sal.Debug = 0;
    sal.EnableBackButton(true); //turns on the back buttons.
    sal.EnableBookmarks(true); //saves state in the clients cookies so bookmarks will work provided they havn't deleted their cookies.
    sal.OnStart = 'TestOnStart()'; //enables a script to run before the request is made. e.g. change pointer/icon/loading section of page.
    sal.OnEnd = 'TestOnEnd()'; //enables a script to run after the request is returned. e.g. change pointer/icon/loading section of page.
    sal.PresendHtml = '<img border="0" src="http://www.ajaxload.info/cache/ff/ff/ff/00/80/ff/24-1.gif"/>';
    sal.OnError = 'DefaultOnError()';//set a function to pass to if there is an error.
    sal.OnErrorHtml = '<img border="0" src="http://www.register.com/images/icons/error_icon.gif" /><font color="red">Error!</font>'; //When calling  etInnerHTMLFromAjaxResponse and there is an error, this will be displayed.
    sal.EvalScripts = true; //if set to true, will evaluate any javascript in the responseText. 
                             //NOTE: to use functions returned in your responseText you must declare the functions in your ajax response like this:
                             //         var FunctionToChange = function(var1,var2)
                             //         { 
                             //             //do stuff
                             //         }
                             //            
    this.KeepDotNetViewState = true; //if set to true will post the current viewstate when using .NET
    //end setting the salajax settings.
    
    
    Some examples of main usage in web page:
    sal.PassAjaxResponseToFunction('/myscript.*?getsomehtml=1', 'FunctionToHandleTheResponse');
    sal.PassAjaxResponseToFunction(document.forms[0], 'FunctionToHandleTheResponse');

	sal.SetInnerHTMLFromAjaxResponse('/myscript.*?getsomehtml=1', 'id_of_div'); //using get and string of id div.
	sal.SetInnerHTMLFromAjaxResponse(document.forms[0], object);//using post and object to change the innerhtml of.
	sal.SetInnerHTMLFromAjaxResponse('form', 'id_of_div');//using post ('form' will submit forms[0]'), object to change the innerhtml of.

    Read function definitions for more detail.



*/
function salajax()
{
    this.Debug = 0;//1=Debug, 2=Verbose - will cause alert statements to popup.
    this.PresendHtml = 'Loading...'; //TODO: use an image. When set to null, this will leave the current html until the response is returned.
    this.OnStart = '';//set a function to pass to eval.
    this.OnEnd = '';//set a function to pass to eval.
    this.OnError = 'DefaultOnError()';//set a function to pass if there is an error.
    this.OnErrorHtml = '<font color="red">Error!</font>'; //When setting InnerHtml and there is an error this will be displayed. Set to null to turn this feature off.
    this.EvalScripts = false; //if set to true, will evaluate any javascript in the responseText.
    this.KeepDotNetViewState = false; //if set to true will post the current viewstate when using .NET
    this.EnableBookmarkDays = 600; //how many days to keep the bookmarks..
    //TODO: Possibly save state on server, send the key in the request to the server or make a seperate ajax call to get and save state...
    //this.SaveStateOnServer = false; //if set to true will send the key name with the request.
    
    //Also Available are these two functions.
    //this.EnableBackButton(false);
    //this.EnableBookmarks(false);

    var _backButtonEnabled = false;
    var _bookmarksEnabled = false;
    var _savedstate = new Object();
    var _savedkeys = new Array();
    
    var self = this;
    
    
    //enables back button and storing of state keys in the # of the url.
    //will also start polling for any changes to the hash, so as to update the ajax section of the page.
    this.EnableBackButton = function(blnEnable) 
    {
        _backButtonEnabled = blnEnable;
        if(blnEnable)
        {
            this.PollForStateChange();
        }
    }
    
    //Default Function to call when there is an error.
    var DefaultOnError = function()
    {
        alert('There was an error loading the data. Sorry for the inconvenience.');
    }
    
    
    /**
    <summary>
    Gets the response stream from the passed url, and then calls the callbackFuntion passing the response and the div_ids.
    </summary>
    <param name="url">The url to make the request to get the response data.</param>
    <param name="callbackFunction">The function to call after the response has been recieved. the response <b>must</b> always be the first argument to the function.</param>
    </summary>
    <example>
	<code>
	var sal = new salajax();
	sal.PassAjaxResponseToFunction('?getsomehtml=1', 'FunctionToHandleTheResponse');

    function FunctionToHandleTheResponse(response){
	    var data = response.split(';');
	    document.getElementById('d1').innerHTML = data[0];
	    document.getElementById('d2').innerHTML = data[1];
	    document.getElementById('d3').innerHTML = data[2];
    }
	    </code>
    </example>
    */
    this.PassAjaxResponseToFunction = function (urlOrForm, callbackFunction)
    {		
      if(this.onStart != '')
      {
        eval(this.OnStart);
      }
      var xmlhttp = new this.GetXmlHttp();
      //now we got the XmlHttpRequest object, send the request.
      if(this.Debug >= 2)
      {
        alert(urlOrForm);
      }

      if (xmlhttp)
      {
         xmlhttp = this.SetReadyStateForFunction(xmlhttp, callbackFunction)                          
         this.SubmitXmlHttp(urlOrForm, xmlhttp, 'f|'+callbackFunction);
      }

    }


    /**
    ///<summary>
    ///Sets the innerHTML property of obj_id with the response from the passed url or form./
    ///</summary>
    ///<param name="urlOrForm">The url or form to submit to make the request to get the response data.</param>
    ///<param name="obj_id">The object or the id as a string of the object to set the innerHTML for.</param>
    <example>
	<code>
	var sal = new salajax();
	sal.SetInnerHTMLFromAjaxResponse('?getsomehtml=1', 'id_of_div'); //using get and string of id div.
	sal.SetInnerHTMLFromAjaxResponse(document.forms[0], object);//using post and object to change the innerhtml of.
	sal.SetInnerHTMLFromAjaxResponse('form', object);//using post ('form' will submit forms[0]'), object to change the innerhtml of.
	</code>
    </example>
    */
    this.SetInnerHTMLFromAjaxResponse = function (urlOrForm, obj_id)
    {	
		show_loader();
      if(this.onStart != '')	                                                    {
        eval(this.OnStart);
      }
	  
      
      var xmlhttp = new this.GetXmlHttp();
      //now we got the XmlHttpRequest object, send the request.
      if (xmlhttp)
      { 
        if(typeof obj_id == 'string')
        {
           obj_id = document.getElementById(obj_id);
        }
        
        xmlhttp = this.SetReadyStateForInnerHtml(xmlhttp, obj_id)
       
        if(this.PresendHtml != null)
        {
            obj_id.innerHTML = this.PresendHtml;
        }
		
        var bb_div_id = obj_id.id;
	    this.SubmitXmlHttp(urlOrForm, xmlhttp, 'h|'+bb_div_id);

      }
    }
    

    /**
    Browser Compatability function.
    Returns the correct XMLHttpRequest depending on the current browser.
    */
    this.GetXmlHttp = function() {	
                var xmlhttp = false;
                if (window.XMLHttpRequest)
                {
                    xmlhttp = new XMLHttpRequest();
                }
                else if (window.ActiveXObject)// code for IE
                {
                    try 
                    {
	                    xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
                    } 
                    catch (e) 
                    {
	                    try 
	                    {
		                    xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
	                    } catch (E) {
		                    xmlhttp=false;
	                    }
                    }
                }
                return xmlhttp;
            }

    /**
        Returns the values of the form as a Post string to add to the header of the request.
        Modified from code here: http://www.codeproject.com/Ajax/AJAXWasHere-Part1.asp
    */
    this.GetPostDataFromForm = function(theform)
    {
        var theData = '';
        var eName = '';

        if(this.Debug >= 1)
        {
			alert('Form:'+theform.name + 'fields:'+theform.elements.length);
        }
    	
        theData = 'ajax=true&';
        for( var i=0; i<theform.elements.length; i++ )
        {
            eName = theform.elements[i].name;
            if(eName == '')
            {
                eName = theform.elements[i].id;
            }

            if(this.Debug >= 2)
            {
                alert('FormElement:'+eName+'='+theform.elements[i]);
            }

            //Handle .NET VIEWSTATE
            if( eName && eName != '')
            {
              
              if(  eName == '__EVENTTARGET' 
                || eName == '__EVENTARGUMENT' 
                || eName == '__VIEWSTATE' )
              {
                if(eName = '__VIEWSTATE' && this.KeepDotNetViewState)
                {
                    theData += '__VIEWSTATE=' + escape(theform.__VIEWSTATE.value).replace(new RegExp('\\+', 'g'), '%2b') + '&';
                }
              }
              else
              {
				//check if field is a checkbox
				if(theform.elements[i].type=="checkbox"){
					var cv="0";
					if(theform.elements[i].checked) cv="1";
					theData = theData + escape(eName) + '=' + encodeURIComponent(cv);
				}
				else if(theform.elements[i].type == "radio"){
					if (theform.elements[i].checked) theData = theData + escape(eName) + '=' + encodeURIComponent(theform.elements[i].value);
				}
				else if(theform.elements[i].type == "select-one"){
					if (theform.elements[i].options.length) 
					{
						theData = theData + escape(eName) + '=' + encodeURIComponent(theform.elements[i].options[theform.elements[i].selectedIndex].value);
					}
				}
                else theData = theData + escape(eName) + '=' + encodeURIComponent(theform.elements[i].value);
                if( i != theform.elements.length - 1 )
                  theData = theData + '&';
              }
            }
            }//end for
            if(this.Debug >= 1)
            {
                alert('DataToSend:'+theData);
            }
        return theData;
        }


        /**
            Sets up the xmlhttp object to pass the responseText to a the specified callbackfunction.
            Private method.
        */
        this.SetReadyStateForFunction = function (xmlhttp, callbackFunction)
        {
            var debug = this.Debug;
            var onEnd = this.OnEnd;
            var onError = this.OnError;
            
             xmlhttp.onreadystatechange = function () 
                                            {
                                                if (xmlhttp && xmlhttp.readyState==4)
                                                {//we got something back..
                                                    if (xmlhttp.status==200)
                                                    {
	                                                    var response = xmlhttp.responseText;
	                                                    var functionToCall = callbackFunction+'(response)';
	                                                    if(debug >= 2)
														{
		                                                    alert(response);
		                                                    alert(functionToCall);
	                                                    }
	                                                    if(typeof(callbackFunction=='function')) callbackFunction(response);
														else eval(functionToCall);
    	                                                
	                                                    if(onEnd != '')
                                                        {
                                                            eval(onEnd);
                                                        }
                                                        
                                                    } 
                                                    else
                                                    {
                                                      if(onError != '')
                                                      {
                                                        eval(onError);
                                                      }
                                                      if(debug >= 1)
                                                      {
	                                                    document.write(xmlhttp.responseText);
                                                      }
                                                    }
                                                    

                                                }
                                            }
            return xmlhttp;
        }
        
         /**
            Sets up the xmlhttp object to update the innerHTML of the obj_id with the responseText.
            Private method.
        */
        this.SetReadyStateForInnerHtml = function (xmlhttp, obj_id)
        {

            var onEnd = this.OnEnd;
            var debug = this.Debug;
            var onError = this.OnError;
            var self = this;
            
                xmlhttp.onreadystatechange = function () 
                                            {
                                                if (xmlhttp && xmlhttp.readyState==4)
                                                {//we got something back..
                                                    if (xmlhttp.status==200)
                                                    {
	                                                    if(debug >= 1){
		                                                    alert(xmlhttp.responseText);
	                                                    }
		                                                obj_id.innerHTML = xmlhttp.responseText;
														hide_loader();
    	                                                
	                                                    if(self.EvalScripts)
                                                        {
                                                            self.EvaluateScripts(xmlhttp.responseText);
                                                        }
                                                        
	                                                    if(onEnd != '')
                                                        {
                                                            eval(onEnd);
                                                        }
         
                                                    } 
                                                    else
                                                    {
                                                      if(onError != '')
                                                      {
                                                        eval(onError);
                                                        obj_id.innerHTML = self.OnErrorHtml;
                                                      }
                                                      if(debug >= 1)
                                                      {
	                                                    document.write(xmlhttp.responseText);
                                                      }
                                                    }
                                                }
                                            }
            return xmlhttp;
        }

        /**
            Evaluates any javascript that is in the responseText.
            **NOTE: if you want to use functions that are in the responseText, the function must be written as a variable.
            (this can easily be achieved by swapping the name and the function declaration around and adding an '=' sign.)
            e.g.
                
                AFunctionInTheResponse = function(some, vars)
                {
                    //do stuff with some vars
                }
                NOT: function AFunctionInTheResponse(some, vars){ // this will not work. }
            Private Method.
        */            
        this.EvaluateScripts = function(responseText)
        {
			
			var rt=responseText.replace(/<textarea[.\s\S]*\/textarea>/gi,'');
            var matchAll = new RegExp('(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)', 'img');
            var scripts = '';
            while (scripts = matchAll.exec(rt))
            {
                eval(scripts[1]);
            }
        }
             
            
        /*
        Submits the initialised xmlhttp object to the server.
        and updates the address bar if back button is enabled.
        Private Method.
        */
        this.SubmitXmlHttp = function (urlOrForm, xmlhttp, callid)
        {
			
            //quick param for submitting the first form                        
            if(urlOrForm == 'form'){
                urlOrForm = document.forms[0];
            }          
            
            var bb_params;		
                                                                            
            if(typeof urlOrForm == 'string')
            { //it a get request.          
              var url = urlOrForm;
              if(url.indexOf('?') == 0)//is shortcut link
              {
                url = document.location.pathname+url;
              }
                xmlhttp.open("GET",url,true);
                xmlhttp.send(null);
    			
                bb_params = '|g|'+url+'|'+callid
            } 
            else 
            { //it is a form.... submit all the values
                var f = urlOrForm
                var theData = this.GetPostDataFromForm(f);
				
                if(f.action == null || f.action == "")
                {
                    f.action = document.location.pathname;
                }
                if(f.action.indexOf('?') == 0)
                {
                    f.action = document.location.pathname+f.action;
                }
                
                xmlhttp.open('POST', f.action, true);
                xmlhttp.setRequestHeader('Content-Type', 
												                    'application/x-www-form-urlencoded');
                xmlhttp.send(theData);
                bb_params = theData+'|p|'+f.action+'|'+callid
    			   
            } 
            if(_backButtonEnabled)
            {
                UpdateAddressBar(bb_params);
            }
        }
             
             
             
             

                
    /*
    Updates the address bar and adds the saved params using the hashlistenter.
    //extra vals stored as | [posttype(g=get,p=post) | url/action | f=function,h=setinnerhtml | funcname or divname
    */
    var UpdateAddressBar = function(address) {
    
        var split = address.split('|');
        //the last is the Div that was changed.
        var keyn = split[split.length-1]; //use this as the key to store the data.
        var hash = hashListener.getHash().substring(1);//remove the '#'
        var hashkeys = hash.split(':');
        var keysaved = false;
        var stateIsSavedAs = '';
        
        if(_bookmarksEnabled)
        { //check cookies to see if the state has been saved in da cookie
            var cs = document.cookie.split(';');
            for(var c=0;c<cs.length;c++)
            {
                var ckey = cs[c].substring(0,cs[c].indexOf('=')).trim()
                var ckeyn = ckey.split('@');
                ckeyn = ckeyn[0];
                var cval = cs[c].substring(cs[c].indexOf('=')+1,cs[c].length);
                //alert('cookKey'+c+':'+ckey+'\n'+'cookVal'+c+':'+cval);
                if(keyn == ckeyn && cval == address)
                {
                    var stateissaved = cs[c].split('=');
                    stateIsSavedAs = stateissaved[0].trim();
                    break;
                }
            }
        }
        
        //check in the state object
        if(stateIsSavedAs == '')
        {
            for(var i=0;i<_savedkeys.length;i++)
            {
                var skey = _savedkeys[i];
                var skeyn = skey.split('@');
                skeyn = skeyn[0];
                //alert('Checking if Saved\n'+'Key:'+_savedkeys[i]+'\n'+address + ' ==\n'+ _savedstate[_savedkeys[i]]);
                if(skeyn == keyn && address == _savedstate[skey])
                {
                    stateIsSavedAs = skey; //set to the key that has been saved.
                    break;
                }
            }
        }
        
        //work out the old key
        var oldkey = '';
        for(var i=1; i<hashkeys.length; i++)
        {
            var hashkey = hashkeys[i].split('@');
            var hashkeyn = hashkey[0];
            var hashkeye = hashkey[1];

            if(hashkeyn == keyn)//this section has been changed by an ajax request.
            {
                oldkey=hashkeys[i];
                break;
            }
        }
        
        //if the state hasn't been saved we need to create a new key.
        if(stateIsSavedAs == '')
        {
            g_eventCount++;
            key = keyn +'@'+g_eventCount;
            SaveState(key, address);
//alert('Created New Key:'+key);
        } 
        else //just save the state
        {
            key = stateIsSavedAs;
//alert('Key is saved:'+key);
            SaveState(key, address);
        }
        
        
        if(oldkey == '')
        {
            hash+=':'+key;
        } else {  
            hash = hash.replace(oldkey, key);
        }
        
        hashListener.setHash(hash);
    }      
    
    
    //Used for saving the state of an ajax request.
    var SaveState = function(key, data)
    {
        _savedstate[key] = data;
        _savedkeys.push(key);
         if(_bookmarksEnabled)
         {
            createCookie(key, data, self.EnableBookmarkDays);
         }
         //TODO:Store state information on server via ajax requests? Cookie is limited to 4K. (not much)
         //Or Maybe one of these methods http://www.niallkennedy.com/blog/archives/2007/01/ajax-performance-local-storage.html
    }
    
    //Gets the state of an ajax element.
    var GetState = function(key)
    {
        if(_bookmarksEnabled && _savedstate[key] == null)
        {
            return readCookie(key);
        } else {
            return _savedstate[key];
        }
        //TODO:Get state information from server via ajax requests?
    }
    
    
    
    //Private Function to update all the ajax elements 
    //from the keys that are contained in the hash of the url.
    var UpdateAjaxDivs = function()
    {
       //TODO: get key from the address bar 
       // return state information from a cookie
       // or on the server using the key as a reference.
        var hash = hashListener.getHash();
        hash = hash.substring(1);
        if(hash != '')
        {
            var savedkeys = hash.split(':');
            for(var i=1;i<savedkeys.length;i++)
            {
                //TODO: keep/find the last state of this div
                //So we don't make any uneeded ajax requests divs, ie already set.
                
                var data = GetState(savedkeys[i])
                if(data != null)
                {
				var data = data.split('|');
                if(data.length >= 4) 
                {
                    var funcdiv = data.pop();
                    var fh = data.pop();
                    var url = data.pop();
                    var postget = data.pop();
                    var xmlhttp = self.GetXmlHttp();
                    //now we got the XmlHttpRequest object, send the request.
                    if (xmlhttp)
                    { 
                        if(self.onStart != '')
                        {
                            eval(self.OnStart);
                        }
                    
                        if(fh == 'h')
                        {
                           var fd = document.getElementById(funcdiv);
                           if(fd == null)
                           {
                                //setTimeout(this.PollForStateChange, this.BBPoleTime);
                                return;
                           }
                           xmlhttp =  self.SetReadyStateForInnerHtml(xmlhttp, fd)
                        } else {//set for function.
                            
                           xmlhttp = self.SetReadyStateForFunction(xmlhttp, funcdiv)
                        }
                        
                        //set the inner html if we are affecting a div.
                        if(fd)
                        {
                            if(self.PresendHtml != null)
                            {
                                fd.innerHTML = self.PresendHtml;
                            }
                        }
                        
                        //send the request via ajax
                        if(postget == 'p')
                        {
                            //reconstruct theData
                            var theData = data.pop(); 
                            
                            xmlhttp.open('POST', url, true);
                            xmlhttp.setRequestHeader('Content-Type','application/x-www-form-urlencoded');

                            if(self.Debug > 0){
					            alert('TheData:'+theData);
					        }
							
                            xmlhttp.send(theData);

                        } else {//g
                            xmlhttp.open('GET',url,true);
                            xmlhttp.send(null);
                        }
                    }
                }
                }//if data.length
            } //end for
        }else{//no hash
            //document.location.reload();
        } 
    }
    
    
    //if set to true will store state information in cookies
    //on the clients computer.
    this.EnableBookmarks = function(blnEnable) 
    {
        _bookmarksEnabled = blnEnable
        if(blnEnable)
        {
            setTimeout(UpdateAjaxDivs,100);
        }
    }
    
    
    
    /*
    If the back button is enabled this method will watch for changes to the hash
    and update the ajax areas when a change is detected.
    */
    this.PollForStateChange = function()
    {
        if(_backButtonEnabled)
        {
           hashListener.onHashChanged = UpdateAjaxDivs
        } 
        else 
        {//disable back button - could potentially remove other instances that are monitoring.
         //hashListener.onHashChanged = function(){}
        }
    }      
}//END salajax_class






String.prototype.trim = function() {return this.replace(/^\s+|\s+$/g,"");}
//String.prototype.ltrim = function() {return this.replace(/^\s+/g,"");}
//String.prototype.rtrim = function() {return this.replace(/\s+$/g,"");}


/* Backward compatability. */
function PassAjaxResponseToFunction(urlOrForm, callbackFunction)
{
    var sal = new salajax();
    sal.PresendHtml = null;
    sal.OnError = '';
    sal.ErrorHtml == null;
    sal.PassAjaxResponseToFunction(urlOrForm, callbackFunction);
}

/* Backward compatability. */
function SetInnerHTMLFromAjaxResponse(urlOrForm, obj_id)
{
    var sal = new salajax();
    sal.PresendHtml = null;
    sal.OnError = '';
    sal.ErrorHtml == null;
    sal.SetInnerHTMLFromAjaxResponse(urlOrForm, obj_id);
}

/*
//This ensures that bookmarks cannot be overridden by replacing the key values saved in cookies.
//NOTE: cookies do have a limitation in size of data that can be saved..
//NOTE: ints may eventually run out and cause issues
//TODO: fix these potential problems.
*/
function GetSafeEventCount()
{
    var retVal = 0;    
    var cs = document.cookie
    cs = cs.split(';');
    for(var c=0;c<cs.length;c++)
    {
        var ckey = cs[c].substring(0,cs[c].indexOf('='))
        var ckeyn = ckey.split('@');
        if(ckeyn[1] != null && ckeyn[1] > retVal)
        {
            retVal = ckeyn[1];
        }
    }
    return parseInt(retVal);
}                      
var g_eventCount = GetSafeEventCount(); 
    







/*----------------------------------------------------------------------------\
|                             Hash Listener 1.0                               |
|-----------------------------------------------------------------------------|
|                         Created by Erik Arvidsson                           |
|                  (http://webfx.eae.net/contact.html#erik)                   |
|                      For WebFX (http://webfx.eae.net/)                      |
|-----------------------------------------------------------------------------|
|   Basic object to allow updating the hash part of the document location.    |
|-----------------------------------------------------------------------------|
|                  Copyright (c) 1998 - 2005 Erik Arvidsson                   |
|-----------------------------------------------------------------------------|
| Basic object to allow updating the hash part of the document location.      |
| Mozilla always adds an entry to the history but for IE we add an optional   |
| flag whether to add an entry to the history and if this is set an iframe is |
| used to support this behavior (this is on by default).                      |
|                                                                             |
| When the hash value changes onHashChanged is called. Override this to do    |
| your own callbacks.                                                         |
|                                                                             |
| Usage: Include script                                                       |
|        Override onHashChanged: hashListener.onHashChanged = fn              |
|                                                                             |
| Known issues: Known to not work with Opera                                  |
|               Not tested with KHTML/Safari                                  |
|               Might interfere with other iframe based loading               |
|- ---------------------------------------------------------------------------|
| This software is provided "as is", without warranty of any kind, express or |
| implied, including  but not limited  to the warranties of  merchantability, |
| fitness for a particular purpose and noninfringement. In no event shall the |
| authors or  copyright  holders be  liable for any claim,  damages or  other |
| liability, whether  in an  action of  contract, tort  or otherwise, arising |
| from,  out of  or in  connection with  the software or  the  use  or  other |
| dealings in the software.                                                   |
| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
| ... removed standard license part of header for now...                      |
|-----------------------------------------------------------------------------|
| 2005-05-15 | First version                                                  |
|-----------------------------------------------------------------------------|
| Created 2005-05-15 | All changes are in the log above. | Updated 2005-05-15 |
\----------------------------------------------------------------------------*/
//Note that I have made some changes to this class in order to get it to work with salajax class.
var hashListener = {
	ie:		/MSIE/.test(navigator.userAgent),
	ieSupportBack:	true,
	hash:	document.location.hash,
	initialised: false,
	check:	function () {
		var h = document.location.hash
		var h2 = this.hash

		if (h != h2) {
		    //alert(h+"\n:\n"+h2)
			this.hash = h;
			this.onHashChanged();
		}
	},
	init:	function () {

		// for IE we need the iframe state trick
		if (this.ie && this.ieSupportBack) {
			var frame = document.createElement("iframe");
			frame.id = "state-frame";
			frame.style.display = "none";
			document.body.appendChild(frame);
			this.writeFrame("");
		}

		var self = this;

		// IE
		if ("onpropertychange" in document && "attachEvent" in document) {
			document.attachEvent("onpropertychange", function () {
				if (event.propertyName == "location") {
					self.check();
				}
			});
		} else {
		// poll for changes of the hash
		    window.setInterval(function () { self.check() }, 100);
		}
		this.initialised = true;
	},
	setHash: function (s) {
	    this.hash = '#'+s;
		// Mozilla always adds an entry to the history
		//this.init();
		
		if(!this.initialised)
		{
		    this.init();
		}
		
		if (this.ie && this.ieSupportBack) {
			this.writeFrame(s);
		}
		//if (this.hash != '' && this.hash != document.location.hash) {
			document.location.hash = this.hash;
		//}
	},
	getHash: function () {
		return document.location.hash;
	},
	writeFrame:	function (s) {
		var f = document.getElementById("state-frame");
		var d = f.contentDocument || f.contentWindow.document;
		
		d.open();
		d.write("<script>window._hash = '" + s + "'; window.onload = parent.hashListener.syncHash;<\/script>");
		d.close();
	},
	syncHash:	function () {
		var s = this._hash;
		
		if (s != '' && s != document.location.hash) {
			document.location.hash = s;
		}
	},
	onHashChanged:	function () {}
};


function createCookie(name, value, days) {
	if (days) {
		var date = new Date();
		date.setTime(date.getTime()+(days*24*60*60*1000));
		var expires = "; expires="+date.toGMTString();
	}
	else var expires = "";
	document.cookie = name+"="+value+expires+"; path=/";
}

function createCookieSec(name, value, seconds) {
	if (seconds) {
		var date = new Date();
		date.setTime(date.getTime()+(seconds*1000));
		var expires = "; expires="+date.toGMTString();
	}
	else var expires = "";
	document.cookie = name+"="+value+expires+"; path=/";
}


function readCookie(name) {
	var nameEQ = name + "=";
	var ca = document.cookie.split(';');
	for(var i=0;i < ca.length;i++) {
		var c = ca[i];
		while (c.charAt(0)==' ') c = c.substring(1,c.length);
		if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
	}
	return null;
}


function eraseCookie(name) {
	createCookie(name,"",-1);
}

