/* $Date: 2009-01-16 00:58:23 $ */

Array.prototype.each = function(f) {
    for (var i = 0; i < this.length; ++i) {
        f(this[i], i);
    }
    return this;
};
Array.prototype.map = function(f) {
    var a = [];
    this.each(function(v, i) {
        a.push(f(v, i));
    });
    return a;
};

var PARAMETERS = {};
PARAMETERS.parse = function(q) {
    var map = {};
    if (q) {
        q.substring(1).replace(/([^&=]+)([=]([^&]*))?(&|$)/g, function(s, k, q, v) {
            if (undefined === map[k]) {
                map[k] = [];
            }
            map[k].push(decodeURIComponent(v));
        });
        for (var k in map) {
            var a = map[k];
            map[k] = ((1 == a.length) ? a[0] : a);
        }
    }
    return map;
};
PARAMETERS.load = function() {
    PARAMETERS.map = PARAMETERS.parse(window.location.search);
};
PARAMETERS.load();

var COOKIES = {};
COOKIES.load = function() {
    COOKIES.map = {};
    document.cookie.replace(/([^ ;=]*)=([^;]*)/g, function(s, k, v) {
        if (undefined === COOKIES.map[k]) {
            COOKIES.map[k] = [];
        }
        COOKIES.map[k].push(COOKIES.decode(v));
    });
    for (var k in COOKIES.map) {
        var a = COOKIES.map[k];
        COOKIES.map[k] = ((1 == a.length) ? a[0] : a);
    }
};
COOKIES.encode = function(s) {
    var v = s.replace(/%/g, '%0').replace(/;/g, '%1');
    return ((v == s) ? s : ('%%' + v));
};
COOKIES.decode = function(s) {
    return (/^%%/.test(s) ? s.substring(2).replace(/%1/g, ';').replace(/%0/g, '%') : s);
};
COOKIES.save = function(k, v, t) {
    if (undefined === t) {
        t = '';
    } else {
        var now = new Date();
        now.setTime(now.getTime() + t);
        t = '; expires=' + now.toGMTString();
    }
    document.cookie = k + '=' + COOKIES.encode(v) + t;
    COOKIES.load();
};
COOKIES.load();

var DOM = {};
DOM.onload = function(f) {
    var f0 = window.onload;
    window.onload = (f0 ? function() {
        f0();
        f();
    }
 : f);
};
DOM.asArray = function(o, i) {
    var a = [];
    for (i = i || 0; i < o.length; ++i) {
        a.push(o[i]);
    }
    return a;
};
DOM.preventDefault = function(e) {
    e = e || event;
    if (e.preventDefault) {
        e.preventDefault();
    }
    e.returnValue = false;
    return false;
};
DOM.nodeKind = function(o) {
    return (o ? (o.nodeName + (o.className ? ("." + o.className) : "") + (o.id ? ("#" + o.id) : "")) : 'NULL');
};
DOM.byId = function() {
    var map = {};
    DOM.asArray(arguments).each(function(name) {
        var v = name.split('.');
        var m = map;
        while (1 < v.length) {
            var s = v.shift();
            m = m[s] || (m[s] = {});
        }
        m[v[0]] = document.getElementById(name);
    });
    return map;
};
DOM.byName = function(root) {
    var map = {};
    var walk = function(o) {
        var name = o.getAttribute && o.getAttribute('name');
        if (name) {
            var v = name.split('.');
            var m = map;
            while (1 < v.length) {
                var s = v.shift();
                m = m[s] || (m[s] = {});
            }
            m[v[0]] = o;
        }
        for (o = o.firstChild; o; o = o.nextSibling) {
            walk(o);
        }
    };
    walk(root);
    return map;
};
(function(m) {
    DOM.encode = function(s) {
        return s.toString().replace(/[<>&]/g, function(c) {
            return m[c];
        });
    };
    var r = {};
    for (var k in m) {
        r[m[k]] = k;
    }
    DOM.decode = function(s) {
        return s.replace(/(&[a-z]*;)/gi, function(c) {
            var v = r[c.toLowerCase()];
            return (v ? v : c);
        });
    };
})({
    '<': '&lt;',
    '>': '&gt;',
    '&': '&amp;'
});
DOM.handler = function(f) {
    return function(e) {
        f(e);
        return DOM.preventDefault(e);
    };
}
DOM.onclick = function(node, f) {
    node.onclick = DOM.handler(f);
};
(function() {
    if (window.addEventListener) {
        DOM.forEvent = function(node, name, handler) {
            node.addEventListener(name, handler, false);
        }
    } else if (window.attachEvent) {
        DOM.forEvent = function(node, name, handler) {
            node.attachEvent("on" + name, handler);
        }
    } else {
        DOM.forEvent = function(node, name, handler) {
            node["on" + name] = handler;
        }
    }
})();

//  Clone and transform the given template.
//  Alter the cloned fragment by applying the map of ids and functions.
//  Apply the associated function to each node with an id in the map.
DOM.expandTemplate = function(oTemplate, fm) {
    var apply = function(node) {
        var f = fm[node.id]
        if (!f) {
            for (var oNext = node.firstChild; oNext;) {
                var o = oNext;
                oNext = o.nextSibling;
                apply(o);
            }
        } else if ('Q' == node.tagName) {
            var oParent = node.parentNode;
            var oText = document.createTextNode(f);
            oParent.replaceChild(oText, node);
        } else {
            node.removeAttribute("id");
            f(node);
        }
    }
    oTemplate = oTemplate.cloneNode(true)
    oTemplate.removeAttribute("id")
    apply(oTemplate)
    return oTemplate
};

DOM.offsetOf = function(node) {
    var p = {
        x: 0,
        y: 0
    };
    for (var o = node; o; o = o.offsetParent) {
        p.x += o.offsetLeft;
        p.y += o.offsetTop;
    }
    return p;
};
DOM.positionOf = function(node, base) {
    var p = DOM.offsetOf(node);
    base = base || document.body;
    for (var o = node; o != base; o = o.parentNode) {
        p.x -= o.scrollLeft || 0;
        p.y -= o.scrollTop || 0;
    }
    return p;
};
