/*
    jaxx : javascript asynchronous xml & xslt
    v0.96 beta
    
    Copyright (c) 2006 WebEffekt.no
    Licensed under the MIT License:
    http://www.opensource.org/licenses/mit-license.php

    Inspired/based on the work of:
    prototype.conio.net		simon.incutio.com			jquery.com
    moofx.mad4milk.net		dean.edwards.name		erik.eae.ne
    
    Please send a mail to jaxx AT webeffekt . no if you find bugs
    or something that can be done in a smaller / faster way!
    
    More about jaxx on http://jaxx.WebEffekt.no
    
*/


var __handlers = [];
var __extend = {
        override: {},
        dynamic: {}
};

if (!String.trim) String.prototype.trim = function(){
    //trimms left and right whitspace on strings
    return this.replace(/^\s+|\s+$/g,'');
};

if (!window.XMLHttpRequest && window.ActiveXObject) var XMLHttpRequest = function(){
    //XMLHttpRequest wrapper for ie browsers that do not support XMLHttpRequest nativly
    return new ActiveXObject(/MSIE 5/.test(navigator.userAgent) ? "Microsoft.XMLHTTP" : "Msxml2.XMLHTTP");
};

if (!Function.bind) Function.prototype.bind = function(){
    //binds variables to a function callback
    var __m = this, args = $c(arguments), object = args.shift();
    return function(){ return __m.apply(object, args)}
};

if (!Function.bindE) Function.prototype.bindE = function(){
    //binds variables to a function callback, also includes variables when called (like event)
    var __m = this, args = $c(arguments), object = args.shift();
    return function(){ return __m.apply(object, $c(arguments).concat(args))}
};


/* --------------- jaxx.Common --------------- */

function $c( obj, s )
{
    //Creates an array out of anything, also support splitting strings by string s
    var r=[], el;
    if (typeof obj != 'object' && obj.constructor != Object && obj != '[object NodeList]') obj = [obj];
    for (var i=0;(el=obj[i]) != undefined;i++)
    (s !== undefined && typeof el == 'string') ? r = r.concat(el.split(s)) : r.push(el);
    return $ext((r.length !== 0 || (obj.length !== undefined && obj.length === 0)) ? r : [obj], $jaxxJS16, true);
}

function $ext( dest, props, soft )
{
    //extends dest object with object props properties, overwrites existing properties if soft is false / undefined
    for (prop in props || {}){ if (!soft || dest[prop] === undefined) dest[prop] = props[prop]};
    return dest;
}

function $getPos( el )
{
    //gets the position on element
    var pT = 0, pL = 0, t = -1, o = el, s = {sl:0,st:0};
    if ( $getStyle(o).display == 'none' ) t = $show(o,t);
    do{	pT = pT + el.offsetTop || 0;
        pL = pL + el.offsetLeft || 0;
        el = el.offsetParent;
    } while (el);
    if (t != -1) $hide(o,t);
    return {pl: pL, pt: pT};
}

function $getScroll()
{
    //get document scroll   todo: elemement support (overflow:scroll)
    var r = {sl:0,st:0}, d = document, w = window;
    if ( d.documentElement.scrollTop ) r = {sl: d.documentElement.scrollLeft, st: d.documentElement.scrollTop};
    else if ( typeof w.pageYOffset == 'number' ) r = {sl: w.pageXOffset, st: w.pageYOffset};
    else if ( d.body.scrollTop ) r = {sl: d.body.scrollLeft, st: d.body.scrollTop};
    return r;
}

function $getSize( el )
{
    //gets the size on element
    if ( !el ) el = (document.body.clientWidth && !window.opera)? document.body : document.documentElement;
    var t = ( $getStyle(el).display == 'none' ) ? $show(el,-1,1) : -1;
    var r = {ow:el.offsetWidth, oh:el.offsetHeight, sw:el.scrollWidth, sh:el.scrollHeight};
    if (t != -1) $hide(el,t,1);
    return r;
}

function $getStyle( el )
{
    //function to get calculated styles on element
    var r = (document.defaultView) ? document.defaultView.getComputedStyle(el, null) : el.currentStyle;
    return (r === null) ? {display:'none'} : r; //"fix" for safari
}

function $hide( el, s, r )
{
    //hides a display:none element after finding position or size
    var els = el.style, elp = el.parentNode.style;
    els.display = 'none';
    els.position = s.e;
    if (r) elp.position = s.p;
    els.visibility = 'visible';
}

function $show( el, s, r )
{
    //shows a display:none element so that position or size can be found
    var els = el.style, elp = el.parentNode.style, e = els.position, p = elp.position;
    if (r && p == '') elp.position = 'relative';
    els.visibility = 'hidden';
    els.position = 'absolute';
    els.display = '';
    return {e:e,p:p};
}

function $strippAnonymous( fn )
{
    //Stripps anonymous wrapper functions
    var str = (fn || "").toString();
    if (str.indexOf('anonymous') === -1) return fn;
    else return str.match(/function anonymous\(\)\n\{\n(.*)\n\}/gi) ?  RegExp.$1 : str;
}

function $setCookie( n, v, d )
{
    //sets cookies value with name, value and days to expiration, if d is undefined the cookie will be deleted
    var date = new Date();
    date.setTime(date.getTime()+((d || -1)*86400));
    document.cookie = n+"="+v+"; expires="+date.toUTCString()+"; path=/";
}

function $getCookie( n )
{
    //get cookie value by name
    var r = "", cookArr = document.cookie.split(';'), t;
    n = n + "=";
    for (var i=0,l=cookArr.length;i<l;i++)
    {
        t = cookArr[i].trim();
        if (t.indexOf(n)==0) r = t.substring(n.length,t.length);
    }
    return r;
}

function $addEvent( el, t, h )
{
    // method for setting element event
    t = t.trim().replace(/^on/i,'');
    if (el.addEventListener) el.addEventListener(t, h, false);
    else if (el.attachEvent) el.attachEvent('on' + t, h);
    else {
        var c = el['on' + t];
        if (typeof c != 'function')el['on' + t] = h;
        else el['on' + t] = function(){h();c()};
    }
    __handlers.push(arguments);
}

function $removeEvent( el, t, h )
{
    //method for removing element event
    t = t.trim().replace(/^on/i,'');
    if (el.removeEventListener) el.removeEventListener(t, h, false);
    else if (el.detachEvent) try {el.detachEvent(t,h)} catch ($i){};
}

if ( window.detachEvent && !window.opera ) window.attachEvent('onunload',function(){
    //automaticly cleans up events in ie to avoid some event related memory leaks
    for (var i = 0, l = __handlers.length; i < l; i++) __handlers[i][0].detachEvent('on'+__handlers[i][1], __handlers[i][2]);
});


/* --------------- jaxx.Dom  ----------------- */

function $$()
{
    //css query function, returns a $jaxx extended array of elements 
    var args = $c(arguments, ','), d = [document], r = [], atr, ati;
    if (typeof args[args.length -1] == 'object') d = args.pop();
    args.forEach(function(el)
    {
        if (typeof el=='string')
        {
            var par = $c(d); 
            $c(el.trim(), /\s+/).forEach(function(str)
            {
                var temp = $c([]), tag = (str.match(/^(\w+)([.#\[]?)\s?/)) ? RegExp.$1 : "*", id = false, cn = false, at = false;
                if (str.match(/([\#])([a-zA-Z0-9_\-]+)([.#\[]?)\s?/)) id = RegExp.$2;
                if (str.match(/([\.])([a-zA-Z0-9_\-]+)([.#\[]?)\s?/)) cn = ' ' + RegExp.$2 + ' ';
                if (str.match(/\[(\w+)([~\|\^\$\*]?)=?"?([^\]"]*)"?\]/)) at = [RegExp.$1 , RegExp.$2, RegExp.$3];
                par.forEach(function(doc)
                {
                    $c((doc === document  && id && tag == "*") ? doc.getElementById(id) : doc.getElementsByTagName(tag)).forEach(function(i){
                        if (id && (!i.getAttribute("id") || i.getAttribute("id")!=id)) return;
                        if (at)
                        {
                            atr = $strippAnonymous(i.getAttribute(at[0]));
                            if ( atr )
                            {
                                ati = atr.indexOf(at[2]);
                                if (at[2]=='');
                                else if (at[1] == '' && atr == at[2]);
                                else if (at[1] == '*' && ati != -1);
                                else if (at[1] == '~' && (' '+atr+' ').indexOf(' '+at[2]+' ') != -1);
                                else if (at[1] == '^' && ati == 0);
                                else if (at[1] == '$' && ati == (atr.length-at[2].length) && ati != -1);
                                else return;
                            } else return;
                        }
                        if (cn && (' '+i.className+' ').indexOf( cn ) == -1) return;
                        temp.push(i); 
                    });
                });
                par = temp;
            });
            r = r.concat(par);
        } else r.push(el);
    }, this);
    return $ext(r, new $jaxx()).init();
}

function $(a)
{
    //id query function, returns a $jaxx extended array of elements 
    if (a.jaxx) return a;
    var m = $c(arguments).map(function(el){return (typeof el=='string') ? document.getElementById(el) : el});
    return $ext(m, new $jaxx()).init();
}

var fx = {
    //inculded set of fx's to use with animations
    linear: function(p){return {h:p,w:p,o:p,pl:p,pt:p,t:p}},
    cubic: function(p){p = Math.pow(p,3); return {h:p,w:p,o:p,pl:p,pt:p,t:p}},
    circ: function(p){p = Math.sqrt(p); return {h:p,w:p,o:p,pl:p,pt:p,t:p}},
    sinoidal: function(p){p = ((-Math.cos(p*Math.PI)/2) + 0.5); return {h:p,w:p,o:p,pl:p,pt:p,t:p}}
};


/* --------------- jaxx       ------------- */
function $jaxx()
{
    //init function for $jaxx, extends itself with all objects set in __extend
    $ext(this, __extend.override);
    $ext(this, __extend.dynamic, 1);
}

$jaxx.prototype = {
    jaxx: 0.96,
    fI: 1, fs: 1, sI: -1, fT: 0, mT: 0,mH: 0, nArr: [],

    add: function(str)
    {
        //append content to all elements
        this.forEach(function( el )
        {
            if (el.nodeName == "SELECT" && el.outerHTML) el.outerHTML = el.outerHTML.replace(el.innerHTML, el.innerHTML+str);
            else if (el.value !== undefined && el.nodeName != "SELECT") el.value += str;
            else el.innerHTML += str;
        });
        return this;
    },

    addClass: function( c, t, r )
    {
        //add class, removes the class first from the whole array unless r is set
        this.removeClass( c, r );
        this.forEach(function(el, i)
        {
            if (t === undefined || el === t || i === t)el.className = el.className + (el.className.length > 0 ? ' ' : '') + c;
        });
        return this;
    },

    addEvent: function( t, h, b, el )
    {
        //add event to the whole element array unless el is set, b is optional 'this' override
        this.forEach(function(el2,i){
            if (el === undefined || el === el2 || el === i)
                $addEvent(el2,t,h.bindE(this, el2, i))
        }, b);
        return this;
    },

    check: function( s )
    {
        //short cut for checking / unchecking  an array of checkboxes
        s = (s==undefined) ? ((this[0].checked) ? false : true) : ((s)? true : false);
        this.forEach(function(el){ if (el.type=="checkbox") el.checked = s; });
    },

    click: function( h, b, el )
    {
        //shortcut for addEvent('click',h,b,el)
        return this.addEvent('click',h,b,el);
    },
    
    formSerial: function()
    {
        var pB = '';
        this.forEach(function(el){
            var tpB = '';
            if (el.type == 'radio' || el.type == 'checkbox') tpB  = (el.checked) ? el.name + '=' + el.value: '';
            else if (el.type == 'select-one') tpB = (el.selectedIndex != -1) ? el.name + '=' + el.options[el.selectedIndex].value: '';
            else if (el.tagName == "OPTION") tpB = (el.selected && el.parentNode.type == 'select-multiple') ? el.parentNode.name + '=' + el.value: '';
            else if (el.name && el.value !== undefined && el.type != 'select-multiple') tpB  = el.name + '=' + el.value;
            if (tpB) pB = pB + ((pB == '') ? '' : '&') + tpB;
        });
        return pB;
    },

    fx: function( o, t, sT )
    {
        //init function for animations, can set options, target values and startTime for auto slideshow
        if (o && o.cookie) $c($getCookie(o.cookie),',').forEach(function(el,i){if (el == 1) o.defSlide = i});
        if (o && o.defSlide !== undefined && o.defSlide != -1) this.slide(o.defSlide);
        $ext(this.o, o || {});
        $ext(this.t, t || {});
        this.fI = this.fs = Math.round(this.o.duration/this.o.ft);
        if (this.p.length != this.length) this.setP();
        this.p = $c(this.map(function(el,i){ return $ext($ext(this.p[i], $getSize(el)), $getPos(el))},this));
        if (sT) this.start(sT);
        return this;
    },

    fxprep: function( hide, item, noslide )
    {
        //private preperation function for animations, have optional onStart event
        if (this.fT) clearInterval(this.fT);
        this.fI = this.fs - this.fI;
        if (this.p.length != this.length) this.setP();
        var twoPass = (this.o.twoPass) ? 1 : false;
        this.forEach(function(el, i)
        {
            var p = this.p[i], t, r = (el===item || i===item || item === undefined) ? 1 : 0;
            if (hide !== undefined) t = (hide) ? -1 : 1;
            else t = (p.a == 0) ? -p.d : -p.a;
            t = (r) ? t : -t;
            this.p[i].a = t = ((!r && noslide) || p.d == t && (p.a == 0 || p.a == t)) ? 0 : t;
            if (t == -1 && twoPass) twoPass = t;
        }, this);	
        this.fT = setInterval(this.fxStep.bind(this, twoPass),this.o.ft);
        if (this.o.onStart) this.o.onStart(this);
        this.fxStep(twoPass);
    },

    fxStep: function(twoPass)
    {
        //private animation function, is started by fxprep, have optional onComplete/onHide/onShow events
        this.fI++;
        if (this.p.length != this.length) this.setP();
        var ot = this.fI/this.fs, els, p, t = this.t, o = this.o, pos = o.transition(ot), iPos = o.transition(1-ot);
        if (this.fI == this.fs)
        {
            clearInterval(this.fT);
            this.forEach(function(el,i)
            {
                if (this.p[i].a == -1){
                    el.style.display = o.display;
                    this.p[i].d = -1;
                    if (o.onHide) o.onHide(el, i, this);
                }
            }, this);
            if (!twoPass || twoPass == 1)
            {
                if ( o.onComplete ) o.onComplete(this);
                if ( o.cookie && this.p.map ) $setCookie( o.cookie, this.p.map(function(p){return p.d} ), (o.cookieDays || 10)); 
            } else {
                this.fT = setInterval( this.fxStep.bind(this, 1), this.o.ft );
                this.fI = this.fs - this.fI;
                this.fxStep( 1 );
            }
        }
        this.forEach(function(el,i)
        {
            if (this.p[i].a != 0 &&(!twoPass || twoPass == this.p[i].a))
            {
                els = el.style;
                p = this.p[i];
                ot = (p.a == 1) ? pos : iPos;
                if (o.height) els.height = ((t.h-p.sh) * (1-ot.h) + p.sh) + "px";
                if (o.width) els.width = ((t.w-p.ow) * (1-ot.w) + p.ow) + "px";//convert to sw when Opera9 handels it
                if (o.text) els.fontSize = ((t.t-1) * (1-ot.t) + 1) * 100 + '%';
                if (o.position){
                    els.top = ((t.pt-p.pt) * (1-ot.pt) + p.pt) + 'px';
                    els.left = ((t.pl-p.pl) * (1-ot.pl) + p.pl) + 'px';
                }
                if (o.opacity)
                {
                    ot = (t.o-1) * (1-ot.o) + 1;
                    if (els.opacity != undefined) els.opacity = (ot >= 1) ? "" : ot;
                    else if (els.filter != undefined) els.filter = (ot >= 1) ? "" : "alpha(opacity=" + ot*100 + ")";
                }
                if (p.a == 1 && p.d == -1)
                {
                    els.display = '';
                    this.p[i].d = 1;
                    if (o.onShow) o.onShow(el, i, this);
                }
            }
        }, this);
    },

    hide: function( h )
    {
        //hides the whole array unless h (element or index) is set
        this.fxprep(true,h,true);
    },

    init: function( r )
    {
        //private init function to be called right after array is extended
        this.o = {duration:20, ft:20, display:'none', transition:fx.linear, defSlide:-1, selected:'selected'};
        this.t = {h:0,w:0,o:0,pl:0,pt:0,t:0};
        this.p = $c([]);
        return this;
    },

    load: function(u, el, pB)
    {
        //shortcut to ajax functionality to target server response directly to element (index or element)
        if ( el === undefined ) el = this[0];
        else if ( typeof el == 'number' ) el = this[el];
        if ( !this.ajax ) this.ajax = new $ajax( this.o );
        if ( !this.o.update ) this.ajax.o.update = el;
        if ( this.o.preUpdate ) this.ajax.o.preUpdate = this.o.preUpdate.bindE( this , el );
        if ( this.o.onLoad ) this.ajax.o.onLoad = this.o.onLoad.bindE( this , el );
        this.ajax.load( u, pB || undefined);
    },

    merge: function(a)
    {
        //merge array with other array or element
        $c(a).forEach(function(el)
        {
                if (el !== "" && this.indexOf(el) == -1) this.push(el);
        }, this);
        return this;
    },

    mf: function(c)
    {
        //private mouse on focus function
        clearInterval(this.mT);
        this.mH = 1;
        this.forEach(function(el, i)
        {
            if (i == c && c != this.sI) this.slide(c);
        }, this);
        this.mT = setInterval(this.muf.bind(this), 2700);
    },

    muf: function()
    {
        //private mouse unfocus function
        if (this.mH == false)
        {
            clearInterval(this.mT);
            this.slide(this.o.defSlide);
        }
    },

    nav: function(n,m,v)
    {
        //set navigation options, n is navigation array and m us true/false value for mouse or click navigation
        if (m)
        {
            if (n)
            {
                n.addEvent("mouseover",function(e,el,i){this.mf(i)},this);
                n.addEvent("mouseout",function(){this.mH=0},this)
            }
            this.addEvent("mouseover",function(e,el,i){this.mf(i)},this);
            this.addEvent("mouseout",function(){this.mH=0},this);
        } else n.click(((n.length == 1) ? function(){this.toggle()} : function(e,el,i){this.slide(i)}),this);
        if (n) this.nArr = (v) ? n.voidLink() : n;
        return this;
    },

    remove: function(x)
    {
        //removes all element or element(x) from document and array
        this.forEach(function(el,i)
        {
            if (x === undefined || x === el || x === i)
            {
                el.parentNode.removeChild(el);
                this[i] = 0;
            }
        }, this);
        this.filter(function(el){return el});//need testing!
        return this;
    },

    removeClass: function(c, t)
    {
        //removes className from all elements unless t is set (index or element)
        this.forEach(function(el){
        if (t === undefined || el === t || i === t)
            el.className = $c(el.className, ' ').filter(function(cn, i){return (cn!=c) ? 1: 0;}).join(' ');
        });
        return this;
    },

    set: function( str )
    {
        //overwrite content
        this.forEach(function(el){
            if (el.nodeName == "SELECT" && el.outerHTML){
                if (!el.innerHTML.trim()) el.outerHTML = el.outerHTML.replace(/\s?<\/select>/i, str + '</select>' );
                else el.outerHTML = el.outerHTML.replace(el.innerHTML, str);
            } else if (el.value !== undefined && el.nodeName != "SELECT") el.value = str;
            else el.innerHTML = str;
        }); return this;
    },

    setP: function(){
        //private function to reseting element propertie cache (size / position....)
        this.p = $c(this.map(function(el){return {a:0,d:((el.style.display == 'none') ? -1 : 1)}}));
    },

    setStyle: function( s, t )
    {
        //shortcut to set multiple styles by an object of name and value
        this.forEach(function(el,i){
            if (t === undefined || el === t || i === t)
            for (z in s) el.style[z] = s[z];
        }); return this;
    },

    show: function( s )
    {
        //shows the whole array unless h (element or index) is set
        this.fxprep(false, s, true);
    },

    start: function( t )
    {
        //start automatic slideshow, t is intervall time
        this.sT = setInterval(this.slide.bind(this),t);
        return this;
    },

    stop: function()
    {
        //stop automatic slideshow
        if (this.sT) clearInterval(this.sT);
        return this;
    },

    slide: function( s, r )
    {
        //slides the the animation, slides to specific index if s is set (index or element)
        // does it relativ if r is true, and simply slide to next one if s/r not set
        if (s != -1 || r)
        {
            s = ((s === undefined) ? this.sI + 1 : ((r) ? this.sI : 0 ) + (( typeof s == 'number' ) ? s : this.indexOf( s )));
            s = ( s > this.length-1 ) ? 0 : ((s < 0) ? this.length-1 : s);
        }
        this.sI = s = (this.o.onSlide) ? this.o.onSlide(s, this) : s;
        this.addClass( this.o.selected, s );
        if ( this.nArr.addClass ) this.nArr.addClass( this.o.selected, s );
        this.fxprep( false, s );
    },

    toggle: function( t )
    {
        //toggles the whole array unless t (element or index) is set
        this.fxprep( undefined, t, true );
    },

    voidLink: function()
    {
        //substitutes href values for harmless void(0) calls (== do nothing)
        this.forEach( function(el){if (el.href) el.href="JavaScript:void(0)"} );
        return this;
    }
};


/* --------------- jaxx.Drag --------------- */
__extend.override = {
    //dragNdrop functionality as an extension
    drag: -1,
    dpi: -1,
    odpi: -1,
    drag: function(par)
    {
        //init function to make elements elements dragable, optional parent containers as array
        //calls fx to preper aniamtion but sets display to '' to avoid hiding on drag
        this.fx({display:''}).forEach(function(el,i){
            $addEvent(el, 'mousedown', this.dragStart.bindE(this));
        }, this);
        $addEvent(document, 'mousemove', this.dragMove.bindE(this));
        $addEvent(document, 'mouseup', this.dragStop.bindE(this));
        this.dp = (par) ? par.fx() : false;
        return this;
    },

    dragMove: function(e)
    {
        //private window on mouse move function
        if (this.drag > -1)
        {
            var i = this.dpi, s = $getScroll(), l = e.clientX + s.sl, t = e.clientY + s.st, x = this.drag;
            this[x].style.left = (l - this.p[x].pl - this.tpl  - this.tps.sl) + 'px';
            this[x].style.top = (t - this.p[x].pt - this.tpt  - this.tps.st) + 'px';
            if (this.dp) i = this.dp.parentPosition(l,t);
            if (this.dpi != i) this.dp.addClass(this.o.selected, this.dpi = i);
        }
        return false;
    },

    dragStart: function(e)
    {
        //private on drag function, optional onDrag event, 'hides' element
        var el = e.target || e.srcElement, p = $getPos(el);
        this.drag = this.indexOf(el);
        this.tpl = e.clientX - p.pl;
        this.tpt = e.clientY - p.pt;
        this.tps = $getScroll();
        if (this.dp) this.dpi = this.odpi = this.dp.parentPosition(e.clientX + this.tps.sl, e.clientY + this.tps.st);
        if (this.dpi != -1) this.dp.addClass(this.o.selected, this.dpi);
        if (this.o.onDrag) this.o.onDrag(el);
        else this.hide(el);
    },

    dragStop: function(e)
    {
        //private on drop function, optional onDrop event, 'shows' element
        if (this.drag != -1)
        {
            e = this[this.drag];
            this.drag=-1;
            if (this.dp) this.dp.removeClass(this.o.selected);
            if (this.o.onDrop) this.o.onDrop(e);
            else this.show(e);
        }
    },

    parentIndex: function(c)
    {
        //finding first element in array that is parent of c by index
        var i = -1;
        do {
            c = c.parentNode;
            i = this.indexOf(c);
        } while (c && i==-1);
        return i;
    },

    parentPosition: function(l, t)
    {
        //finding first element in array that is parent of c by l: left and t: top position
        var i = -1, p;
        this.forEach(function(el,x)
        {
            p = this.p[x];
            if (l >= p.pl && l <= p.pl + p.ow && t >= p.pt && t <= p.pt + p.oh) i = x;
        }, this);
        return i;
    }
};


/*----------------jaxx.js16 Array functions ----------------*/
var $jaxxJS16 = {
    indexOf: function(sE, sI)
    { //javascript 1.6: finds the first index that is like sE, sI is optional start index
        for (var i=sI||0,l=this.length;i<l;i++) if (this[i]==sE) return i;
        return -1;
    },

    forEach: function(cB, tO)
    { //javascript 1.6: iterate thrue an array and calls cB on each iteration, t0 optionally overrides 'this'
        for (var i=0,l=this.length;i<l;i++) cB.call(tO,this[i],i,this);
    },

    filter: function(cB, tO)
    { //javascript 1.6: filter return values of cB that evaluets to true, t0 optionally overrides 'this'
        for(var i=0,r=[],l=this.length;i<l;i++) cB.call(tO,this[i],i,this) && r.push(this[i]);
        return r;
    },

    map: function(cB, tO)
    { //javascript 1.6: maps the return value of a callback function, t0 optionally overrides 'this'
        for(var i=0,r=[],l=this.length;i<l;i++) r[i] = cB.call(tO,this[i],i,this);
        return r;
    }
};
__extend.dynamic = $jaxxJS16;

/* --------------- jaxx.Ajax --------------- */
function $ajax(o,u)
{
    //init function for $ajax, if url is specified the call will be done imidently
    this.o = $ext({method: "GET"}, o || {});
    if (u)this.load(u, this.o.postBody || null);
}

$ajax.prototype = {
    last: '',
    load: function(u, pB){
        //function for re calling same ajax object with different url and postBody
        if (!this.req) this.req = new XMLHttpRequest();
        if ((u + '|' + pB) == this.last && !this.o.noCache) return this.done();
        this.last = (u + '|' + pB);
        if (0 < this.req.readyState && this.req.readyState < 4){
            this.req.onreadystatechange = function(){};
            this.req.abort();
        }
        this.req.open(this.o.method, u, true);
        this.req.onreadystatechange = function()
        {
            if (this.req.readyState==4)
            {
                if ( this.req.status == 200 || this.req.status == 0 ) this.done();
                else if (this.o.onError) this.o.onError(this.req.status, this.req.statusText);
                this.req.onreadystatechange = function(){};
            }}.bind(this);
        if (this.o.method=='POST')
        {
            this.req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded; charset=UTF-8');
            if (this.req.overrideMimeType) this.req.setRequestHeader('Connection', 'close');
        }
        this.req.setRequestHeader("X-Requested-With", "XMLHttpRequest");
        if (this.o.onSend) this.o.onSend(this.req, this.o, pB);
        if (this.o.onWait) this.o.onWait.show();
        this.req.send(pB || null);
        return this;
    },

    done: function()
    {
        //private function called when ajax call is done. Optional update element, preUpdate and onLoad callBacks.
        var r=this.req;
        var o=this.o;
        var el = ((o.update) ? o.update : false);
        if (el) el.innerHTML = (o.preUpdate)? o.preUpdate(r, o): r.responseText;
        if (this.o.onWait) this.o.onWait.hide();
        if (o.onLoad) o.onLoad(r, el, o);
    }
};

function $xslt( xml, xsl, v )
{
    //cross browser function for clientside  xsl transformation
    var xslP, tb, r = xml.responseText;
    if( document.implementation && document.implementation.createDocument )
    {
        xslP = new XSLTProcessor();
        xslP.importStylesheet( xsl.responseXML );
        if ( xslP.setParameter && v ) for ( name in v ) xslP.setParameter( null, name, v[name] );	
        tb = document.createElement("div");
        tb.appendChild( xslP.transformToFragment( xml.responseXML, document ) );
        r = tb.innerHTML;
    }
    else if( window.ActiveXObject )
    {
        var xslDoc = new ActiveXObject("Msxml2.FreeThreadedDOMDocument");
        xslDoc.async = false;
        xslDoc.loadXML( xsl.responseText );
        var xslT = new ActiveXObject("Msxml2.XSLTemplate"), xmlDoc = new ActiveXObject("Msxml2.DOMDocument");
        xslT.stylesheet = xslDoc;
        xslP = xslT.createProcessor();
        if ( v ) for ( name in v ) xslP.addParameter( name, v[name] );
        xmlDoc.async = false;
        xmlDoc.loadXML( r );
        xslP.input = xmlDoc;
        xslP.transform();
        r = xslP.output;
    }
    return r;
}


function $json( str, oC )
{
    //json function, str handles both script url(optional onComplete callback) and script string
    var scr = document.createElement('script');
    scr.type = 'text/javascript';
    if (str.indexOf('.js') != -1)
    {
        scr.src = str;
        if (oC) $addEvent(script, 'load', oC);
    } else scr.text = str;
    $$('head')[0].appendChild(scr);
}
