An Evolution of Service tackles the Ajax History paradigmThe idea of an Ajax Service is a class instance that handles all interactions with remote requests(XHRs). Coupled through an observer pattern is the interface components that render the data into DOM elements. Ajax.HistoryServiceThe idea of the Ajax Service quickly lead to realization that if instead of dispatching this information per request, I could save it, then potentially have it available for dispatching that same request, thus bringing my interface back to that state. An HTML Microformat, HistoryElementI had looked into previous methods of the history paradigm and the problem most people were running into was that JS created objects had horrible problems, but an object created from HTML and the browser's native processing worked much better across the board. So instead of attempting to create objects inside the JS class I have used an HTML object which follows a microformat. The microformat being that it will contain at least two elements, one being an IFrame and the other being a Form. We will use these objects to mimic form submissions in the window without a top level reload. This action will register with the browser's history module as that is what we're going for to capture the back and forth buttons on our page, and how can we do that? By capturing the load event of the IFrame. Look Ma, No PollingInstead of polling the window.location like other history solutions. The HistoryService just listens to the iframe's load event, which occurs everytime the service registers a request, or when the user hits back and forward. So basically it only takes action when you'd expect, and doesn't slow already intense applications with polling intervals. Nuts and BoltsInstead of the service directly dispatching events upon receiving the data it stashes the data and the event type in an object and pushes it onto the historyArray that it stores as a property of the instance. Upon stashing it immediately submits the form which initiates a load event which will infact dispatch that event. The advantage of this is that the event architecture is completely reliant on the iframe's reloading, such that when the user clicks back it is dispatching previously registered requests, thus updating the information in each interface component. For a page dedicated to displaying all class extensions on top of prototype.js needed to get your own copy of Ajax.HistoryService working, check out the code base The DemoCurrent History Index :
A Grander DemonstrationI understand that the math demo doesn't entail all aspects of an application, I've set up a Google Map interface so you can progress into deeper, richer levels of state and see how the interface responds to the actions of back and forward. View Google Map demo The CodeThis code relies on the EventDispatcher class and Ajax.Application.Base to build the Ajax Service which is what the code below is built upon.
/**
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.Application.Event = function(){};
Object.extend(Object.extend(Ajax.Application.Event.prototype, Ajax.Application.Base.prototype), EventDispatcher.prototype);
Ajax.Service = {};
Ajax.Service.Base = function(){};
Ajax.Service.History = function(){};
Object.extend(Object.extend(Ajax.Service.Base.prototype, Ajax.Application.Event.prototype),
{
sendRequest : function(dto, cb){
this.dispatchEvent("request", { dto : dto, callback : cb });
Ajax.Application.Event.prototype.sendRequest.apply(this, [dto, cb]);
},
receiveRequest : function(cb, eAja){
this.dispatchEvent("response", eAja);
Ajax.Application.Event.prototype.receiveRequest.apply(this, [cb, eAja]);
}
}
);
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();
}
}
);
|
||||||||||||||
CommentsSeptember 12, 2007Casper This is great. Any chance this could somehow be used to tackle the Ajax bookmarking problem also? October 15, 2007the friendly ghost Sweet! Since you're not polling this even works on Opera 9.23. October 27, 2007Mr Friendly Yeah this code seems great, just need some help implementing it lol, if anyone can help me out let me know. Sent you an email with my email too hope u got 5-10 mins to spare cheers Mr Friendly. November 08, 2007Ehsun Hi, November 27, 2007Steve I'm not quite sure how to integrate this . January 12, 2008Yusuf Akyol Hi, May 29, 2008Rushiraj Yadav Would please send me some demo files how to implement the provided code. July 09, 2008Jimmy First of all, love your work! So thank you for sharing it with us. August 19, 2008John King I too like the looks of your script and would love a tutorial of how to implement it. I have been trying to work it out from this page .. but there seems to be something missing. September 18, 2008Driver indirme sitesi site haritası Thanks September 22, 2008joelkoe I would like some help implementing it too... I've got the code base, but I'm struggling... September 27, 2008Games Thanks October 20, 2008evden eve nakliyat Thank you very much for this information. I like this site. October 23, 2008evden eve nakliyat Thanks October 29, 2008figurin Thank you very much for this information. November 09, 2008laptop battery a good read. December 22, 2008Gazeteler Thank you very much for this information. January 03, 2009daran rajah I am trying integrate this code. January 05, 2009penis büyütücü than k you very much January 06, 2009Shop Thank you very much for this information. January 09, 2009SANANE izlesene video film January 09, 2009evden eve nakliyat great entry thanx January 12, 2009pornohttp://bgobiavi.info/porn-sex-seks-shop-adult.html thanx January 13, 2009izlesene18 izlesene video film January 15, 2009Cheese Lover I Like Cheese January 16, 2009airbag tamiri thanks January 17, 2009cem www.adultt.org |
||
This code is pretty genius, you're the only one who seems to have cracked the safari problem.
How does this degrade for a browser that does not support iFrames? Does it still load the new content, or will it fail at the iFrame step?