/**
 * @author Bodi Zsolt <bodi.zsolt@gmail.com>
 * @version 1.7
 */ 
var MWW = {
	'namespace' : function(name){
		if(!!MWW[name]){
			return MWW[name];
		}
		MWW[name] = {};	
		return MWW[name];
	},	
	'map' : function (a,f){
				var n=[],v;				
				for(var i=0;i<a.length;i++){
					 v = f(a[i]);
					if(v!==null){
						n.push(v);
					}
				}
				return n;
	},
	nodeWalk: function (node, visitor) {
        var nodes = [node];
        var extend = MochiKit.Base.extend;
        while (nodes.length) {
            var res = visitor(nodes.shift());
            if (res) {
                extend(nodes, res);
            }
        }
    },
	 concat: function (/* lst... */) {
        var rval = [];
        var extend = MWW.extend;
        for (var i = 0; i < arguments.length; i++) {
            extend(rval, arguments[i]);
        }
        return rval;
    },
	 'filter': function (fn, lst, self) {
        var rval = [];
        // allow an iterable to be passed
        var m = MWW;
        if (!m.isArrayLike(lst)) {
                throw new TypeError("Argument not an array-like");
        }
        if (fn === null) {
            fn = m.operator.truth;
        }
        if (typeof(Array.prototype.filter) == 'function') {
            // Mozilla fast-path
            return Array.prototype.filter.call(lst, fn, self);
        } else if (typeof(self) == 'undefined' || self === null) {
            for (var i = 0; i < lst.length; i++) {
                var o = lst[i];
                if (fn(o)) {
                    rval.push(o);
                }
            }
        } else {
            for (i = 0; i < lst.length; i++) {
                o = lst[i];
                if (fn.call(self, o)) {
                    rval.push(o);
                }
            }
        }
        return rval;
    },
	'update' : function (self, obj/*, ... */) {
	    if (self === null || self === undefined) {
	        self = {};
	    }
	    for (var i = 1; i < arguments.length; i++) {
	        var o = arguments[i];
	        if (typeof(o) != 'undefined' && o !== null) {
	            for (var k in o) {
	                self[k] = o[k];
	            }
	        }
	    }
	    return self;
	},
	'_wrapDumbFunction': function (func) {
        return function () {
            // fast path!
            switch (arguments.length) {
                case 0: return func();
                case 1: return func(arguments[0]);
                case 2: return func(arguments[0], arguments[1]);
                case 3: return func(arguments[0], arguments[1], arguments[2]);
            }
            var args = [];
            for (var i = 0; i < arguments.length; i++) {
                args.push("arguments[" + i + "]");
            }
            return eval("(func(" + args.join(",") + "))");
        };
    },
	 'bind': function (func, self/* args... */) {
        if (typeof(func) == "string") {
            func = self[func];
        }
        var im_func = func.im_func;
        var im_preargs = func.im_preargs;
        var im_self = func.im_self;
        var m = MWW;
        if (typeof(func) == "function" && typeof(func.apply) == "undefined") {
            // this is for cases where JavaScript sucks ass and gives you a
            // really dumb built-in function like alert() that doesn't have
            // an apply
            func = m._wrapDumbFunction(func);
        }
        if (typeof(im_func) != 'function') {
            im_func = func;
        }
        if (typeof(self) != 'undefined') {
            im_self = self;
        }
        if (typeof(im_preargs) == 'undefined') {
            im_preargs = [];
        } else  {
            im_preargs = im_preargs.slice();
        }
        m.extend(im_preargs, arguments, 2);
        var newfunc = function () {
            var args = arguments;
            var me = arguments.callee;
            if (me.im_preargs.length > 0) {
                args = m.concat(me.im_preargs, args);
            }
            var self = me.im_self;
            if (!self) {
                self = this;
            }
            return me.im_func.apply(self, args);
        };
        newfunc.im_self = im_self;
        newfunc.im_func = im_func;
        newfunc.im_preargs = im_preargs;
        return newfunc;
    },
	'bindMethods': function (self) {
        var bind = MWW.bind;
        for (var k in self) {
            var func = self[k];
            if (typeof(func) == 'function') {
                self[k] = bind(func, self);
            }
        }
    },
	'flattenArguments': function (lst/* ...*/) {
        var res = [];
        var m = MWW;
        var args = m.extend(null, arguments);
        while (args.length) {
            var o = args.shift();
            if (o && typeof(o) == "object" && typeof(o.length) == "number") {
                for (var i = o.length - 1; i >= 0; i--) {
                    args.unshift(o[i]);
                }
            } else {
                res.push(o);
            }
        }
        return res;
    },    
	'isArrayLike': function () {
        for (var i = 0; i < arguments.length; i++) {
            var o = arguments[i];
            var typ = typeof(o);
            if (
                (typ != 'object' && !(typ == 'function' && typeof(o.item) == 'function')) || o === null ||
                typeof(o.length) != 'number' ||
                o.nodeType === 3 ||
                o.nodeType === 4
            ) {
                return false;
            }
        }
        return true;
    },
    'extend': function (self, obj, /* optional */skip) {
        // Extend an array with an array-like object starting
        // from the skip index
        if (!skip) {
            skip = 0;
        }
        if (obj) {
            // allow iterable fall-through, but skip the full isArrayLike
            // check for speed, this is called often.
            var l = obj.length;
            if (typeof(l) != 'number' /* !isArrayLike(obj) */) {
                  throw new TypeError("Argument not an array-like");                
            }
            if (!self) {
                self = [];
            }
            for (var i = skip; i < l; i++) {
                self.push(obj[i]);
            }
        }
        // This mutates, but it's convenient to return because
        // it's often used like a constructor when turning some
        // ghetto array-like to a real array
        return self;
    },
	'findIdentical': function (lst, value, start/* = 0 */, /* optional */end) {
        if (typeof(end) == "undefined" || end === null) {
            end = lst.length;
        }
        if (typeof(start) == "undefined" || start === null) {
            start = 0;
        }
        for (var i = start; i < end; i++) {
            if (lst[i] === value) {
                return i;
            }
        }
        return -1;
    },
	items: function (obj) {
        var rval = [];
        var e;
        for (var prop in obj) {
            var v;
            try {
                v = obj[prop];
            } catch (e) {
                continue;
            }
            rval.push([prop, v]);
        }
        return rval;
    }
};
MWW.namespace('dom'); 
MWW.dom.NAME = 'MWW.dom';
MWW.dom.VERSION = '2.0';
MWW.update(MWW.dom,{	
	'toString' : function(){
		return MWW.dom.NAME + ' '+ MWW.dom.VERSION;	
	},
	'getById' : function(){
		 		var elements = [],el;
			  for (var i = 0; i < arguments.length; i++) {
			    el = arguments[i];
			    if(typeof(el) === 'string'){
			      el = document.getElementById(el);
				}
			    if(arguments.length == 1){
			      return el;
				}
			    elements.push(el);
			  }			
			  return elements;		
	},	
	'getElementsByTagAndClassName': function (tagName, className,/* optional */parent) {
        var self = MWW.dom;
        if (typeof(tagName) == 'undefined' || tagName === null) {
            tagName = '*';
        }
        if (typeof(parent) == 'undefined' || parent === null) {
            parent = self._document;
        }
        parent = self.getById(parent);
        var children = (parent.getElementsByTagName(tagName)
            || self._document.all);
        if (typeof(className) == 'undefined' || className === null) {
            return MWW.extend(null, children);
        }

        var elements = [];
        for (var i = 0; i < children.length; i++) {
            var child = children[i];
            var cls = child.className;
            if (!cls) {
                continue;
            }
            var classNames = cls.split(' ');
            for (var j = 0; j < classNames.length; j++) {
                if (classNames[j] == className) {
                    elements.push(child);
                    break;
                }
            }
        }

        return elements;
    },
	'getElementsByClassName' : function(className,parent){
		if(!!document.evaluate){
			var q = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]";
			return MWW.dom._getElementsByXPath(q, parent);
		}else{
			var children = (MWW.dom.getById(parent) || MWW.dom._document).getElementsByTagName('*');
			var elements = [],child;
			for(var i=0, length = children.length;i< length;i++){
				child = children[i];
				if(MWW.dom.hasClass(child,className)){
					elements[elements.length] = child;
				}
			}
			return elements;
		}
	},
	'_getElementsByXPath' : function(expression, parentElement){
					var results = [];
					var query = document.evaluate(expression,MWW.dom.getById(parentElement) || document,null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
					for(var i = 0, length = query.snapshotLength;i < length; i++){
						results[results.length] = query.snapshotItem(i);
					}
					return results;
	},	
	'create' : function(data) {
				var el;
				if (typeof(data) == 'string') {
					el = document.createTextNode(data);
				} else {
					//create the element
					el=document.createElement(data.tag);
					delete(data.tag);			
					//append the children
					if (typeof(data.children) != 'undefined'){
						if (typeof(data.children)== 'string' || typeof(data.children.length)=='undefined'){
							//strings and single elements
							el.appendChild(MWW.dom.create(data.children));
						} else {
							//arrays of elements
							for (var i=0, child=null; typeof(child=data.children[i]) != 'undefined'; i++) {
								el.appendChild(MWW.dom.create(child));
							}
						}
						delete(data.children);
					}
					//any other data is attributes
					for (var attr in data) {
						if(attr == 'class'){
							 if (MWW.dom.attributeArray.compliant) {
								el.setAttribute("class", data[attr]);
							} else {
								el.setAttribute("className", data[attr]);
							}						
						}else{
							el.setAttribute(attr,data[attr]);	
						}
					}
				}
				return el;
	},
	'getFirstParentByTagAndClassName': function (elem, tagName, className) {
        var self = MWW.dom;
        elem = self.getById(elem);
        if (typeof(tagName) == 'undefined' || tagName === null) {
            tagName = '*';
        } else {
            tagName = tagName.toUpperCase();
        }
        if (typeof(className) == 'undefined' || className === null) {
            className = null;
        }

        var classList = '';
        var curTagName = '';
        while (elem && elem.tagName) {
            elem = elem.parentNode;
            if (tagName == '*' && className === null) {
                return elem;
            }
            classList = elem.className.split(' ');
            curTagName = elem.tagName.toUpperCase();
            if (className === null && tagName == curTagName) {
                return elem;
            } else if (className !== null) {
                for (var i = 0; i < classList.length; i++) {
                    if (tagName == '*' && classList[i] == className) {
                        return elem;
                    } else if (tagName == curTagName && classList[i] == className) {
                        return elem;
                    }
                }
            }
        }
        return elem;
		},		
	'showElement': function(el){
					if(typeof(el)=="string"){
						el = MWW.dom.getById(el);	
					}
					MWW.dom.toggleClass('hide',el);
				},
	'hideElement': function(el){
					if(typeof(el)=="string"){
						el = MWW.dom.getById(el);	
					}
					MWW.dom.toggleClass('hide',el);
				},
	'nextSibling' : function(el){
					if(typeof(el)=='string'){
						el = MWW.dom.getById(el);	
					}
					while(el.nextSibling.nodeType!=1){
						el = el.nextSibling;
					}
					return el.nextSibling;
				},
	'prevSibling' : function(el){
					if(typeof(el)=='string'){
						el = MWW.dom.getById(el);	
					}
					while(el.previousSibling.nodeType!=1){
						el = el.previousSibling;
					}
					return el.previousSibling;					
				},
	'firstChild' : function(el){
					if(typeof(el)=='string'){
						el = MWW.dom.getById(el);	
					}
					el = el.firstChild;
					return MWW.dom.nextSibling(el);
				},
	'lastChild' : function(el){
					if(typeof(el)=='string'){
						el = MWW.dom.getById(el);	
					}
					el = el.lastChild;
					return MWW.dom.prevSibling(el);
				},
	'isChildNode': function (node, maybeparent) {
        var self = MWW.dom;
        if (typeof(node) == "string") {
            node = self.getById(node);
        }
        if (typeof(maybeparent) == "string") {
            maybeparent = self.getElement(maybeparent);
        }
        if (typeof(node) == 'undefined' || node === null || node === self._document) {
            return false;
        }
        do {
            if (node === maybeparent) {
                return true;
            }
            var tagName = node.tagName;
            node = node.parentNode;
            if (!tagName) {
                break;
            }
            tagName = tagName.toUpperCase();
        } while (tagName != "BODY" && tagName != "HTML");
        return false;
    },
 	'setClass': function (element, className) {
        var self = MWW.dom;
        var obj = self.getById(element);
        if (self.attributeArray.compliant) {
            obj.setAttribute("class", className);
        } else {
            obj.setAttribute("className", className);
        }
    },    
    'toggleClass': function (className/*, element... */) {
        var self = MWW.dom;
        for (var i = 1; i < arguments.length; i++) {
            var obj = self.getById(arguments[i]);
            if (!self.addClass(obj, className)) {
                self.removeClass(obj, className);
            }
        }
    },
    'addClass': function (element, className) {
        var self = MWW.dom;
        var obj = self.getById(element);
        var cls = obj.className;
        // trivial case, no className yet
        if (cls == undefined || cls.length === 0) {
            self.setClass(obj, className);
            return true;
        }
        // the other trivial case, already set as the only class
        if (cls == className) {
            return false;
        }
        var classes = cls.split(" ");
        for (var i = 0; i < classes.length; i++) {
            // already present
            if (classes[i] == className) {
                return false;
            }
        }
        // append class
        self.setClass(obj, cls + " " + className);
        return true;
    },    
    'removeClass': function (element, className) {
        var self = MWW.dom;
        var obj = self.getById(element);
        var cls = obj.className;        
        if (cls == undefined || cls.length === 0) {
            return false;
        }
        // other trivial case, set only to className
        if (cls == className) {
            self.setClass(obj, "");
            return true;
        }
        var classes = cls.split(" ");
        for (var i = 0; i < classes.length; i++) {
            // already present
            if (classes[i] == className) {
                // only check sane case where the class is used once
                classes.splice(i, 1);
                self.setClass(obj, classes.join(" "));
                return true;
            }
        }
        // not found
        return false;
    },
    'swapClass': function (element, fromClass, toClass) {
        var obj = MWW.dom.getById(element);
        var res = MWW.dom.removeClass(obj, fromClass);
        if (res) {
            MWW.dom.addClass(obj, toClass);
        }
        return res;
    },    
    'hasClass': function (element, className/*...*/) {
        var obj = MWW.dom.getById(element);
        var cls = obj.className;
        if (!cls) {
            return false;
        }
        var classes = cls.split(" ");
        for (var i = 1; i < arguments.length; i++) {
            var good = false;
            for (var j = 0; j < classes.length; j++) {
                if (classes[j] == arguments[i]) {
                    good = true;
                    break;
                }
            }
            if (!good) {
                return false;
            }
        }
        return true;
    },
	'onAvailable': function(id,callback){
		if(this == MWW.dom){
			return new MWW.dom.onAvailable(id,callback);
		}
		var stack = [], interval, loaded, ident;
		var doPoll = function() {
		  var notFound = [];
		  for (var i=0; i<stack.length; i++){
			if (MWW.dom.getById(stack[i].id)){
		      stack[i].callback();
		    }else{
		      notFound.push(stack[i]);
		    }
		  }
		  stack = notFound;
		  if (notFound.length < 1 || loaded) {
		    stopPolling();
		  }
		};
		var startPolling = function() {
		  if(interval){return;}
		  interval = setInterval(doPoll, 10);
		};
		var stopPolling = function() {
		  if (!interval) {return;}
		  clearInterval(interval);
		  interval = null;
		  stack = [];
		};
	    stack[stack.length] = {'id': id,'callback':callback};
		startPolling();
		if(!!!ident){
	    	ident = MWW.signal.connect(window,'onload',MWW.bind(function(){loaded = true;ident = null;doPoll();},this));
		}
	},
	'onContentAvailable':function(id,callback){
		if(this == MWW.dom){
			return new MWW.dom.onContentAvailable(id,callback);
		}
		var stack = [], interval, loaded,ident;		
		var hasNextSibling = function(el){
			return el.nextSibling || (el.parentNode && hasNextSibling(el.parentNode));			
		};
		var doPoll = function(){
			var notFound = [];
			for(var i =0,len = stack.length;i<len;i++){
				var el = MWW.dom.getById(stack[i].id);
				if(el && hasNextSibling(el) || loaded){
					stack[i].callback();
				}else{
					notFound[notFound.length] = stack[i];
				}
			}
			stack = notFound;
			if(notFound.length < 1 || loaded){
				stopPolling();
			}
		};
		var startPolling = function() {
		  if(interval){return;}
		  interval = setInterval(doPoll, 10);
		};
		var stopPolling = function() {
		  if (!interval) {return;}
		  clearInterval(interval);
		  interval = null;
		};
		var lastPoll = function() {
		  if (loaded) {return;}
		  loaded = true;
		  doPoll();
		};
	    stack[stack.length] = {'id': id,'callback':callback};
		startPolling();
		if(!!!ident){
	    	ident = MWW.signal.connect(window,'onload',MWW.bind(function(){loaded = true;ident = null;lastPoll();},this));
		}		
	},
   'discardElement': function(element) {
	    var garbageBin = MWW.dom.getById('IELeakGarbageBin');
	    if (!garbageBin) {
	        garbageBin = MWW.dom.create({'tag':'DIV'});
	        garbageBin.id = 'IELeakGarbageBin';
	        garbageBin.style.display = 'none';
	        document.body.appendChild(garbageBin);
	    }
	    // move the element to the garbage bin
	    garbageBin.appendChild(element);
	    garbageBin.innerHTML = '';
		garbageBin = null;
	},
	 formContents: function (elem/* = document.body */) {
        var names = [];
        var values = [];
        var m = MWW;
        var self = MWW.dom;
        if (typeof(elem) == "undefined" || elem === null) {
            elem = self._document.body;
        } else {
            elem = self.getById(elem);
        }
        m.nodeWalk(elem, function (elem) {
            var name = elem.name;
            if (MWW.lang.isNotEmpty(name)) {
                var tagName = elem.tagName.toUpperCase();
                if (tagName === "INPUT"
                    && (elem.type == "radio" || elem.type == "checkbox")
                    && !elem.checked
                ) {
                    return null;
                }
                if (tagName === "SELECT") {
                    if (elem.type == "select-one") {
                        if (elem.selectedIndex >= 0) {
                            var opt = elem.options[elem.selectedIndex];
                            var v = opt.value;
                            if (!v) {
                                var h = opt.outerHTML;
                                // internet explorer sure does suck.
                                if (h && !h.match(/^[^>]+\svalue\s*=/i)) {
                                    v = opt.text;
                                }
                            }
                            names.push(name);
                            values.push(v);
                            return null;
                        }
                        // no form elements?
                        names.push(name);
                        values.push("");
                        return null;
                    } else {
                        var opts = elem.options;
                        if (!opts.length) {
                            names.push(name);
                            values.push("");
                            return null;
                        }
                        for (var i = 0; i < opts.length; i++) {
                            var opt = opts[i];
                            if (!opt.selected) {
                                continue;
                            }
                            var v = opt.value;
                            if (!v) {
                                var h = opt.outerHTML;
                                // internet explorer sure does suck.
                                if (h && !h.match(/^[^>]+\svalue\s*=/i)) {
                                    v = opt.text;
                                }
                            }
                            names.push(name);
                            values.push(v);
                        }
                        return null;
                    }
                }
                if (tagName === "FORM" || tagName === "P" || tagName === "SPAN"
                    || tagName === "DIV"
                ) {
                    return elem.childNodes;
                }
                names.push(name);
                values.push(elem.value || '');
                return null;
            }
            return elem.childNodes;
        });
        return [names, values];
    },
	queryString: function (names, values){
        if(arguments.length == 1 && (MWW.lang.isString(names) || (
                !MWW.lang.isUndefined(names.nodeType) && names.nodeType > 0
            ))
        ) {
            var kv = MWW.dom.formContents(names);
            names = kv[0];
            values = kv[1];
        } else if (arguments.length == 1) {
            // Allow the return value of formContents to be passed directly
            if (MWW.lang.isNumber(name.length) && names.length == 2) {
                return arguments.callee(names[0], names[1]);
            }
            var o = names;
            names = [];
            values = [];
            for (var k in o) {
                var v = o[k];
                if (typeof(v) == "function") {
                    continue;
                } else if (MWW.isArrayLike(v)){
                    for (var i = 0; i < v.length; i++) {
                        names.push(k);
                        values.push(v[i]);
                    }
                } else {
                    names.push(k);
                    values.push(v);
                }
            }
        }
        var rval = [];
		if(MWW.lang.isString(names) && MWW.lang.isString(values)){
	        var urlEncode = MWW.dom._urlEncode;
            if (typeof(values) != 'undefined' && values !== null){
                rval.push(urlEncode(names) + "=" + urlEncode(values));
            }	        			
		}else{
	        var len = Math.min(names.length, values.length);
	        var urlEncode = MWW.dom._urlEncode;
	        for (var i = 0; i < len; i++) {
	            v = values[i];
	            if (typeof(v) != 'undefined' && v !== null) {
	                rval.push(urlEncode(names[i]) + "=" + urlEncode(v));
	            }
	        }
		}
        return rval.join("&");
    },
	_urlEncode : function(unencoded){
		if (typeof(encodeURIComponent) != "undefined") {      
            return encodeURIComponent(unencoded).replace(/\'/g, '%27');
        }else{
	        return escape(unencoded).replace(/\+/g, '%2B').replace(/\"/g,'%22').rval.replace(/\'/g, '%27');       
    	}
	},
	'__new__': function (win) {

        var m = MWW;
        if (typeof(document) != "undefined") {
            this._document = document;
            var kXULNSURI = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
            this._xhtml = (document.documentElement && document.createElementNS && document.documentElement.namespaceURI === kXULNSURI);
        }
        this._window = win;
        var __tmpElement = this._document.createElement("span");
        var attributeArray;
        if (__tmpElement && __tmpElement.attributes && __tmpElement.attributes.length > 0) {
            // for braindead browsers (IE) that insert extra junk
            var filter = m.filter;
            attributeArray = function (node) {
                return filter(attributeArray.ignoreAttrFilter, node.attributes);
            };
            attributeArray.ignoreAttr = {};
            var attrs = __tmpElement.attributes;
            var ignoreAttr = attributeArray.ignoreAttr;
            for (var i = 0; i < attrs.length; i++) {
                var a = attrs[i];
                ignoreAttr[a.name] = a.value;
            }
            attributeArray.ignoreAttrFilter = function (a) {
                return (attributeArray.ignoreAttr[a.name] != a.value);
            };
            attributeArray.compliant = false;
            attributeArray.renames = {
                "class": "className",
                "checked": "defaultChecked",
                "usemap": "useMap",
                "for": "htmlFor",
                "readonly": "readOnly",
                "colspan": "colSpan",
                "bgcolor": "bgColor",
                "cellspacing": "cellSpacing",
                "cellpadding": "cellPadding"
            };
        } else {
            attributeArray = function (node) {
                return node.attributes;
            };
            attributeArray.compliant = true;
            attributeArray.renames = {};
        }
        this.attributeArray = attributeArray;
	}
});	
MWW.dom.__new__(((typeof(window) == "undefined") ? this : window));

MWW.namespace('signal');
MWW.signal.NAME = 'MWW.signal';
MWW.signal.version = '1.8';
MWW.signal._observers = [];
MWW.signal.Event = function (src, e) {
    this._event = e || window.event;
    this._src = src;
};
MWW.update(MWW.signal.Event.prototype ,{
	 'src' : function () {
    	return this._src;
    },
	'event': function () {
        return this._event;
    },		
	'type': function () {
        return this._event.type || undefined;
    },
	 'target': function () {
        return this._event.target || this._event.srcElement;
    },
	'relatedTarget': function () {
        if (this._relatedTarget !== null) {
            return this._relatedTarget;
        }

        var elem = null;
        if (this.type() == 'mouseover') {
            elem = (this._event.relatedTarget ||
                this._event.fromElement);
        } else if (this.type() == 'mouseout') {
            elem = (this._event.relatedTarget ||
                this._event.toElement);
        }
        if (elem !== null) {
            this._relatedTarget = elem;
            return elem;
        }

        return undefined;
    },
	'modifier': function () {
        if (this._modifier !== null) {
            return this._modifier;
        }
        var m = {};
        m.alt = this._event.altKey;
        m.ctrl = this._event.ctrlKey;
        m.meta = this._event.metaKey || false; // IE and Opera punt here
        m.shift = this._event.shiftKey;
        m.any = m.alt || m.ctrl || m.shift || m.meta;
        this._modifier = m;
        return m;
    },
	 'key': function () {
        if (this._key !== null) {
            return this._key;
        }
        var k = {};
        if (this.type() && this.type().indexOf('key') === 0) {
            /* look for special keys here */
            if (this.type() == 'keydown' || this.type() == 'keyup') {
                k.code = this._event.keyCode;
                k.string = (MWW.signal._specialKeys[k.code] ||
                    'KEY_UNKNOWN');
                this._key = k;
                return k;

            /* look for characters here */
            } else if (this.type() == 'keypress') {

                k.code = 0;
                k.string = '';

                if (typeof(this._event.charCode) != 'undefined' &&
                    this._event.charCode !== 0 &&
                    !MWW.signal._specialMacKeys[this._event.charCode]) {
                    k.code = this._event.charCode;
                    k.string = String.fromCharCode(k.code);
                } else if (this._event.keyCode &&
                    typeof(this._event.charCode) == 'undefined') { // IE
                    k.code = this._event.keyCode;
                    k.string = String.fromCharCode(k.code);
                }

                this._key = k;
                return k;
            }
        }
        return undefined;
    },
	'stop': function () {
        this.stopPropagation();
        this.preventDefault();
    },
	 'stopPropagation': function () {
        if (this._event.stopPropagation) {
            this._event.stopPropagation();
        } else {
            this._event.cancelBubble = true;
        }
    },
	 'preventDefault': function () {
        if (this._event.preventDefault) {
            this._event.preventDefault();
        } else if (this._confirmUnload === null) {
            this._event.returnValue = false;
        }
   },
    '_confirmUnload': null,
	'confirmUnload': function (msg) {
        if (this.type() == 'beforeunload') {
            this._confirmUnload = msg;
            this._event.returnValue = msg;
        }
    }	
});
MWW.signal._specialMacKeys = {
    3: 'KEY_ENTER',
    63289: 'KEY_NUM_PAD_CLEAR',
    63276: 'KEY_PAGE_UP',
    63277: 'KEY_PAGE_DOWN',
    63275: 'KEY_END',
    63273: 'KEY_HOME',
    63234: 'KEY_ARROW_LEFT',
    63232: 'KEY_ARROW_UP',
    63235: 'KEY_ARROW_RIGHT',
    63233: 'KEY_ARROW_DOWN',
    63302: 'KEY_INSERT',
    63272: 'KEY_DELETE'
};

/* for KEY_F1 - KEY_F12 */
(function () {
    var _specialMacKeys = MWW.signal._specialMacKeys;
    for (var i = 63236; i <= 63242; i++) {
        // no F0
        _specialMacKeys[i] = 'KEY_F' + (i - 63236 + 1);
    }
})();
MWW.signal._specialKeys = {
    8: 'KEY_BACKSPACE',
    9: 'KEY_TAB',
    12: 'KEY_NUM_PAD_CLEAR', // weird, for Safari and Mac FF only
    13: 'KEY_ENTER',
    16: 'KEY_SHIFT',
    17: 'KEY_CTRL',
    18: 'KEY_ALT',
    19: 'KEY_PAUSE',
    20: 'KEY_CAPS_LOCK',
    27: 'KEY_ESCAPE',
    32: 'KEY_SPACEBAR',
    33: 'KEY_PAGE_UP',
    34: 'KEY_PAGE_DOWN',
    35: 'KEY_END',
    36: 'KEY_HOME',
    37: 'KEY_ARROW_LEFT',
    38: 'KEY_ARROW_UP',
    39: 'KEY_ARROW_RIGHT',
    40: 'KEY_ARROW_DOWN',
    44: 'KEY_PRINT_SCREEN',
    45: 'KEY_INSERT',
    46: 'KEY_DELETE',
    59: 'KEY_SEMICOLON', // weird, for Safari and IE only
    91: 'KEY_WINDOWS_LEFT',
    92: 'KEY_WINDOWS_RIGHT',
    93: 'KEY_SELECT',
    106: 'KEY_NUM_PAD_ASTERISK',
    107: 'KEY_NUM_PAD_PLUS_SIGN',
    109: 'KEY_NUM_PAD_HYPHEN-MINUS',
    110: 'KEY_NUM_PAD_FULL_STOP',
    111: 'KEY_NUM_PAD_SOLIDUS',
    144: 'KEY_NUM_LOCK',
    145: 'KEY_SCROLL_LOCK',
    186: 'KEY_SEMICOLON',
    187: 'KEY_EQUALS_SIGN',
    188: 'KEY_COMMA',
    189: 'KEY_HYPHEN-MINUS',
    190: 'KEY_FULL_STOP',
    191: 'KEY_SOLIDUS',
    192: 'KEY_GRAVE_ACCENT',
    219: 'KEY_LEFT_SQUARE_BRACKET',
    220: 'KEY_REVERSE_SOLIDUS',
    221: 'KEY_RIGHT_SQUARE_BRACKET',
    222: 'KEY_APOSTROPHE'
    // undefined: 'KEY_UNKNOWN'
};
(function () {
    /* for KEY_0 - KEY_9 */
    var _specialKeys = MWW.signal._specialKeys;
    for (var i = 48; i <= 57; i++) {
        _specialKeys[i] = 'KEY_' + (i - 48);
    }

    /* for KEY_A - KEY_Z */
    for (var i = 65; i <= 90; i++) {
        _specialKeys[i] = 'KEY_' + String.fromCharCode(i);
    }

    /* for KEY_NUM_PAD_0 - KEY_NUM_PAD_9 */
    for (var i = 96; i <= 105; i++) {
        _specialKeys[i] = 'KEY_NUM_PAD_' + (i - 96);
    }

    /* for KEY_F1 - KEY_F12 */
    for (var i = 112; i <= 123; i++) {
        // no F0
        _specialKeys[i] = 'KEY_F' + (i - 112 + 1);
    }
})();

MWW.signal.Ident = function (ident) {
    this.source = ident.source;
    this.signal = ident.signal;
    this.listener = ident.listener;
    this.isDOM = ident.isDOM;
    this.objOrFunc = ident.objOrFunc;
    this.funcOrStr = ident.funcOrStr;
    this.connected = ident.connected;
};

MWW.signal.Ident.prototype = {};
MWW.update(MWW.signal,{
 	'_unloadCache': function () {
        var self = MWW.signal;
        var observers = self._observers;

        for (var i = 0; i < observers.length; i++) {
            if (observers[i].signal !== 'onload' && observers[i].signal !== 'onunload') {
                self._disconnect(observers[i]);
            }
        }
    },
    '_listener': function (src, sig, func, obj, isDOM) {
        var self = MWW.signal;
        var E = self.Event;
        if (!isDOM) {
            /* We don't want to re-bind already bound methods */
            if (typeof(func.im_self) == 'undefined') {
                return MWW.bind(func, obj);
            } else {
                return func;
            }
        }
        obj = obj || src;
        if (typeof(func) == "string") {
            if (sig === 'onload' || sig === 'onunload') {
                return function (nativeEvent) {
                    obj[func].apply(obj, [new E(src, nativeEvent)]);
                    
                    var ident = new MWW.signal.Ident({
                        source: src, signal: sig, objOrFunc: obj, funcOrStr: func});                    
                    MWW.signal._disconnect(ident);
                };
            } else {
                return function (nativeEvent) {
                    obj[func].apply(obj, [new E(src, nativeEvent)]);
                };
            }
        } else {
            if (sig === 'onload' || sig === 'onunload') {
                return function (nativeEvent) {
                    func.apply(obj, [new E(src, nativeEvent)]);                    
                    var ident = new MWW.signal.Ident({
                        source: src, signal: sig, objOrFunc: func});                    
                    MWW.signal._disconnect(ident);
                };
            } else {
                return function (nativeEvent) {
                    func.apply(obj, [new E(src, nativeEvent)]);
                };
            }
        }
    },

    '_browserAlreadyHasMouseEnterAndLeave': function () {
        return (/MSIE/.test(navigator.userAgent));
    },
    '_mouseEnterListener': function (src, sig, func, obj) {
        var E = MWW.signal.Event;
        return function (nativeEvent) {
            var e = new E(src, nativeEvent);
            try {
                e.relatedTarget().nodeName;
            } catch (err) {
                /* probably hit a permission denied error; possibly one of
                 * firefox's screwy anonymous DIVs inside an input element.
                 * Allow this event to propogate up.
                 */
                return;
            }
            e.stop();
            if (MWW.dom.isChildNode(e.relatedTarget(), src)) {
                /* We've moved between our node and a child. Ignore. */
                return;
            }
            e.type = function () { return sig; };
            if (typeof(func) == "string") {
                return obj[func].apply(obj, [e]);
            } else {
                return func.apply(obj, [e]);
            }
        };
    },
    '_getDestPair': function (objOrFunc, funcOrStr) {
        var obj = null;
        var func = null;
        if (typeof(funcOrStr) != 'undefined') {
            obj = objOrFunc;
            func = funcOrStr;
            if (typeof(funcOrStr) == 'string') {
                if (typeof(objOrFunc[funcOrStr]) != "function") {
                    throw new Error("'funcOrStr' must be a function on 'objOrFunc'");
                }
            } else if (typeof(funcOrStr) != 'function') {
                throw new Error("'funcOrStr' must be a function or string");
            }
        } else if (typeof(objOrFunc) != "function") {
            throw new Error("'objOrFunc' must be a function if 'funcOrStr' is not given");
        } else {
            func = objOrFunc;
        }
        return [obj, func];
    },  
    'connect': function (src, sig, objOrFunc/* optional */, funcOrStr) {
        src = MWW.dom.getById(src);
        var self = MWW.signal;

        if (typeof(sig) != 'string') {
            throw new Error("'sig' must be a string");
        }

        var destPair = self._getDestPair(objOrFunc, funcOrStr);
        var obj = destPair[0];
        var func = destPair[1];
        if (typeof(obj) == 'undefined' || obj === null) {
            obj = src;
        }

        var isDOM = !!(src.addEventListener || src.attachEvent);
        if (isDOM && (sig === "onmouseenter" || sig === "onmouseleave") && !self._browserAlreadyHasMouseEnterAndLeave()) {
            var listener = self._mouseEnterListener(src, sig.substr(2), func, obj);
            if (sig === "onmouseenter") {
                sig = "onmouseover";
            } else {
                sig = "onmouseout";
            }
        } else {
            var listener = self._listener(src, sig, func, obj, isDOM);
        }

        if (src.addEventListener) {
            src.addEventListener(sig.substr(2), listener, false);
        } else if (src.attachEvent) {
            src.attachEvent(sig, listener); // useCapture unsupported
        }

        var ident = new MWW.signal.Ident({
            source: src, 
            signal: sig, 
            listener: listener, 
            isDOM: isDOM, 
            objOrFunc: objOrFunc, 
            funcOrStr: funcOrStr, 
            connected: true
        });
        self._observers.push(ident);

        if (!isDOM && typeof(src.__connect__) == 'function') {
            var args = MWW.extend([ident], arguments, 1);
            src.__connect__.apply(src, args);
        }

        return ident;
    },
    '_disconnect': function (ident) {
        // already disconnected
        if (!ident.connected) {
            return;
        }
        ident.connected = false;
        // check isDOM
        if (!ident.isDOM) {
            return;
        }
        var src = ident.source;
        var sig = ident.signal;
        var listener = ident.listener;

        if (src.removeEventListener) {
            src.removeEventListener(sig.substr(2), listener, false);
        } else if (src.detachEvent) {
            src.detachEvent(sig, listener); // useCapture unsupported
        } else {
            throw new Error("'src' must be a DOM element");
        }
    },    
    'disconnect': function (ident) {
        var self = MWW.signal;
        var observers = self._observers;
        var m = MWW;
        if (arguments.length > 1) {
            // compatibility API
            var src = MWW.dom.getById(arguments[0]);
            var sig = arguments[1];
            var obj = arguments[2];
            var func = arguments[3];
            for (var i = observers.length - 1; i >= 0; i--) {
                var o = observers[i];
                if (o.source === src && o.signal === sig && o.objOrFunc === obj && o.funcOrStr === func) {
                    self._disconnect(o);
                    if (!self._lock) {
                        observers[i] = null;
                    } else {
                        self._dirty = true;
                    }
                    return true;
                }
            }
        } else {
            var idx = m.findIdentical(observers, ident);
            if (idx >= 0) {
                self._disconnect(ident);
                if (!self._lock) {
                    observers.splice(idx, 1);
                } else {
                    self._dirty = true;
                }
                return true;
            }
        }
        return false;
    },
    'disconnectAllTo': function (objOrFunc, /* optional */funcOrStr) {
        var self = MWW.signal;
        var observers = self._observers;
        var disconnect = self._disconnect;
        var locked = self._lock;
        var dirty = self._dirty;
        if (typeof(funcOrStr) === 'undefined') {
            funcOrStr = null;
        }
        for (var i = observers.length - 1; i >= 0; i--) {
            var ident = observers[i];
            if (ident.objOrFunc === objOrFunc &&
                    (funcOrStr === null || ident.funcOrStr === funcOrStr)) {
                disconnect(ident);
                if (locked) {
                    dirty = true;
                } else {
                    observers.splice(i, 1);
                }
            }
        }
        self._dirty = dirty;
    },  
    'disconnectAll': function (src/* optional */, sig) {
        src = MWW.dom.getById(src);
        var m = MWW;
        var signals = m.flattenArguments(m.extend(null, arguments, 1));
        var self = MWW.signal;
        var disconnect = self._disconnect;
        var observers = self._observers;
        var i, ident;
        var locked = self._lock;
        var dirty = self._dirty;
        if (signals.length === 0) {
            // disconnect all
            for (var i = observers.length - 1; i >= 0; i--) {
                ident = observers[i];
                if (ident.source === src) {
                    disconnect(ident);
                    if (!locked) {
                        observers.splice(i, 1);
                    } else {
                        dirty = true;
                    }
                }
            }
        } else {
            var sigs = {};
            for (var i = 0; i < signals.length; i++) {
                sigs[signals[i]] = true;
            }
            for (var i = observers.length - 1; i >= 0; i--) {
                ident = observers[i];
                if (ident.source === src && ident.signal in sigs) {
                    disconnect(ident);
                    if (!locked) {
                        observers.splice(i, 1);
                    } else {
                        dirty = true;
                    }
                }
            }
        }
        self._dirty = dirty;
    },
   
   'signal': function (src, sig) {
        var self = MWW.signal;
        var observers = self._observers;
        src = MWW.dom.getById(src);
        var args = MWW.extend(null, arguments, 2);
        var errors = [];
        self._lock = true;
        for (var i = 0; i < observers.length; i++) {
            var ident = observers[i];
            if (ident.source === src && ident.signal === sig &&
                    ident.connected) {
                try {
                    ident.listener.apply(src, args);
                } catch (e) {
                    errors.push(e);
                }
            }
        }
        self._lock = false;
        if (self._dirty) {
            self._dirty = false;
            for (var i = observers.length - 1; i >= 0; i--) {
                if (!observers[i].connected) {
                    observers.splice(i, 1);
                }
            }
        }
        if (errors.length == 1) {
            throw errors[0];
        } else if (errors.length > 1) {
            var e = new Error("Multiple errors thrown in handling 'sig', see errors property");
            e.errors = errors;
            throw e;
        }
    }
});
MWW.namespace('lang');
MWW.lang.NAME = 'MWW.lang';
MWW.lang.VERSION = '1.0';
MWW.lang.toString = function(){return MWW.lang.NAME+' '+MWW.lang.VERSION;};
MWW.update(MWW.lang,{
    isArray: function(o) {
        if (o) {
           var l = MWW.lang;
           return l.isNumber(o.length) && l.isFunction(o.splice) && !l.hasOwnProperty(o.length);
        }
        return false;
    },
    isBoolean: function(o) {
        return typeof(o) === 'boolean';
    },
    isFunction: function(o) {
        return typeof(o) === 'function';
    },
    isNull: function(o) {
        return o === null;
    },
    isNumber: function(o) {
        return typeof(o) === 'number' && isFinite(o);
    },
    isObject: function(o) {
		return (o && (typeof(o) === 'object' || MWW.lang.isFunction(o))) || false;
    },
    isString: function(o) {
        return typeof(o) === 'string';
    },
    isUndefined: function(o) {
        return typeof(o) === 'undefined';
    }, 
	hasProperty: function(o,prop){
        if (Object.prototype.hasOwnProperty) {
            return o.hasOwnProperty(prop);
        }        
        return !MWW.lang.isUndefined(o[prop]) && o.constructor.prototype[prop] !== o[prop];
	},
	isNotEmpty: function (obj) {
        for (var i = 0; i < arguments.length; i++) {
            var o = arguments[i];
            if (!(o && o.length)) {
                return false;
            }
        }
        return true;
    }
});
MWW.namespace('widget');
MWW.widget.NAME = 'MWW.widget';
MWW.widget.VERSION = '1.0';
