More awesome free code! May 29, 2008
I just have to ask that you send $5 to me via email. Thanks.
It turns out that I needed a way to raise events in my pager from the last post. Like when the page changed, I wanted to display "Page 3 of 5 (9 elements)" (for my test size of 2 elements per page (not likely to happen)). But also, for future reference, if say, to save on load times, only load X pages, we'll call it 5, at a time, so 10 elements, so then when they got to page 4 or 5, the non-pager code can load 10 more elements asynchronously, and call refresh on the pager to update the page count etc. Here's the event object:
var EventList = new Array();
function Event(obj, type){
if (EventList[type]) return;
EventList[type] = true;
this.handlers = new Array();
this.type = type;
this.obj = obj;
this.obj._event = new Array();
this.obj._event[type] = this;
if (typeof(this.obj.addCustomEvent) != "function"){
this.obj.addCustomEvent = function(type, fn){
if (typeof(fn) == "function"){
this._event[type].handlers.push(fn);
return true;
}
return false;
}
}
this.raise = function(sender, args){
for(var i = 0; i < this.handlers.length; i++){
this.handlers[i](sender, args);
}
}
}
// addEvent(obj, "event", func);
function addEvent(obj, evType, fn, useCapture){
if (EventList[evType] && obj.addCustomEvent){
var r = obj.addCustomEvent(evType, fn);
return r;
}
else if (obj.addEventListener){
obj.addEventListener(evType, fn, useCapture);
return true;
} else if (obj.attachEvent){
var r = obj.attachEvent("on"+evType, fn);
return r;
} else {
alert("Handler could not be attached");
}
}
Yup, it only handles on event per object right now. That's easily remedied if I use something other than "obj._event". Like this.obj._event = new Array(); this.obj._event[type] = this;
. Will do that soon. UPDATE: Fixed that, and used the EventList array to keep track of custom events, and modified the addEvent function to use that and see if it's a custom event first. This way, if I add custom events to a "div" html element, it will work, whereas before it would have evaluated one of the other ones (attachEvent or addEventListener) before it would have added the event where I wanted it. UPDATE 2: Damn, that still has a shortcoming. To be fixed later, like Tuesday. I'm booked this weekend. If you can point out the shortcoming, I'll give YOU $5 :P A hint would be that you don't have to worry about "click" events, only custom events... but damn near everything has a "click" event.
Notice that I modified the "addEvent" function that I shamelessly stole from QuirksMode.org to check if the object that we're adding the event to has an "addCustomEvent" function on it. If it does, call it, which is added to the object when it creates a new event. This is how the pager uses it:function Pager(){
this.init = function(divid){
...
this.textspan = null;
this.onPageChanged = new Event(this, "pageChanged");
addEvent(this, "pageChanged", this.internalOnPageChanged);
this.initialized = true;
}
...
this.pageChanged = function(pageNumber){
// change page functionality here...
this.onPageChanged.raise(this, { page : this.currentPage, pages: this.pageCount, total: this.elementCount});
}
...
this.internalOnPageChanged = function(pager, args){
if (pager.textspan){
clearChildren(pager.textspan);
pager.textspan.appendChild(document.createTextNode("Page " + (args.page+1) + " of " + args.pages + " (" + args.total + " elements)"));
}
}
I removed unnecessary code but you get the idea. As always, I found code online to do it, but it was too complicated (KISS = Keep it simple stupid). If I have to add to it I will but it doesn't have to solve all of my problems right now. In my html page that is apart from the pager, I add another handler for "pageChanged" to just test it out. Integrating it seamlessly with the "addEvent" function is crucial, so now I just use the same exact syntax for every event, whether it's custom or not. So this works perfectly: addEvent(window, "load", loaded);
var pager = new Pager();
function loaded(){
pager.init("pager");
addEvent(pager, "pageChanged", pagerPageChanged);
loadNotes();
}
function pagerPageChanged(p, args){
var i = args.page;
//alert("page changed : " + args.page + " of " + args.pages + " pages, " + args.total + " elements in all");
}
That's from "index.html" because I don't need any kind of server side scripting language with my new Ajax framework. And it's loading data, saving data, deleting data, even will begin to authenticate users soon, on the server. This keeps the custom code on the server down to 0 lines. Yup, no lines of Java pertaining to a "Notes" application (basic and without user authentication or authorization). I like writing Java but this will make things quicker :) When I incorporate YUI! into it, it'll even be beautiful. Ahh, until that day.