The Code Base

Here is a list of all classes needed to get you up to speed with the Ajax.Service.History. These classes require Prototype.js 1.5 or higher. If you have questions please leave a post in the comments at the bottom.

Ajax.Application.Base

/**
 * @contributor Matthew Foster
 * @date 		February 4th 2007
 * @purpose 	This class should be considered an "abstract" it is never intended to be a concrete class, notice there is no initialize function.
 *				This class is intended to be extended from, allowing an overwritable yet base functions for processing ajax requests.  The proposed advantage to this structure
 *				Is that during debugging all of your requests are being processed in the same area, thus allowing an easier target for reviewing ajax data.  As well as handling
 *				more of what I believe to be the monotoneous routines involved in sending ajax requests.
 */			
Ajax.Application = {}

Ajax.Application.Base = Class.create(); 
	
Object.extend(Ajax.Application.Base.prototype,
                {
                    
                    sendRequest : function(dto, cb){
                        var p = "";
                        
                        if(typeof dto == "object")
                            p = $H(dto).toQueryString();
                        else if(typeof dto == "string")
                            p = dto;
                        else
                            throw { message : "object sent to sendRequest was invalid type.  Type = " +typeof dto };
                            
                        
                        
                        new Ajax.Request(this.url,
                                            {
                                                parameters   : p,
                                                onComplete   : this.receiveRequest.bind(this, cb),
                                                onFailure    : this.ajaxFailure.bind(this),
                                                onException  : this.ajaxException.bind(this)
                                            }
                                        );                    
                    },
                    
                    receiveRequest : function(cb, eAja){
                        
                        cb(eAja);
                                
                    },
                    ajaxFailure : function(){
                        if(typeof console == "object")
                            console.log("Ajax Request failed args = %o ", arguments);
                        else
                            alert("Ajax request has failed. Application integrity has been compromised.");
                    },
                    ajaxException : function(){
                        
                        if(typeof console == "object")
                            console.log("ajax exception occured args = %o", arguments);
                        
                        
                    }
                
                
                }
    );            		
					

Ajax.Application.Cache

/**
 * @author Matthew Foster
 * @date   April 24th 2007
 * @purpose    This class is an extension of the base class with added functionality to allow for transparent caching.  The idea is to save the query string as a key in a hash object
 *             and if that query string has already been sent for it will already have an ajax response and it will simply pass that immediately to the call back function
 */
Object.extend(Object.extend(Ajax.Application.Cache.prototype, Ajax.Application.Base.prototype),
                    {
                        getCache : function(){
                            
                            if(!this.requestCache)
                                this.requestCache = {};
                            
                            return this.requestCache;
                        
                        },
                        setCache : function(obj){
                        
                            Object.extend(this.requestCache, obj || {});
                        
                        },
                        sendRequest : function(dto, cb){
                            
                            var cache = this.getCache();
                            
                            var key = this.compileDTO(dto);
                            
                            if(!cache[key]){
                                var cachedCallBack = this.registerCache.bind(this, cb, key);
                                Ajax.Application.Base.prototype.sendRequest.apply(this, [key, cachedCallBack]);
                            }
                            else
                                cb(cache[key]);
                        },
                        registerCache : function(cb, key, eAja){
                            var cache = {};
                            
                            cache[key] = eAja;
                            
                            this.setCache(cache);
                            
                            cb(eAja);
                            
                        }                
                    }
            );        
			

EventDispatcher

/**
 * @author 		Matthew Foster
 * @date		June 6th 2007
 * @purpose		To have a base class to extend subclasses from to inherit event dispatching functionality.
 * @procedure	Use a hash of event "types" that will contain an array of functions to execute.  The logic is if any function explicitally returns false the chain will halt execution.
 */
 var EventDispatcher = function(){};
     
     
     Object.extend(EventDispatcher.prototype,
                         {
                              
                              buildListenerChain : function(){
                                   
                                   if(!this.listenerChain)
                                        this.listenerChain = {};                                   
                              
                              },
                              addEventListener : function(type, listener){
                                   
                                   if(!listener instanceof Function)
                                        throw { message : "Listener isn't a function" };
                                   
                                   this.buildListenerChain();
                                   
                                   
                                   
                                   if(!this.listenerChain[type])                         
                                        this.listenerChain[type] = [listener];
                                   else
                                        this.listenerChain[type].push(listener);
                                   
                              },
                              hasEventListener : function(type){
                                   
                                   return (typeof this.listenerChain[type] != "undefined");
                              
                              },
                              removeEventListener : function(type, listener){
                                   if(!this.hasEventListener(type))
                                        return false;
                                        
                                   for(var i = 0; i < this.listenerChain[type].length; i++)
                                        if(this.listenerChain[type][i] == listener)
                                             this.listenerChain.splice(i, 1);
                              
                              },
                              dispatchEvent : function(type, args){
                                   this.buildListenerChain();
                                   
                                   if(!this.hasEventListener(type))
                                        return false;
                                        
                                   this.listenerChain[type].any(function(f){ return (f(args) == false ? true : false); });
                              
                              }
                         }
                         
                    );

Ajax.Application.Event

/**
 * @author Matthew Foster
 * @purpose To provide a class that merges Ajax.Application.Base and EventDispatcher functions.
 */
 
Ajax.Application.Event = function(){};

Object.extend(Object.extend(Ajax.Application.Event.prototype, Ajax.Application.Base.prototype), EventDispatcher.prototype);

Ajax.Service.Base

/**
 * @author Matthew Foster
 * @purpose To provide a base class for the Ajax.Service package, as of now it is simply mirror Ajax.Application.Event but reserved the namespace for future improvements.
 */
	Ajax.Service = {};
	Ajax.Service.Base = Ajax.Application.Event;

Ajax.Service.History

				/**

Copyright (c) 2007 Matthew E. Foster

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE 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.

Ajax.Service.History = Class.create();

Object.extend(Object.extend(Ajax.Service.History.prototype, Ajax.Service.Base.prototype),    

                            buildInterface : function(obj){
                                
                                this.historyArr = [];
                                this.historyIndex = undefined;
                                
                                
                                this.container = $(obj);
                                this.historyFrame = this.container.down("iframe");
                                this.form = this.container.down("form");
                            
                            },
                            attachListener : function(){
                            
                                Event.observe(this.historyFrame, "load", this.reloadHandle);
                            
                            },
                            createListener : function(){
                                                                
                                this.reloadHandle = this.handleReload.bindAsEventListener(this);
                            
                            },
                            handleReload : function(e){
                                            
                                var index = parseInt(this.getHistoryIndex());
                                
                                var obj = this.historyArr[index];
                                
                                if(!obj)
                                    return true;
                                
                                this.historyIndex = index+1;
                                
                                this.dispatchEvent("reload", [obj, index]);
                                this.dispatchEvent(obj.type, obj.arg);
                                
                            
                            },
                            
                            getHistoryIndex : function(){
                                
                                return this.getIndex(this.historyFrame.contentWindow.location.toString());
                                
                            },
                            getIndex : function(str){
                                
                                return str.replace(/.*index=/gi, "");
                            
                            },
                            getQuery : function(str){
                                
                                return str.replace(/[^?]+?/gi, "");
                            
                            },
                            
                            registerRequest : function(type, eAja){
                            
                                if(this.historyIndex && this.historyIndex < this.historyArr.length)
                                    this.historyArr.length = this.historyIndex;
                                    
                                this.form.index.value = this.historyArr.length;    
                                
                                this.historyArr.push({ type : type, arg : eAja});
                                                                
                                this.form.submit();
                            
                            }
                    );

Comments are Disabled.