/*
File:   Application.js
Author: Kevin Parker (www.administerweb.com)
Notes:  You MUST include jQuery.js 1.3.2 or later just BEFORE Application.js like so:
    <script src="/workspace/scripts/application/jquery.js" type="text/javascript"></script>
    <script src="/workspace/scripts/application/Application.js" type="text/javascript"></script>

What I'm trying to do here:
 * Make a façade method for each of the local AJAX events that are similar to ColdFusion (etc.) Application events for ease of programming between server/client.
 * Also, make a façade method for each of the global AJAX methods, so that other events (e.g., hiding/showing progress indicators) can subscribe to them.

LOCAL AJAX EVENTS:

These are callbacks that you can subscribe to within the Ajax request object, like so:

 $.ajax({
   beforeSend: function(){
     // Handle the beforeSend event
   },
   complete: function(){
     // Handle the complete event
   }
   // ......
 });

GLOBAL AJAX EVENTS:

These events are broadcast to all elements in the DOM, triggering any handlers which may be listening. You can listen for these events like so:

 $("#loading").bind("ajaxSend", function(){
   $(this).show();
 }).bind("ajaxComplete", function(){
   $(this).hide();
 });

Global events can be disabled, for a particular Ajax request, by passing in the global option, like so:

 $.ajax({
   url: "test.html",
   global: false,
   // ...
 });

[edit]
Events

This is the full list of AJAX events that are broadcast, and in the order in which they are broadcast. 
The indented events are broadcast for each and every AJAX request (unless a global option has been set).
The ajaxStart and ajaxStop events are events that relate to all AJAX requests together.

    * ajaxStart (Global Event)
      This event is broadcast if an AJAX request is started and no other AJAX requests are currently running.
          o beforeSend (Local Event)
            This event, which is triggered before an AJAX request is started, allows you to modify the XMLHttpRequest object (setting additional headers, if need be.)
          o ajaxSend (Global Event)
            This global event is also triggered before the request is run.
          o success (Local Event)
            This event is only called if the request was successful (no errors from the server, no errors with the data).
          o ajaxSuccess (Global Event)
            This event is also only called if the request was successful.
          o error (Local Event)
            This event is only called if an error occurred with the request (you can never have both an error and a success callback with a request).
          o ajaxError (Global Event)
            This global event behaves the same as the local error event.
          o complete (Local Event)
            This event is called regardless of if the request was successful, or not. You will always receive a complete callback, even for synchronous requests.
          o ajaxComplete (Global Event)
            This event behaves the same as the complete event and will be triggered every time an AJAX request finishes. 
    * ajaxStop (Global Event)
      This global event is triggered if there are no more AJAX requests being processed.  

*/

// Allow whoever wants it use of $; Keep use of $ for jQuery to the private function below:
jQuery.noConflict();
(function($){
	
	// I am the class that controls the JavaScript framework.
	function Application(){
		
		// I am a unique ID of this application instance: (NOTE: not currently used.)
		this.id = ("app-" + (new Date()).getTime());

		// Create a safe façade reference for the jQuery object: (Usage: "application.$(){};")
		this.$ = jQuery;
		
		// Allows actions on elements to subscribe to global AJAX events:
		this.registerAjaxListener = function(onEvent,onSelector,doAction,Args){
			switch(onEvent){
				case 'onSessionStart':
					$(onSelector).ajaxStart(function(){    //This event is broadcast if an AJAX request is started and no other AJAX requests are currently running.
						window.application[doAction](Args);
						//$("<p>onSessionStart was successfully registered by " + onSelector + " on " + onEvent + ".</p>").appendTo("body");
					});
					break;
				case 'onRequestStart':
					$(onSelector).ajaxSend(function(){     //This global event is also triggered before the request is run.
						window.application[doAction](Args);
						//$("<p>onRequestStart was successfully registered by " + onSelector + " on " + onEvent + ".</p>").appendTo("body");
					});
					break;
				case 'onRequestSuccess':
					$(onSelector).ajaxSuccess(function(){  //This event is also only called if the request was successful.
						window.application[doAction](Args);
						//$("<p>onRequestSuccess was successfully registered by " + onSelector + " on " + onEvent + ".</p>").appendTo("body");
					});
					break;
				case 'onRequestError':
					$(onSelector).ajaxError(function(){    //This global event behaves the same as the local error event.
						window.application[doAction](Args);
						//$("<p>onRequestError was successfully registered by " + onSelector + " on " + onEvent + ".</p>").appendTo("body");
					});
					break;
				case 'onRequestEnd':
					$(onSelector).ajaxComplete(function(){ //This event behaves the same as the complete event and will be triggered every time an AJAX request finishes. 
						window.application[doAction](Args);
						//$("<p>onRequestEnd was successfully registered by " + onSelector + " on " + onEvent + ".</p>").appendTo("body");
					});
					break;
				case 'onSessionEnd':
					$(onSelector).ajaxStop(function(){     //This global event is triggered if there are no more AJAX requests being processed.
						window.application[doAction](Args);
						//$("<p>onSessionEnd was successfully registered by " + onSelector + " on " + onEvent + ".</p>").appendTo("body");
					});
					break;
			}
		};
			
	};

	// Fires when user navigates away from the page:
	Application.prototype.onApplicationEnd = function(){
		//$("<p>onApplicationEnd was fired!</p>").appendTo("body");
		
	};
	
	// Fires when the user makes an AJAX request and no other AJAX requests are in progress:
	Application.prototype.onSessionStart = function(){
		//$("<p>onSessionStart was fired!</p>").appendTo("body");
		
	};
	
	// Fires when the last AJAX request is finished (i.e., no others are in progress):
	Application.prototype.onSessionEnd = function(){
		//$("<p>onSessionEnd was fired!</p>").appendTo("body");

	};
	
	// Fires when the user makes an AJAX request:
	Application.prototype.onRequestStart = function(){
		//$("<p>onRequestStart was fired!</p>").appendTo("body");
		
	};
	
	// Fires when an AJAX request is finished:
	Application.prototype.onRequestEnd = function(){
		//$("<p>onRequestEnd was fired!</p>").appendTo("body");
		
	};
	
	// Fires when the AJAX request is successful:
	Application.prototype.onRequestSuccess = function(data){
		//$("<p>onRequestSuccess was fired!</p>").appendTo("body");
		
	};
	
	// Fires when the AJAX request throws an error:
	Application.prototype.onRequestError = function(xhr, status, error){
		//$("<p>An error occurred: " + error + "</p>").appendTo("body");
	};
	
	// Fires when the page is first loaded synchronously:
	Application.prototype.onApplicationStart = function(){
		
		// Flag that the application is running:
		this.isRunning = true;
		//$("<p>onApplicationStart was fired!</p>").appendTo("body");

		// Set up local AJAX request events:
		$.ajaxSetup({
			cache: true,
			dataType: 'json',
			timeout: 60000,  //Timeout of 60 seconds.
			type: 'POST',
			url: '/?requesttype=ajax',  //Default url; can be overridden.
			beforeSend: function(){
				window.application.onRequestStart(); //Fire this custom event handler.
			},
			success: function(data){
				window.application.onRequestSuccess(data); //Fire this custom event handler.
			},
			error: function(xhr, status, error){
				window.application.onRequestError(xhr, status, error); //Fire this custom event handler.
			},
			complete: function(){
				window.application.onRequestEnd();  //Fire this custom event handler.
			}
		});
		
		// When closing or navigating away from the page, end the application:
		$(window).unload(function(){
			window.application.onApplicationEnd();
		});
		
		// Register the onSessionStart event:
		window.application.registerAjaxListener('onSessionStart','body','onSessionStart','');
		// Register the onSessionEnd event:
		window.application.registerAjaxListener('onSessionEnd','body','onSessionEnd','');

		// Get some needed scripts:
		$.getScript("/workspace/scripts/application/ui/jquery-ui.js");
		
	};
	
	// Create a new instance of the application and store it in the window:
	window.application = new Application();
	// When the DOM is ready, run the application.
	$(function(){
		window.application.onApplicationStart();
		// Return a new application instance:
	});
	return(window.application);
	
})(jQuery);
