/*
 * jQuery Easing v1.3 - #1#
 * jQuery history plugin - #2#
 * jQuery router plugin 0.4.4 - (modified) - #3#
 * jQuery VGrid - v0.1.6 - (modified) - #4#
 * jQuery BBQ: Back Button & Query Library - v1.2.1 - ($.deparam method only) - #5#
 * jQuery.ScrollTo - 1.4.2 - #6#
 * jQuery Templates Plugin - preBeta1.0.1 - #7#
 * jQuery Form Plugin - 2.47 - (modified) - НЕ ОБНОВЛЯТЬ - #8#
 * jQuery validation plug-in - 1.7 - (modified) - НЕ ОБНОВЛЯТЬ - #9#
 * jQuery UI Core - 1.8.7 -  #10#
 * jQuery UI Widget - 1.8.7 - #11#
 * jQuery UI Mouse - 1.8.7 - #12#
 * jQuery UI Draggable - 1.8.7 - #13#
 * jQuery Alert Dialogs Plugin - (modified) - 1.1 - #14#
 * jQuery Cookie plugin - January 09, 2010 - #15#
 * jQuery UI Slider 1.8.7 - #16#
 * jQuery Mousewheel 3.0.4 - #17#
 * jQuery resize event - v1.1 - 3/14/2010 - (modified str_delay) - #18#
 * jQuery UI Tabs - 1.8.7 - #19#
 * jquery.Jcrop.js v0.9.8 - #20#
*/

/* #1# */
/*
 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
 *
 * Uses the built in easing capabilities added In jQuery 1.1
 * to offer multiple easing options
 *
 * Open source under the BSD License. 
 * 
 * Copyright © 2008 George McGinley Smith
 * All rights reserved.
 *
*/

// t: current time, b: begInnIng value, c: change In value, d: duration
jQuery.easing['jswing'] = jQuery.easing['swing'];

jQuery.extend( jQuery.easing,
{
    def: 'easeOutQuad',
    swing: function (x, t, b, c, d) {
        //alert(jQuery.easing.default);
        return jQuery.easing[jQuery.easing.def](x, t, b, c, d);
    },
    easeInQuad: function (x, t, b, c, d) {
        return c*(t/=d)*t + b;
    },
    easeOutQuad: function (x, t, b, c, d) {
        return -c *(t/=d)*(t-2) + b;
    },
    easeInOutQuad: function (x, t, b, c, d) {
        if ((t/=d/2) < 1) return c/2*t*t + b;
        return -c/2 * ((--t)*(t-2) - 1) + b;
    },
    easeInCubic: function (x, t, b, c, d) {
        return c*(t/=d)*t*t + b;
    },
    easeOutCubic: function (x, t, b, c, d) {
        return c*((t=t/d-1)*t*t + 1) + b;
    },
    easeInOutCubic: function (x, t, b, c, d) {
        if ((t/=d/2) < 1) return c/2*t*t*t + b;
        return c/2*((t-=2)*t*t + 2) + b;
    },
    easeInQuart: function (x, t, b, c, d) {
        return c*(t/=d)*t*t*t + b;
    },
    easeOutQuart: function (x, t, b, c, d) {
        return -c * ((t=t/d-1)*t*t*t - 1) + b;
    },
    easeInOutQuart: function (x, t, b, c, d) {
        if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
        return -c/2 * ((t-=2)*t*t*t - 2) + b;
    },
    easeInQuint: function (x, t, b, c, d) {
        return c*(t/=d)*t*t*t*t + b;
    },
    easeOutQuint: function (x, t, b, c, d) {
        return c*((t=t/d-1)*t*t*t*t + 1) + b;
    },
    easeInOutQuint: function (x, t, b, c, d) {
        if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
        return c/2*((t-=2)*t*t*t*t + 2) + b;
    },
    easeInSine: function (x, t, b, c, d) {
        return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
    },
    easeOutSine: function (x, t, b, c, d) {
        return c * Math.sin(t/d * (Math.PI/2)) + b;
    },
    easeInOutSine: function (x, t, b, c, d) {
        return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
    },
    easeInExpo: function (x, t, b, c, d) {
        return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
    },
    easeOutExpo: function (x, t, b, c, d) {
        return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
    },
    easeInOutExpo: function (x, t, b, c, d) {
        if (t==0) return b;
        if (t==d) return b+c;
        if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
        return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
    },
    easeInCirc: function (x, t, b, c, d) {
        return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
    },
    easeOutCirc: function (x, t, b, c, d) {
        return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
    },
    easeInOutCirc: function (x, t, b, c, d) {
        if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
        return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
    },
    easeInElastic: function (x, t, b, c, d) {
        var s=1.70158;
        var p=0;
        var a=c;
        if (t==0) return b;
        if ((t/=d)==1) return b+c;
        if (!p) p=d*.3;
        if (a < Math.abs(c)) {
            a=c;
            var s=p/4;
        }
        else var s = p/(2*Math.PI) * Math.asin (c/a);
        return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
    },
    easeOutElastic: function (x, t, b, c, d) {
        var s=1.70158;
        var p=0;
        var a=c;
        if (t==0) return b;
        if ((t/=d)==1) return b+c;
        if (!p) p=d*.3;
        if (a < Math.abs(c)) {
            a=c;
            var s=p/4;
        }
        else var s = p/(2*Math.PI) * Math.asin (c/a);
        return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
    },
    easeInOutElastic: function (x, t, b, c, d) {
        var s=1.70158;
        var p=0;
        var a=c;
        if (t==0) return b;
        if ((t/=d/2)==2) return b+c;
        if (!p) p=d*(.3*1.5);
        if (a < Math.abs(c)) {
            a=c;
            var s=p/4;
        }
        else var s = p/(2*Math.PI) * Math.asin (c/a);
        if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
        return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
    },
    easeInBack: function (x, t, b, c, d, s) {
        if (s == undefined) s = 1.70158;
        return c*(t/=d)*t*((s+1)*t - s) + b;
    },
    easeOutBack: function (x, t, b, c, d, s) {
        if (s == undefined) s = 1.70158;
        return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
    },
    easeInOutBack: function (x, t, b, c, d, s) {
        if (s == undefined) s = 1.70158;
        if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
        return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
    },
    easeInBounce: function (x, t, b, c, d) {
        return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b;
    },
    easeOutBounce: function (x, t, b, c, d) {
        if ((t/=d) < (1/2.75)) {
            return c*(7.5625*t*t) + b;
        } else if (t < (2/2.75)) {
            return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
        } else if (t < (2.5/2.75)) {
            return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
        } else {
            return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
        }
    },
    easeInOutBounce: function (x, t, b, c, d) {
        if (t < d/2) return jQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
        return jQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
    }
});

/* #2# */
/*
 * jQuery history plugin
 * 
 * The MIT License
 * 
 * Copyright (c) 2006-2009 Taku Sano (Mikage Sawatari)
 * Copyright (c) 2010 Takayuki Miwa
 */

(function($) {
    var locationWrapper = {
        put: function(hash, win) {
            (win || window).location.hash = this.encoder(hash);
        },
        get: function(win) {
            var hash = ((win || window).location.hash).replace(/^#/, '');
            try {
                return $.browser.mozilla ? hash : decodeURIComponent(hash);
            }
            catch (error) {
                return hash;
            }
        },
        encoder: encodeURIComponent
    };

    var iframeWrapper = {
        id: "__jQuery_history",
        init: function() {
            var html = '<iframe id="'+ this.id +'" style="display:none" src="javascript:false;" />';
            $("body").prepend(html);
            return this;
        },
        _document: function() {
            return $("#"+ this.id)[0].contentWindow.document;
        },
        put: function(hash) {
            var doc = this._document();
            doc.open();
            doc.close();
            locationWrapper.put(hash, doc);
        },
        get: function() {
            return locationWrapper.get(this._document());
        }
    };

    function initObjects(options) {
        options = $.extend({
            unescape: false
        }, options || {});

        locationWrapper.encoder = encoder(options.unescape);

        function encoder(unescape_) {
            if(unescape_ === true) {
                return function(hash){
                    return hash;
                };
            }
            if(typeof unescape_ == "string" &&
                (unescape_ = partialDecoder(unescape_.split("")))
                || typeof unescape_ == "function") {
                return function(hash) {
                    return unescape_(encodeURIComponent(hash));
                };
            }
            return encodeURIComponent;
        }

        function partialDecoder(chars) {
            var re = new RegExp($.map(chars, encodeURIComponent).join("|"), "ig");
            return function(enc) {
                return enc.replace(re, decodeURIComponent);
            };
        }
    }

    var implementations = {};

    implementations.base = {
        callback: undefined,
        type: undefined,

        check: function() {},
        load:  function(hash) {},
        init:  function(callback, options) {
            initObjects(options);
            self.callback = callback;
            self._options = options;
            self._init();
        },

        _init: function() {},
        _options: {}
    };

    implementations.timer = {
        _appState: undefined,
        _init: function() {
            var current_hash = locationWrapper.get();
            self._appState = current_hash;
            self.callback(current_hash);
            setInterval(self.check, 100);
        },
        check: function() {
            var current_hash = locationWrapper.get();
            if(current_hash != self._appState) {
                self._appState = current_hash;
                self.callback(current_hash);
            }
        },
        load: function(hash) {
            if(hash != self._appState) {
                locationWrapper.put(hash);
                self._appState = hash;
                self.callback(hash);
            }
        }
    };

    implementations.iframeTimer = {
        _appState: undefined,
        _init: function() {
            var current_hash = locationWrapper.get();
            self._appState = current_hash;
            iframeWrapper.init().put(current_hash);
            self.callback(current_hash);
            setInterval(self.check, 100);
        },
        check: function() {
            var iframe_hash = iframeWrapper.get(),
            location_hash = locationWrapper.get();

            if (location_hash != iframe_hash) {
                if (location_hash == self._appState) {    // user used Back or Forward button
                    self._appState = iframe_hash;
                    locationWrapper.put(iframe_hash);
                    self.callback(iframe_hash); 
                } else {                              // user loaded new bookmark
                    self._appState = location_hash;  
                    iframeWrapper.put(location_hash);
                    self.callback(location_hash);
                }
            }
        },
        load: function(hash) {
            if(hash != self._appState) {
                locationWrapper.put(hash);
                iframeWrapper.put(hash);
                self._appState = hash;
                self.callback(hash);
            }
        }
    };

    implementations.hashchangeEvent = {
        _init: function() {
            self.callback(locationWrapper.get());
            $(window).bind('hashchange', self.check);
        },
        check: function() {
            self.callback(locationWrapper.get());
        },
        load: function(hash) {
            locationWrapper.put(hash);
        }
    };

    var self = $.extend({}, implementations.base);

    if($.browser.msie && ($.browser.version < 8 || document.documentMode < 8)) {
        self.type = 'iframeTimer';
    } else if("onhashchange" in window) {
        self.type = 'hashchangeEvent';
    } else {
        self.type = 'timer';
    }

    $.extend(self, implementations[self.type]);
    $.history = self;
})(jQuery);


/* #3# */
/*
 * jQuery router plugin 0.4.4 (modefied)
 * 
 * The BSD licenses
 * http://en.wikipedia.org/wiki/BSD_licenses
 * 
 * url http://ti.y1.ru/jquery/router/
 * author Ti
 *
 */
 
(function($) {
    var list = [];
    var history = [];

    var RouterRegExp = function(regExp, init, leave) {
		
        var matches, _leave
        this.test = function(hash) {
            matches = regExp.exec(hash)
            return matches && true
        }
        this.exec = function() {
            _leave = init.apply(null, matches) || leave
            return 'function' == typeof _leave
        }
        this.leave = function() {
            _leave.apply(null, matches)
        }
        this.remove = function(sign) {
            if (regExp == sign) return true
            if (init == sign) return true
            if (leave == sign) delete leave
            if (_leave == sign) _leave = null
            return false
        }
    }
    var RouterStatic = function(name, init, leave) {
        this.test = function(hash) {
            return name == hash
        }
        this.exec = function() {
            this.leave = init() || leave
            return 'function' == typeof this.leave
        }
        this.remove = function(sign) {
            if (name == sign) return true
            if (init == sign) return true
            if (leave == sign) delete leave
            return false
        }
    }
    var RouterMap = function(map, leave) {
        var init
        this.test = function(hash) {
            init = map[hash]
            return init && true
        }
        this.exec = function(hash) {
            this.leave = init() || leave
            return 'function' == typeof this.leave
        }
        this.remove = function(sign) {
            if (map == sign) return true

            do {
                var found = false
                $.each(map, function(key, value) {
                    if (key == sign || value == sign) {
                        found = key
                        return false
                    }
                })
                if (found) {
                    delete map[found]
                }
            }
            while(found)

            if (init == sign) return true
            if (leave == sign) delete leave
            return false
        }
    }
    var RouterCallback = function(callback, leave) {
        var init
        this.test = function(hash) {
            init = callback(hash)
            return init && true
        }
        this.exec = function() {
            this.leave = init() || leave
            return 'function' == typeof this.leave
        }
        this.remove = function(sign) {
            if (callback == sign) return true
            if (leave == sign) delete leave
            return false
        }
    }
    var RouterLeave = function(callback) {
        this.test = function() {
            return false
            }
        this.exec = function() {
            return false
            }
        this.leave = function() {
            callback()
            $.router.remove(callback)
        }
        this.remove = function(sign) {
            return callback == sign
        }
    }
    var nr = false;
    var run = function(hash) {
        var i = list.length-1, found = false, lnr = nr;
        while(!found && 0 <= i) {
            found = list[i].test(hash)
            if (found) {
                runRouter(list[i])
                nr = i;
            }
            i--
        }
        history.push(hash);
        
        return {
            found: found,
            change: (nr != lnr)
            };
    }
	
    var runLeave = function() {
        if (leaveRouter) {
            leaveRouter.leave()
            leaveRouter = null
        }
    }

    var runRouter = function(router) {
        if (router.exec()) leaveRouter = router;
    }

	
    var n = false;
    $.router = function(key, callback, leave) {
        var r;
        if (key instanceof RegExp){
            r = new RouterRegExp(key, callback, leave)
        }else if ('function' == typeof key){
            r = new RouterCallback(key, callback)
        }else if ('object' == typeof key){
            r = new RouterMap(key, callback)
        }else{
            r = new RouterStatic(key, callback, leave)
        }
        
        list.push(r)
        var hash = $.router.last()
        // если добавили с текущим хешом - запускаем
        if (r.test(hash)) {
            nr = n;
            $.router.isFound = true;
            runLeave()
            // извлекаем текущий хеш из истории
            $.router.pop()
            // запуск
            runRouter(r)
            // ложим обратно в историю
            history.push(hash)
			
        }
        n++;
        return $
    }
    $.router.isFound = false;

    $.router.last = function() {
        return 0 < history.length ? history[history.length-1] : ''
    }


    $.router.pop = function() {
        return history.pop()
    }

    $.router.remove = function(remove) {
        // без аргументов - очистить все
        if (0 == arguments.length) {
            list = []
            leaveRouter = null
            return $
        }

        // убрать конкретные
        $(arguments).each(function(i, signRoute) {
            var r, newList = []
            while(r = list.pop()) {
                if (r.leave == signRoute) {
                    r.leave = null
                    if (leaveRouter == r) leaveRouter = null
                }
                if (r.remove(signRoute)) {
                    if (leaveRouter == r) leaveRouter = null
                    continue
                }
                newList.push(r)
            }
            list = newList
        })

        return $
    }
	
    $.router.leave = function(fn) {
        if ('function' !== typeof fn) throw new Error('Invalid leave callback. Function required!')
        leaveRouter = new RouterLeave(fn)
        return $
    }
	
    $.router.notFound = false;
    $.router.hashChange = false;
    $.router.change = false;
	
    var leaveRouter
    var boot = false;
	
    $.router.init = function() {
        $.history.init(function(hash) {
            runLeave();
            var r = run(hash);
            if(boot && !r.found && $.isFunction($.router.notFound)){
                $.router.notFound.call($, hash);
            }
            if($.isFunction($.router.hashChange)){
                $.router.hashChange.call($, hash);
            }
            if(r.change && $.isFunction($.router.change)){
                $.router.change.call($, hash);
            }
        },
        {
            unescape: '/?=&'
        }
        )
        boot = true;
    }

//if ($.browser.msie) $(window).load($.router.init)
//else $.router.init()
})(jQuery);

/* #4# */
/*
 * jQuery VGrid v0.1.6 - variable grid layout plugin
 *
 * Terms of Use - jQuery VGrid
 * under the MIT (http://www.opensource.org/licenses/mit-license.php) License.
 *
 * Copyright 2009-2010 xlune.com All rights reserved.
 * (http://blog.xlune.com/2009/09/jqueryvgrid.html)
 */
(function($)
{
    function makePos(self)
    {
        var _childs = self.data("_vgchild");
        var _width = self.width();
        var _matrix = [[0,_width,0]];
        var _hmax=0, _c, _size, _point, _wmax=0;
        _childs.each(function(i)
        {
            _c = $(this);
            _size = getSize(_c);
            _point = getAttachPoint(_matrix, _size[0]);
            _matrix = updateAttachArea(_matrix, _point, _size);
            _hmax = Math.max(_hmax, _point[1] + _size[1]);
            _wmax = Math.max(_wmax, _point[0] + _size[0]);
            _c.data("_vgleft", _point[0]);
            _c.data("_vgtop", _point[1]);
        });
        self.data("_vgwrapheight", _hmax);
        self.data("_vgwrapwidth", _wmax);
        heightTo(self);
        self.width(_wmax)
    };
    function getAttachPoint(mtx, width)
    {
        var _mtx = mtx.concat().sort(matrixSortDepth);
        var _max = _mtx[_mtx.length-1][2];
        for(var i=0,imax=_mtx.length; i<imax; i++)
        {
            if(_mtx[i][2] >= _max) break;
            if(_mtx[i][1]-_mtx[i][0] >= width)
            {
                return [_mtx[i][0], _mtx[i][2]];
            }
        }
        return [0, _max];
    };
    function updateAttachArea(mtx, point, size)
    {
        var _mtx = mtx.concat().sort(matrixSortDepth);
        var _cell = [point[0], point[0]+size[0], point[1]+size[1]];
        for(var i=0,imax=_mtx.length; i<imax; i++)
        {
            if(_cell[0] <= _mtx[i][0] && _mtx[i][1] <= _cell[1])
            {
                delete _mtx[i];
            }
            else
            {
                _mtx[i] = matrixTrimWidth(_mtx[i], _cell);
            }
        }
        return matrixJoin(_mtx, _cell);
    };
    function matrixSortDepth(a, b)
    {
        if(!a || !b) return 0;
        return ((a[2] == b[2] && a[0] > b[0]) || a[2] > b[2]) ? 1 : -1;
    };
    function matrixSortX(a, b)
    {
        if(!a || !b) return 0;
        return (a[0] > b[0]) ? 1 : -1;
    };
    function matrixJoin(mtx, cell)
    {
        var _mtx = mtx.concat([cell]).sort(matrixSortX);
        var _mtx_join = [];
        for(var i=0,imax=_mtx.length; i<imax; i++)
        {
            if(!_mtx[i]) continue;
            if(_mtx_join.length > 0
                && _mtx_join[_mtx_join.length-1][1] == _mtx[i][0]
                && _mtx_join[_mtx_join.length-1][2] == _mtx[i][2])
                {
                _mtx_join[_mtx_join.length-1][1] = _mtx[i][1];
            }
            else
            {
                _mtx_join.push(_mtx[i]);
            }
        }
        return _mtx_join;
    };
    function matrixTrimWidth(a, b)
    {
        if(a[0] >= b[0] && a[0] < b[1] || a[1] >= b[0] && a[1] < b[1])
        {
            if(a[0] >= b[0] && a[0] < b[1])
            {
                a[0] = b[1];
            }
            else
            {
                a[1] = b[0];
            }
        }
        return a;
    };
    function getSize(child)
    {
        var _w = child.width();
        var _h = child.height();
        _w += Number(child.css("margin-left").replace('px', ''))
        +Number(child.css("padding-left").replace('px', ''))
        +Number(child.get(0).style.borderLeftWidth.replace('px', ''))
        +Number(child.css("margin-right").replace('px', ''))
        +Number(child.css("padding-right").replace('px', ''))
        +Number(child.get(0).style.borderRightWidth.replace('px', ''));
        _h += Number(child.css("margin-top").replace('px', ''))
        +Number(child.css("padding-top").replace('px', ''))
        +Number(child.get(0).style.borderTopWidth.replace('px', ''))
        +Number(child.css("margin-bottom").replace('px', ''))
        +Number(child.css("padding-bottom").replace('px', ''))
        +Number(child.get(0).style.borderBottomWidth.replace('px', ''));
        return [_w, _h];
    };
    function heightTo(self)
    {
        var _self = self;
        var _delay = _self.data("_vgchild").length
        * (_self.data("_vgopt").delay || 0)
        + _self.data("_vgopt").time || 500;
        _self.stop();
        if(_self.height() < _self.data("_vgwrapheight"))
        {
            if($.browser.msie)
            {
                _self.height(_self.data("_vgwrapheight"));
            }
            else
            {
                _self.animate(
                {
                    height: _self.data("_vgwrapheight")+"px"
                },
                (_self.data("_vgopt").time || 500),
                    "easeOutQuart"
                    );
            }
        }
        else
        {
            clearTimeout(_self.data("_vgwraptimeout"));
            _self.data("_vgwraptimeout", setTimeout(function(){
                if($.browser.msie)
                {
                    _self.height(_self.data("_vgwrapheight"));
                }
                else
                {
                    _self.animate(
                    {
                        height: _self.data("_vgwrapheight")+"px"
                    },
                    (_self.data("_vgopt").time || 500),
                        "easeOutQuart"
                        );
                }
            }, _delay));
        }
    };
    function moveTo(childs)
    {
        var _c;
        childs.each(function(i)
        {
            _c = $(this);
            _c.css("left", ~~_c.data("_vgleft")+"px");
            _c.css("top", ~~_c.data("_vgtop")+"px");
        });
    };
    function animateTo(childs, easing, time, delay)
    {
        var _self = $(childs).parent();
        var isMove = false;
        var imax = childs.length;
        var i,_c,_pos;
        for(i=0; i<imax; i++)
        {
            _c = $(childs[i]);
            _pos = _c.position();
            if(_pos.left != _c.data("_vgleft") && _pos.top != _c.data("_vgtop"))
            {
                isMove = true;
            }
        }
        if(isMove)
        {
            if(typeof(_self.data("_vgopt").onStart) == "function") _self.data("_vgopt").onStart();
            childs.each(function(i)
            {
                var _c = $(this);
                var _opt = {
                    duration: time,
                    easing: easing
                };
                if(childs.size()-1 == i)
                {
                    _opt.complete = _self.data("_vgopt").onFinish || null;
                }
                clearTimeout(_c.data("_vgtimeout"));
                _c.data("_vgtimeout", setTimeout(function(){
                    _c.animate(
                    {
                        left: _c.data("_vgleft")+"px",
                        top: _c.data("_vgtop")+"px"
                    },
                    _opt
                    );
                }, i*delay));
            });
        }
    };
    function refleshHandler(tg)
    {
        var _self = tg;
        clearTimeout(_self.data("_vgtimeout"));
        makePos(_self);
        _self.data("_vgtimeout", setTimeout(function(){
            animateTo(
                _self.data("_vgchild"),
                _self.data("_vgopt").easeing || "linear",
                _self.data("_vgopt").time || 500,
                _self.data("_vgopt").delay || 0
                );
        }, 500));
    };
    function setFontSizeListener(self, func)
    {
        var s = $("<span />")
        .text(" ")
        .attr("id", "_vgridspan")
        .hide()
        .appendTo("body");
        s.data("size", s.css("font-size"));
        s.data("timer", setInterval(function(){
            if(s.css("font-size") != s.data("size"))
            {
                s.data("size", s.css("font-size"));
                func(self);
            }
        }, 1000));
    };
    function setImgLoadEvent(self, func)
    {
        self.bind("vgrid-added", function(){
            self.find("img").bind("load", function(){
                func(self);
            });
        });
        self.trigger("vgrid-added");
        var _append = self.append;
        var _prepend = self.prepend;
        self.append = function(){
            _append.apply(self, arguments);
            self.trigger("vgrid-added");
        };
        self.prepend = function(){
            _prepend.apply(self, arguments);
            self.trigger("vgrid-added");
        };
    };
    $.fn.extend({
        vgrid: function(option)
        {
            var _self = $(this);
            var _opt = option || {};
            _self.data("_vgopt", _opt);
            _self.data("_vgchild", _self.find("> *"));
            _self.data("_vgdefchild", _self.data("_vgchild"));
            _self.css({
                "position": "relative",
                "width": "auto"
            });
            _self.data("_vgchild").css("position", "absolute");
            makePos(_self);
            moveTo(_self.data("_vgchild"));
            if(_self.data("_vgopt").fadeIn)
            {
                var _prop = (typeof(_self.data("_vgopt").fadeIn)=='object')
                ? _self.data("_vgopt").fadeIn
                : {
                    time: _self.data("_vgopt").fadeIn
                    } ;
                _self.data("_vgchild").each(function(i)
                {
                    var _c = $(this);
                    _c.css('display', 'none');
                    setTimeout(function(){
                        _c.fadeIn(_prop.time || 250);
                    }, i * (_prop.delay || 0));
                });
            }
            $(window).unbind('resize.variableGrid').bind('resize.variableGrid', function(e)
            {
                _self.width('auto');
                refleshHandler(_self);
            });

            if(_opt.useLoadImageEvent) setImgLoadEvent(_self, refleshHandler);
            if(_opt.useFontSizeListener) setFontSizeListener(_self, refleshHandler);
            return _self;
        },
        vgrefresh: function(easeing, time, delay, func)
        {
            var _obj = $(this);
            _obj.width('auto');
            if(_obj.data("_vgchild"))
            {
                _obj.data("_vgchild", _obj.find("> *"));
                _obj.data("_vgchild").css("position", "absolute");
                makePos(_obj);
                time = typeof(time)=="number" ? time : _obj.data("_vgopt").time || 500;
                delay = typeof(delay)=="number" ? delay : _obj.data("_vgopt").delay || 0;
                animateTo(
                    _obj.data("_vgchild"),
                    easeing || _obj.data("_vgopt").easeing || "linear",
                    time,
                    delay
                    );
                if(typeof(func)=='function')
                {
                    setTimeout(
                        func,
                        _obj.data("_vgchild").length * delay + time
                        );
                }
            }
            return _obj;
        },
        vgrepos: function(){
            var _obj = $(this);
            _obj.width('auto');
            if(_obj.data("_vgchild"))
            {
                _obj.data("_vgchild", _obj.find("> *"));
                _obj.data("_vgchild").css("position", "absolute");
                _obj.data("_vgchild").css("position", "absolute");
                makePos(_obj);
                moveTo(_obj.data("_vgchild"));
            }
        },
        vgsort: function(func, easeing, time, delay)
        {
            var _obj = $(this);
            if(_obj.data("_vgchild"))
            {
                _obj.data("_vgchild", _obj.data("_vgchild").sort(func));
                _obj.data("_vgchild").each(function(num){
                    $(this).appendTo(_obj);
                });
                makePos(_obj);
                animateTo(
                    _obj.data("_vgchild"),
                    easeing || _obj.data("_vgopt").easeing || "linear",
                    typeof(time)=="number" ? time : _obj.data("_vgopt").time || 500,
                    typeof(delay)=="number" ? delay : _obj.data("_vgopt").delay || 0
                    );
            }
            return _obj;
        }
    });
})(jQuery);

/* #5# */
/*
 * jQuery BBQ: Back Button & Query Library - v1.2.1 - 2/17/2010
 * http://benalman.com/projects/jquery-bbq-plugin/
 * 
 * Copyright (c) 2010 "Cowboy" Ben Alman
 * Dual licensed under the MIT and GPL licenses.
 * http://benalman.com/about/license/
 *
 * $.deparam method only
 */
$.deparam = function( params, coerce ) {
    var obj = {},
    coerce_types = {
        'true': !0,
        'false': !1,
        'null': null
    };
    $.each( params.replace( /\+/g, ' ' ).split( '&' ), function(j,v){
        var param = v.split( '=' ),
        key = decodeURIComponent( param[0] ),
        val,
        cur = obj,
        i = 0,
        keys = key.split( '][' ),
        keys_last = keys.length - 1;
        if ( /\[/.test( keys[0] ) && /\]$/.test( keys[ keys_last ] ) ) {
            keys[ keys_last ] = keys[ keys_last ].replace( /\]$/, '' );
            keys = keys.shift().split('[').concat( keys );
            keys_last = keys.length - 1;
        } else {
            keys_last = 0;
        }
        if ( param.length === 2 ) {
            val = decodeURIComponent( param[1] );
            if ( coerce ) {
                val = val && !isNaN(val) ? +val
                : val === 'undefined' ? undefined
                : coerce_types[val] !== undefined ? coerce_types[val]
                : val;
            }
            if ( keys_last ) {
                for ( ; i <= keys_last; i++ ) {
                    key = keys[i] === '' ? cur.length : keys[i];
                    cur = cur[key] = i < keys_last ? cur[key] || ( keys[i+1] && isNaN( keys[i+1] ) ? {} : [] ) : val;
                }
            } else {
                if ( $.isArray( obj[key] ) ) {
                    obj[key].push( val );
                } else if ( obj[key] !== undefined ) {
                    obj[key] = [ obj[key], val ];
                } else {
                    obj[key] = val;
                }
            }
        } else if ( key ) {
            obj[key] = coerce ? undefined : '';
        }
    });
    return obj;
};

/* #6# */
/*
 * jQuery.ScrollTo
 * Copyright (c) 2007-2009 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
 * Dual licensed under MIT and GPL.
 * Date: 5/25/2009
 *
 * projectDescription Easy element scrolling using jQuery.
 * http://flesler.blogspot.com/2007/10/jqueryscrollto.html
 * Works with jQuery +1.2.6. Tested on FF 2/3, IE 6/7/8, Opera 9.5/6, Safari 3, Chrome 1 on WinXP.
 *
 * author Ariel Flesler
 * version 1.4.2
 */
;
(function( $ ){
	
    var $scrollTo = $.scrollTo = function( target, duration, settings ){
        $(window).scrollTo( target, duration, settings );
    };

    $scrollTo.defaults = {
        axis:'xy',
        duration: parseFloat($.fn.jquery) >= 1.3 ? 0 : 1
    };

    // Returns the element that needs to be animated to scroll the window.
    // Kept for backwards compatibility (specially for localScroll & serialScroll)
    $scrollTo.window = function( scope ){
        return $(window)._scrollable();
    };

    // Hack, hack, hack :)
    // Returns the real elements to scroll (supports window/iframes, documents and regular nodes)
    $.fn._scrollable = function(){
        return this.map(function(){
            var elem = this,
            isWin = !elem.nodeName || $.inArray( elem.nodeName.toLowerCase(), ['iframe','#document','html','body'] ) != -1;

            if( !isWin )
                return elem;

            var doc = (elem.contentWindow || elem).document || elem.ownerDocument || elem;
			
            return $.browser.safari || doc.compatMode == 'BackCompat' ?
            doc.body :
            doc.documentElement;
        });
    };

    $.fn.scrollTo = function( target, duration, settings ){
        if( typeof duration == 'object' ){
            settings = duration;
            duration = 0;
        }
        if( typeof settings == 'function' )
            settings = {
                onAfter:settings
            };
			
        if( target == 'max' )
            target = 9e9;
			
        settings = $.extend( {}, $scrollTo.defaults, settings );
        // Speed is still recognized for backwards compatibility
        duration = duration || settings.speed || settings.duration;
        // Make sure the settings are given right
        settings.queue = settings.queue && settings.axis.length > 1;
		
        if( settings.queue )
            // Let's keep the overall duration
            duration /= 2;
        settings.offset = both( settings.offset );
        settings.over = both( settings.over );

        return this._scrollable().each(function(){
            var elem = this,
            $elem = $(elem),
            targ = target, toff, attr = {},
            win = $elem.is('html,body');

            switch( typeof targ ){
                // A number will pass the regex
                case 'number':
                case 'string':
                    if( /^([+-]=)?\d+(\.\d+)?(px|%)?$/.test(targ) ){
                        targ = both( targ );
                        // We are done
                        break;
                    }
                    // Relative selector, no break!
                    targ = $(targ,this);
                case 'object':
                    // DOMElement / jQuery
                    if( targ.is || targ.style )
                        // Get the real position of the target
                        toff = (targ = $(targ)).offset();
            }
            $.each( settings.axis.split(''), function( i, axis ){
                var Pos	= axis == 'x' ? 'Left' : 'Top',
                pos = Pos.toLowerCase(),
                key = 'scroll' + Pos,
                old = elem[key],
                max = $scrollTo.max(elem, axis);

                if( toff ){// jQuery / DOMElement
                    attr[key] = toff[pos] + ( win ? 0 : old - $elem.offset()[pos] );

                    // If it's a dom element, reduce the margin
                    if( settings.margin ){
                        attr[key] -= parseInt(targ.css('margin'+Pos)) || 0;
                        attr[key] -= parseInt(targ.css('border'+Pos+'Width')) || 0;
                    }
					
                    attr[key] += settings.offset[pos] || 0;
					
                    if( settings.over[pos] )
                        // Scroll to a fraction of its width/height
                        attr[key] += targ[axis=='x'?'width':'height']() * settings.over[pos];
                }else{
                    var val = targ[pos];
                    // Handle percentage values
                    attr[key] = val.slice && val.slice(-1) == '%' ?
                    parseFloat(val) / 100 * max
                    : val;
                }

                // Number or 'number'
                if( /^\d+$/.test(attr[key]) )
                    // Check the limits
                    attr[key] = attr[key] <= 0 ? 0 : Math.min( attr[key], max );

                // Queueing axes
                if( !i && settings.queue ){
                    // Don't waste time animating, if there's no need.
                    if( old != attr[key] )
                        // Intermediate animation
                        animate( settings.onAfterFirst );
                    // Don't animate this axis again in the next iteration.
                    delete attr[key];
                }
            });

            animate( settings.onAfter );

            function animate( callback ){
                $elem.animate( attr, duration, settings.easing, callback && function(){
                    callback.call(this, target, settings);
                });
            };

        }).end();
    };
	
    // Max scrolling position, works on quirks mode
    // It only fails (not too badly) on IE, quirks mode.
    $scrollTo.max = function( elem, axis ){
        var Dim = axis == 'x' ? 'Width' : 'Height',
        scroll = 'scroll'+Dim;
		
        if( !$(elem).is('html,body') )
            return elem[scroll] - $(elem)[Dim.toLowerCase()]();
		
        var size = 'client' + Dim,
        html = elem.ownerDocument.documentElement,
        body = elem.ownerDocument.body;

        return Math.max( html[scroll], body[scroll] )
        - Math.min( html[size]  , body[size]   );
			
    };

    function both( val ){
        return typeof val == 'object' ? val : {
            top:val,
            left:val
        };
    };

})( jQuery );

/* #7# */
/*
 * jQuery Templates Plugin preBeta1.0.1
 * http://github.com/jquery/jquery-tmpl
 *
 * Copyright Software Freedom Conservancy, Inc.
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 */
(function( jQuery, undefined ){
    var oldManip = jQuery.fn.domManip, tmplItmAtt = "_tmplitem", htmlExpr = /^[^<]*(<[\w\W]+>)[^>]*$|\{\{\! /,
    newTmplItems = {}, wrappedItems = {}, appendToTmplItems, topTmplItem = {
        key: 0,
        data: {}
}, itemKey = 0, cloneIndex = 0, stack = [];

function newTmplItem( options, parentItem, fn, data ) {
    // Returns a template item data structure for a new rendered instance of a template (a 'template item').
    // The content field is a hierarchical array of strings and nested items (to be
    // removed and replaced by nodes field of dom elements, once inserted in DOM).
    var newItem = {
        data: data || (parentItem ? parentItem.data : {}),
        _wrap: parentItem ? parentItem._wrap : null,
        tmpl: null,
        parent: parentItem || null,
        nodes: [],
        calls: tiCalls,
        nest: tiNest,
        wrap: tiWrap,
        html: tiHtml,
        update: tiUpdate
    };
    if ( options ) {
        jQuery.extend( newItem, options, {
            nodes: [],
            parent: parentItem,
            data: newItem.data
            });
    }
    if ( fn ) {
        // Build the hierarchical content to be used during insertion into DOM
        newItem.tmpl = fn;
        newItem._ctnt = newItem._ctnt || newItem.tmpl( jQuery, newItem );
        newItem.key = ++itemKey;
        // Keep track of new template item, until it is stored as jQuery Data on DOM element
        (stack.length ? wrappedItems : newTmplItems)[itemKey] = newItem;
    }
    return newItem;
}

// Override appendTo etc., in order to provide support for targeting multiple elements. (This code would disappear if integrated in jquery core).
jQuery.each({
    appendTo: "append",
    prependTo: "prepend",
    insertBefore: "before",
    insertAfter: "after",
    replaceAll: "replaceWith"
}, function( name, original ) {
    jQuery.fn[ name ] = function( selector ) {
        var ret = [], insert = jQuery( selector ), elems, i, l, tmplItems,
        parent = this.length === 1 && this[0].parentNode;

        appendToTmplItems = newTmplItems || {};
        if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {
            insert[ original ]( this[0] );
            ret = this;
        } else {
            for ( i = 0, l = insert.length; i < l; i++ ) {
                cloneIndex = i;
                elems = (i > 0 ? this.clone(true) : this).get();
                jQuery.fn[ original ].apply( jQuery(insert[i]), elems );
                ret = ret.concat( elems );
            }
            cloneIndex = 0;
            ret = this.pushStack( ret, name, insert.selector );
        }
        tmplItems = appendToTmplItems;
        appendToTmplItems = null;
        jQuery.tmpl.complete( tmplItems );
        return ret;
    };
});

jQuery.fn.extend({
    // Use first wrapped element as template markup.
    // Return wrapped set of template items, obtained by rendering template against data.
    tmpl: function( data, options, parentItem ) {
        return jQuery.tmpl( this[0], data, options, parentItem );
    },

    // Find which rendered template item the first wrapped DOM element belongs to
    tmplItem: function() {
        return jQuery.tmplItem( this[0] );
    },

    // Consider the first wrapped element as a template declaration, and get the compiled template or store it as a named template.
    template: function( name ) {
        return jQuery.template( name, this[0] );
    },

    domManip: function( args, table, callback, options ) {
        // This appears to be a bug in the appendTo, etc. implementation
        // it should be doing .call() instead of .apply(). See #6227
        if ( args[0] && args[0].nodeType ) {
            var dmArgs = jQuery.makeArray( arguments ), argsLength = args.length, i = 0, tmplItem;
            while ( i < argsLength && !(tmplItem = jQuery.data( args[i++], "tmplItem" ))) {}
            if ( argsLength > 1 ) {
                dmArgs[0] = [jQuery.makeArray( args )];
            }
            if ( tmplItem && cloneIndex ) {
                dmArgs[2] = function( fragClone ) {
                    // Handler called by oldManip when rendered template has been inserted into DOM.
                    jQuery.tmpl.afterManip( this, fragClone, callback );
                };
            }
            oldManip.apply( this, dmArgs );
        } else {
            oldManip.apply( this, arguments );
        }
        cloneIndex = 0;
        if ( !appendToTmplItems ) {
            jQuery.tmpl.complete( newTmplItems );
        }
        return this;
    }
});

jQuery.extend({
    // Return wrapped set of template items, obtained by rendering template against data.
    tmpl: function( tmpl, data, options, parentItem ) {
        var ret, topLevel = !parentItem;
        if ( topLevel ) {
            // This is a top-level tmpl call (not from a nested template using {{tmpl}})
            parentItem = topTmplItem;
            tmpl = jQuery.template[tmpl] || jQuery.template( null, tmpl );
            wrappedItems = {}; // Any wrapped items will be rebuilt, since this is top level
        } else if ( !tmpl ) {
            // The template item is already associated with DOM - this is a refresh.
            // Re-evaluate rendered template for the parentItem
            tmpl = parentItem.tmpl;
            newTmplItems[parentItem.key] = parentItem;
            parentItem.nodes = [];
            if ( parentItem.wrapped ) {
                updateWrapped( parentItem, parentItem.wrapped );
            }
            // Rebuild, without creating a new template item
            return jQuery( build( parentItem, null, parentItem.tmpl( jQuery, parentItem ) ));
        }
        if ( !tmpl ) {
            return []; // Could throw...
        }
        if ( typeof data === "function" ) {
            data = data.call( parentItem || {} );
        }
        if ( options && options.wrapped ) {
            updateWrapped( options, options.wrapped );
        }
        ret = jQuery.isArray( data ) ?
        jQuery.map( data, function( dataItem ) {
            return dataItem ? newTmplItem( options, parentItem, tmpl, dataItem ) : null;
        }) :
        [ newTmplItem( options, parentItem, tmpl, data ) ];
        return topLevel ? jQuery( build( parentItem, null, ret ) ) : ret;
    },

    // Return rendered template item for an element.
    tmplItem: function( elem ) {
        var tmplItem;
        if ( elem instanceof jQuery ) {
            elem = elem[0];
        }
        while ( elem && elem.nodeType === 1 && !(tmplItem = jQuery.data( elem, "tmplItem" )) && (elem = elem.parentNode) ) {}
        return tmplItem || topTmplItem;
    },

    // Set:
    // Use $.template( name, tmpl ) to cache a named template,
    // where tmpl is a template string, a script element or a jQuery instance wrapping a script element, etc.
    // Use $( "selector" ).template( name ) to provide access by name to a script block template declaration.

    // Get:
    // Use $.template( name ) to access a cached template.
    // Also $( selectorToScriptBlock ).template(), or $.template( null, templateString )
    // will return the compiled template, without adding a name reference.
    // If templateString includes at least one HTML tag, $.template( templateString ) is equivalent
    // to $.template( null, templateString )
    template: function( name, tmpl ) {
        if (tmpl) {
            // Compile template and associate with name
            if ( typeof tmpl === "string" ) {
                // This is an HTML string being passed directly in.
                tmpl = buildTmplFn( tmpl )
            } else if ( tmpl instanceof jQuery ) {
                tmpl = tmpl[0] || {};
            }
            if ( tmpl.nodeType ) {
                // If this is a template block, use cached copy, or generate tmpl function and cache.
                tmpl = jQuery.data( tmpl, "tmpl" ) || jQuery.data( tmpl, "tmpl", buildTmplFn( tmpl.innerHTML ));
            }
            return typeof name === "string" ? (jQuery.template[name] = tmpl) : tmpl;
        }
        // Return named compiled template
        return name ? (typeof name !== "string" ? jQuery.template( null, name ):
            (jQuery.template[name] ||
                // If not in map, treat as a selector. (If integrated with core, use quickExpr.exec)
                jQuery.template( null, htmlExpr.test( name ) ? name : jQuery( name )))) : null;
    },

    encode: function( text ) {
        // Do HTML encoding replacing < > & and ' and " by corresponding entities.
        return ("" + text).split("<").join("&lt;").split(">").join("&gt;").split('"').join("&#34;").split("'").join("&#39;");
    }
});

jQuery.extend( jQuery.tmpl, {
    tag: {
        "tmpl": {
            _default: {
                $2: "null"
            },
            open: "if($notnull_1){_=_.concat($item.nest($1,$2));}"
        // tmpl target parameter can be of type function, so use $1, not $1a (so not auto detection of functions)
        // This means that {{tmpl foo}} treats foo as a template (which IS a function).
        // Explicit parens can be used if foo is a function that returns a template: {{tmpl foo()}}.
        },
        "wrap": {
            _default: {
                $2: "null"
            },
            open: "$item.calls(_,$1,$2);_=[];",
            close: "call=$item.calls();_=call._.concat($item.wrap(call,_));"
        },
        "each": {
            _default: {
                $2: "$index, $value"
            },
            open: "if($notnull_1){$.each($1a,function($2){with(this){",
            close: "}});}"
        },
        "if": {
            open: "if(($notnull_1) && $1a){",
            close: "}"
        },
        "else": {
            _default: {
                $1: "true"
            },
            open: "}else if(($notnull_1) && $1a){"
        },
        "html": {
            // Unecoded expression evaluation.
            open: "if($notnull_1){_.push($1a);}"
        },
        "=": {
            // Encoded expression evaluation. Abbreviated form is ${}.
            _default: {
                $1: "$data"
            },
            open: "if($notnull_1){_.push($.encode($1a));}"
        },
        "!": {
            // Comment tag. Skipped by parser
            open: ""
        }
    },

    // This stub can be overridden, e.g. in jquery.tmplPlus for providing rendered events
    complete: function( items ) {
        newTmplItems = {};
    },

    // Call this from code which overrides domManip, or equivalent
    // Manage cloning/storing template items etc.
    afterManip: function afterManip( elem, fragClone, callback ) {
        // Provides cloned fragment ready for fixup prior to and after insertion into DOM
        var content = fragClone.nodeType === 11 ?
        jQuery.makeArray(fragClone.childNodes) :
        fragClone.nodeType === 1 ? [fragClone] : [];

        // Return fragment to original caller (e.g. append) for DOM insertion
        callback.call( elem, fragClone );

        // Fragment has been inserted:- Add inserted nodes to tmplItem data structure. Replace inserted element annotations by jQuery.data.
        storeTmplItems( content );
        cloneIndex++;
    }
});

//========================== Private helper functions, used by code above ==========================

function build( tmplItem, nested, content ) {
    // Convert hierarchical content into flat string array
    // and finally return array of fragments ready for DOM insertion
    var frag, ret = content ? jQuery.map( content, function( item ) {
        return (typeof item === "string") ?
        // Insert template item annotations, to be converted to jQuery.data( "tmplItem" ) when elems are inserted into DOM.
        (tmplItem.key ? item.replace( /(<\w+)(?=[\s>])(?![^>]*_tmplitem)([^>]*)/g, "$1 " + tmplItmAtt + "=\"" + tmplItem.key + "\" $2" ) : item) :
        // This is a child template item. Build nested template.
        build( item, tmplItem, item._ctnt );
    }) :
    // If content is not defined, insert tmplItem directly. Not a template item. May be a string, or a string array, e.g. from {{html $item.html()}}.
    tmplItem;
    if ( nested ) {
        return ret;
    }

    // top-level template
    ret = ret.join("");

    // Support templates which have initial or final text nodes, or consist only of text
    // Also support HTML entities within the HTML markup.
    ret.replace( /^\s*([^<\s][^<]*)?(<[\w\W]+>)([^>]*[^>\s])?\s*$/, function( all, before, middle, after) {
        frag = jQuery( middle ).get();

        storeTmplItems( frag );
        if ( before ) {
            frag = unencode( before ).concat(frag);
        }
        if ( after ) {
            frag = frag.concat(unencode( after ));
        }
    });
    return frag ? frag : unencode( ret );
}

function unencode( text ) {
    // Use createElement, since createTextNode will not render HTML entities correctly
    var el = document.createElement( "div" );
    el.innerHTML = text;
    return jQuery.makeArray(el.childNodes);
}

// Generate a reusable function that will serve to render a template against data
function buildTmplFn( markup ) {
    return new Function("jQuery","$item",
        "var $=jQuery,call,_=[],$data=$item.data;" +

        // Introduce the data as local variables using with(){}
        "with($data){_.push('" +

        // Convert the template into pure JavaScript
        jQuery.trim(markup)
        .replace( /([\\'])/g, "\\$1" )
        .replace( /[\r\t\n]/g, " " )
        .replace( /\$\{([^\}]*)\}/g, "{{= $1}}" )
        .replace( /\{\{(\/?)(\w+|.)(?:\(((?:[^\}]|\}(?!\}))*?)?\))?(?:\s+(.*?)?)?(\(((?:[^\}]|\}(?!\}))*?)\))?\s*\}\}/g,
            function( all, slash, type, fnargs, target, parens, args ) {
                var tag = jQuery.tmpl.tag[ type ], def, expr, exprAutoFnDetect;
                if ( !tag ) {
                    throw "Template command not found: " + type;
                }
                def = tag._default || [];
                if ( parens && !/\w$/.test(target)) {
                    target += parens;
                    parens = "";
                }
                if ( target ) {
                    target = unescape( target );
                    args = args ? ("," + unescape( args ) + ")") : (parens ? ")" : "");
                    // Support for target being things like a.toLowerCase();
                    // In that case don't call with template item as 'this' pointer. Just evaluate...
                    expr = parens ? (target.indexOf(".") > -1 ? target + unescape( parens ) : ("(" + target + ").call($item" + args)) : target;
                    exprAutoFnDetect = parens ? expr : "(typeof(" + target + ")==='function'?(" + target + ").call($item):(" + target + "))";
                } else {
                    exprAutoFnDetect = expr = def.$1 || "null";
                }
                fnargs = unescape( fnargs );
                return "');" +
                tag[ slash ? "close" : "open" ]
                .split( "$notnull_1" ).join( target ? "typeof(" + target + ")!=='undefined' && (" + target + ")!=null" : "true" )
                .split( "$1a" ).join( exprAutoFnDetect )
                .split( "$1" ).join( expr )
                .split( "$2" ).join( fnargs ?
                    fnargs.replace( /\s*([^\(]+)\s*(\((.*?)\))?/g, function( all, name, parens, params ) {
                        params = params ? ("," + params + ")") : (parens ? ")" : "");
                        return params ? ("(" + name + ").call($item" + params) : all;
                    })
                    : (def.$2||"")
                    ) +
                "_.push('";
            }) +
        "');}return _;"
        );
}
function updateWrapped( options, wrapped ) {
    // Build the wrapped content.
    options._wrap = build( options, true,
        // Suport imperative scenario in which options.wrapped can be set to a selector or an HTML string.
        jQuery.isArray( wrapped ) ? wrapped : [htmlExpr.test( wrapped ) ? wrapped : jQuery( wrapped ).html()]
        ).join("");
}

function unescape( args ) {
    return args ? args.replace( /\\'/g, "'").replace(/\\\\/g, "\\" ) : null;
}
function outerHtml( elem ) {
    var div = document.createElement("div");
    div.appendChild( elem.cloneNode(true) );
    return div.innerHTML;
}

// Store template items in jQuery.data(), ensuring a unique tmplItem data data structure for each rendered template instance.
function storeTmplItems( content ) {
    var keySuffix = "_" + cloneIndex, elem, elems, newClonedItems = {}, i, l, m;
    for ( i = 0, l = content.length; i < l; i++ ) {
        if ( (elem = content[i]).nodeType !== 1 ) {
            continue;
        }
        elems = elem.getElementsByTagName("*");
        for ( m = elems.length - 1; m >= 0; m-- ) {
            processItemKey( elems[m] );
        }
        processItemKey( elem );
    }
    function processItemKey( el ) {
        var pntKey, pntNode = el, pntItem, tmplItem, key;
        // Ensure that each rendered template inserted into the DOM has its own template item,
        if ( (key = el.getAttribute( tmplItmAtt ))) {
            while ( pntNode.parentNode && (pntNode = pntNode.parentNode).nodeType === 1 && !(pntKey = pntNode.getAttribute( tmplItmAtt ))) { }
            if ( pntKey !== key ) {
                // The next ancestor with a _tmplitem expando is on a different key than this one.
                // So this is a top-level element within this template item
                // Set pntNode to the key of the parentNode, or to 0 if pntNode.parentNode is null, or pntNode is a fragment.
                pntNode = pntNode.parentNode ? (pntNode.nodeType === 11 ? 0 : (pntNode.getAttribute( tmplItmAtt ) || 0)) : 0;
                if ( !(tmplItem = newTmplItems[key]) ) {
                    // The item is for wrapped content, and was copied from the temporary parent wrappedItem.
                    tmplItem = wrappedItems[key];
                    tmplItem = newTmplItem( tmplItem, newTmplItems[pntNode]||wrappedItems[pntNode] );
                    tmplItem.key = ++itemKey;
                    newTmplItems[itemKey] = tmplItem;
                }
                if ( cloneIndex ) {
                    cloneTmplItem( key );
                }
            }
            el.removeAttribute( tmplItmAtt );
        } else if ( cloneIndex && (tmplItem = jQuery.data( el, "tmplItem" )) ) {
            // This was a rendered element, cloned during append or appendTo etc.
            // TmplItem stored in jQuery data has already been cloned in cloneCopyEvent. We must replace it with a fresh cloned tmplItem.
            cloneTmplItem( tmplItem.key );
            newTmplItems[tmplItem.key] = tmplItem;
            pntNode = jQuery.data( el.parentNode, "tmplItem" );
            pntNode = pntNode ? pntNode.key : 0;
        }
        if ( tmplItem ) {
            pntItem = tmplItem;
            // Find the template item of the parent element.
            // (Using !=, not !==, since pntItem.key is number, and pntNode may be a string)
            while ( pntItem && pntItem.key != pntNode ) {
                // Add this element as a top-level node for this rendered template item, as well as for any
                // ancestor items between this item and the item of its parent element
                pntItem.nodes.push( el );
                pntItem = pntItem.parent;
            }
            // Delete content built during rendering - reduce API surface area and memory use, and avoid exposing of stale data after rendering...
            delete tmplItem._ctnt;
            delete tmplItem._wrap;
            // Store template item as jQuery data on the element
            jQuery.data( el, "tmplItem", tmplItem );
        }
        function cloneTmplItem( key ) {
            key = key + keySuffix;
            tmplItem = newClonedItems[key] =
            (newClonedItems[key] || newTmplItem( tmplItem, newTmplItems[tmplItem.parent.key + keySuffix] || tmplItem.parent ));
        }
    }
}

//---- Helper functions for template item ----

function tiCalls( content, tmpl, data, options ) {
    if ( !content ) {
        return stack.pop();
    }
    stack.push({
        _: content,
        tmpl: tmpl,
        item:this,
        data: data,
        options: options
    });
}

function tiNest( tmpl, data, options ) {
    // nested template, using {{tmpl}} tag
    return jQuery.tmpl( jQuery.template( tmpl ), data, options, this );
}

function tiWrap( call, wrapped ) {
    // nested template, using {{wrap}} tag
    var options = call.options || {};
    options.wrapped = wrapped;
    // Apply the template, which may incorporate wrapped content,
    return jQuery.tmpl( jQuery.template( call.tmpl ), call.data, options, call.item );
}

function tiHtml( filter, textOnly ) {
    var wrapped = this._wrap;
    return jQuery.map(
        jQuery( jQuery.isArray( wrapped ) ? wrapped.join("") : wrapped ).filter( filter || "*" ),
        function(e) {
            return textOnly ?
            e.innerText || e.textContent :
            e.outerHTML || outerHtml(e);
        });
}

function tiUpdate() {
    var coll = this.nodes;
    jQuery.tmpl( null, null, null, this).insertBefore( coll[0] );
    jQuery( coll ).remove();
}
})( jQuery );

/* #8# */ // НЕ ОБНОВЛЯТЬ
/*
 * jQuery Form Plugin
 * version: 2.47 (04-SEP-2010)
 * @requires jQuery v1.3.2 or later
 *
 * Examples and documentation at: http://malsup.com/jquery/form/
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 */
;
(function($) {

    /*
	Usage Note:
	-----------
	Do not use both ajaxSubmit and ajaxForm on the same form.  These
	functions are intended to be exclusive.  Use ajaxSubmit if you want
	to bind your own submit handler to the form.  For example,

	$(document).ready(function() {
		$('#myForm').bind('submit', function() {
			$(this).ajaxSubmit({
				target: '#output'
			});
			return false; // <-- important!
		});
	});

	Use ajaxForm when you want the plugin to manage all the event binding
	for you.  For example,

	$(document).ready(function() {
		$('#myForm').ajaxForm({
			target: '#output'
		});
	});

	When using ajaxForm, the ajaxSubmit function will be invoked for you
	at the appropriate time.
*/

    /**
 * ajaxSubmit() provides a mechanism for immediately submitting
 * an HTML form using AJAX.
 */
    $.fn.ajaxSubmit = function(options) {
        // fast fail if nothing selected (http://dev.jquery.com/ticket/2752)
        if (!this.length) {
            log('ajaxSubmit: skipping submit process - no element selected');
            return this;
        }

        if (typeof options == 'function') {
            options = {
                success: options
            };
        }

        var url = $.trim(this.attr('action'));
        if (url) {
            // clean url (don't include hash vaue)
            url = (url.match(/^([^#]+)/)||[])[1];
        }
        url = url || window.location.href || '';

        options = $.extend(true, {
            url:  url,
            type: this.attr('method') || 'GET',
            iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank'
        }, options);

        // hook for manipulating the form data before it is extracted;
        // convenient for use with rich editors like tinyMCE or FCKEditor
        var veto = {};
        this.trigger('form-pre-serialize', [this, options, veto]);
        if (veto.veto) {
            log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');
            return this;
        }

        // provide opportunity to alter form data before it is serialized
        if (options.beforeSerialize && options.beforeSerialize(this, options) === false) {
            log('ajaxSubmit: submit aborted via beforeSerialize callback');
            return this;
        }

        var n,v,a = this.formToArray(options.semantic);
        if (options.data) {
            options.extraData = options.data;
            for (n in options.data) {
                if(options.data[n] instanceof Array) {
                    for (var k in options.data[n]) {
                        a.push( {
                            name: n,
                            value: options.data[n][k]
                            } );
                    }
                }
                else {
                    v = options.data[n];
                    v = $.isFunction(v) ? v() : v; // if value is fn, invoke it
                    a.push( {
                        name: n,
                        value: v
                    } );
                }
            }
        }

        // give pre-submit callback an opportunity to abort the submit
        if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) {
            log('ajaxSubmit: submit aborted via beforeSubmit callback');
            return this;
        }

        // fire vetoable 'validate' event
        this.trigger('form-submit-validate', [a, this, options, veto]);
        if (veto.veto) {
            log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
            return this;
        }

        var q = $.param(a);

        if (options.type.toUpperCase() == 'GET') {
            options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
            options.data = null;  // data is null for 'get'
        }
        else {
            options.data = q; // data is the query string for 'post'
        }

        var $form = this, callbacks = [];
        if (options.resetForm) {
            callbacks.push(function() {
                $form.resetForm();
            });
        }
        if (options.clearForm) {
            callbacks.push(function() {
                $form.clearForm();
            });
        }

        // perform a load on the target only if dataType is not provided
        if (!options.dataType && options.target) {
            var oldSuccess = options.success || function(){};
            callbacks.push(function(data) {
                var fn = options.replaceTarget ? 'replaceWith' : 'html';
                $(options.target)[fn](data).each(oldSuccess, arguments);
            });
        }
        else if (options.success) {
            callbacks.push(options.success);
        }

        options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg
            var context = options.context || options;   // jQuery 1.4+ supports scope context
            for (var i=0, max=callbacks.length; i < max; i++) {
                callbacks[i].apply(context, [data, status, xhr || $form, $form]);
            }
        };

        // are there files to upload?
        var fileInputs = $('input:file', this).length > 0;
        var mp = 'multipart/form-data';
        var multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp);

        // options.iframe allows user to force iframe mode
        // 06-NOV-09: now defaulting to iframe mode if file input is detected
        if (options.iframe !== false && (fileInputs || options.iframe || multipart)) {
            // hack to fix Safari hang (thanks to Tim Molendijk for this)
            // see:  http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
            if (options.closeKeepAlive) {
                $.get(options.closeKeepAlive, fileUpload);
            }
            else {
                fileUpload();
            }
        }
        else {
            $.ajax(options);
        }

        // fire 'notify' event
        this.trigger('form-submit-notify', [this, options]);
        return this;


        // private function for handling file uploads (hat tip to YAHOO!)
        function fileUpload() {
            var form = $form[0];

            if ($(':input[name=submit],:input[id=submit]', form).length) {
                // if there is an input with a name or id of 'submit' then we won't be
                // able to invoke the submit fn on the form (at least not x-browser)
                alert('Error: Form elements must not have name or id of "submit".');
                return;
            }

            var s = $.extend(true, {}, $.ajaxSettings, options);
            s.context = s.context || s;
            var id = 'jqFormIO' + (new Date().getTime()), fn = '_'+id;
            window[fn] = function() {
                var f = $io.data('form-plugin-onload');
                if (f) {
                    f();
                    window[fn] = undefined;
                    try {
                        delete window[fn];
                    } catch(e){}
                }
            }
            var $io = $('<iframe id="' + id + '" name="' + id + '" src="'+ s.iframeSrc +'" onload="window[\'_\'+this.id]()" />');
            var io = $io[0];

            $io.css({
                position: 'absolute',
                top: '-1000px',
                left: '-1000px'
            });

            var xhr = { // mock object
                aborted: 0,
                responseText: null,
                responseXML: null,
                status: 0,
                statusText: 'n/a',
                getAllResponseHeaders: function() {},
                getResponseHeader: function() {},
                setRequestHeader: function() {},
                abort: function() {
                    this.aborted = 1;
                    $io.attr('src', s.iframeSrc); // abort op in progress
                }
            };

            var g = s.global;
            // trigger ajax global events so that activity/block indicators work like normal
            if (g && ! $.active++) {
                $.event.trigger("ajaxStart");
            }
            if (g) {
                $.event.trigger("ajaxSend", [xhr, s]);
            }

            if (s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false) {
                if (s.global) {
                    $.active--;
                }
                return;
            }
            if (xhr.aborted) {
                return;
            }

            var cbInvoked = false;
            var timedOut = 0;

            // add submitting element to data if we know it
            var sub = form.clk;
            if (sub) {
                var n = sub.name;
                if (n && !sub.disabled) {
                    s.extraData = s.extraData || {};
                    s.extraData[n] = sub.value;
                    if (sub.type == "image") {
                        s.extraData[n+'.x'] = form.clk_x;
                        s.extraData[n+'.y'] = form.clk_y;
                    }
                }
            }

            // take a breath so that pending repaints get some cpu time before the upload starts
            function doSubmit() {
                // make sure form attrs are set
                var t = $form.attr('target'), a = $form.attr('action');

                // update form attrs in IE friendly way
                form.setAttribute('target',id);
                if (form.getAttribute('method') != 'POST') {
                    form.setAttribute('method', 'POST');
                }
                if (form.getAttribute('action') != s.url) {
                    form.setAttribute('action', s.url);
                }

                // ie borks in some cases when setting encoding
                if (! s.skipEncodingOverride) {
                    $form.attr({
                        encoding: 'multipart/form-data',
                        enctype:  'multipart/form-data'
                    });
                }

                // support timout
                if (s.timeout) {
                    setTimeout(function() {
                        timedOut = true;
                        cb();
                    }, s.timeout);
                }

                // add "extra" data to form if provided in options
                var extraInputs = [];
                try {
                    if (s.extraData) {
                        for (var n in s.extraData) {
                            extraInputs.push(
                                $('<input type="hidden" name="'+n+'" value="'+s.extraData[n]+'" />')
                                .appendTo(form)[0]);
                        }
                    }

                    // add iframe to doc and submit the form
                    $io.appendTo('body');
                    $io.data('form-plugin-onload', cb);
                    form.submit();
                }
                finally {
                    // reset attrs and remove "extra" input elements
                    form.setAttribute('action',a);
                    if(t) {
                        form.setAttribute('target', t);
                    } else {
                        $form.removeAttr('target');
                    }
                    $(extraInputs).remove();
                }
            }

            if (s.forceSync) {
                doSubmit();
            }
            else {
                setTimeout(doSubmit, 10); // this lets dom updates render
            }

            var data, doc, domCheckCount = 50;

            function cb() {
                if (cbInvoked) {
                    return;
                }

                $io.removeData('form-plugin-onload');

                var ok = true;
                try {
                    if (timedOut) {
                        throw 'timeout';
                    }
                    // extract the server response from the iframe
                    doc = io.contentWindow ? io.contentWindow.document : io.contentDocument ? io.contentDocument : io.document;

                    var isXml = s.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc);
                    log('isXml='+isXml);
                    if (!isXml && window.opera && (doc.body == null || doc.body.innerHTML == '')) {
                        if (--domCheckCount) {
                            // in some browsers (Opera) the iframe DOM is not always traversable when
                            // the onload callback fires, so we loop a bit to accommodate
                            log('requeing onLoad callback, DOM not available');
                            setTimeout(cb, 250);
                            return;
                        }
                    // let this fall through because server response could be an empty document
                    //log('Could not access iframe DOM after mutiple tries.');
                    //throw 'DOMException: not available';
                    }

                    //log('response detected');
                    cbInvoked = true;
                    xhr.responseText = doc.body ? doc.body.innerHTML : null;
                    xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
                    xhr.getResponseHeader = function(header){
                        var headers = {
                            'content-type': s.dataType
                            };
                        return headers[header];
                    };

                    var scr = /(json|script)/.test(s.dataType);
                    if (scr || s.textarea) {
                        // see if user embedded response in textarea
                        var ta = doc.getElementsByTagName('textarea')[0];
                        if (ta) {
                            xhr.responseText = ta.value;
                        }
                        else if (scr) {
                            // account for browsers injecting pre around json response
                            var pre = doc.getElementsByTagName('pre')[0];
                            if (pre) {
                                xhr.responseText = pre.innerHTML;
                            }
                        }
                    }
                    else if (s.dataType == 'xml' && !xhr.responseXML && xhr.responseText != null) {
                        xhr.responseXML = toXml(xhr.responseText);
                    }
                    data = $.httpData(xhr, s.dataType);
                }
                catch(e){
                    log('error caught:',e);
                    ok = false;
                    xhr.error = e;
                    $.handleError(s, xhr, 'error', e);
                }

                // ordering of these callbacks/triggers is odd, but that's how $.ajax does it
                if (ok) {
                    s.success.call(s.context, data, 'success', xhr);
                    if (g) {
                        $.event.trigger("ajaxSuccess", [xhr, s]);
                    }
                }
                if (g) {
                    $.event.trigger("ajaxComplete", [xhr, s]);
                }
                if (g && ! --$.active) {
                    $.event.trigger("ajaxStop");
                }
                if (s.complete) {
                    s.complete.call(s.context, xhr, ok ? 'success' : 'error');
                }

                // clean up
                setTimeout(function() {
                    $io.removeData('form-plugin-onload');
                    $io.remove();
                    xhr.responseXML = null;
                }, 100);
            }

            function toXml(s, doc) {
                if (window.ActiveXObject) {
                    doc = new ActiveXObject('Microsoft.XMLDOM');
                    doc.async = 'false';
                    doc.loadXML(s);
                }
                else {
                    doc = (new DOMParser()).parseFromString(s, 'text/xml');
                }
                return (doc && doc.documentElement && doc.documentElement.tagName != 'parsererror') ? doc : null;
            }
        }
    };

    /**
 * ajaxForm() provides a mechanism for fully automating form submission.
 *
 * The advantages of using this method instead of ajaxSubmit() are:
 *
 * 1: This method will include coordinates for <input type="image" /> elements (if the element
 *	is used to submit the form).
 * 2. This method will include the submit element's name/value data (for the element that was
 *	used to submit the form).
 * 3. This method binds the submit() method to the form for you.
 *
 * The options argument for ajaxForm works exactly as it does for ajaxSubmit.  ajaxForm merely
 * passes the options argument along after properly binding events for submit elements and
 * the form itself.
 */
    $.fn.ajaxForm = function(options) {
        // in jQuery 1.3+ we can fix mistakes with the ready state
        if (this.length === 0) {
            var o = {
                s: this.selector,
                c: this.context
                };
            if (!$.isReady && o.s) {
                log('DOM not ready, queuing ajaxForm');
                $(function() {
                    $(o.s,o.c).ajaxForm(options);
                });
                return this;
            }
            // is your DOM ready?  http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
            log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)'));
            return this;
        }

        return this.ajaxFormUnbind().bind('submit.form-plugin', function(e) {
            if (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed
                e.preventDefault();
                $(this).ajaxSubmit(options);
            }
        }).bind('click.form-plugin', function(e) {
            var target = e.target;
            var $el = $(target);
            if (!($el.is(":submit,input:image"))) {
                // is this a child element of the submit el?  (ex: a span within a button)
                var t = $el.closest(':submit');
                if (t.length == 0) {
                    return;
                }
                target = t[0];
            }
            var form = this;
            form.clk = target;
            if (target.type == 'image') {
                if (e.offsetX != undefined) {
                    form.clk_x = e.offsetX;
                    form.clk_y = e.offsetY;
                } else if (typeof $.fn.offset == 'function') { // try to use dimensions plugin
                    var offset = $el.offset();
                    form.clk_x = e.pageX - offset.left;
                    form.clk_y = e.pageY - offset.top;
                } else {
                    form.clk_x = e.pageX - target.offsetLeft;
                    form.clk_y = e.pageY - target.offsetTop;
                }
            }
            // clear form vars
            setTimeout(function() {
                form.clk = form.clk_x = form.clk_y = null;
            }, 100);
        });
    };

    // ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
    $.fn.ajaxFormUnbind = function() {
        return this.unbind('submit.form-plugin click.form-plugin');
    };

    /**
 * formToArray() gathers form element data into an array of objects that can
 * be passed to any of the following ajax functions: $.get, $.post, or load.
 * Each object in the array has both a 'name' and 'value' property.  An example of
 * an array for a simple login form might be:
 *
 * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]
 *
 * It is this array that is passed to pre-submit callback functions provided to the
 * ajaxSubmit() and ajaxForm() methods.
 */
    $.fn.formToArray = function(semantic) {
        var a = [];
        if (this.length === 0) {
            return a;
        }

        var form = this[0];
        var els = semantic ? form.getElementsByTagName('*') : form.elements;
        if (!els) {
            return a;
        }
        if ('object' == typeof(els.length)) {
            els = form.getElementsByTagName('*')
        }
        if ('object' == typeof(els.length)) {
            els = $('*', form)
        }
        var i,j,n,v,el, max, jmax;
        for(i=0, max = els.length; i < max; i++) {
            el = els[i];
            n = el.name;
            if (!n) {
                continue;
            }

            if (semantic && form.clk && el.type == "image") {
                // handle image inputs on the fly when semantic == true
                if(!el.disabled && form.clk == el) {
                    a.push({
                        name: n,
                        value: $(el).val()
                        });
                    a.push({
                        name: n+'.x',
                        value: form.clk_x
                        }, {
                        name: n+'.y',
                        value: form.clk_y
                        });
                }
                continue;
            }

            v = $.fieldValue(el, true);
            if (v && v.constructor == Array) {
                for(j=0, jmax=v.length; j < jmax; j++) {
                    a.push({
                        name: n,
                        value: v[j]
                        });
                }
            }
            else if (v !== null && typeof v != 'undefined') {
                a.push({
                    name: n,
                    value: v
                });
            }
        }

        if (!semantic && form.clk) {
            // input type=='image' are not found in elements array! handle it here
            var $input = $(form.clk), input = $input[0];
            n = input.name;
            if (n && !input.disabled && input.type == 'image') {
                a.push({
                    name: n,
                    value: $input.val()
                    });
                a.push({
                    name: n+'.x',
                    value: form.clk_x
                    }, {
                    name: n+'.y',
                    value: form.clk_y
                    });
            }
        }
        return a;
    };

    /**
 * Serializes form data into a 'submittable' string. This method will return a string
 * in the format: name1=value1&amp;name2=value2
 */
    $.fn.formSerialize = function(semantic) {
        //hand off to jQuery.param for proper encoding
        return $.param(this.formToArray(semantic));
    };

    /**
 * Serializes all field elements in the jQuery object into a query string.
 * This method will return a string in the format: name1=value1&amp;name2=value2
 */
    $.fn.fieldSerialize = function(successful) {
        var a = [];
        this.each(function() {
            var n = this.name;
            if (!n) {
                return;
            }
            var v = $.fieldValue(this, successful);
            if (v && v.constructor == Array) {
                for (var i=0,max=v.length; i < max; i++) {
                    a.push({
                        name: n,
                        value: v[i]
                        });
                }
            }
            else if (v !== null && typeof v != 'undefined') {
                a.push({
                    name: this.name,
                    value: v
                });
            }
        });
        //hand off to jQuery.param for proper encoding
        return $.param(a);
    };

    /**
 * Returns the value(s) of the element in the matched set.  For example, consider the following form:
 *
 *  <form><fieldset>
 *	  <input name="A" type="text" />
 *	  <input name="A" type="text" />
 *	  <input name="B" type="checkbox" value="B1" />
 *	  <input name="B" type="checkbox" value="B2"/>
 *	  <input name="C" type="radio" value="C1" />
 *	  <input name="C" type="radio" value="C2" />
 *  </fieldset></form>
 *
 *  var v = $(':text').fieldValue();
 *  // if no values are entered into the text inputs
 *  v == ['','']
 *  // if values entered into the text inputs are 'foo' and 'bar'
 *  v == ['foo','bar']
 *
 *  var v = $(':checkbox').fieldValue();
 *  // if neither checkbox is checked
 *  v === undefined
 *  // if both checkboxes are checked
 *  v == ['B1', 'B2']
 *
 *  var v = $(':radio').fieldValue();
 *  // if neither radio is checked
 *  v === undefined
 *  // if first radio is checked
 *  v == ['C1']
 *
 * The successful argument controls whether or not the field element must be 'successful'
 * (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).
 * The default value of the successful argument is true.  If this value is false the value(s)
 * for each element is returned.
 *
 * Note: This method *always* returns an array.  If no valid value can be determined the
 *	   array will be empty, otherwise it will contain one or more values.
 */
    $.fn.fieldValue = function(successful) {
        for (var val=[], i=0, max=this.length; i < max; i++) {
            var el = this[i];
            var v = $.fieldValue(el, successful);
            if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) {
                continue;
            }
            v.constructor == Array ? $.merge(val, v) : val.push(v);
        }
        return val;
    };

    /**
 * Returns the value of the field element.
 */
    $.fieldValue = function(el, successful) {
        var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
        if (successful === undefined) {
            successful = true;
        }

        if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
            (t == 'checkbox' || t == 'radio') && !el.checked ||
            (t == 'submit' || t == 'image') && el.form && el.form.clk != el ||
            tag == 'select' && el.selectedIndex == -1)) {
            return null;
        }

        if (tag == 'select') {
            var index = el.selectedIndex;
            if (index < 0) {
                return null;
            }
            var a = [], ops = el.options;
            var one = (t == 'select-one');
            var max = (one ? index+1 : ops.length);
            for(var i=(one ? index : 0); i < max; i++) {
                var op = ops[i];
                if (op.selected) {
                    var v = op.value;
                    if (!v) { // extra pain for IE...
                        v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value;
                    }
                    if (one) {
                        return v;
                    }
                    a.push(v);
                }
            }
            return a;
        }
        return $(el).val();
    };

    /**
 * Clears the form data.  Takes the following actions on the form's input fields:
 *  - input text fields will have their 'value' property set to the empty string
 *  - select elements will have their 'selectedIndex' property set to -1
 *  - checkbox and radio inputs will have their 'checked' property set to false
 *  - inputs of type submit, button, reset, and hidden will *not* be effected
 *  - button elements will *not* be effected
 */
    $.fn.clearForm = function() {
        return this.each(function() {
            $('input,select,textarea', this).clearFields();
        });
    };

    /**
 * Clears the selected form elements.
 */
    $.fn.clearFields = $.fn.clearInputs = function() {
        return this.each(function() {
            var t = this.type, tag = this.tagName.toLowerCase();
            if (t == 'text' || t == 'password' || tag == 'textarea') {
                this.value = '';
            }
            else if (t == 'checkbox' || t == 'radio') {
                this.checked = false;
            }
            else if (tag == 'select') {
                this.selectedIndex = -1;
            }
        });
    };

    /**
 * Resets the form data.  Causes all form elements to be reset to their original value.
 */
    $.fn.resetForm = function() {
        return this.each(function() {
            // guard against an input with the name of 'reset'
            // note that IE reports the reset function as an 'object'
            if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType)) {
                this.reset();
            }
        });
    };

    /**
 * Enables or disables any matching elements.
 */
    $.fn.enable = function(b) {
        if (b === undefined) {
            b = true;
        }
        return this.each(function() {
            this.disabled = !b;
        });
    };

    /**
 * Checks/unchecks any matching checkboxes or radio buttons and
 * selects/deselects and matching option elements.
 */
    $.fn.selected = function(select) {
        if (select === undefined) {
            select = true;
        }
        return this.each(function() {
            var t = this.type;
            if (t == 'checkbox' || t == 'radio') {
                this.checked = select;
            }
            else if (this.tagName.toLowerCase() == 'option') {
                var $sel = $(this).parent('select');
                if (select && $sel[0] && $sel[0].type == 'select-one') {
                    // deselect all other options
                    $sel.find('option').selected(false);
                }
                this.selected = select;
            }
        });
    };

    // helper fn for console logging
    // set $.fn.ajaxSubmit.debug to true to enable debug logging
    function log() {
        if ($.fn.ajaxSubmit.debug) {
            var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,'');
            if (window.console && window.console.log) {
                window.console.log(msg);
            }
            else if (window.opera && window.opera.postError) {
                window.opera.postError(msg);
            }
        }
    };

})(jQuery);

/* #9# */
/*
 * jQuery validation plug-in 1.7
 *
 * http://bassistance.de/jquery-plugins/jquery-plugin-validation/
 * http://docs.jquery.com/Plugins/Validation
 *
 * Copyright (c) 2006 - 2008 JУЖrn Zaefferer
 *
 * $Id: jquery.validate.js 6403 2009-06-17 14:27:16Z joern.zaefferer $
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 */

(function($) {

    $.extend($.fn, {
        // http://docs.jquery.com/Plugins/Validation/validate
        validate: function( options ) {

            // if nothing is selected, return nothing; can't chain anyway
            if (!this.length) {
                options && options.debug && window.console && console.warn( "nothing selected, can't validate, returning nothing" );
                return;
            }

            // check if a validator for this form was already created
            var validator = $.data(this[0], 'validator');
            if ( validator ) {
                return validator;
            }
		
            validator = new $.validator( options, this[0] );
            $.data(this[0], 'validator', validator);
		
            if ( validator.settings.onsubmit ) {
		
                // allow suppresing validation by adding a cancel class to the submit button
                this.find("input, button").filter(".cancel").click(function() {
                    validator.cancelSubmit = true;
                });
			
                // when a submitHandler is used, capture the submitting button
                if (validator.settings.submitHandler) {
                    this.find("input, button").filter(":submit").click(function() {
                        validator.submitButton = this;
                    });
                }
		
                // validate the form on submit
                this.submit( function( event ) {
                    if ( validator.settings.debug )
                        // prevent form submit to be able to see console output
                        event.preventDefault();
					
                    function handle() {
                        if ( validator.settings.submitHandler ) {
                            if (validator.submitButton) {
                                // insert a hidden input as a replacement for the missing submit button
                                var hidden = $("<input type='hidden'/>").attr("name", validator.submitButton.name).val(validator.submitButton.value).appendTo(validator.currentForm);
                            }
                            validator.settings.submitHandler.call( validator, validator.currentForm );
                            if (validator.submitButton) {
                                // and clean up afterwards; thanks to no-block-scope, hidden can be referenced
                                hidden.remove();
                            }
                            return false;
                        }
                        return true;
                    }
					
                    // prevent submit for invalid forms or custom submit handlers
                    if ( validator.cancelSubmit ) {
                        validator.cancelSubmit = false;
                        return handle();
                    }
                    if ( validator.form() ) {
                        if ( validator.pendingRequest ) {
                            validator.formSubmitted = true;
                            return false;
                        }
                        return handle();
                    } else {
                        validator.focusInvalid();
                        return false;
                    }
                });
            }
		
            return validator;
        },
        // http://docs.jquery.com/Plugins/Validation/valid
        valid: function() {
            if ( $(this[0]).is('form')) {
                return this.validate().form();
            } else {
                var valid = true;
                var validator = $(this[0].form).validate();
                this.each(function() {
                    valid &= validator.element(this);
                });
                return valid;
            }
        },
        // attributes: space seperated list of attributes to retrieve and remove
        removeAttrs: function(attributes) {
            var result = {},
            $element = this;
            $.each(attributes.split(/\s/), function(index, value) {
                result[value] = $element.attr(value);
                $element.removeAttr(value);
            });
            return result;
        },
        // http://docs.jquery.com/Plugins/Validation/rules
        rules: function(command, argument) {
            var element = this[0];
		
            if (command) {
                var settings = $.data(element.form, 'validator').settings;
                var staticRules = settings.rules;
                var existingRules = $.validator.staticRules(element);
                switch(command) {
                    case "add":
                        $.extend(existingRules, $.validator.normalizeRule(argument));
                        staticRules[element.name] = existingRules;
                        if (argument.messages)
                            settings.messages[element.name] = $.extend( settings.messages[element.name], argument.messages );
                        break;
                    case "remove":
                        if (!argument) {
                            delete staticRules[element.name];
                            return existingRules;
                        }
                        var filtered = {};
                        $.each(argument.split(/\s/), function(index, method) {
                            filtered[method] = existingRules[method];
                            delete existingRules[method];
                        });
                        return filtered;
                }
            }
		
            var data = $.validator.normalizeRules(
                $.extend(
                {},
                    $.validator.metadataRules(element),
                    $.validator.classRules(element),
                    $.validator.attributeRules(element),
                    $.validator.staticRules(element)
                    ), element);
		
            // make sure required is at front
            if (data.required) {
                var param = data.required;
                delete data.required;
                data = $.extend({
                    required: param
                }, data);
            }
		
            return data;
        }
    });

    // Custom selectors
    $.extend($.expr[":"], {
        // http://docs.jquery.com/Plugins/Validation/blank
        blank: function(a) {
            return !$.trim("" + a.value);
        },
        // http://docs.jquery.com/Plugins/Validation/filled
        filled: function(a) {
            return !!$.trim("" + a.value);
        },
        // http://docs.jquery.com/Plugins/Validation/unchecked
        unchecked: function(a) {
            return !a.checked;
        }
    });

    // constructor for validator
    $.validator = function( options, form ) {
        this.settings = $.extend( true, {}, $.validator.defaults, options );
        this.currentForm = form;
        this.init();
    };

    $.validator.format = function(source, params) {
    
        if ( arguments.length == 1 )
            return function() {
                var args = $.makeArray(arguments);
                args.unshift(source);
                return $.validator.format.apply( this, args );
            };
        if ( arguments.length > 2 && params.constructor !== Array  ) {
            params = $.makeArray(arguments).slice(1);
        }
        if ( params.constructor !== Array ) {
            params = [ params ];
        }
        return source.sprintf.apply( source, params );
    };

    $.extend($.validator, {
	
        defaults: {
            messages: {},
            groups: {},
            rules: {},
            errorClass: "error",
            validClass: "valid",
            errorElement: "label",
            focusInvalid: true,
            errorContainer: $( [] ),
            errorLabelContainer: $( [] ),
            onsubmit: true,
            ignore: [],
            ignoreTitle: false,
            onfocusin: function(element) {
                this.lastActive = element;
				
                // hide error label and remove error class on focus if enabled
                if ( this.settings.focusCleanup && !this.blockFocusCleanup ) {
                    this.settings.unhighlight && this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass );
                    this.errorsFor(element).hide();
                }
            },
            onfocusout: function(element) {
                if ( !this.checkable(element) && (element.name in this.submitted || !this.optional(element)) ) {
                    this.element(element);
                }
            },
            onkeyup: function(element) {
                if ( element.name in this.submitted || element == this.lastElement ) {
                    this.element(element);
                }
            },
            onclick: function(element) {
                // click on selects, radiobuttons and checkboxes
                if ( element.name in this.submitted )
                    this.element(element);
                // or option elements, check parent select in that case
                else if (element.parentNode.name in this.submitted)
                    this.element(element.parentNode);
            },
            highlight: function( element, errorClass, validClass ) {
                $(element).addClass(errorClass).removeClass(validClass);
            },
            unhighlight: function( element, errorClass, validClass ) {
                $(element).removeClass(errorClass).addClass(validClass);
            }
        },

        // http://docs.jquery.com/Plugins/Validation/Validator/setDefaults
        setDefaults: function(settings) {
            $.extend( $.validator.defaults, settings );
        },

        messages: {},
	
        autoCreateRanges: false,
	
        prototype: {
		
            init: function() {
                this.labelContainer = $(this.settings.errorLabelContainer);
                this.errorContext = this.labelContainer.length && this.labelContainer || $(this.currentForm);
                this.containers = $(this.settings.errorContainer).add( this.settings.errorLabelContainer );
                this.submitted = {};
                this.valueCache = {};
                this.pendingRequest = 0;
                this.pending = {};
                this.invalid = {};
                this.reset();
			
                var groups = (this.groups = {});
                $.each(this.settings.groups, function(key, value) {
                    $.each(value.split(/\s/), function(index, name) {
                        groups[name] = key;
                    });
                });
                var rules = this.settings.rules;
                $.each(rules, function(key, value) {
                    rules[key] = $.validator.normalizeRule(value);
                });
			
                function delegate(event) {
                    var validator = $.data(this[0].form, "validator"),
                    eventType = "on" + event.type.replace(/^validate/, "");
                    validator.settings[eventType] && validator.settings[eventType].call(validator, this[0] );
                }
                $(this.currentForm)
                .validateDelegate(":text, :password, :file, select, textarea", "focusin focusout keyup", delegate)
                .validateDelegate(":radio, :checkbox, select, option", "click", delegate);

                if (this.settings.invalidHandler)
                    $(this.currentForm).bind("invalid-form.validate", this.settings.invalidHandler);
            },

            // http://docs.jquery.com/Plugins/Validation/Validator/form
            form: function() {
                this.checkForm();
                $.extend(this.submitted, this.errorMap);
                this.invalid = $.extend({}, this.errorMap);
                if (!this.valid())
                    $(this.currentForm).triggerHandler("invalid-form", [this]);
                this.showErrors();
                return this.valid();
            },
		
            checkForm: function() {
                this.prepareForm();
                for ( var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++ ) {
                    this.check( elements[i] );
                }
                return this.valid();
            },
		
            // http://docs.jquery.com/Plugins/Validation/Validator/element
            element: function( element ) {
                element = this.clean( element );
                this.lastElement = element;
                this.prepareElement( element );
                this.currentElements = $(element);
                var result = this.check( element );
                if ( result ) {
                    delete this.invalid[element.name];
                } else {
                    this.invalid[element.name] = true;
                }
                if ( !this.numberOfInvalids() ) {
                    // Hide error containers on last error
                    this.toHide = this.toHide.add( this.containers );
                }
                this.showErrors();
                return result;
            },

            // http://docs.jquery.com/Plugins/Validation/Validator/showErrors
            showErrors: function(errors) {
                if(errors) {
                    // add items to error list and map
                    $.extend( this.errorMap, errors );
                    this.errorList = [];
                    for ( var name in errors ) {
                        this.errorList.push({
                            message: errors[name],
                            element: this.findByName(name)[0]
                        });
                    }
                    // remove items from success list
                    this.successList = $.grep( this.successList, function(element) {
                        return !(element.name in errors);
                    });
                }
                this.settings.showErrors
                ? this.settings.showErrors.call( this, this.errorMap, this.errorList )
                : this.defaultShowErrors();
            },
		
            // http://docs.jquery.com/Plugins/Validation/Validator/resetForm
            resetForm: function() {
                if ( $.fn.resetForm )
                    $( this.currentForm ).resetForm();
                this.submitted = {};
                this.prepareForm();
                this.hideErrors();
                this.elements().removeClass( this.settings.errorClass );
            },
		
            numberOfInvalids: function() {
                return this.objectLength(this.invalid);
            },
		
            objectLength: function( obj ) {
                var count = 0;
                for ( var i in obj )
                    count++;
                return count;
            },
		
            hideErrors: function() {
                this.addWrapper( this.toHide ).hide();
            },
		
            valid: function() {
                return this.size() == 0;
            },
		
            size: function() {
                return this.errorList.length;
            },
		
            focusInvalid: function() {
                if( this.settings.focusInvalid ) {
                    try {
                        $(this.findLastActive() || this.errorList.length && this.errorList[0].element || [])
                        .filter(":visible")
                        .focus()
                        // manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find
                        .trigger("focusin");
                    } catch(e) {
                    // ignore IE throwing errors when focusing hidden elements
                    }
                }
            },
		
            findLastActive: function() {
                var lastActive = this.lastActive;
                return lastActive && $.grep(this.errorList, function(n) {
                    return n.element.name == lastActive.name;
                }).length == 1 && lastActive;
            },
		
            elements: function() {
                var validator = this,
                rulesCache = {};
			
                // select all valid inputs inside the form (no submit or reset buttons)
                // workaround $Query([]).add until http://dev.jquery.com/ticket/2114 is solved
                return $([]).add(this.currentForm.elements)
                .filter(":input")
                .not(":submit, :reset, :image, [disabled]")
                .not( this.settings.ignore )
                .filter(function() {
                    !this.name && validator.settings.debug && window.console && console.error( "%o has no name assigned", this);
			
                    // select only the first element for each name, and only those with rules specified
                    if ( this.name in rulesCache || !validator.objectLength($(this).rules()) )
                        return false;
				
                    rulesCache[this.name] = true;
                    return true;
                });
            },
		
            clean: function( selector ) {
                return $( selector )[0];
            },
		
            errors: function() {
                return $( this.settings.errorElement + "." + this.settings.errorClass, this.errorContext );
            },
		
            reset: function() {
                this.successList = [];
                this.errorList = [];
                this.errorMap = {};
                this.toShow = $([]);
                this.toHide = $([]);
                this.currentElements = $([]);
            },
		
            prepareForm: function() {
                this.reset();
                this.toHide = this.errors().add( this.containers );
            },
		
            prepareElement: function( element ) {
                this.reset();
                this.toHide = this.errorsFor(element);
            },
	
            check: function( element ) {
                element = this.clean( element );
			
                // if radio/checkbox, validate first element in group instead
                if (this.checkable(element)) {
                    element = this.findByName( element.name )[0];
                }
			
                var rules = $(element).rules();
                var dependencyMismatch = false;
                for( method in rules ) {
                    var rule = {
                        method: method,
                        parameters: rules[method]
                        };
                    try {
                        var result = $.validator.methods[method].call( this, element.value.replace(/\r/g, ""), element, rule.parameters );
					
                        // if a method indicates that the field is optional and therefore valid,
                        // don't mark it as valid when there are no other rules
                        if ( result == "dependency-mismatch" ) {
                            dependencyMismatch = true;
                            continue;
                        }
                        dependencyMismatch = false;
					
                        if ( result == "pending" ) {
                            this.toHide = this.toHide.not( this.errorsFor(element) );
                            return;
                        }
					
                        if( !result ) {
                            this.formatAndAdd( element, rule );
                            return false;
                        }
                    } catch(e) {
                        this.settings.debug && window.console && console.log("exception occured when checking element " + element.id
                            + ", check the '" + rule.method + "' method", e);
                        throw e;
                    }
                }
                if (dependencyMismatch)
                    return;
                if ( this.objectLength(rules) )
                    this.successList.push(element);
                return true;
            },
		
            // return the custom message for the given element and validation method
            // specified in the element's "messages" metadata
            customMetaMessage: function(element, method) {
                if (!$.metadata)
                    return;
			
                var meta = this.settings.meta
                ? $(element).metadata()[this.settings.meta]
                : $(element).metadata();
			
                return meta && meta.messages && meta.messages[method];
            },
		
            // return the custom message for the given element name and validation method
            customMessage: function( name, method ) {
                var m = this.settings.messages[name];
                return m && (m.constructor == String
                    ? m
                    : m[method]);
            },
		
            // return the first defined argument, allowing empty strings
            findDefined: function() {
                for(var i = 0; i < arguments.length; i++) {

                    if (arguments[i] !== undefined)
                        return arguments[i];
                }
                return undefined;
            },
		
            defaultMessage: function( element, method) {
                return this.findDefined(
                    this.customMessage( element.name, method ),
                    this.customMetaMessage( element, method ),
                    // title is never undefined, so handle empty string as undefined
                    !this.settings.ignoreTitle && element.title || undefined,
                    $.validator.messages[method],
                    "<strong>Warning: No message defined for " + element.name + "</strong>"
                    );
            },
		
            formatAndAdd: function( element, rule ) {
                var message = this.defaultMessage( element, rule.method ),
                theregex = /\$?\{(\d+)\}/g;
                if ( typeof message == "function" ) {
                    message = message.call(this, rule.parameters, element);
                } else if (theregex.test(message)) {
                    message = jQuery.format(message.replace(theregex, '{$1}'), rule.parameters);
                }
                this.errorList.push({
                    message: message,
                    element: element
                });
			
                this.errorMap[element.name] = message;
                this.submitted[element.name] = message;
            },
		
            addWrapper: function(toToggle) {
                if ( this.settings.wrapper )
                    toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) );
                return toToggle;
            },
		
            defaultShowErrors: function() {
                for ( var i = 0; this.errorList[i]; i++ ) {
                    var error = this.errorList[i];
                    this.settings.highlight && this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass );
                    this.showLabel( error.element, error.message );
                }
                if( this.errorList.length ) {
                    this.toShow = this.toShow.add( this.containers );
                }
                if (this.settings.success) {
                    for ( var i = 0; this.successList[i]; i++ ) {
                        this.showLabel( this.successList[i] );
                    }
                }
                if (this.settings.unhighlight) {
                    for ( var i = 0, elements = this.validElements(); elements[i]; i++ ) {
                        this.settings.unhighlight.call( this, elements[i], this.settings.errorClass, this.settings.validClass );
                    }
                }
                this.toHide = this.toHide.not( this.toShow );
                this.hideErrors();
                this.addWrapper( this.toShow ).show();
            },
		
            validElements: function() {
                return this.currentElements.not(this.invalidElements());
            },
		
            invalidElements: function() {
                return $(this.errorList).map(function() {
                    return this.element;
                });
            },
		
            showLabel: function(element, message) {
                var label = this.errorsFor( element );
                if ( label.length ) {
                    // refresh error/success class
                    label.removeClass().addClass( this.settings.errorClass );
			
                    // check if we have a generated label, replace the message then
                    label.attr("generated") && label.html(message);
                } else {
                    // create label
                    label = $("<" + this.settings.errorElement + "/>")
                    .attr({
                        "for":  this.idOrName(element),
                        generated: true
                    })
                    .addClass(this.settings.errorClass)
                    .html(message || "");
                    if ( this.settings.wrapper ) {
                        // make sure the element is visible, even in IE
                        // actually showing the wrapped element is handled elsewhere
                        label = label.hide().show().wrap("<" + this.settings.wrapper + "/>").parent();
                    }
                    if ( !this.labelContainer.append(label).length )
                        this.settings.errorPlacement
                        ? this.settings.errorPlacement(label, $(element) )
                        : label.insertAfter(element);
                }
                if ( !message && this.settings.success ) {
                    label.text("");
                    typeof this.settings.success == "string"
                    ? label.addClass( this.settings.success )
                    : this.settings.success( label );
                }
                this.toShow = this.toShow.add(label);
            },
		
            errorsFor: function(element) {
                var name = this.idOrName(element);
                return this.errors().filter(function() {
                    return $(this).attr('for') == name;
                });
            },
		
            idOrName: function(element) {
                return this.groups[element.name] || (this.checkable(element) ? element.name : element.id || element.name);
            },

            checkable: function( element ) {
                return /radio|checkbox/i.test(element.type);
            },
		
            findByName: function( name ) {
                // select by name and filter by form for performance over form.find("[name=...]")
                var form = this.currentForm;
                return $(document.getElementsByName(name)).map(function(index, element) {
                    return element.form == form && element.name == name && element  || null;
                });
            },
		
            getLength: function(value, element) {
                switch( element.nodeName.toLowerCase() ) {
                    case 'select':
                        return $("option:selected", element).length;
                    case 'input':
                        if( this.checkable( element) )
                            return this.findByName(element.name).filter(':checked').length;
                }
                return value.length;
            },
	
            depend: function(param, element) {
                return this.dependTypes[typeof param]
                ? this.dependTypes[typeof param](param, element)
                : true;
            },
	
            dependTypes: {
                "boolean": function(param, element) {
                    return param;
                },
                "string": function(param, element) {
                    return !!$(param, element.form).length;
                },
                "function": function(param, element) {
                    return param(element);
                }
            },
		
            optional: function(element) {
                return !$.validator.methods.required.call(this, $.trim(element.value), element) && "dependency-mismatch";
            },
		
            startRequest: function(element) {
                if (!this.pending[element.name]) {
                    this.pendingRequest++;
                    this.pending[element.name] = true;
                }
            },
		
            stopRequest: function(element, valid) {
                this.pendingRequest--;
                // sometimes synchronization fails, make sure pendingRequest is never < 0
                if (this.pendingRequest < 0)
                    this.pendingRequest = 0;
                delete this.pending[element.name];
                if ( valid && this.pendingRequest == 0 && this.formSubmitted && this.form() ) {
                    $(this.currentForm).submit();
                    this.formSubmitted = false;
                } else if (!valid && this.pendingRequest == 0 && this.formSubmitted) {
                    $(this.currentForm).triggerHandler("invalid-form", [this]);
                    this.formSubmitted = false;
                }
            },
		
            previousValue: function(element) {
                return $.data(element, "previousValue") || $.data(element, "previousValue", {
                    old: null,
                    valid: true,
                    message: this.defaultMessage( element, "remote" )
                });
            }
		
        },
	
        classRuleSettings: {
            required: {
                required: true
            },
            email: {
                email: true
            },
            url: {
                url: true
            },
            date: {
                date: true
            },
            dateISO: {
                dateISO: true
            },
            dateDE: {
                dateDE: true
            },
            number: {
                number: true
            },
            numberDE: {
                numberDE: true
            },
            digits: {
                digits: true
            },
            creditcard: {
                creditcard: true
            }
        },
	
        addClassRules: function(className, rules) {
            className.constructor == String ?
            this.classRuleSettings[className] = rules :
            $.extend(this.classRuleSettings, className);
        },
	
        classRules: function(element) {
            var rules = {};
            var classes = $(element).attr('class');
            classes && $.each(classes.split(' '), function() {
                if (this in $.validator.classRuleSettings) {
                    $.extend(rules, $.validator.classRuleSettings[this]);
                }
            });
            return rules;
        },
	
        attributeRules: function(element) {
            var rules = {};
            var $element = $(element);
		
            for (method in $.validator.methods) {
                var value = $element.attr(method);
                if (value) {
                    rules[method] = value;
                }
            }
		
            // maxlength may be returned as -1, 2147483647 (IE) and 524288 (safari) for text inputs
            if (rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength)) {
                delete rules.maxlength;
            }
		
            return rules;
        },
	
        metadataRules: function(element) {
            if (!$.metadata) return {};
		
            var meta = $.data(element.form, 'validator').settings.meta;
            return meta ?
            $(element).metadata()[meta] :
            $(element).metadata();
        },
	
        staticRules: function(element) {
            var rules = {};
            var validator = $.data(element.form, 'validator');
            if (validator.settings.rules) {
                rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {};
            }
            return rules;
        },
	
        normalizeRules: function(rules, element) {
            // handle dependency check
            $.each(rules, function(prop, val) {
                // ignore rule when param is explicitly false, eg. required:false
                if (val === false) {
                    delete rules[prop];
                    return;
                }
                if (val.param || val.depends) {
                    var keepRule = true;
                    switch (typeof val.depends) {
                        case "string":
                            keepRule = !!$(val.depends, element.form).length;
                            break;
                        case "function":
                            keepRule = val.depends.call(element, element);
                            break;
                    }
                    if (keepRule) {
                        rules[prop] = val.param !== undefined ? val.param : true;
                    } else {
                        delete rules[prop];
                    }
                }
            });
		
            // evaluate parameters
            $.each(rules, function(rule, parameter) {
                rules[rule] = $.isFunction(parameter) ? parameter(element) : parameter;
            });
		
            // clean number parameters
            $.each(['minlength', 'maxlength', 'min', 'max'], function() {
                if (rules[this]) {
                    rules[this] = Number(rules[this]);
                }
            });
            $.each(['rangelength', 'range'], function() {
                if (rules[this]) {
                    rules[this] = [Number(rules[this][0]), Number(rules[this][1])];
                }
            });
		
            if ($.validator.autoCreateRanges) {
                // auto-create ranges
                if (rules.min && rules.max) {
                    rules.range = [rules.min, rules.max];
                    delete rules.min;
                    delete rules.max;
                }
                if (rules.minlength && rules.maxlength) {
                    rules.rangelength = [rules.minlength, rules.maxlength];
                    delete rules.minlength;
                    delete rules.maxlength;
                }
            }
		
            // To support custom messages in metadata ignore rule methods titled "messages"
            if (rules.messages) {
                delete rules.messages;
            }
		
            return rules;
        },
	
        // Converts a simple string to a {string: true} rule, e.g., "required" to {required:true}
        normalizeRule: function(data) {
            if( typeof data == "string" ) {
                var transformed = {};
                $.each(data.split(/\s/), function() {
                    transformed[this] = true;
                });
                data = transformed;
            }
            return data;
        },
	
        // http://docs.jquery.com/Plugins/Validation/Validator/addMethod
        addMethod: function(name, method, message) {
            $.validator.methods[name] = method;
            $.validator.messages[name] = message != undefined ? message : $.validator.messages[name];
            if (method.length < 3) {
                $.validator.addClassRules(name, $.validator.normalizeRule(name));
            }
        },

        methods: {
            // new
            regex:  function(value, element, param) {
                var re = new RegExp(param);
                return this.optional(element) || re.test(value);
            },
            // http://docs.jquery.com/Plugins/Validation/Methods/required
            required: function(value, element, param) {
                // check if dependency is met
                if ( !this.depend(param, element) )
                    return "dependency-mismatch";
                switch( element.nodeName.toLowerCase() ) {
                    case 'select':
                        // could be an array for select-multiple or a string, both are fine this way
                        var val = $(element).val();
                        return val && val.length > 0;
                    case 'input':
                        if ( this.checkable(element) )
                            return this.getLength(value, element) > 0;
                    default:
                        return $.trim(value).length > 0;
                }
            },
            // modified
            remote: function(value, element, param) {
                if ( this.optional(element) )
                    return "dependency-mismatch";
			
                var previous = this.previousValue(element);
                if (!this.settings.messages[element.name] )
                    this.settings.messages[element.name] = {};
                previous.originalMessage = this.settings.messages[element.name].remote;
                this.settings.messages[element.name].remote = previous.message;
			
                param = typeof param == "string" && {
                    url:param
                } || param;
			
                if ( previous.old !== value ) {
                    previous.old = value;
                    var validator = this;
                    this.startRequest(element);
                    var data = {};
                    data[element.name] = value;
                    $.ajax($.extend(true, {
                        url: param,
                        mode: "abort",
                        port: "validate" + element.name,
                        dataType: "json",
                        data: data,
                        success: function(response) {
                            var valid = response.status;
                            if ($.isFunction(param.actionAfter)) {
                                param.actionAfter(response);
                            }

                            if (valid) {
                                var submitted = validator.formSubmitted;
                                validator.prepareElement(element);
                                validator.formSubmitted = submitted;
                                validator.successList.push(element);
                                validator.showErrors();
                            } else {
                                var errors = [];
                                errors[element.name] = (previous.message = response.message || validator.defaultMessage( element, "customRemote" ));

                                validator.showErrors(errors);
                            }
                            previous.valid = valid;
                            validator.stopRequest(element, valid);
                        }
                    }, param));
                    return "pending";
                } else if( this.pending[element.name] ) {
                    return "pending";
                }
                return previous.valid;
            },

            // http://docs.jquery.com/Plugins/Validation/Methods/minlength
            minlength: function(value, element, param) {
                return this.optional(element) || this.getLength($.trim(value), element) >= param;
            },
		
            // http://docs.jquery.com/Plugins/Validation/Methods/maxlength
            maxlength: function(value, element, param) {
                return this.optional(element) || this.getLength($.trim(value), element) <= param;
            },
		
            // http://docs.jquery.com/Plugins/Validation/Methods/rangelength
            rangelength: function(value, element, param) {
                var length = this.getLength($.trim(value), element);
                return this.optional(element) || ( length >= param[0] && length <= param[1] );
            },
		
            // http://docs.jquery.com/Plugins/Validation/Methods/min
            min: function( value, element, param ) {
                return this.optional(element) || value >= param;
            },
		
            // http://docs.jquery.com/Plugins/Validation/Methods/max
            max: function( value, element, param ) {
                return this.optional(element) || value <= param;
            },
		
            // http://docs.jquery.com/Plugins/Validation/Methods/range
            range: function( value, element, param ) {
                return this.optional(element) || ( value >= param[0] && value <= param[1] );
            },
		
            // http://docs.jquery.com/Plugins/Validation/Methods/email
            email: function(value, element) {
                // contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/
                return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value);
            },
	
            // http://docs.jquery.com/Plugins/Validation/Methods/url
            url: function(value, element) {
                // contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/
                return this.optional(element) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value);
            },
        
            // http://docs.jquery.com/Plugins/Validation/Methods/date
            date: function(value, element) {
                return this.optional(element) || !/Invalid|NaN/.test(new Date(value));
            },
	
            // http://docs.jquery.com/Plugins/Validation/Methods/dateISO
            dateISO: function(value, element) {
                return this.optional(element) || /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(value);
            },
	
            // http://docs.jquery.com/Plugins/Validation/Methods/number
            number: function(value, element) {
                return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(value);
            },
	
            // http://docs.jquery.com/Plugins/Validation/Methods/digits
            digits: function(value, element) {
                return this.optional(element) || /^\d+$/.test(value);
            },
		
            // http://docs.jquery.com/Plugins/Validation/Methods/creditcard
            // based on http://en.wikipedia.org/wiki/Luhn
            creditcard: function(value, element) {
                if ( this.optional(element) )
                    return "dependency-mismatch";
                // accept only digits and dashes
                if (/[^0-9-]+/.test(value))
                    return false;
                var nCheck = 0,
                nDigit = 0,
                bEven = false;

                value = value.replace(/\D/g, "");

                for (var n = value.length - 1; n >= 0; n--) {
                    var cDigit = value.charAt(n);
                    var nDigit = parseInt(cDigit, 10);
                    if (bEven) {
                        if ((nDigit *= 2) > 9)
                            nDigit -= 9;
                    }
                    nCheck += nDigit;
                    bEven = !bEven;
                }

                return (nCheck % 10) == 0;
            },
		
            // http://docs.jquery.com/Plugins/Validation/Methods/accept
            accept: function(value, element, param) {
                param = typeof param == "string" ? param.replace(/,/g, '|') : "png|jpe?g|gif";
                return this.optional(element) || value.match(new RegExp(".(" + param + ")$", "i"));
            },
		
            // http://docs.jquery.com/Plugins/Validation/Methods/equalTo
            equalTo: function(value, element, param) {
                // bind to the blur event of the target in order to revalidate whenever the target field is updated
                // TODO find a way to bind the event just once, avoiding the unbind-rebind overhead
                var target = $(param).unbind(".validate-equalTo").bind("blur.validate-equalTo", function() {
                    $(element).valid();
                });
                return value == target.val();
            }
		
        }
	
    });

    // deprecated, use $.validator.format instead
    $.format = $.validator.format;

})(jQuery);

// ajax mode: abort
// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});
// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort() 
;
(function($) {
    var ajax = $.ajax;
    var pendingRequests = {};
    $.ajax = function(settings) {
        // create settings for compatibility with ajaxSetup
        settings = $.extend(settings, $.extend({}, $.ajaxSettings, settings));
        var port = settings.port;
        if (settings.mode == "abort") {
            if ( pendingRequests[port] ) {
                pendingRequests[port].abort();
            }
            return (pendingRequests[port] = ajax.apply(this, arguments));
        }
        return ajax.apply(this, arguments);
    };
})(jQuery);

// provides cross-browser focusin and focusout events
// IE has native support, in other browsers, use event caputuring (neither bubbles)

// provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation
// handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target 
;
(function($) {
    // only implement if not provided by jQuery core (since 1.4)
    // TODO verify if jQuery 1.4's implementation is compatible with older jQuery special-event APIs
    if (!jQuery.event.special.focusin && !jQuery.event.special.focusout && document.addEventListener) {
        $.each({
            focus: 'focusin',
            blur: 'focusout'
        }, function( original, fix ){
            $.event.special[fix] = {
                setup:function() {
                    this.addEventListener( original, handler, true );
                },
                teardown:function() {
                    this.removeEventListener( original, handler, true );
                },
                handler: function(e) {
                    arguments[0] = $.event.fix(e);
                    arguments[0].type = fix;
                    return $.event.handle.apply(this, arguments);
                }
            };
            function handler(e) {
                e = $.event.fix(e);
                e.type = fix;
                return $.event.handle.call(this, e);
            }
        });
    };
    $.extend($.fn, {
        validateDelegate: function(delegate, type, handler) {
            return this.bind(type, function(event) {
                var target = $(event.target);
                if (target.is(delegate)) {
                    return handler.apply(target, arguments);
                }
            });
        }
    });
})(jQuery);

/* #10# */

/*!
 * jQuery UI 1.8.7
 *
 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI
 */
(function( $, undefined ) {

    // prevent duplicate loading
    // this is only a problem because we proxy existing functions
    // and we don't want to double proxy them
    $.ui = $.ui || {};
    if ( $.ui.version ) {
        return;
    }

    $.extend( $.ui, {
        version: "1.8.7",

        keyCode: {
            ALT: 18,
            BACKSPACE: 8,
            CAPS_LOCK: 20,
            COMMA: 188,
            COMMAND: 91,
            COMMAND_LEFT: 91, // COMMAND
            COMMAND_RIGHT: 93,
            CONTROL: 17,
            DELETE: 46,
            DOWN: 40,
            END: 35,
            ENTER: 13,
            ESCAPE: 27,
            HOME: 36,
            INSERT: 45,
            LEFT: 37,
            MENU: 93, // COMMAND_RIGHT
            NUMPAD_ADD: 107,
            NUMPAD_DECIMAL: 110,
            NUMPAD_DIVIDE: 111,
            NUMPAD_ENTER: 108,
            NUMPAD_MULTIPLY: 106,
            NUMPAD_SUBTRACT: 109,
            PAGE_DOWN: 34,
            PAGE_UP: 33,
            PERIOD: 190,
            RIGHT: 39,
            SHIFT: 16,
            SPACE: 32,
            TAB: 9,
            UP: 38,
            WINDOWS: 91 // COMMAND
        }
    });

    // plugins
    $.fn.extend({
        _focus: $.fn.focus,
        focus: function( delay, fn ) {
            return typeof delay === "number" ?
            this.each(function() {
                var elem = this;
                setTimeout(function() {
                    $( elem ).focus();
                    if ( fn ) {
                        fn.call( elem );
                    }
                }, delay );
            }) :
            this._focus.apply( this, arguments );
        },

        scrollParent: function() {
            var scrollParent;
            if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
                scrollParent = this.parents().filter(function() {
                    return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
                }).eq(0);
            } else {
                scrollParent = this.parents().filter(function() {
                    return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
                }).eq(0);
            }

            return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
        },

        zIndex: function( zIndex ) {
            if ( zIndex !== undefined ) {
                return this.css( "zIndex", zIndex );
            }

            if ( this.length ) {
                var elem = $( this[ 0 ] ), position, value;
                while ( elem.length && elem[ 0 ] !== document ) {
                    // Ignore z-index if position is set to a value where z-index is ignored by the browser
                    // This makes behavior of this function consistent across browsers
                    // WebKit always returns auto if the element is positioned
                    position = elem.css( "position" );
                    if ( position === "absolute" || position === "relative" || position === "fixed" ) {
                        // IE returns 0 when zIndex is not specified
                        // other browsers return a string
                        // we ignore the case of nested elements with an explicit value of 0
                        // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
                        value = parseInt( elem.css( "zIndex" ), 10 );
                        if ( !isNaN( value ) && value !== 0 ) {
                            return value;
                        }
                    }
                    elem = elem.parent();
                }
            }

            return 0;
        },

        disableSelection: function() {
            return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
                ".ui-disableSelection", function( event ) {
                    event.preventDefault();
                });
        },

        enableSelection: function() {
            return this.unbind( ".ui-disableSelection" );
        }
    });

    $.each( [ "Width", "Height" ], function( i, name ) {
        var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
        type = name.toLowerCase(),
        orig = {
            innerWidth: $.fn.innerWidth,
            innerHeight: $.fn.innerHeight,
            outerWidth: $.fn.outerWidth,
            outerHeight: $.fn.outerHeight
        };

        function reduce( elem, size, border, margin ) {
            $.each( side, function() {
                size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0;
                if ( border ) {
                    size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0;
                }
                if ( margin ) {
                    size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0;
                }
            });
            return size;
        }

        $.fn[ "inner" + name ] = function( size ) {
            if ( size === undefined ) {
                return orig[ "inner" + name ].call( this );
            }

            return this.each(function() {
                $( this ).css( type, reduce( this, size ) + "px" );
            });
        };

        $.fn[ "outer" + name] = function( size, margin ) {
            if ( typeof size !== "number" ) {
                return orig[ "outer" + name ].call( this, size );
            }

            return this.each(function() {
                $( this).css( type, reduce( this, size, true, margin ) + "px" );
            });
        };
    });

    // selectors
    function visible( element ) {
        return !$( element ).parents().andSelf().filter(function() {
            return $.curCSS( this, "visibility" ) === "hidden" ||
            $.expr.filters.hidden( this );
        }).length;
    }

    $.extend( $.expr[ ":" ], {
        data: function( elem, i, match ) {
            return !!$.data( elem, match[ 3 ] );
        },

        focusable: function( element ) {
            var nodeName = element.nodeName.toLowerCase(),
            tabIndex = $.attr( element, "tabindex" );
            if ( "area" === nodeName ) {
                var map = element.parentNode,
                mapName = map.name,
                img;
                if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
                    return false;
                }
                img = $( "img[usemap=#" + mapName + "]" )[0];
                return !!img && visible( img );
            }
            return ( /input|select|textarea|button|object/.test( nodeName )
                ? !element.disabled
                : "a" == nodeName
                ? element.href || !isNaN( tabIndex )
                : !isNaN( tabIndex ))
            // the element and all of its ancestors must be visible
            && visible( element );
        },

        tabbable: function( element ) {
            var tabIndex = $.attr( element, "tabindex" );
            return ( isNaN( tabIndex ) || tabIndex >= 0 ) && $( element ).is( ":focusable" );
        }
    });

    // support
    $(function() {
        var body = document.body,
        div = body.appendChild( div = document.createElement( "div" ) );

        $.extend( div.style, {
            minHeight: "100px",
            height: "auto",
            padding: 0,
            borderWidth: 0
        });

        $.support.minHeight = div.offsetHeight === 100;
        $.support.selectstart = "onselectstart" in div;

        // set display to none to avoid a layout bug in IE
        // http://dev.jquery.com/ticket/4014
        body.removeChild( div ).style.display = "none";
    });





    // deprecated
    $.extend( $.ui, {
        // $.ui.plugin is deprecated.  Use the proxy pattern instead.
        plugin: {
            add: function( module, option, set ) {
                var proto = $.ui[ module ].prototype;
                for ( var i in set ) {
                    proto.plugins[ i ] = proto.plugins[ i ] || [];
                    proto.plugins[ i ].push( [ option, set[ i ] ] );
                }
            },
            call: function( instance, name, args ) {
                var set = instance.plugins[ name ];
                if ( !set || !instance.element[ 0 ].parentNode ) {
                    return;
                }
	
                for ( var i = 0; i < set.length; i++ ) {
                    if ( instance.options[ set[ i ][ 0 ] ] ) {
                        set[ i ][ 1 ].apply( instance.element, args );
                    }
                }
            }
        },
	
        // will be deprecated when we switch to jQuery 1.4 - use jQuery.contains()
        contains: function( a, b ) {
            return document.compareDocumentPosition ?
            a.compareDocumentPosition( b ) & 16 :
            a !== b && a.contains( b );
        },
	
        // only used by resizable
        hasScroll: function( el, a ) {
	
            //If overflow is hidden, the element might have extra content, but the user wants to hide it
            if ( $( el ).css( "overflow" ) === "hidden") {
                return false;
            }
	
            var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
            has = false;
	
            if ( el[ scroll ] > 0 ) {
                return true;
            }
	
            // TODO: determine which cases actually cause this to happen
            // if the element doesn't have the scroll set, see if it's possible to
            // set the scroll
            el[ scroll ] = 1;
            has = ( el[ scroll ] > 0 );
            el[ scroll ] = 0;
            return has;
        },
	
        // these are odd functions, fix the API or move into individual plugins
        isOverAxis: function( x, reference, size ) {
            //Determines when x coordinate is over "b" element axis
            return ( x > reference ) && ( x < ( reference + size ) );
        },
        isOver: function( y, x, top, left, height, width ) {
            //Determines when x, y coordinates is over "b" element
            return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
        }
    });

})( jQuery );


/* #11# */

/*!
 * jQuery UI Widget 1.8.7
 *
 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Widget
 */
(function( $, undefined ) {

    // jQuery 1.4+
    if ( $.cleanData ) {
        var _cleanData = $.cleanData;
        $.cleanData = function( elems ) {
            for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
                $( elem ).triggerHandler( "remove" );
            }
            _cleanData( elems );
        };
    } else {
        var _remove = $.fn.remove;
        $.fn.remove = function( selector, keepData ) {
            return this.each(function() {
                if ( !keepData ) {
                    if ( !selector || $.filter( selector, [ this ] ).length ) {
                        $( "*", this ).add( [ this ] ).each(function() {
                            $( this ).triggerHandler( "remove" );
                        });
                    }
                }
                return _remove.call( $(this), selector, keepData );
            });
        };
    }

    $.widget = function( name, base, prototype ) {
        var namespace = name.split( "." )[ 0 ],
        fullName;
        name = name.split( "." )[ 1 ];
        fullName = namespace + "-" + name;

        if ( !prototype ) {
            prototype = base;
            base = $.Widget;
        }

        // create selector for plugin
        $.expr[ ":" ][ fullName ] = function( elem ) {
            return !!$.data( elem, name );
        };

        $[ namespace ] = $[ namespace ] || {};
        $[ namespace ][ name ] = function( options, element ) {
            // allow instantiation without initializing for simple inheritance
            if ( arguments.length ) {
                this._createWidget( options, element );
            }
        };

        var basePrototype = new base();
        // we need to make the options hash a property directly on the new instance
        // otherwise we'll modify the options hash on the prototype that we're
        // inheriting from
        //	$.each( basePrototype, function( key, val ) {
        //		if ( $.isPlainObject(val) ) {
        //			basePrototype[ key ] = $.extend( {}, val );
        //		}
        //	});
        basePrototype.options = $.extend( true, {}, basePrototype.options );
        $[ namespace ][ name ].prototype = $.extend( true, basePrototype, {
            namespace: namespace,
            widgetName: name,
            widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,
            widgetBaseClass: fullName
        }, prototype );

        $.widget.bridge( name, $[ namespace ][ name ] );
    };

    $.widget.bridge = function( name, object ) {
        $.fn[ name ] = function( options ) {
            var isMethodCall = typeof options === "string",
            args = Array.prototype.slice.call( arguments, 1 ),
            returnValue = this;

            // allow multiple hashes to be passed on init
            options = !isMethodCall && args.length ?
            $.extend.apply( null, [ true, options ].concat(args) ) :
            options;

            // prevent calls to internal methods
            if ( isMethodCall && options.charAt( 0 ) === "_" ) {
                return returnValue;
            }

            if ( isMethodCall ) {
                this.each(function() {
                    var instance = $.data( this, name ),
                    methodValue = instance && $.isFunction( instance[options] ) ?
                    instance[ options ].apply( instance, args ) :
                    instance;
                    // TODO: add this back in 1.9 and use $.error() (see #5972)
                    //				if ( !instance ) {
                    //					throw "cannot call methods on " + name + " prior to initialization; " +
                    //						"attempted to call method '" + options + "'";
                    //				}
                    //				if ( !$.isFunction( instance[options] ) ) {
                    //					throw "no such method '" + options + "' for " + name + " widget instance";
                    //				}
                    //				var methodValue = instance[ options ].apply( instance, args );
                    if ( methodValue !== instance && methodValue !== undefined ) {
                        returnValue = methodValue;
                        return false;
                    }
                });
            } else {
                this.each(function() {
                    var instance = $.data( this, name );
                    if ( instance ) {
                        instance.option( options || {} )._init();
                    } else {
                        $.data( this, name, new object( options, this ) );
                    }
                });
            }

            return returnValue;
        };
    };

    $.Widget = function( options, element ) {
        // allow instantiation without initializing for simple inheritance
        if ( arguments.length ) {
            this._createWidget( options, element );
        }
    };

    $.Widget.prototype = {
        widgetName: "widget",
        widgetEventPrefix: "",
        options: {
            disabled: false
        },
        _createWidget: function( options, element ) {
            // $.widget.bridge stores the plugin instance, but we do it anyway
            // so that it's stored even before the _create function runs
            $.data( element, this.widgetName, this );
            this.element = $( element );
            this.options = $.extend( true, {},
                this.options,
                this._getCreateOptions(),
                options );

            var self = this;
            this.element.bind( "remove." + this.widgetName, function() {
                self.destroy();
            });

            this._create();
            this._trigger( "create" );
            this._init();
        },
        _getCreateOptions: function() {
            return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ];
        },
        _create: function() {},
        _init: function() {},

        destroy: function() {
            this.element
            .unbind( "." + this.widgetName )
            .removeData( this.widgetName );
            this.widget()
            .unbind( "." + this.widgetName )
            .removeAttr( "aria-disabled" )
            .removeClass(
                this.widgetBaseClass + "-disabled " +
                "ui-state-disabled" );
        },

        widget: function() {
            return this.element;
        },

        option: function( key, value ) {
            var options = key;

            if ( arguments.length === 0 ) {
                // don't return a reference to the internal hash
                return $.extend( {}, this.options );
            }

            if  (typeof key === "string" ) {
                if ( value === undefined ) {
                    return this.options[ key ];
                }
                options = {};
                options[ key ] = value;
            }

            this._setOptions( options );

            return this;
        },
        _setOptions: function( options ) {
            var self = this;
            $.each( options, function( key, value ) {
                self._setOption( key, value );
            });

            return this;
        },
        _setOption: function( key, value ) {
            this.options[ key ] = value;

            if ( key === "disabled" ) {
                this.widget()
                [ value ? "addClass" : "removeClass"](
                    this.widgetBaseClass + "-disabled" + " " +
                    "ui-state-disabled" )
                .attr( "aria-disabled", value );
            }

            return this;
        },

        enable: function() {
            return this._setOption( "disabled", false );
        },
        disable: function() {
            return this._setOption( "disabled", true );
        },

        _trigger: function( type, event, data ) {
            var callback = this.options[ type ];

            event = $.Event( event );
            event.type = ( type === this.widgetEventPrefix ?
                type :
                this.widgetEventPrefix + type ).toLowerCase();
            data = data || {};

            // copy original event properties over to the new event
            // this would happen if we could call $.event.fix instead of $.Event
            // but we don't have a way to force an event to be fixed multiple times
            if ( event.originalEvent ) {
                for ( var i = $.event.props.length, prop; i; ) {
                    prop = $.event.props[ --i ];
                    event[ prop ] = event.originalEvent[ prop ];
                }
            }

            this.element.trigger( event, data );

            return !( $.isFunction(callback) &&
                callback.call( this.element[0], event, data ) === false ||
                event.isDefaultPrevented() );
        }
    };

})( jQuery );


/* #12# */

/*!
 * jQuery UI Mouse 1.8.7
 *
 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Mouse
 *
 * Depends:
 *	jquery.ui.widget.js
 */
(function( $, undefined ) {

    $.widget("ui.mouse", {
        options: {
            cancel: ':input,option',
            distance: 1,
            delay: 0
        },
        _mouseInit: function() {
            var self = this;

            this.element
            .bind('mousedown.'+this.widgetName, function(event) {
                return self._mouseDown(event);
            })
            .bind('click.'+this.widgetName, function(event) {
                if (true === $.data(event.target, self.widgetName + '.preventClickEvent')) {
                    $.removeData(event.target, self.widgetName + '.preventClickEvent');
                    event.stopImmediatePropagation();
                    return false;
                }
            });

            this.started = false;
        },

        // TODO: make sure destroying one instance of mouse doesn't mess with
        // other instances of mouse
        _mouseDestroy: function() {
            this.element.unbind('.'+this.widgetName);
        },

        _mouseDown: function(event) {
            // don't let more than one widget handle mouseStart
            // TODO: figure out why we have to use originalEvent
            event.originalEvent = event.originalEvent || {};
            if (event.originalEvent.mouseHandled) {
                return;
            }

            // we may have missed mouseup (out of window)
            (this._mouseStarted && this._mouseUp(event));

            this._mouseDownEvent = event;

            var self = this,
            btnIsLeft = (event.which == 1),
            elIsCancel = (typeof this.options.cancel == "string" ? $(event.target).parents().add(event.target).filter(this.options.cancel).length : false);
            if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
                return true;
            }

            this.mouseDelayMet = !this.options.delay;
            if (!this.mouseDelayMet) {
                this._mouseDelayTimer = setTimeout(function() {
                    self.mouseDelayMet = true;
                }, this.options.delay);
            }

            if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
                this._mouseStarted = (this._mouseStart(event) !== false);
                if (!this._mouseStarted) {
                    event.preventDefault();
                    return true;
                }
            }

            // these delegates are required to keep context
            this._mouseMoveDelegate = function(event) {
                return self._mouseMove(event);
            };
            this._mouseUpDelegate = function(event) {
                return self._mouseUp(event);
            };
            $(document)
            .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
            .bind('mouseup.'+this.widgetName, this._mouseUpDelegate);

            event.preventDefault();
            event.originalEvent.mouseHandled = true;
            return true;
        },

        _mouseMove: function(event) {
            // IE mouseup check - mouseup happened when mouse was out of window
            if ($.browser.msie && !(document.documentMode >= 9) && !event.button) {
                return this._mouseUp(event);
            }

            if (this._mouseStarted) {
                this._mouseDrag(event);
                return event.preventDefault();
            }

            if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
                this._mouseStarted =
                (this._mouseStart(this._mouseDownEvent, event) !== false);
                (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
            }

            return !this._mouseStarted;
        },

        _mouseUp: function(event) {
            $(document)
            .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
            .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);

            if (this._mouseStarted) {
                this._mouseStarted = false;

                if (event.target == this._mouseDownEvent.target) {
                    $.data(event.target, this.widgetName + '.preventClickEvent', true);
                }

                this._mouseStop(event);
            }

            return false;
        },

        _mouseDistanceMet: function(event) {
            return (Math.max(
                Math.abs(this._mouseDownEvent.pageX - event.pageX),
                Math.abs(this._mouseDownEvent.pageY - event.pageY)
                ) >= this.options.distance
            );
        },

        _mouseDelayMet: function(event) {
            return this.mouseDelayMet;
        },

        // These are placeholder methods, to be overriden by extending plugin
        _mouseStart: function(event) {},
        _mouseDrag: function(event) {},
        _mouseStop: function(event) {},
        _mouseCapture: function(event) {
            return true;
        }
    });

})(jQuery);


/* #13# */

/*
 * jQuery UI Draggable 1.8.7
 *
 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Draggables
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.mouse.js
 *	jquery.ui.widget.js
 */
(function( $, undefined ) {

    $.widget("ui.draggable", $.ui.mouse, {
        widgetEventPrefix: "drag",
        options: {
            addClasses: true,
            appendTo: "parent",
            axis: false,
            connectToSortable: false,
            containment: false,
            cursor: "auto",
            cursorAt: false,
            grid: false,
            handle: false,
            helper: "original",
            iframeFix: false,
            opacity: false,
            refreshPositions: false,
            revert: false,
            revertDuration: 500,
            scope: "default",
            scroll: true,
            scrollSensitivity: 20,
            scrollSpeed: 20,
            snap: false,
            snapMode: "both",
            snapTolerance: 20,
            stack: false,
            zIndex: false
        },
        _create: function() {

            if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
                this.element[0].style.position = 'relative';

            (this.options.addClasses && this.element.addClass("ui-draggable"));
            (this.options.disabled && this.element.addClass("ui-draggable-disabled"));

            this._mouseInit();

        },

        destroy: function() {
            if(!this.element.data('draggable')) return;
            this.element
            .removeData("draggable")
            .unbind(".draggable")
            .removeClass("ui-draggable"
                + " ui-draggable-dragging"
                + " ui-draggable-disabled");
            this._mouseDestroy();

            return this;
        },

        _mouseCapture: function(event) {

            var o = this.options;

            // among others, prevent a drag on a resizable-handle
            if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
                return false;

            //Quit if we're not on a valid handle
            this.handle = this._getHandle(event);
            if (!this.handle)
                return false;

            return true;

        },

        _mouseStart: function(event) {

            var o = this.options;

            //Create and append the visible helper
            this.helper = this._createHelper(event);

            //Cache the helper size
            this._cacheHelperProportions();

            //If ddmanager is used for droppables, set the global draggable
            if($.ui.ddmanager)
                $.ui.ddmanager.current = this;

            /*
		 * - Position generation -
		 * This block generates everything position related - it's the core of draggables.
		 */

            //Cache the margins of the original element
            this._cacheMargins();

            //Store the helper's css position
            this.cssPosition = this.helper.css("position");
            this.scrollParent = this.helper.scrollParent();

            //The element's absolute position on the page minus margins
            this.offset = this.positionAbs = this.element.offset();
            this.offset = {
                top: this.offset.top - this.margins.top,
                left: this.offset.left - this.margins.left
            };

            $.extend(this.offset, {
                click: { //Where the click happened, relative to the element
                    left: event.pageX - this.offset.left,
                    top: event.pageY - this.offset.top
                },
                parent: this._getParentOffset(),
                relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
            });

            //Generate the original position
            this.originalPosition = this.position = this._generatePosition(event);
            this.originalPageX = event.pageX;
            this.originalPageY = event.pageY;

            //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
            (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));

            //Set a containment if given in the options
            if(o.containment)
                this._setContainment();

            //Trigger event + callbacks
            if(this._trigger("start", event) === false) {
                this._clear();
                return false;
            }

            //Recache the helper size
            this._cacheHelperProportions();

            //Prepare the droppable offsets
            if ($.ui.ddmanager && !o.dropBehaviour)
                $.ui.ddmanager.prepareOffsets(this, event);

            this.helper.addClass("ui-draggable-dragging");
            this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
            return true;
        },

        _mouseDrag: function(event, noPropagation) {

            //Compute the helpers position
            this.position = this._generatePosition(event);
            this.positionAbs = this._convertPositionTo("absolute");

            //Call plugins and callbacks and use the resulting position if something is returned
            if (!noPropagation) {
                var ui = this._uiHash();
                if(this._trigger('drag', event, ui) === false) {
                    this._mouseUp({});
                    return false;
                }
                this.position = ui.position;
            }

            if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
            if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
            if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);

            return false;
        },

        _mouseStop: function(event) {

            //If we are using droppables, inform the manager about the drop
            var dropped = false;
            if ($.ui.ddmanager && !this.options.dropBehaviour)
                dropped = $.ui.ddmanager.drop(this, event);

            //if a drop comes from outside (a sortable)
            if(this.dropped) {
                dropped = this.dropped;
                this.dropped = false;
            }
		
            //if the original element is removed, don't bother to continue
            if(!this.element[0] || !this.element[0].parentNode)
                return false;

            if((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
                var self = this;
                $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
                    if(self._trigger("stop", event) !== false) {
                        self._clear();
                    }
                });
            } else {
                if(this._trigger("stop", event) !== false) {
                    this._clear();
                }
            }

            return false;
        },
	
        cancel: function() {
		
            if(this.helper.is(".ui-draggable-dragging")) {
                this._mouseUp({});
            } else {
                this._clear();
            }
		
            return this;
		
        },

        _getHandle: function(event) {

            var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
            $(this.options.handle, this.element)
            .find("*")
            .andSelf()
            .each(function() {
                if(this == event.target) handle = true;
            });

            return handle;

        },

        _createHelper: function(event) {

            var o = this.options;
            var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone() : this.element);

            if(!helper.parents('body').length)
                helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));

            if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
                helper.css("position", "absolute");

            return helper;

        },

        _adjustOffsetFromHelper: function(obj) {
            if (typeof obj == 'string') {
                obj = obj.split(' ');
            }
            if ($.isArray(obj)) {
                obj = {
                    left: +obj[0],
                    top: +obj[1] || 0
                    };
            }
            if ('left' in obj) {
                this.offset.click.left = obj.left + this.margins.left;
            }
            if ('right' in obj) {
                this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
            }
            if ('top' in obj) {
                this.offset.click.top = obj.top + this.margins.top;
            }
            if ('bottom' in obj) {
                this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
            }
        },

        _getParentOffset: function() {

            //Get the offsetParent and cache its position
            this.offsetParent = this.helper.offsetParent();
            var po = this.offsetParent.offset();

            // This is a special case where we need to modify a offset calculated on start, since the following happened:
            // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
            // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
            //    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
            if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
                po.left += this.scrollParent.scrollLeft();
                po.top += this.scrollParent.scrollTop();
            }

            if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
                || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
                po = {
                    top: 0,
                    left: 0
                };

            return {
                top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
                left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
            };

        },

        _getRelativeOffset: function() {

            if(this.cssPosition == "relative") {
                var p = this.element.position();
                return {
                    top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
                    left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
                };
            } else {
                return {
                    top: 0,
                    left: 0
                };
            }

        },

        _cacheMargins: function() {
            this.margins = {
                left: (parseInt(this.element.css("marginLeft"),10) || 0),
                top: (parseInt(this.element.css("marginTop"),10) || 0)
            };
        },

        _cacheHelperProportions: function() {
            this.helperProportions = {
                width: this.helper.outerWidth(),
                height: this.helper.outerHeight()
            };
        },

        _setContainment: function() {

            var o = this.options;
            if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
            if(o.containment == 'document' || o.containment == 'window') this.containment = [
                (o.containment == 'document' ? 0 : $(window).scrollLeft()) - this.offset.relative.left - this.offset.parent.left,
                (o.containment == 'document' ? 0 : $(window).scrollTop()) - this.offset.relative.top - this.offset.parent.top,
                (o.containment == 'document' ? 0 : $(window).scrollLeft()) + $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
                (o.containment == 'document' ? 0 : $(window).scrollTop()) + ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
                ];

            if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
                var ce = $(o.containment)[0];
                if(!ce) return;
                var co = $(o.containment).offset();
                var over = ($(ce).css("overflow") != 'hidden');

                this.containment = [
                co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
                co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
                co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
                co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
                ];
            } else if(o.containment.constructor == Array) {
                this.containment = o.containment;
            }

        },

        _convertPositionTo: function(d, pos) {

            if(!pos) pos = this.position;
            var mod = d == "absolute" ? 1 : -1;
            var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);

            return {
                top: (
                    pos.top																	// The absolute mouse position
                    + this.offset.relative.top * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
                    + this.offset.parent.top * mod											// The offsetParent's offset without borders (offset + border)
                    - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
                    ),
                left: (
                    pos.left																// The absolute mouse position
                    + this.offset.relative.left * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
                    + this.offset.parent.left * mod											// The offsetParent's offset without borders (offset + border)
                    - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
                    )
            };

        },

        _generatePosition: function(event) {

            var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
            var pageX = event.pageX;
            var pageY = event.pageY;

            /*
		 * - Position constraining -
		 * Constrain the position to a mix of grid, containment.
		 */

            if(this.originalPosition) { //If we are not dragging yet, we won't check for options

                if(this.containment) {
                    if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
                    if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
                    if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
                    if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
                }

                if(o.grid) {
                    var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
                    pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;

                    var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
                    pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
                }

            }

            return {
                top: (
                    pageY																// The absolute mouse position
                    - this.offset.click.top													// Click offset (relative to the element)
                    - this.offset.relative.top												// Only for relative positioned nodes: Relative offset from element to offset parent
                    - this.offset.parent.top												// The offsetParent's offset without borders (offset + border)
                    + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
                    ),
                left: (
                    pageX																// The absolute mouse position
                    - this.offset.click.left												// Click offset (relative to the element)
                    - this.offset.relative.left												// Only for relative positioned nodes: Relative offset from element to offset parent
                    - this.offset.parent.left												// The offsetParent's offset without borders (offset + border)
                    + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
                    )
            };

        },

        _clear: function() {
            this.helper.removeClass("ui-draggable-dragging");
            if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
            //if($.ui.ddmanager) $.ui.ddmanager.current = null;
            this.helper = null;
            this.cancelHelperRemoval = false;
        },

        // From now on bulk stuff - mainly helpers

        _trigger: function(type, event, ui) {
            ui = ui || this._uiHash();
            $.ui.plugin.call(this, type, [event, ui]);
            if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
            return $.Widget.prototype._trigger.call(this, type, event, ui);
        },

        plugins: {},

        _uiHash: function(event) {
            return {
                helper: this.helper,
                position: this.position,
                originalPosition: this.originalPosition,
                offset: this.positionAbs
            };
        }

    });

    $.extend($.ui.draggable, {
        version: "1.8.7"
    });

    $.ui.plugin.add("draggable", "connectToSortable", {
        start: function(event, ui) {

            var inst = $(this).data("draggable"), o = inst.options,
            uiSortable = $.extend({}, ui, {
                item: inst.element
                });
            inst.sortables = [];
            $(o.connectToSortable).each(function() {
                var sortable = $.data(this, 'sortable');
                if (sortable && !sortable.options.disabled) {
                    inst.sortables.push({
                        instance: sortable,
                        shouldRevert: sortable.options.revert
                    });
                    sortable._refreshItems();	//Do a one-time refresh at start to refresh the containerCache
                    sortable._trigger("activate", event, uiSortable);
                }
            });

        },
        stop: function(event, ui) {

            //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
            var inst = $(this).data("draggable"),
            uiSortable = $.extend({}, ui, {
                item: inst.element
                });

            $.each(inst.sortables, function() {
                if(this.instance.isOver) {

                    this.instance.isOver = 0;

                    inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
                    this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)

                    //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
                    if(this.shouldRevert) this.instance.options.revert = true;

                    //Trigger the stop of the sortable
                    this.instance._mouseStop(event);

                    this.instance.options.helper = this.instance.options._helper;

                    //If the helper has been the original item, restore properties in the sortable
                    if(inst.options.helper == 'original')
                        this.instance.currentItem.css({
                            top: 'auto',
                            left: 'auto'
                        });

                } else {
                    this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
                    this.instance._trigger("deactivate", event, uiSortable);
                }

            });

        },
        drag: function(event, ui) {

            var inst = $(this).data("draggable"), self = this;

            var checkPos = function(o) {
                var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
                var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
                var itemHeight = o.height, itemWidth = o.width;
                var itemTop = o.top, itemLeft = o.left;

                return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
            };

            $.each(inst.sortables, function(i) {
			
                //Copy over some variables to allow calling the sortable's native _intersectsWith
                this.instance.positionAbs = inst.positionAbs;
                this.instance.helperProportions = inst.helperProportions;
                this.instance.offset.click = inst.offset.click;
			
                if(this.instance._intersectsWith(this.instance.containerCache)) {

                    //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
                    if(!this.instance.isOver) {

                        this.instance.isOver = 1;
                        //Now we fake the start of dragging for the sortable instance,
                        //by cloning the list group item, appending it to the sortable and using it as inst.currentItem
                        //We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
                        this.instance.currentItem = $(self).clone().appendTo(this.instance.element).data("sortable-item", true);
                        this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
                        this.instance.options.helper = function() {
                            return ui.helper[0];
                        };

                        event.target = this.instance.currentItem[0];
                        this.instance._mouseCapture(event, true);
                        this.instance._mouseStart(event, true, true);

                        //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
                        this.instance.offset.click.top = inst.offset.click.top;
                        this.instance.offset.click.left = inst.offset.click.left;
                        this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
                        this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;

                        inst._trigger("toSortable", event);
                        inst.dropped = this.instance.element; //draggable revert needs that
                        //hack so receive/update callbacks work (mostly)
                        inst.currentItem = inst.element;
                        this.instance.fromOutside = inst;

                    }

                    //Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
                    if(this.instance.currentItem) this.instance._mouseDrag(event);

                } else {

                    //If it doesn't intersect with the sortable, and it intersected before,
                    //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
                    if(this.instance.isOver) {

                        this.instance.isOver = 0;
                        this.instance.cancelHelperRemoval = true;
					
                        //Prevent reverting on this forced stop
                        this.instance.options.revert = false;
					
                        // The out event needs to be triggered independently
                        this.instance._trigger('out', event, this.instance._uiHash(this.instance));
					
                        this.instance._mouseStop(event, true);
                        this.instance.options.helper = this.instance.options._helper;

                        //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
                        this.instance.currentItem.remove();
                        if(this.instance.placeholder) this.instance.placeholder.remove();

                        inst._trigger("fromSortable", event);
                        inst.dropped = false; //draggable revert needs that
                    }

                };

            });

        }
    });

    $.ui.plugin.add("draggable", "cursor", {
        start: function(event, ui) {
            var t = $('body'), o = $(this).data('draggable').options;
            if (t.css("cursor")) o._cursor = t.css("cursor");
            t.css("cursor", o.cursor);
        },
        stop: function(event, ui) {
            var o = $(this).data('draggable').options;
            if (o._cursor) $('body').css("cursor", o._cursor);
        }
    });

    $.ui.plugin.add("draggable", "iframeFix", {
        start: function(event, ui) {
            var o = $(this).data('draggable').options;
            $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
                $('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
                .css({
                    width: this.offsetWidth+"px",
                    height: this.offsetHeight+"px",
                    position: "absolute",
                    opacity: "0.001",
                    zIndex: 1000
                })
                .css($(this).offset())
                .appendTo("body");
            });
        },
        stop: function(event, ui) {
            $("div.ui-draggable-iframeFix").each(function() {
                this.parentNode.removeChild(this);
            }); //Remove frame helpers
        }
    });

    $.ui.plugin.add("draggable", "opacity", {
        start: function(event, ui) {
            var t = $(ui.helper), o = $(this).data('draggable').options;
            if(t.css("opacity")) o._opacity = t.css("opacity");
            t.css('opacity', o.opacity);
        },
        stop: function(event, ui) {
            var o = $(this).data('draggable').options;
            if(o._opacity) $(ui.helper).css('opacity', o._opacity);
        }
    });

    $.ui.plugin.add("draggable", "scroll", {
        start: function(event, ui) {
            var i = $(this).data("draggable");
            if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
        },
        drag: function(event, ui) {

            var i = $(this).data("draggable"), o = i.options, scrolled = false;

            if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {

                if(!o.axis || o.axis != 'x') {
                    if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
                        i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
                    else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)
                        i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
                }

                if(!o.axis || o.axis != 'y') {
                    if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
                        i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
                    else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)
                        i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
                }

            } else {

                if(!o.axis || o.axis != 'x') {
                    if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
                        scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
                    else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
                        scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
                }

                if(!o.axis || o.axis != 'y') {
                    if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
                        scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
                    else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
                        scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
                }

            }

            if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
                $.ui.ddmanager.prepareOffsets(i, event);

        }
    });

    $.ui.plugin.add("draggable", "snap", {
        start: function(event, ui) {

            var i = $(this).data("draggable"), o = i.options;
            i.snapElements = [];

            $(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
                var $t = $(this);
                var $o = $t.offset();
                if(this != i.element[0]) i.snapElements.push({
                    item: this,
                    width: $t.outerWidth(),
                    height: $t.outerHeight(),
                    top: $o.top,
                    left: $o.left
                });
            });

        },
        drag: function(event, ui) {

            var inst = $(this).data("draggable"), o = inst.options;
            var d = o.snapTolerance;

            var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
            y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;

            for (var i = inst.snapElements.length - 1; i >= 0; i--){

                var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
                t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;

                //Yes, I know, this is insane ;)
                if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) {
                    if(inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), {
                        snapItem: inst.snapElements[i].item
                        })));
                    inst.snapElements[i].snapping = false;
                    continue;
                }

                if(o.snapMode != 'inner') {
                    var ts = Math.abs(t - y2) <= d;
                    var bs = Math.abs(b - y1) <= d;
                    var ls = Math.abs(l - x2) <= d;
                    var rs = Math.abs(r - x1) <= d;
                    if(ts) ui.position.top = inst._convertPositionTo("relative", {
                        top: t - inst.helperProportions.height,
                        left: 0
                    }).top - inst.margins.top;
                    if(bs) ui.position.top = inst._convertPositionTo("relative", {
                        top: b,
                        left: 0
                    }).top - inst.margins.top;
                    if(ls) ui.position.left = inst._convertPositionTo("relative", {
                        top: 0,
                        left: l - inst.helperProportions.width
                        }).left - inst.margins.left;
                    if(rs) ui.position.left = inst._convertPositionTo("relative", {
                        top: 0,
                        left: r
                    }).left - inst.margins.left;
                }

                var first = (ts || bs || ls || rs);

                if(o.snapMode != 'outer') {
                    var ts = Math.abs(t - y1) <= d;
                    var bs = Math.abs(b - y2) <= d;
                    var ls = Math.abs(l - x1) <= d;
                    var rs = Math.abs(r - x2) <= d;
                    if(ts) ui.position.top = inst._convertPositionTo("relative", {
                        top: t,
                        left: 0
                    }).top - inst.margins.top;
                    if(bs) ui.position.top = inst._convertPositionTo("relative", {
                        top: b - inst.helperProportions.height,
                        left: 0
                    }).top - inst.margins.top;
                    if(ls) ui.position.left = inst._convertPositionTo("relative", {
                        top: 0,
                        left: l
                    }).left - inst.margins.left;
                    if(rs) ui.position.left = inst._convertPositionTo("relative", {
                        top: 0,
                        left: r - inst.helperProportions.width
                        }).left - inst.margins.left;
                }

                if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
                    (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), {
                        snapItem: inst.snapElements[i].item
                        })));
                inst.snapElements[i].snapping = (ts || bs || ls || rs || first);

            };

        }
    });

    $.ui.plugin.add("draggable", "stack", {
        start: function(event, ui) {

            var o = $(this).data("draggable").options;

            var group = $.makeArray($(o.stack)).sort(function(a,b) {
                return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
            });
            if (!group.length) {
                return;
            }
		
            var min = parseInt(group[0].style.zIndex) || 0;
            $(group).each(function(i) {
                this.style.zIndex = min + i;
            });

            this[0].style.zIndex = min + group.length;

        }
    });

    $.ui.plugin.add("draggable", "zIndex", {
        start: function(event, ui) {
            var t = $(ui.helper), o = $(this).data("draggable").options;
            if(t.css("zIndex")) o._zIndex = t.css("zIndex");
            t.css('zIndex', o.zIndex);
        },
        stop: function(event, ui) {
            var o = $(this).data("draggable").options;
            if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
        }
    });

})(jQuery);


/* #14# */
/* jQuery Alert Dialogs Plugin
 * Version 1.1
 * Cory S.N. LaViska
 * A Beautiful Site (http://abeautifulsite.net/)
 * 14 May 2009
 * Visit http://abeautifulsite.net/notebook/87 for more information
 * License:
 * This plugin is dual-licensed under the GNU General Public License and the MIT License and
 * is copyright 2008 A Beautiful Site, LLC.
*/
$.extend({
    dialog: {

        // These properties can be read/written by accessing $.dialog.propertyName from your scripts at any time
		
        verticalOffset: -75,                // vertical offset of the dialog from center screen, in pixels
        horizontalOffset: 0,                // horizontal offset of the dialog from center screen, in pixels/
        repositionOnResize: true,           // re-centers the dialog on window resize
        overlayOpacity: .9,                // transparency level of overlay
        overlayColor: '#FFF',               // base color of overlay
        draggable: true,                    // make the dialogs draggable (requires UI Draggables plugin)
        okButton: 'Ok',         // text for the OK button /* #lang# */
        sendButton: 'Send',     /* #lang# */
        reloadButton: 'Reload',     /* #lang# */
        cancelButton: 'Cancel', // text for the Cancel button /* #lang# */
        dialogClass: null,                  // if specified, this class will be applied to all dialogs
		
        // Public methods
		
        alert: function(message, title, callback) {
            if( title == null ) title = 'Alert'; /* #lang# */
            $.dialog._show(title, message, null, 'alert', function(result) {
                if( callback ) callback(result);
            });
        },
		
        confirm: function(message, title, callback) {
        
            if( title == null ) title = 'Confirm'; /* #lang# */
            $.dialog._show(title, message, null, 'confirm', function(result) {
                if( callback ) callback(result);
            });
        },
			
        prompt: function(message, value, title, callback) {
            if( title == null ) title = 'Prompt'; /* #lang# */
            $.dialog._show(title, message, value, 'prompt', function(result) {
                if( callback ) callback(result);
            });
        },
		
        captcha: function(message, title, captcha_type, callback) {
            if( title == null ) title = 'Captcha image verification'; /* #lang# */
            if( message == null ) message = 'Please enter the text in the image'; /* #lang# */
            if( captcha_type == null ) captcha_type = 0;
            $.dialog._show(title, message, captcha_type, 'captcha', function(result) {
                if( callback ) callback(result);
            });
        },
		
        // Private methods
		
        _show: function(title, msg, value, type, callback) {
            var display = false;
            if($('#popup_container').attr('id')){
                display = true;
            }
            $.dialog._hide();
            $.dialog._overlay('show');
			
            var popup_container = $(
                '<div id="popup_container" class="formBlack">' +
                (title === false ? '' : '<h1 id="popup_title"></h1>') +
                '<div id="popup_content">' +
                '<span class="icon icon48"/>' +
                '<div id="popup_message"></div>' +
                '</div>' +
                '</div>'
                ).hide();
			
            $('body').append(popup_container);
			
            if( $.dialog.dialogClass ) popup_container.addClass($.dialog.dialogClass);
			
            // IE6 Fix
            var pos = ($.browser.msie && parseInt($.browser.version) <= 6 ) ? 'absolute' : 'fixed';
			
            popup_container.css({
                position: pos,
                zIndex: 99991,
                padding: 0,
                margin: 0
            });
            
            popup_container.addClass(type);
            if(title !== false){
                $("#popup_title").text(title);
            }
            $("#popup_message").text(msg);
            $("#popup_message").html( $("#popup_message").text().replace(/\n/g, '<br />') );
			
            popup_container.css({
                minWidth: popup_container.outerWidth(),
                maxWidth: popup_container.outerWidth()
            });
			
            $.dialog._reposition();
            $.dialog._maintainPosition(true);
            switch( type ) {
                case 'alert':
                    $("#popup_content").after('<div id="popup_panel"><input class="button" type="button" value="' + $.dialog.okButton + '" id="popup_ok" /></div>');
                    $("#popup_ok").click( function() {
                        $.dialog._hideFX();
                        callback(true);
                    });
                    if(display){
                        popup_container.show();
                    }else{
                        popup_container.css({
                            'margin-top':-70,
                            'opacity':0
                        }).show().animate({
                            'margin-top':0,
                            'opacity':1
                        }, 'fast');
                    }
                    $("#popup_ok").focus().keypress( function(e) {
                        if( e.keyCode == 13 || e.keyCode == 27 ) $("#popup_ok").trigger('click');
                    });
                    break;
                case 'confirm':
                    $("#popup_content").after('<div id="popup_panel"><input type="button" class="button" value="' + $.dialog.okButton + '" id="popup_ok" /> <input type="button" class="button" value="' + $.dialog.cancelButton + '" id="popup_cancel" /></div>');
                    $("#popup_ok").click( function() {
                        $.dialog._hideFX();
                        if( callback ) callback(true);
                    });
                    $("#popup_cancel").click( function() {
                        $.dialog._hideFX();
                        if( callback ) callback(false);
                    });
                    if(display){
                        popup_container.show();
                    }else{
                        popup_container.css({
                            'margin-top':-70,
                            'opacity':0
                        }).show().animate({
                            'margin-top':0,
                            'opacity':1
                        }, 'fast');
                    }
                    $("#popup_ok").focus();
                    $("#popup_ok, #popup_cancel").keypress( function(e) {
                        if( e.keyCode == 13 ) $("#popup_ok").trigger('click');
                        if( e.keyCode == 27 ) $("#popup_cancel").trigger('click');
                    });
                    break;
                case 'prompt':
                    $("#popup_content").append('<div id="popup_prompt_box"><input type="text" size="30" id="popup_prompt" /></div>').after('<div id="popup_panel"><input type="button" class="button" value="' + $.dialog.okButton + '" id="popup_ok" /> <input type="button" class="button" value="' + $.dialog.cancelButton + '" id="popup_cancel" /></div>');
                    $("#popup_prompt").width( $("#popup_message").width() -80);
                    $("#popup_ok").click( function() {
                        var val = $("#popup_prompt").val();
                        $.dialog._hideFX();
                        if( callback ) callback( val );
                    });
                    $("#popup_cancel").click( function() {
                        $.dialog._hideFX();
                        if( callback ) callback( null );
                    });
                    if(display){
                        popup_container.show();
                    }else{
                        popup_container.css({
                            'margin-top':-70,
                            'opacity':0
                        }).show().animate({
                            'margin-top':0,
                            'opacity':1
                        }, 'fast');
                    }
                    $("#popup_prompt, #popup_ok, #popup_cancel").keypress( function(e) {
                        if( e.keyCode == 13 ) $("#popup_ok").trigger('click');
                        if( e.keyCode == 27 ) $("#popup_cancel").trigger('click');
                    });
                    if( value ) $("#popup_prompt").val(value);
                    $("#popup_prompt").focus().select();
                    break;
                case 'captcha':
                    //$("#popup_content").append('<div id="popup_captcha_box"><input type="text" size="30" id="popup_prompt" /></div>').after('<div id="popup_panel"><input type="button" class="button" value="' + $.dialog.sendButton + '" id="popup_ok" /> <input type="button" class="button" value="' + $.dialog.cancelButton + '" id="popup_cancel" /></div>');
                    //$("#popup_prompt").width( $("#popup_message").width() -80);
					
                    var $form = $([
                        '<form class="formCaptcha" method="post" action="/">',
                        '<fieldset class="captchaBox">',
                        '<div class="captchaImg"><img width="120" height="60" alt="" src="" id="captcha_string"></div>',
                        '<div class="captchaField"><input type="hidden" name="captcha_id" id="captcha_id" value="" />',
                        '<input type="text" maxlength="10" name="captcha_input" id="captcha_field"></div>',
                        '<div class="error error-captcha_input"></div>',
                        '<a href="#captcha_reload" class="actionTextLink">' + $.dialog.reloadButton + '</a>',
                        '</fieldset>',
                        '<fieldset id="popup_panel"><input type="submit" class="button" value="' + $.dialog.sendButton + '" id="popup_ok" /> <input type="button" class="button" value="' + $.dialog.cancelButton + '" id="popup_cancel" /></fieldset>',
                        '</form><div class="clear" />'
                        ].join(''));
					
                    $("#popup_content").append($form);

                    var validator_captcha = $form.validate(formActions.captchaForm);
                    formActions.captchaForm.captchaAction = callback || false;
                    $form.data('captchaType', value);
                    $form.submitAjaxIndikator();
                    actions.captchaLoad($form, validator_captcha);
                    $('a[href="#captcha_reload"]', $form).bind('click', function(event){
                        event.preventDefault();
                        actions.captchaLoad($form, validator_captcha);
                    });
                    $("#popup_cancel").click( function() {
                        $.dialog._hideFX();
                    //if( callback ) callback( null );
                    });
                    if(display){
                        popup_container.show();
                    }else{
                        popup_container.css({
                            'margin-top':-70,
                            'opacity':0
                        }).show().animate({
                            'margin-top':0,
                            'opacity':1
                        }, 'fast');
                    }
                    $("#captcha_field, #popup_ok, #popup_cancel").keypress( function(e) {
                        if( e.keyCode == 27 ) $("#popup_cancel").trigger('click');
                    });
                    $("#captcha_field").focus().select();
                    break;
            }

            // Make draggable
            if( $.dialog.draggable ) {
                try {
                    popup_container.draggable({
                        handle: $("#popup_title")
                    });
                    $("#popup_title").css({
                        cursor: 'move'
                    });
                } catch(e) { /* requires jQuery UI draggables */ }
            }
        },
        _hide: function() {
            $("#popup_container").remove();
            $.dialog._overlay('hide');
            $.dialog._maintainPosition(false);
        },		
        _hideFX: function() {
            $("#popup_container").stop(true,true).animate(
            {
                'margin-top':50,
                'opacity':0
            },
            'fast',
            function(){
                $(this).remove();
            }
            );
            $.dialog._overlay('hide');
            $.dialog._maintainPosition(false);
        },		
        _overlay: function(status) {
            switch( status ) {
                case 'show':
                    $.dialog._overlay('hide');
                    $("BODY").append('<div id="popup_overlay"></div>');
                    $("#popup_overlay").css({
                        position: 'absolute',
                        zIndex: 99990,
                        top: '0px',
                        left: '0px',
                        width: '100%',
                        height: $(document).height(),
                        /*background: $.dialog.overlayColor,*/
                        opacity: $.dialog.overlayOpacity
                    });
                    break;
                case 'hide':
                    $("#popup_overlay").remove();
                    break;
            }
        },
		
        _reposition: function() {
            var top = (($(window).height() / 2) - ($("#popup_container").outerHeight() / 2)) + $.dialog.verticalOffset;
            var left = (($(window).width() / 2) - ($("#popup_container").outerWidth() / 2)) + $.dialog.horizontalOffset;
            if( top < 0 ) top = 0;
            if( left < 0 ) left = 0;
			
            // IE6 fix
            if( $.browser.msie && parseInt($.browser.version) <= 6 ) top = top + $(window).scrollTop();
			
            $("#popup_container").css({
                top: top + 'px',
                left: left + 'px'
            });
            $("#popup_overlay").height( $(document).height() );
        },
		
        _maintainPosition: function(status) {
            if( $.dialog.repositionOnResize ) {
                switch(status) {
                    case true:
                        $(window).bind('resize', $.dialog._reposition);
                        break;
                    case false:
                        $(window).unbind('resize', $.dialog._reposition);
                        break;
                }
            }
        }
		
    }
});

/* #15# */
/*
 * jQuery Cookie plugin
 *
 * Copyright (c) 2010 Klaus Hartl (stilbuero.de)
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 *
 */

jQuery.cookie = function (key, value, options) {

    // key and value given, set cookie...
    if (arguments.length > 1 && (value === null || typeof value !== "object")) {
        options = jQuery.extend({}, options);

        if (value === null) {
            options.expires = -1;
        }

        if (typeof options.expires === 'number') {
            var days = options.expires, t = options.expires = new Date();
            t.setDate(t.getDate() + days);
        }

        return (document.cookie = [
            encodeURIComponent(key), '=',
            options.raw ? String(value) : encodeURIComponent(String(value)),
            options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
            options.path ? '; path=' + options.path : '',
            options.domain ? '; domain=' + options.domain : '',
            options.secure ? '; secure' : ''
            ].join(''));
    }

    // key and possibly options given, get cookie...
    options = value || {};
    var result, decode = options.raw ? function (s) {
        return s;
    } : decodeURIComponent;
    return (result = new RegExp('(?:^|; )' + encodeURIComponent(key) + '=([^;]*)').exec(document.cookie)) ? decode(result[1]) : null;
};

/* #16# */
/*
 * jQuery UI Slider 1.8.7
 *
 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Slider
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.mouse.js
 *	jquery.ui.widget.js
 */
(function( $, undefined ) {

    // number of pages in a slider
    // (how many times can you page up/down to go through the whole range)
    var numPages = 5;

    $.widget( "ui.slider", $.ui.mouse, {

        widgetEventPrefix: "slide",

        options: {
            animate: false,
            distance: 0,
            max: 100,
            min: 0,
            orientation: "horizontal",
            range: false,
            step: 1,
            value: 0,
            values: null
        },

        _create: function() {
            var self = this,
            o = this.options;

            this._keySliding = false;
            this._mouseSliding = false;
            this._animateOff = true;
            this._handleIndex = null;
            this._detectOrientation();
            this._mouseInit();

            this.element
            .addClass( "ui-slider" +
                " ui-slider-" + this.orientation +
                " ui-widget" +
                " ui-widget-content" +
                " ui-corner-all" );
		
            if ( o.disabled ) {
                this.element.addClass( "ui-slider-disabled ui-disabled" );
            }

            this.range = $([]);

            if ( o.range ) {
                if ( o.range === true ) {
                    this.range = $( "<div></div>" );
                    if ( !o.values ) {
                        o.values = [ this._valueMin(), this._valueMin() ];
                    }
                    if ( o.values.length && o.values.length !== 2 ) {
                        o.values = [ o.values[0], o.values[0] ];
                    }
                } else {
                    this.range = $( "<div></div>" );
                }

                this.range
                .appendTo( this.element )
                .addClass( "ui-slider-range" );

                if ( o.range === "min" || o.range === "max" ) {
                    this.range.addClass( "ui-slider-range-" + o.range );
                }

                // note: this isn't the most fittingly semantic framework class for this element,
                // but worked best visually with a variety of themes
                this.range.addClass( "ui-widget-header" );
            }

            if ( $( ".ui-slider-handle", this.element ).length === 0 ) {
                $( "<a href='#'></a>" )
                .appendTo( this.element )
                .addClass( "ui-slider-handle" );
            }

            if ( o.values && o.values.length ) {
                while ( $(".ui-slider-handle", this.element).length < o.values.length ) {
                    $( "<a href='#'></a>" )
                    .appendTo( this.element )
                    .addClass( "ui-slider-handle" );
                }
            }

            this.handles = $( ".ui-slider-handle", this.element )
            .addClass( "ui-state-default" +
                " ui-corner-all" );

            this.handle = this.handles.eq( 0 );

            this.handles.add( this.range ).filter( "a" )
            .click(function( event ) {
                event.preventDefault();
            })
            .hover(function() {
                if ( !o.disabled ) {
                    $( this ).addClass( "ui-state-hover" );
                }
            }, function() {
                $( this ).removeClass( "ui-state-hover" );
            })
            .focus(function() {
                if ( !o.disabled ) {
                    $( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" );
                    $( this ).addClass( "ui-state-focus" );
                } else {
                    $( this ).blur();
                }
            })
            .blur(function() {
                $( this ).removeClass( "ui-state-focus" );
            });

            this.handles.each(function( i ) {
                $( this ).data( "index.ui-slider-handle", i );
            });

            this.handles
            .keydown(function( event ) {
                var ret = true,
                index = $( this ).data( "index.ui-slider-handle" ),
                allowed,
                curVal,
                newVal,
                step;
	
                if ( self.options.disabled ) {
                    return;
                }
	
                switch ( event.keyCode ) {
                    case $.ui.keyCode.HOME:
                    case $.ui.keyCode.END:
                    case $.ui.keyCode.PAGE_UP:
                    case $.ui.keyCode.PAGE_DOWN:
                    case $.ui.keyCode.UP:
                    case $.ui.keyCode.RIGHT:
                    case $.ui.keyCode.DOWN:
                    case $.ui.keyCode.LEFT:
                        ret = false;
                        if ( !self._keySliding ) {
                            self._keySliding = true;
                            $( this ).addClass( "ui-state-active" );
                            allowed = self._start( event, index );
                            if ( allowed === false ) {
                                return;
                            }
                        }
                        break;
                }
	
                step = self.options.step;
                if ( self.options.values && self.options.values.length ) {
                    curVal = newVal = self.values( index );
                } else {
                    curVal = newVal = self.value();
                }
	
                switch ( event.keyCode ) {
                    case $.ui.keyCode.HOME:
                        newVal = self._valueMin();
                        break;
                    case $.ui.keyCode.END:
                        newVal = self._valueMax();
                        break;
                    case $.ui.keyCode.PAGE_UP:
                        newVal = self._trimAlignValue( curVal + ( (self._valueMax() - self._valueMin()) / numPages ) );
                        break;
                    case $.ui.keyCode.PAGE_DOWN:
                        newVal = self._trimAlignValue( curVal - ( (self._valueMax() - self._valueMin()) / numPages ) );
                        break;
                    case $.ui.keyCode.UP:
                    case $.ui.keyCode.RIGHT:
                        if ( curVal === self._valueMax() ) {
                            return;
                        }
                        newVal = self._trimAlignValue( curVal + step );
                        break;
                    case $.ui.keyCode.DOWN:
                    case $.ui.keyCode.LEFT:
                        if ( curVal === self._valueMin() ) {
                            return;
                        }
                        newVal = self._trimAlignValue( curVal - step );
                        break;
                }
	
                self._slide( event, index, newVal );
	
                return ret;
	
            })
            .keyup(function( event ) {
                var index = $( this ).data( "index.ui-slider-handle" );
	
                if ( self._keySliding ) {
                    self._keySliding = false;
                    self._stop( event, index );
                    self._change( event, index );
                    $( this ).removeClass( "ui-state-active" );
                }
	
            });

            this._refreshValue();

            this._animateOff = false;
        },

        destroy: function() {
            this.handles.remove();
            this.range.remove();

            this.element
            .removeClass( "ui-slider" +
                " ui-slider-horizontal" +
                " ui-slider-vertical" +
                " ui-slider-disabled" +
                " ui-widget" +
                " ui-widget-content" +
                " ui-corner-all" )
            .removeData( "slider" )
            .unbind( ".slider" );

            this._mouseDestroy();

            return this;
        },

        _mouseCapture: function( event ) {
            var o = this.options,
            position,
            normValue,
            distance,
            closestHandle,
            self,
            index,
            allowed,
            offset,
            mouseOverHandle;

            if ( o.disabled ) {
                return false;
            }

            this.elementSize = {
                width: this.element.outerWidth(),
                height: this.element.outerHeight()
            };
            this.elementOffset = this.element.offset();

            position = {
                x: event.pageX,
                y: event.pageY
                };
            normValue = this._normValueFromMouse( position );
            distance = this._valueMax() - this._valueMin() + 1;
            self = this;
            this.handles.each(function( i ) {
                var thisDistance = Math.abs( normValue - self.values(i) );
                if ( distance > thisDistance ) {
                    distance = thisDistance;
                    closestHandle = $( this );
                    index = i;
                }
            });

            // workaround for bug #3736 (if both handles of a range are at 0,
            // the first is always used as the one with least distance,
            // and moving it is obviously prevented by preventing negative ranges)
            if( o.range === true && this.values(1) === o.min ) {
                index += 1;
                closestHandle = $( this.handles[index] );
            }

            allowed = this._start( event, index );
            if ( allowed === false ) {
                return false;
            }
            this._mouseSliding = true;

            self._handleIndex = index;

            closestHandle
            .addClass( "ui-state-active" )
            .focus();
		
            offset = closestHandle.offset();
            mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" );
            this._clickOffset = mouseOverHandle ? {
                left: 0,
                top: 0
            } : {
                left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
                top: event.pageY - offset.top -
                ( closestHandle.height() / 2 ) -
                ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
                ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
                ( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
            };

            if ( !this.handles.hasClass( "ui-state-hover" ) ) {
                this._slide( event, index, normValue );
            }
            this._animateOff = true;
            return true;
        },

        _mouseStart: function( event ) {
            return true;
        },

        _mouseDrag: function( event ) {
            var position = {
                x: event.pageX,
                y: event.pageY
                },
            normValue = this._normValueFromMouse( position );
		
            this._slide( event, this._handleIndex, normValue );

            return false;
        },

        _mouseStop: function( event ) {
            this.handles.removeClass( "ui-state-active" );
            this._mouseSliding = false;

            this._stop( event, this._handleIndex );
            this._change( event, this._handleIndex );

            this._handleIndex = null;
            this._clickOffset = null;
            this._animateOff = false;

            return false;
        },
	
        _detectOrientation: function() {
            this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
        },

        _normValueFromMouse: function( position ) {
            var pixelTotal,
            pixelMouse,
            percentMouse,
            valueTotal,
            valueMouse;

            if ( this.orientation === "horizontal" ) {
                pixelTotal = this.elementSize.width;
                pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
            } else {
                pixelTotal = this.elementSize.height;
                pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
            }

            percentMouse = ( pixelMouse / pixelTotal );
            if ( percentMouse > 1 ) {
                percentMouse = 1;
            }
            if ( percentMouse < 0 ) {
                percentMouse = 0;
            }
            if ( this.orientation === "vertical" ) {
                percentMouse = 1 - percentMouse;
            }

            valueTotal = this._valueMax() - this._valueMin();
            valueMouse = this._valueMin() + percentMouse * valueTotal;

            return this._trimAlignValue( valueMouse );
        },

        _start: function( event, index ) {
            var uiHash = {
                handle: this.handles[ index ],
                value: this.value()
            };
            if ( this.options.values && this.options.values.length ) {
                uiHash.value = this.values( index );
                uiHash.values = this.values();
            }
            return this._trigger( "start", event, uiHash );
        },

        _slide: function( event, index, newVal ) {
            var otherVal,
            newValues,
            allowed;

            if ( this.options.values && this.options.values.length ) {
                otherVal = this.values( index ? 0 : 1 );

                if ( ( this.options.values.length === 2 && this.options.range === true ) &&
                    ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
                    ) {
                    newVal = otherVal;
                }

                if ( newVal !== this.values( index ) ) {
                    newValues = this.values();
                    newValues[ index ] = newVal;
                    // A slide can be canceled by returning false from the slide callback
                    allowed = this._trigger( "slide", event, {
                        handle: this.handles[ index ],
                        value: newVal,
                        values: newValues
                    } );
                    otherVal = this.values( index ? 0 : 1 );
                    if ( allowed !== false ) {
                        this.values( index, newVal, true );
                    }
                }
            } else {
                if ( newVal !== this.value() ) {
                    // A slide can be canceled by returning false from the slide callback
                    allowed = this._trigger( "slide", event, {
                        handle: this.handles[ index ],
                        value: newVal
                    } );
                    if ( allowed !== false ) {
                        this.value( newVal );
                    }
                }
            }
        },

        _stop: function( event, index ) {
            var uiHash = {
                handle: this.handles[ index ],
                value: this.value()
            };
            if ( this.options.values && this.options.values.length ) {
                uiHash.value = this.values( index );
                uiHash.values = this.values();
            }

            this._trigger( "stop", event, uiHash );
        },

        _change: function( event, index ) {
            if ( !this._keySliding && !this._mouseSliding ) {
                var uiHash = {
                    handle: this.handles[ index ],
                    value: this.value()
                };
                if ( this.options.values && this.options.values.length ) {
                    uiHash.value = this.values( index );
                    uiHash.values = this.values();
                }

                this._trigger( "change", event, uiHash );
            }
        },

        value: function( newValue ) {
            if ( arguments.length ) {
                this.options.value = this._trimAlignValue( newValue );
                this._refreshValue();
                this._change( null, 0 );
            }

            return this._value();
        },

        values: function( index, newValue ) {
            var vals,
            newValues,
            i;

            if ( arguments.length > 1 ) {
                this.options.values[ index ] = this._trimAlignValue( newValue );
                this._refreshValue();
                this._change( null, index );
            }

            if ( arguments.length ) {
                if ( $.isArray( arguments[ 0 ] ) ) {
                    vals = this.options.values;
                    newValues = arguments[ 0 ];
                    for ( i = 0; i < vals.length; i += 1 ) {
                        vals[ i ] = this._trimAlignValue( newValues[ i ] );
                        this._change( null, i );
                    }
                    this._refreshValue();
                } else {
                    if ( this.options.values && this.options.values.length ) {
                        return this._values( index );
                    } else {
                        return this.value();
                    }
                }
            } else {
                return this._values();
            }
        },

        _setOption: function( key, value ) {
            var i,
            valsLength = 0;

            if ( $.isArray( this.options.values ) ) {
                valsLength = this.options.values.length;
            }

            $.Widget.prototype._setOption.apply( this, arguments );

            switch ( key ) {
                case "disabled":
                    if ( value ) {
                        this.handles.filter( ".ui-state-focus" ).blur();
                        this.handles.removeClass( "ui-state-hover" );
                        this.handles.attr( "disabled", "disabled" );
                        this.element.addClass( "ui-disabled" );
                    } else {
                        this.handles.removeAttr( "disabled" );
                        this.element.removeClass( "ui-disabled" );
                    }
                    break;
                case "orientation":
                    this._detectOrientation();
                    this.element
                    .removeClass( "ui-slider-horizontal ui-slider-vertical" )
                    .addClass( "ui-slider-" + this.orientation );
                    this._refreshValue();
                    break;
                case "value":
                    this._animateOff = true;
                    this._refreshValue();
                    this._change( null, 0 );
                    this._animateOff = false;
                    break;
                case "values":
                    this._animateOff = true;
                    this._refreshValue();
                    for ( i = 0; i < valsLength; i += 1 ) {
                        this._change( null, i );
                    }
                    this._animateOff = false;
                    break;
            }
        },

        //internal value getter
        // _value() returns value trimmed by min and max, aligned by step
        _value: function() {
            var val = this.options.value;
            val = this._trimAlignValue( val );

            return val;
        },

        //internal values getter
        // _values() returns array of values trimmed by min and max, aligned by step
        // _values( index ) returns single value trimmed by min and max, aligned by step
        _values: function( index ) {
            var val,
            vals,
            i;

            if ( arguments.length ) {
                val = this.options.values[ index ];
                val = this._trimAlignValue( val );

                return val;
            } else {
                // .slice() creates a copy of the array
                // this copy gets trimmed by min and max and then returned
                vals = this.options.values.slice();
                for ( i = 0; i < vals.length; i+= 1) {
                    vals[ i ] = this._trimAlignValue( vals[ i ] );
                }

                return vals;
            }
        },
	
        // returns the step-aligned value that val is closest to, between (inclusive) min and max
        _trimAlignValue: function( val ) {
            if ( val <= this._valueMin() ) {
                return this._valueMin();
            }
            if ( val >= this._valueMax() ) {
                return this._valueMax();
            }
            var step = ( this.options.step > 0 ) ? this.options.step : 1,
            valModStep = (val - this._valueMin()) % step;
            alignValue = val - valModStep;

            if ( Math.abs(valModStep) * 2 >= step ) {
                alignValue += ( valModStep > 0 ) ? step : ( -step );
            }

            // Since JavaScript has problems with large floats, round
            // the final value to 5 digits after the decimal point (see #4124)
            return parseFloat( alignValue.toFixed(5) );
        },

        _valueMin: function() {
            return this.options.min;
        },

        _valueMax: function() {
            return this.options.max;
        },
	
        _refreshValue: function() {
            var oRange = this.options.range,
            o = this.options,
            self = this,
            animate = ( !this._animateOff ) ? o.animate : false,
            valPercent,
            _set = {},
            lastValPercent,
            value,
            valueMin,
            valueMax;

            if ( this.options.values && this.options.values.length ) {
                this.handles.each(function( i, j ) {
                    valPercent = ( self.values(i) - self._valueMin() ) / ( self._valueMax() - self._valueMin() ) * 100;
                    _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
                    $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
                    if ( self.options.range === true ) {
                        if ( self.orientation === "horizontal" ) {
                            if ( i === 0 ) {
                                self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
                                    left: valPercent + "%"
                                    }, o.animate );
                            }
                            if ( i === 1 ) {
                                self.range[ animate ? "animate" : "css" ]( {
                                    width: ( valPercent - lastValPercent ) + "%"
                                    }, {
                                    queue: false,
                                    duration: o.animate
                                    } );
                            }
                        } else {
                            if ( i === 0 ) {
                                self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
                                    bottom: ( valPercent ) + "%"
                                    }, o.animate );
                            }
                            if ( i === 1 ) {
                                self.range[ animate ? "animate" : "css" ]( {
                                    height: ( valPercent - lastValPercent ) + "%"
                                    }, {
                                    queue: false,
                                    duration: o.animate
                                    } );
                            }
                        }
                    }
                    lastValPercent = valPercent;
                });
            } else {
                value = this.value();
                valueMin = this._valueMin();
                valueMax = this._valueMax();
                valPercent = ( valueMax !== valueMin ) ?
                ( value - valueMin ) / ( valueMax - valueMin ) * 100 :
                0;
                _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
                this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );

                if ( oRange === "min" && this.orientation === "horizontal" ) {
                    this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
                        width: valPercent + "%"
                        }, o.animate );
                }
                if ( oRange === "max" && this.orientation === "horizontal" ) {
                    this.range[ animate ? "animate" : "css" ]( {
                        width: ( 100 - valPercent ) + "%"
                        }, {
                        queue: false,
                        duration: o.animate
                        } );
                }
                if ( oRange === "min" && this.orientation === "vertical" ) {
                    this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
                        height: valPercent + "%"
                        }, o.animate );
                }
                if ( oRange === "max" && this.orientation === "vertical" ) {
                    this.range[ animate ? "animate" : "css" ]( {
                        height: ( 100 - valPercent ) + "%"
                        }, {
                        queue: false,
                        duration: o.animate
                        } );
                }
            }
        }

    });

    $.extend( $.ui.slider, {
        version: "1.8.7"
    });

}(jQuery));

/* #17# */

/*! Copyright (c) 2010 Brandon Aaron (http://brandonaaron.net)
 * Licensed under the MIT License (LICENSE.txt).
 *
 * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
 * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
 * Thanks to: Seamus Leahy for adding deltaX and deltaY
 *
 * Version: 3.0.4
 * 
 * Requires: 1.2.2+
 */

(function($) {

    var types = ['DOMMouseScroll', 'mousewheel'];

    $.event.special.mousewheel = {
        setup: function() {
            if ( this.addEventListener ) {
                for ( var i=types.length; i; ) {
                    this.addEventListener( types[--i], handler, false );
                }
            } else {
                this.onmousewheel = handler;
            }
        },
    
        teardown: function() {
            if ( this.removeEventListener ) {
                for ( var i=types.length; i; ) {
                    this.removeEventListener( types[--i], handler, false );
                }
            } else {
                this.onmousewheel = null;
            }
        }
    };

    $.fn.extend({
        mousewheel: function(fn) {
            return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel");
        },
    
        unmousewheel: function(fn) {
            return this.unbind("mousewheel", fn);
        }
    });


    function handler(event) {
        var orgEvent = event || window.event, args = [].slice.call( arguments, 1 ), delta = 0, returnValue = true, deltaX = 0, deltaY = 0;
        event = $.event.fix(orgEvent);
        event.type = "mousewheel";
    
        // Old school scrollwheel delta
        if ( event.wheelDelta ) {
            delta = event.wheelDelta/120;
        }
        if ( event.detail     ) {
            delta = -event.detail/3;
        }
    
        // New school multidimensional scroll (touchpads) deltas
        deltaY = delta;
    
        // Gecko
        if ( orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) {
            deltaY = 0;
            deltaX = -1*delta;
        }
    
        // Webkit
        if ( orgEvent.wheelDeltaY !== undefined ) {
            deltaY = orgEvent.wheelDeltaY/120;
        }
        if ( orgEvent.wheelDeltaX !== undefined ) {
            deltaX = -1*orgEvent.wheelDeltaX/120;
        }
    
        // Add event and delta to the front of the arguments
        args.unshift(event, delta, deltaX, deltaY);
    
        return $.event.handle.apply(this, args);
    }

})(jQuery);

/* #18# */

/*!
 * jQuery resize event - v1.1 - 3/14/2010
 * http://benalman.com/projects/jquery-resize-plugin/
 * 
 * Copyright (c) 2010 "Cowboy" Ben Alman
 * Dual licensed under the MIT and GPL licenses.
 * http://benalman.com/about/license/
 */

(function($,window,undefined){
  '$:nomunge'; // Used by YUI compressor.
  
  // A jQuery object containing all non-window elements to which the resize
  // event is bound.
  var elems = $([]),
    
    // Extend $.resize if it already exists, otherwise create it.
    jq_resize = $.resize = $.extend( $.resize, {} ),
    
    timeout_id,
    
    // Reused strings.
    str_setTimeout = 'setTimeout',
    str_resize = 'resize',
    str_data = str_resize + '-special-event',
    str_delay = 'delay',
    str_throttle = 'throttleWindow';
  
  jq_resize[ str_delay ] = 500;
  
  jq_resize[ str_throttle ] = true;
      
  $.event.special[ str_resize ] = {
    
    // Called only when the first 'resize' event callback is bound per element.
    setup: function() {
      // Since window has its own native 'resize' event, return false so that
      // jQuery will bind the event using DOM methods. Since only 'window'
      // objects have a .setTimeout method, this should be a sufficient test.
      // Unless, of course, we're throttling the 'resize' event for window.
      if ( !jq_resize[ str_throttle ] && this[ str_setTimeout ] ) { return false; }
      
      var elem = $(this);
      
      // Add this element to the list of internal elements to monitor.
      elems = elems.add( elem );
      
      // Initialize data store on the element.
      $.data( this, str_data, { w: elem.width(), h: elem.height() } );
      
      // If this is the first element added, start the polling loop.
      if ( elems.length === 1 ) {
        loopy();
      }
    },
    
    // Called only when the last 'resize' event callback is unbound per element.
    teardown: function() {
      // Since window has its own native 'resize' event, return false so that
      // jQuery will unbind the event using DOM methods. Since only 'window'
      // objects have a .setTimeout method, this should be a sufficient test.
      // Unless, of course, we're throttling the 'resize' event for window.
      if ( !jq_resize[ str_throttle ] && this[ str_setTimeout ] ) { return false; }
      
      var elem = $(this);
      
      // Remove this element from the list of internal elements to monitor.
      elems = elems.not( elem );
      
      // Remove any data stored on the element.
      elem.removeData( str_data );
      
      // If this is the last element removed, stop the polling loop.
      if ( !elems.length ) {
        clearTimeout( timeout_id );
      }
    },
    
    // Called every time a 'resize' event callback is bound per element (new in
    // jQuery 1.4).
    add: function( handleObj ) {
      // Since window has its own native 'resize' event, return false so that
      // jQuery doesn't modify the event object. Unless, of course, we're
      // throttling the 'resize' event for window.
      if ( !jq_resize[ str_throttle ] && this[ str_setTimeout ] ) { return false; }
      
      var old_handler;
      
      // The new_handler function is executed every time the event is triggered.
      // This is used to update the internal element data store with the width
      // and height when the event is triggered manually, to avoid double-firing
      // of the event callback. See the "Double firing issue in jQuery 1.3.2"
      // comments above for more information.
      
      function new_handler( e, w, h ) {
        var elem = $(this),
          data = $.data( this, str_data );
        
        // If called from the polling loop, w and h will be passed in as
        // arguments. If called manually, via .trigger( 'resize' ) or .resize(),
        // those values will need to be computed.
        data.w = w !== undefined ? w : elem.width();
        data.h = h !== undefined ? h : elem.height();
        
        old_handler.apply( this, arguments );
      };
      
      // This may seem a little complicated, but it normalizes the special event
      // .add method between jQuery 1.4/1.4.1 and 1.4.2+
      if ( $.isFunction( handleObj ) ) {
        // 1.4, 1.4.1
        old_handler = handleObj;
        return new_handler;
      } else {
        // 1.4.2+
        old_handler = handleObj.handler;
        handleObj.handler = new_handler;
      }
    }
    
  };
  
  function loopy() {
    
    // Start the polling loop, asynchronously.
    timeout_id = window[ str_setTimeout ](function(){
      
      // Iterate over all elements to which the 'resize' event is bound.
      elems.each(function(){
        var elem = $(this),
          width = elem.width(),
          height = elem.height(),
          data = $.data( this, str_data );
        
        // If element size has changed since the last time, update the element
        // data store and trigger the 'resize' event.
        if ( width !== data.w || height !== data.h ) {
          elem.trigger( str_resize, [ data.w = width, data.h = height ] );
        }
        
      });
      
      // Loop.
      loopy();
      
    }, jq_resize[ str_delay ] );
    
  };
  
})(jQuery,this);


/* #19# */
/*
 * jQuery UI Tabs 1.8.7
 *
 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Tabs
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.widget.js
 */
(function( $, undefined ) {

var tabId = 0,
	listId = 0;

function getNextTabId() {
	return ++tabId;
}

function getNextListId() {
	return ++listId;
}

$.widget( "ui.tabs", {
	options: {
		add: null,
		ajaxOptions: null,
		cache: false,
		cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
		collapsible: false,
		disable: null,
		disabled: [],
		enable: null,
		event: "click",
		fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
		idPrefix: "ui-tabs-",
		load: null,
		panelTemplate: "<div></div>",
		remove: null,
		select: null,
		show: null,
		spinner: "<em>Loading&#8230;</em>",
		tabTemplate: "<li><a href='#{href}'><span>#{label}</span></a></li>"
	},

	_create: function() {
		this._tabify( true );
	},

	_setOption: function( key, value ) {
		if ( key == "selected" ) {
			if (this.options.collapsible && value == this.options.selected ) {
				return;
			}
			this.select( value );
		} else {
			this.options[ key ] = value;
			this._tabify();
		}
	},

	_tabId: function( a ) {
		return a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF-]/g, "" ) ||
			this.options.idPrefix + getNextTabId();
	},

	_sanitizeSelector: function( hash ) {
		// we need this because an id may contain a ":"
		return hash.replace( /:/g, "\\:" );
	},

	_cookie: function() {
		var cookie = this.cookie ||
			( this.cookie = this.options.cookie.name || "ui-tabs-" + getNextListId() );
		return $.cookie.apply( null, [ cookie ].concat( $.makeArray( arguments ) ) );
	},

	_ui: function( tab, panel ) {
		return {
			tab: tab,
			panel: panel,
			index: this.anchors.index( tab )
		};
	},

	_cleanup: function() {
		// restore all former loading tabs labels
		this.lis.filter( ".ui-state-processing" )
			.removeClass( "ui-state-processing" )
			.find( "span:data(label.tabs)" )
				.each(function() {
					var el = $( this );
					el.html( el.data( "label.tabs" ) ).removeData( "label.tabs" );
				});
	},

	_tabify: function( init ) {
		var self = this,
			o = this.options,
			fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash

		this.list = this.element.find( "ol,ul" ).eq( 0 );
		this.lis = $( " > li:has(a[href])", this.list );
		this.anchors = this.lis.map(function() {
			return $( "a", this )[ 0 ];
		});
		this.panels = $( [] );

		this.anchors.each(function( i, a ) {
			var href = $( a ).attr( "href" );
			// For dynamically created HTML that contains a hash as href IE < 8 expands
			// such href to the full page url with hash and then misinterprets tab as ajax.
			// Same consideration applies for an added tab with a fragment identifier
			// since a[href=#fragment-identifier] does unexpectedly not match.
			// Thus normalize href attribute...
			var hrefBase = href.split( "#" )[ 0 ],
				baseEl;
			if ( hrefBase && ( hrefBase === location.toString().split( "#" )[ 0 ] ||
					( baseEl = $( "base" )[ 0 ]) && hrefBase === baseEl.href ) ) {
				href = a.hash;
				a.href = href;
			}

			// inline tab
			if ( fragmentId.test( href ) ) {
				self.panels = self.panels.add( self.element.find( self._sanitizeSelector( href ) ) );
			// remote tab
			// prevent loading the page itself if href is just "#"
			} else if ( href && href !== "#" ) {
				// required for restore on destroy
				$.data( a, "href.tabs", href );

				// TODO until #3808 is fixed strip fragment identifier from url
				// (IE fails to load from such url)
				$.data( a, "load.tabs", href.replace( /#.*$/, "" ) );

				var id = self._tabId( a );
				a.href = "#" + id;
				var $panel = self.element.find( "#" + id );
				if ( !$panel.length ) {
					$panel = $( o.panelTemplate )
						.attr( "id", id )
						.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
						.insertAfter( self.panels[ i - 1 ] || self.list );
					$panel.data( "destroy.tabs", true );
				}
				self.panels = self.panels.add( $panel );
			// invalid tab href
			} else {
				o.disabled.push( i );
			}
		});

		// initialization from scratch
		if ( init ) {
			// attach necessary classes for styling
			this.element.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" );
			this.list.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
			this.lis.addClass( "ui-state-default ui-corner-top" );
			this.panels.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" );

			// Selected tab
			// use "selected" option or try to retrieve:
			// 1. from fragment identifier in url
			// 2. from cookie
			// 3. from selected class attribute on <li>
			if ( o.selected === undefined ) {
				if ( location.hash ) {
					this.anchors.each(function( i, a ) {
						if ( a.hash == location.hash ) {
							o.selected = i;
							return false;
						}
					});
				}
				if ( typeof o.selected !== "number" && o.cookie ) {
					o.selected = parseInt( self._cookie(), 10 );
				}
				if ( typeof o.selected !== "number" && this.lis.filter( ".ui-tabs-selected" ).length ) {
					o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
				}
				o.selected = o.selected || ( this.lis.length ? 0 : -1 );
			} else if ( o.selected === null ) { // usage of null is deprecated, TODO remove in next release
				o.selected = -1;
			}

			// sanity check - default to first tab...
			o.selected = ( ( o.selected >= 0 && this.anchors[ o.selected ] ) || o.selected < 0 )
				? o.selected
				: 0;

			// Take disabling tabs via class attribute from HTML
			// into account and update option properly.
			// A selected tab cannot become disabled.
			o.disabled = $.unique( o.disabled.concat(
				$.map( this.lis.filter( ".ui-state-disabled" ), function( n, i ) {
					return self.lis.index( n );
				})
			) ).sort();

			if ( $.inArray( o.selected, o.disabled ) != -1 ) {
				o.disabled.splice( $.inArray( o.selected, o.disabled ), 1 );
			}

			// highlight selected tab
			this.panels.addClass( "ui-tabs-hide" );
			this.lis.removeClass( "ui-tabs-selected ui-state-active" );
			// check for length avoids error when initializing empty list
			if ( o.selected >= 0 && this.anchors.length ) {
				self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ).removeClass( "ui-tabs-hide" );
				this.lis.eq( o.selected ).addClass( "ui-tabs-selected ui-state-active" );

				// seems to be expected behavior that the show callback is fired
				self.element.queue( "tabs", function() {
					self._trigger( "show", null,
						self._ui( self.anchors[ o.selected ], self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ) ) );
				});

				this.load( o.selected );
			}

			// clean up to avoid memory leaks in certain versions of IE 6
			// TODO: namespace this event
			$( window ).bind( "unload", function() {
				self.lis.add( self.anchors ).unbind( ".tabs" );
				self.lis = self.anchors = self.panels = null;
			});
		// update selected after add/remove
		} else {
			o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
		}

		// update collapsible
		// TODO: use .toggleClass()
		this.element[ o.collapsible ? "addClass" : "removeClass" ]( "ui-tabs-collapsible" );

		// set or update cookie after init and add/remove respectively
		if ( o.cookie ) {
			this._cookie( o.selected, o.cookie );
		}

		// disable tabs
		for ( var i = 0, li; ( li = this.lis[ i ] ); i++ ) {
			$( li )[ $.inArray( i, o.disabled ) != -1 &&
				// TODO: use .toggleClass()
				!$( li ).hasClass( "ui-tabs-selected" ) ? "addClass" : "removeClass" ]( "ui-state-disabled" );
		}

		// reset cache if switching from cached to not cached
		if ( o.cache === false ) {
			this.anchors.removeData( "cache.tabs" );
		}

		// remove all handlers before, tabify may run on existing tabs after add or option change
		this.lis.add( this.anchors ).unbind( ".tabs" );

		if ( o.event !== "mouseover" ) {
			var addState = function( state, el ) {
				if ( el.is( ":not(.ui-state-disabled)" ) ) {
					el.addClass( "ui-state-" + state );
				}
			};
			var removeState = function( state, el ) {
				el.removeClass( "ui-state-" + state );
			};
			this.lis.bind( "mouseover.tabs" , function() {
				addState( "hover", $( this ) );
			});
			this.lis.bind( "mouseout.tabs", function() {
				removeState( "hover", $( this ) );
			});
			this.anchors.bind( "focus.tabs", function() {
				addState( "focus", $( this ).closest( "li" ) );
			});
			this.anchors.bind( "blur.tabs", function() {
				removeState( "focus", $( this ).closest( "li" ) );
			});
		}

		// set up animations
		var hideFx, showFx;
		if ( o.fx ) {
			if ( $.isArray( o.fx ) ) {
				hideFx = o.fx[ 0 ];
				showFx = o.fx[ 1 ];
			} else {
				hideFx = showFx = o.fx;
			}
		}

		// Reset certain styles left over from animation
		// and prevent IE's ClearType bug...
		function resetStyle( $el, fx ) {
			$el.css( "display", "" );
			if ( !$.support.opacity && fx.opacity ) {
				$el[ 0 ].style.removeAttribute( "filter" );
			}
		}

		// Show a tab...
		var showTab = showFx
			? function( clicked, $show ) {
				$( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
				$show.hide().removeClass( "ui-tabs-hide" ) // avoid flicker that way
					.animate( showFx, showFx.duration || "normal", function() {
						resetStyle( $show, showFx );
						self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
					});
			}
			: function( clicked, $show ) {
				$( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
				$show.removeClass( "ui-tabs-hide" );
				self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
			};

		// Hide a tab, $show is optional...
		var hideTab = hideFx
			? function( clicked, $hide ) {
				$hide.animate( hideFx, hideFx.duration || "normal", function() {
					self.lis.removeClass( "ui-tabs-selected ui-state-active" );
					$hide.addClass( "ui-tabs-hide" );
					resetStyle( $hide, hideFx );
					self.element.dequeue( "tabs" );
				});
			}
			: function( clicked, $hide, $show ) {
				self.lis.removeClass( "ui-tabs-selected ui-state-active" );
				$hide.addClass( "ui-tabs-hide" );
				self.element.dequeue( "tabs" );
			};

		// attach tab event handler, unbind to avoid duplicates from former tabifying...
		this.anchors.bind( o.event + ".tabs", function() {
			var el = this,
				$li = $(el).closest( "li" ),
				$hide = self.panels.filter( ":not(.ui-tabs-hide)" ),
				$show = self.element.find( self._sanitizeSelector( el.hash ) );

			// If tab is already selected and not collapsible or tab disabled or
			// or is already loading or click callback returns false stop here.
			// Check if click handler returns false last so that it is not executed
			// for a disabled or loading tab!
			if ( ( $li.hasClass( "ui-tabs-selected" ) && !o.collapsible) ||
				$li.hasClass( "ui-state-disabled" ) ||
				$li.hasClass( "ui-state-processing" ) ||
				self.panels.filter( ":animated" ).length ||
				self._trigger( "select", null, self._ui( this, $show[ 0 ] ) ) === false ) {
				this.blur();
				return false;
			}

			o.selected = self.anchors.index( this );

			self.abort();

			// if tab may be closed
			if ( o.collapsible ) {
				if ( $li.hasClass( "ui-tabs-selected" ) ) {
					o.selected = -1;

					if ( o.cookie ) {
						self._cookie( o.selected, o.cookie );
					}

					self.element.queue( "tabs", function() {
						hideTab( el, $hide );
					}).dequeue( "tabs" );

					this.blur();
					return false;
				} else if ( !$hide.length ) {
					if ( o.cookie ) {
						self._cookie( o.selected, o.cookie );
					}

					self.element.queue( "tabs", function() {
						showTab( el, $show );
					});

					// TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171
					self.load( self.anchors.index( this ) );

					this.blur();
					return false;
				}
			}

			if ( o.cookie ) {
				self._cookie( o.selected, o.cookie );
			}

			// show new tab
			if ( $show.length ) {
				if ( $hide.length ) {
					self.element.queue( "tabs", function() {
						hideTab( el, $hide );
					});
				}
				self.element.queue( "tabs", function() {
					showTab( el, $show );
				});

				self.load( self.anchors.index( this ) );
			} else {
				throw "jQuery UI Tabs: Mismatching fragment identifier.";
			}

			// Prevent IE from keeping other link focussed when using the back button
			// and remove dotted border from clicked link. This is controlled via CSS
			// in modern browsers; blur() removes focus from address bar in Firefox
			// which can become a usability and annoying problem with tabs('rotate').
			if ( $.browser.msie ) {
				this.blur();
			}
		});

		// disable click in any case
		this.anchors.bind( "click.tabs", function(){
			return false;
		});
	},

    _getIndex: function( index ) {
		// meta-function to give users option to provide a href string instead of a numerical index.
		// also sanitizes numerical indexes to valid values.
		if ( typeof index == "string" ) {
			index = this.anchors.index( this.anchors.filter( "[href$=" + index + "]" ) );
		}

		return index;
	},

	destroy: function() {
		var o = this.options;

		this.abort();

		this.element
			.unbind( ".tabs" )
			.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" )
			.removeData( "tabs" );

		this.list.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );

		this.anchors.each(function() {
			var href = $.data( this, "href.tabs" );
			if ( href ) {
				this.href = href;
			}
			var $this = $( this ).unbind( ".tabs" );
			$.each( [ "href", "load", "cache" ], function( i, prefix ) {
				$this.removeData( prefix + ".tabs" );
			});
		});

		this.lis.unbind( ".tabs" ).add( this.panels ).each(function() {
			if ( $.data( this, "destroy.tabs" ) ) {
				$( this ).remove();
			} else {
				$( this ).removeClass([
					"ui-state-default",
					"ui-corner-top",
					"ui-tabs-selected",
					"ui-state-active",
					"ui-state-hover",
					"ui-state-focus",
					"ui-state-disabled",
					"ui-tabs-panel",
					"ui-widget-content",
					"ui-corner-bottom",
					"ui-tabs-hide"
				].join( " " ) );
			}
		});

		if ( o.cookie ) {
			this._cookie( null, o.cookie );
		}

		return this;
	},

	add: function( url, label, index ) {
		if ( index === undefined ) {
			index = this.anchors.length;
		}

		var self = this,
			o = this.options,
			$li = $( o.tabTemplate.replace( /#\{href\}/g, url ).replace( /#\{label\}/g, label ) ),
			id = !url.indexOf( "#" ) ? url.replace( "#", "" ) : this._tabId( $( "a", $li )[ 0 ] );

		$li.addClass( "ui-state-default ui-corner-top" ).data( "destroy.tabs", true );

		// try to find an existing element before creating a new one
		var $panel = self.element.find( "#" + id );
		if ( !$panel.length ) {
			$panel = $( o.panelTemplate )
				.attr( "id", id )
				.data( "destroy.tabs", true );
		}
		$panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide" );

		if ( index >= this.lis.length ) {
			$li.appendTo( this.list );
			$panel.appendTo( this.list[ 0 ].parentNode );
		} else {
			$li.insertBefore( this.lis[ index ] );
			$panel.insertBefore( this.panels[ index ] );
		}

		o.disabled = $.map( o.disabled, function( n, i ) {
			return n >= index ? ++n : n;
		});

		this._tabify();

		if ( this.anchors.length == 1 ) {
			o.selected = 0;
			$li.addClass( "ui-tabs-selected ui-state-active" );
			$panel.removeClass( "ui-tabs-hide" );
			this.element.queue( "tabs", function() {
				self._trigger( "show", null, self._ui( self.anchors[ 0 ], self.panels[ 0 ] ) );
			});

			this.load( 0 );
		}

		this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
		return this;
	},

	remove: function( index ) {
		index = this._getIndex( index );
		var o = this.options,
			$li = this.lis.eq( index ).remove(),
			$panel = this.panels.eq( index ).remove();

		// If selected tab was removed focus tab to the right or
		// in case the last tab was removed the tab to the left.
		if ( $li.hasClass( "ui-tabs-selected" ) && this.anchors.length > 1) {
			this.select( index + ( index + 1 < this.anchors.length ? 1 : -1 ) );
		}

		o.disabled = $.map(
			$.grep( o.disabled, function(n, i) {
				return n != index;
			}),
			function( n, i ) {
				return n >= index ? --n : n;
			});

		this._tabify();

		this._trigger( "remove", null, this._ui( $li.find( "a" )[ 0 ], $panel[ 0 ] ) );
		return this;
	},

	enable: function( index ) {
		index = this._getIndex( index );
		var o = this.options;
		if ( $.inArray( index, o.disabled ) == -1 ) {
			return;
		}

		this.lis.eq( index ).removeClass( "ui-state-disabled" );
		o.disabled = $.grep( o.disabled, function( n, i ) {
			return n != index;
		});

		this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
		return this;
	},

	disable: function( index ) {
		index = this._getIndex( index );
		var self = this, o = this.options;
		// cannot disable already selected tab
		if ( index != o.selected ) {
			this.lis.eq( index ).addClass( "ui-state-disabled" );

			o.disabled.push( index );
			o.disabled.sort();

			this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
		}

		return this;
	},

	select: function( index ) {
		index = this._getIndex( index );
		if ( index == -1 ) {
			if ( this.options.collapsible && this.options.selected != -1 ) {
				index = this.options.selected;
			} else {
				return this;
			}
		}
		this.anchors.eq( index ).trigger( this.options.event + ".tabs" );
		return this;
	},

	load: function( index ) {
		index = this._getIndex( index );
		var self = this,
			o = this.options,
			a = this.anchors.eq( index )[ 0 ],
			url = $.data( a, "load.tabs" );

		this.abort();

		// not remote or from cache
		if ( !url || this.element.queue( "tabs" ).length !== 0 && $.data( a, "cache.tabs" ) ) {
			this.element.dequeue( "tabs" );
			return;
		}

		// load remote from here on
		this.lis.eq( index ).addClass( "ui-state-processing" );

		if ( o.spinner ) {
			var span = $( "span", a );
			span.data( "label.tabs", span.html() ).html( o.spinner );
		}

		this.xhr = $.ajax( $.extend( {}, o.ajaxOptions, {
			url: url,
			success: function( r, s ) {
				self.element.find( self._sanitizeSelector( a.hash ) ).html( r );

				// take care of tab labels
				self._cleanup();

				if ( o.cache ) {
					$.data( a, "cache.tabs", true );
				}

				self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
				try {
					o.ajaxOptions.success( r, s );
				}
				catch ( e ) {}
			},
			error: function( xhr, s, e ) {
				// take care of tab labels
				self._cleanup();

				self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
				try {
					// Passing index avoid a race condition when this method is
					// called after the user has selected another tab.
					// Pass the anchor that initiated this request allows
					// loadError to manipulate the tab content panel via $(a.hash)
					o.ajaxOptions.error( xhr, s, index, a );
				}
				catch ( e ) {}
			}
		} ) );

		// last, so that load event is fired before show...
		self.element.dequeue( "tabs" );

		return this;
	},

	abort: function() {
		// stop possibly running animations
		this.element.queue( [] );
		this.panels.stop( false, true );

		// "tabs" queue must not contain more than two elements,
		// which are the callbacks for the latest clicked tab...
		this.element.queue( "tabs", this.element.queue( "tabs" ).splice( -2, 2 ) );

		// terminate pending requests from other tabs
		if ( this.xhr ) {
			this.xhr.abort();
			delete this.xhr;
		}

		// take care of tab labels
		this._cleanup();
		return this;
	},

	url: function( index, url ) {
		this.anchors.eq( index ).removeData( "cache.tabs" ).data( "load.tabs", url );
		return this;
	},

	length: function() {
		return this.anchors.length;
	}
});

$.extend( $.ui.tabs, {
	version: "1.8.7"
});

/*
 * Tabs Extensions
 */

/*
 * Rotate
 */
$.extend( $.ui.tabs.prototype, {
	rotation: null,
	rotate: function( ms, continuing ) {
		var self = this,
			o = this.options;

		var rotate = self._rotate || ( self._rotate = function( e ) {
			clearTimeout( self.rotation );
			self.rotation = setTimeout(function() {
				var t = o.selected;
				self.select( ++t < self.anchors.length ? t : 0 );
			}, ms );
			
			if ( e ) {
				e.stopPropagation();
			}
		});

		var stop = self._unrotate || ( self._unrotate = !continuing
			? function(e) {
				if (e.clientX) { // in case of a true click
					self.rotate(null);
				}
			}
			: function( e ) {
				t = o.selected;
				rotate();
			});

		// start rotation
		if ( ms ) {
			this.element.bind( "tabsshow", rotate );
			this.anchors.bind( o.event + ".tabs", stop );
			rotate();
		// stop rotation
		} else {
			clearTimeout( self.rotation );
			this.element.unbind( "tabsshow", rotate );
			this.anchors.unbind( o.event + ".tabs", stop );
			delete this._rotate;
			delete this._unrotate;
		}

		return this;
	}
});

})( jQuery );



/* #20# */
/*
 * jquery.Jcrop.js v0.9.8
 * jQuery Image Cropping Plugin
 * @author Kelly Hallman <khallman@gmail.com>
 * Copyright (c) 2008-2009 Kelly Hallman - released under MIT License {{{
 */
(function($) {

$.Jcrop = function(obj,opt)
{
    // Initialization {{{

    // Sanitize some options {{{
    var obj = obj, opt = opt;

    if (typeof(obj) !== 'object') obj = $(obj)[0];
    if (typeof(opt) !== 'object') opt = { };

    // Some on-the-fly fixes for MSIE...sigh
    if (!('trackDocument' in opt))
    {
        opt.trackDocument = $.browser.msie ? false : true;
        if ($.browser.msie && $.browser.version.split('.')[0] == '8')
            opt.trackDocument = true;
    }

    if (!('keySupport' in opt))
            opt.keySupport = $.browser.msie ? false : true;
        
    // }}}
    // Extend the default options {{{
    var defaults = {

        // Basic Settings
        trackDocument:		false,
        baseClass:			'jcrop',
        addClass:			null,

        // Styling Options
        bgColor:			'black',
        bgOpacity:			.6,
        borderOpacity:		.4,
        handleOpacity:		.5,

        handlePad:			5,
        handleSize:			9,
        handleOffset:		5,
        edgeMargin:			14,

        aspectRatio:		0,
        keySupport:			true,
        cornerHandles:		true,
        sideHandles:		true,
        drawBorders:		true,
        dragEdges:			true,

        boxWidth:			0,
        boxHeight:			0,

        boundary:			8,
        animationDelay:		20,
        swingSpeed:			3,

        allowSelect:		true,
        allowMove:			true,
        allowResize:		true,

        minSelect:			[ 0, 0 ],
        maxSize:			[ 0, 0 ],
        minSize:			[ 0, 0 ],

        // Callbacks / Event Handlers
        onChange: function() { },
        onSelect: function() { }

    };
    var options = defaults;
    setOptions(opt);

    // }}}
    // Initialize some jQuery objects {{{

    var $origimg = $(obj);
    var $img = $origimg.clone().removeAttr('id').css({ position: 'absolute' });

    $img.width($origimg.width());
    $img.height($origimg.height());
    $origimg.after($img).hide();

    presize($img,options.boxWidth,options.boxHeight);

    var boundx = $img.width(),
        boundy = $img.height(),

        $div = $('<div />')
            .width(boundx).height(boundy)
            .addClass(cssClass('holder'))
            .css({
                position: 'relative',
                backgroundColor: options.bgColor
            }).insertAfter($origimg).append($img);
    ;
    
    if (options.addClass) $div.addClass(options.addClass);
    //$img.wrap($div);

    var $img2 = $('<img />')/*{{{*/
            .attr('src',$img.attr('src'))
            .css('position','absolute')
            .width(boundx).height(boundy)
    ;/*}}}*/
    var $img_holder = $('<div />')/*{{{*/
        .width(pct(100)).height(pct(100))
        .css({
            zIndex: 310,
            position: 'absolute',
            overflow: 'hidden'
        })
        .append($img2)
    ;/*}}}*/
    var $hdl_holder = $('<div />')/*{{{*/
        .width(pct(100)).height(pct(100))
        .css('zIndex',320);
    /*}}}*/
    var $sel = $('<div />')/*{{{*/
        .css({
            position: 'absolute',
            zIndex: 300
        })
        .insertBefore($img)
        .append($img_holder,$hdl_holder)
    ;/*}}}*/

    var bound = options.boundary;
    var $trk = newTracker().width(boundx+(bound*2)).height(boundy+(bound*2))
        .css({ position: 'absolute', top: px(-bound), left: px(-bound), zIndex: 290 })
        .mousedown(newSelection);	
    
    /* }}} */
    // Set more variables {{{

    var xlimit, ylimit, xmin, ymin;
    var xscale, yscale, enabled = true;
    var docOffset = getPos($img),
        // Internal states
        btndown, lastcurs, dimmed, animating,
        shift_down;

    // }}}
        

        // }}}
    // Internal Modules {{{

    var Coords = function()/*{{{*/
    {
        var x1 = 0, y1 = 0, x2 = 0, y2 = 0, ox, oy;

        function setPressed(pos)/*{{{*/
        {
            var pos = rebound(pos);
            x2 = x1 = pos[0];
            y2 = y1 = pos[1];
        };
        /*}}}*/
        function setCurrent(pos)/*{{{*/
        {
            var pos = rebound(pos);
            ox = pos[0] - x2;
            oy = pos[1] - y2;
            x2 = pos[0];
            y2 = pos[1];
        };
        /*}}}*/
        function getOffset()/*{{{*/
        {
            return [ ox, oy ];
        };
        /*}}}*/
        function moveOffset(offset)/*{{{*/
        {
            var ox = offset[0], oy = offset[1];

            if (0 > x1 + ox) ox -= ox + x1;
            if (0 > y1 + oy) oy -= oy + y1;

            if (boundy < y2 + oy) oy += boundy - (y2 + oy);
            if (boundx < x2 + ox) ox += boundx - (x2 + ox);

            x1 += ox;
            x2 += ox;
            y1 += oy;
            y2 += oy;
        };
        /*}}}*/
        function getCorner(ord)/*{{{*/
        {
            var c = getFixed();
            switch(ord)
            {
                case 'ne': return [ c.x2, c.y ];
                case 'nw': return [ c.x, c.y ];
                case 'se': return [ c.x2, c.y2 ];
                case 'sw': return [ c.x, c.y2 ];
            }
        };
        /*}}}*/
        function getFixed()/*{{{*/
        {
            if (!options.aspectRatio) return getRect();
            // This function could use some optimization I think...
            var aspect = options.aspectRatio,
                min_x = options.minSize[0]/xscale, 
                min_y = options.minSize[1]/yscale,
                max_x = options.maxSize[0]/xscale, 
                max_y = options.maxSize[1]/yscale,
                rw = x2 - x1,
                rh = y2 - y1,
                rwa = Math.abs(rw),
                rha = Math.abs(rh),
                real_ratio = rwa / rha,
                xx, yy
            ;
            if (max_x == 0) { max_x = boundx * 10 }
            if (max_y == 0) { max_y = boundy * 10 }
            if (real_ratio < aspect)
            {
                yy = y2;
                w = rha * aspect;
                xx = rw < 0 ? x1 - w : w + x1;

                if (xx < 0)
                {
                    xx = 0;
                    h = Math.abs((xx - x1) / aspect);
                    yy = rh < 0 ? y1 - h: h + y1;
                }
                else if (xx > boundx)
                {
                    xx = boundx;
                    h = Math.abs((xx - x1) / aspect);
                    yy = rh < 0 ? y1 - h : h + y1;
                }
            }
            else
            {
                xx = x2;
                h = rwa / aspect;
                yy = rh < 0 ? y1 - h : y1 + h;
                if (yy < 0)
                {
                    yy = 0;
                    w = Math.abs((yy - y1) * aspect);
                    xx = rw < 0 ? x1 - w : w + x1;
                }
                else if (yy > boundy)
                {
                    yy = boundy;
                    w = Math.abs(yy - y1) * aspect;
                    xx = rw < 0 ? x1 - w : w + x1;
                }
            }

            // Magic %-)
            if(xx > x1) { // right side
              if(xx - x1 < min_x) {
                xx = x1 + min_x;
              } else if (xx - x1 > max_x) {
                xx = x1 + max_x;
              }
              if(yy > y1) {
                yy = y1 + (xx - x1)/aspect;
              } else {
                yy = y1 - (xx - x1)/aspect;
              }
            } else if (xx < x1) { // left side
              if(x1 - xx < min_x) {
                xx = x1 - min_x
              } else if (x1 - xx > max_x) {
                xx = x1 - max_x;
              }
              if(yy > y1) {
                yy = y1 + (x1 - xx)/aspect;
              } else {
                yy = y1 - (x1 - xx)/aspect;
              }
            }

            if(xx < 0) {
                x1 -= xx;
                xx = 0;
            } else  if (xx > boundx) {
                x1 -= xx - boundx;
                xx = boundx;
            }

            if(yy < 0) {
                y1 -= yy;
                yy = 0;
            } else  if (yy > boundy) {
                y1 -= yy - boundy;
                yy = boundy;
            }

            return last = makeObj(flipCoords(x1,y1,xx,yy));
        };
        /*}}}*/
        function rebound(p)/*{{{*/
        {
            if (p[0] < 0) p[0] = 0;
            if (p[1] < 0) p[1] = 0;

            if (p[0] > boundx) p[0] = boundx;
            if (p[1] > boundy) p[1] = boundy;

            return [ p[0], p[1] ];
        };
        /*}}}*/
        function flipCoords(x1,y1,x2,y2)/*{{{*/
        {
            var xa = x1, xb = x2, ya = y1, yb = y2;
            if (x2 < x1)
            {
                xa = x2;
                xb = x1;
            }
            if (y2 < y1)
            {
                ya = y2;
                yb = y1;
            }
            return [ Math.round(xa), Math.round(ya), Math.round(xb), Math.round(yb) ];
        };
        /*}}}*/
        function getRect()/*{{{*/
        {
            var xsize = x2 - x1;
            var ysize = y2 - y1;

            if (xlimit && (Math.abs(xsize) > xlimit))
                x2 = (xsize > 0) ? (x1 + xlimit) : (x1 - xlimit);
            if (ylimit && (Math.abs(ysize) > ylimit))
                y2 = (ysize > 0) ? (y1 + ylimit) : (y1 - ylimit);

            if (ymin && (Math.abs(ysize) < ymin))
                y2 = (ysize > 0) ? (y1 + ymin) : (y1 - ymin);
            if (xmin && (Math.abs(xsize) < xmin))
                x2 = (xsize > 0) ? (x1 + xmin) : (x1 - xmin);

            if (x1 < 0) { x2 -= x1; x1 -= x1; }
            if (y1 < 0) { y2 -= y1; y1 -= y1; }
            if (x2 < 0) { x1 -= x2; x2 -= x2; }
            if (y2 < 0) { y1 -= y2; y2 -= y2; }
            if (x2 > boundx) { var delta = x2 - boundx; x1 -= delta; x2 -= delta; }
            if (y2 > boundy) { var delta = y2 - boundy; y1 -= delta; y2 -= delta; }
            if (x1 > boundx) { var delta = x1 - boundy; y2 -= delta; y1 -= delta; }
            if (y1 > boundy) { var delta = y1 - boundy; y2 -= delta; y1 -= delta; }

            return makeObj(flipCoords(x1,y1,x2,y2));
        };
        /*}}}*/
        function makeObj(a)/*{{{*/
        {
            return { x: a[0], y: a[1], x2: a[2], y2: a[3],
                w: a[2] - a[0], h: a[3] - a[1] };
        };
        /*}}}*/

        return {
            flipCoords: flipCoords,
            setPressed: setPressed,
            setCurrent: setCurrent,
            getOffset: getOffset,
            moveOffset: moveOffset,
            getCorner: getCorner,
            getFixed: getFixed
        };
    }();

    /*}}}*/
    var Selection = function()/*{{{*/
    {
        var start, end, dragmode, awake, hdep = 370;
        var borders = { };
        var handle = { };
        var seehandles = false;
        var hhs = options.handleOffset;

        /* Insert draggable elements {{{*/

        // Insert border divs for outline
        if (options.drawBorders) {
            borders = {
                    top: insertBorder('hline')
                        .css('top',$.browser.msie?px(-1):px(0)),
                    bottom: insertBorder('hline'),
                    left: insertBorder('vline'),
                    right: insertBorder('vline')
            };
        }

        // Insert handles on edges
        if (options.dragEdges) {
            handle.t = insertDragbar('n');
            handle.b = insertDragbar('s');
            handle.r = insertDragbar('e');
            handle.l = insertDragbar('w');
        }

        // Insert side handles
        options.sideHandles &&
            createHandles(['n','s','e','w']);

        // Insert corner handles
        options.cornerHandles &&
            createHandles(['sw','nw','ne','se']);

        /*}}}*/
        // Private Methods
        function insertBorder(type)/*{{{*/
        {
            var jq = $('<div />')
                .css({position: 'absolute', opacity: options.borderOpacity })
                .addClass(cssClass(type));
            $img_holder.append(jq);
            return jq;
        };
        /*}}}*/
        function dragDiv(ord,zi)/*{{{*/
        {
            var jq = $('<div />')
                .mousedown(createDragger(ord))
                .css({
                    cursor: ord+'-resize',
                    position: 'absolute',
                    zIndex: zi 
                })
            ;
            $hdl_holder.append(jq);
            return jq;
        };
        /*}}}*/
        function insertHandle(ord)/*{{{*/
        {   
            return dragDiv(ord,hdep++)
                .css({ top: px(-hhs+1), left: px(-hhs+1), opacity: options.handleOpacity })
                .addClass(cssClass('handle'));

        };
        /*}}}*/
        function insertDragbar(ord)/*{{{*/
        {
            var s = options.handleSize,
                o = hhs,
                h = s, w = s,
                t = o, l = o;

            switch(ord)
            {
                case 'n': case 's': w = pct(100); break;
                case 'e': case 'w': h = pct(100); break;
            }

            return dragDiv(ord,hdep++).width(w).height(h)
                .css({ top: px(-t+1), left: px(-l+1)});
        };
        /*}}}*/
        function createHandles(li)/*{{{*/
        {
            for(var i = 0, c = li.length; i < c; i++){ 
                handle[li[i]] = insertHandle(li[i]);
            }
        };
        /*}}}*/
        function moveHandles(c)/*{{{*/
        {
            var midvert  = Math.round((c.h / 2) - hhs),
                midhoriz = Math.round((c.w / 2) - hhs),
                north = west = -hhs+1,
                east = c.w - hhs,
                south = c.h - hhs,
                x, y;

            'e' in handle &&
                handle.e.css({ top: px(midvert), left: px(east) }) &&
                handle.w.css({ top: px(midvert) }) &&
                handle.s.css({ top: px(south), left: px(midhoriz) }) &&
                handle.n.css({ left: px(midhoriz) });

            'ne' in handle &&
                handle.ne.css({ left: px(east) }) &&
                handle.se.css({ top: px(south), left: px(east) }) &&
                handle.sw.css({ top: px(south) });

            'b' in handle &&
                handle.b.css({ top: px(south) }) &&
                handle.r.css({ left: px(east) });
        };
        /*}}}*/
        function moveto(x,y)/*{{{*/
        {
            $img2.css({ top: px(-y), left: px(-x) });
            $sel.css({ top: px(y), left: px(x) });
        };
        /*}}}*/
        function resize(w,h)/*{{{*/
        {
            $sel.width(w).height(h);
        };
        /*}}}*/
        function refresh()/*{{{*/
        {
            var c = Coords.getFixed();

            Coords.setPressed([c.x,c.y]);
            Coords.setCurrent([c.x2,c.y2]);

            updateVisible();
        };
        /*}}}*/

        // Internal Methods
        function updateVisible()/*{{{*/
            { if (awake) return update(); };
        /*}}}*/
        function update()/*{{{*/
        {
            var c = Coords.getFixed();

            resize(c.w,c.h);
            moveto(c.x,c.y);

            options.drawBorders &&
                borders['right'].css({ left: px(c.w-1) }) &&
                    borders['bottom'].css({ top: px(c.h-1) });

            seehandles && moveHandles(c);
            awake || show();

            options.onChange(unscale(c));
        };
        /*}}}*/
        function show()/*{{{*/
        {
            $sel.show();
            $img.css('opacity',options.bgOpacity);
            awake = true;
        };
        /*}}}*/
        function release()/*{{{*/
        {
            disableHandles();
            $sel.hide();
            $img.css('opacity',1);
            awake = false;
        };
        /*}}}*/
        function showHandles()//{{{
        {
            if (seehandles)
            {
                moveHandles(Coords.getFixed());
                $hdl_holder.show();
            }
        };
        //}}}
        function enableHandles()/*{{{*/
        { 
            seehandles = true;
            if (options.allowResize)
            {
                moveHandles(Coords.getFixed());
                $hdl_holder.show();
                return true;
            }
        };
        /*}}}*/
        function disableHandles()/*{{{*/
        {
            seehandles = false;
            $hdl_holder.hide();
        };
        /*}}}*/
        function animMode(v)/*{{{*/
        {
            (animating = v) ? disableHandles(): enableHandles();
        };
        /*}}}*/
        function done()/*{{{*/
        {
            animMode(false);
            refresh();
        };
        /*}}}*/

        var $track = newTracker().mousedown(createDragger('move'))
                .css({ cursor: 'move', position: 'absolute', zIndex: 360 })

        $img_holder.append($track);
        disableHandles();

        return {
            updateVisible: updateVisible,
            update: update,
            release: release,
            refresh: refresh,
            setCursor: function (cursor) { $track.css('cursor',cursor); },
            enableHandles: enableHandles,
            enableOnly: function() { seehandles = true; },
            showHandles: showHandles,
            disableHandles: disableHandles,
            animMode: animMode,
            done: done
        };
    }();
    /*}}}*/
    var Tracker = function()/*{{{*/
    {
        var onMove		= function() { },
            onDone		= function() { },
            trackDoc	= options.trackDocument;

        if (!trackDoc)
        {
            $trk
                .mousemove(trackMove)
                .mouseup(trackUp)
                .mouseout(trackUp)
            ;
        }

        function toFront()/*{{{*/
        {
            $trk.css({zIndex:450});
            if (trackDoc)
            {
                $(document)
                    .mousemove(trackMove)
                    .mouseup(trackUp)
                ;
            }
        }
        /*}}}*/
        function toBack()/*{{{*/
        {
            $trk.css({zIndex:290});
            if (trackDoc)
            {
                $(document)
                    .unbind('mousemove',trackMove)
                    .unbind('mouseup',trackUp)
                ;
            }
        }
        /*}}}*/
        function trackMove(e)/*{{{*/
        {
            onMove(mouseAbs(e));
        };
        /*}}}*/
        function trackUp(e)/*{{{*/
        {
            e.preventDefault();
            e.stopPropagation();

            if (btndown)
            {
                btndown = false;

                onDone(mouseAbs(e));
                options.onSelect(unscale(Coords.getFixed()));
                toBack();
                onMove = function() { };
                onDone = function() { };
            }

            return false;
        };
        /*}}}*/

        function activateHandlers(move,done)/* {{{ */
        {
            btndown = true;
            onMove = move;
            onDone = done;
            toFront();
            return false;
        };
        /* }}} */

        function setCursor(t) { $trk.css('cursor',t); };

        $img.before($trk);
        return {
            activateHandlers: activateHandlers,
            setCursor: setCursor
        };
    }();
    /*}}}*/
    var KeyManager = function()/*{{{*/
    {
        var $keymgr = $('<input type="radio" />')
                .css({ position: 'absolute', left: '-30px' })
                .keypress(parseKey)
                .blur(onBlur),

            $keywrap = $('<div />')
                .css({
                    position: 'absolute',
                    overflow: 'hidden'
                })
                .append($keymgr)
        ;

        function watchKeys()/*{{{*/
        {
            if (options.keySupport)
            {
                $keymgr.show();
                $keymgr.focus();
            }
        };
        /*}}}*/
        function onBlur(e)/*{{{*/
        {
            $keymgr.hide();
        };
        /*}}}*/
        function doNudge(e,x,y)/*{{{*/
        {
            if (options.allowMove) {
                Coords.moveOffset([x,y]);
                Selection.updateVisible();
            };
            e.preventDefault();
            e.stopPropagation();
        };
        /*}}}*/
        function parseKey(e)/*{{{*/
        {
            if (e.ctrlKey) return true;
            shift_down = e.shiftKey ? true : false;
            var nudge = shift_down ? 10 : 1;
            switch(e.keyCode)
            {
                case 37: doNudge(e,-nudge,0); break;
                case 39: doNudge(e,nudge,0); break;
                case 38: doNudge(e,0,-nudge); break;
                case 40: doNudge(e,0,nudge); break;

                case 27: Selection.release(); break;

                case 9: return true;
            }

            return nothing(e);
        };
        /*}}}*/
        
        if (options.keySupport) $keywrap.insertBefore($img);
        return {
            watchKeys: watchKeys
        };
    }();
    /*}}}*/

    // }}}
    // Internal Methods {{{

    function px(n) { return '' + parseInt(n) + 'px'; };
    function pct(n) { return '' + parseInt(n) + '%'; };
    function cssClass(cl) { return options.baseClass + '-' + cl; };
    function getPos(obj)/*{{{*/
    {
        // Updated in v0.9.4 to use built-in dimensions plugin
        var pos = $(obj).offset();
        return [ pos.left, pos.top ];
    };
    /*}}}*/
    function mouseAbs(e)/*{{{*/
    {
        return [ (e.pageX - docOffset[0]), (e.pageY - docOffset[1]) ];
    };
    /*}}}*/
    function myCursor(type)/*{{{*/
    {
        if (type != lastcurs)
        {
            Tracker.setCursor(type);
            //Handles.xsetCursor(type);
            lastcurs = type;
        }
    };
    /*}}}*/
    function startDragMode(mode,pos)/*{{{*/
    {
        docOffset = getPos($img);
        Tracker.setCursor(mode=='move'?mode:mode+'-resize');

        if (mode == 'move')
            return Tracker.activateHandlers(createMover(pos), doneSelect);

        var fc = Coords.getFixed();
        var opp = oppLockCorner(mode);
        var opc = Coords.getCorner(oppLockCorner(opp));

        Coords.setPressed(Coords.getCorner(opp));
        Coords.setCurrent(opc);

        Tracker.activateHandlers(dragmodeHandler(mode,fc),doneSelect);
    };
    /*}}}*/
    function dragmodeHandler(mode,f)/*{{{*/
    {
        return function(pos) {
            if (!options.aspectRatio) switch(mode)
            {
                case 'e': pos[1] = f.y2; break;
                case 'w': pos[1] = f.y2; break;
                case 'n': pos[0] = f.x2; break;
                case 's': pos[0] = f.x2; break;
            }
            else switch(mode)
            {
                case 'e': pos[1] = f.y+1; break;
                case 'w': pos[1] = f.y+1; break;
                case 'n': pos[0] = f.x+1; break;
                case 's': pos[0] = f.x+1; break;
            }
            Coords.setCurrent(pos);
            Selection.update();
        };
    };
    /*}}}*/
    function createMover(pos)/*{{{*/
    {
        var lloc = pos;
        KeyManager.watchKeys();

        return function(pos)
        {
            Coords.moveOffset([pos[0] - lloc[0], pos[1] - lloc[1]]);
            lloc = pos;
            
            Selection.update();
        };
    };
    /*}}}*/
    function oppLockCorner(ord)/*{{{*/
    {
        switch(ord)
        {
            case 'n': return 'sw';
            case 's': return 'nw';
            case 'e': return 'nw';
            case 'w': return 'ne';
            case 'ne': return 'sw';
            case 'nw': return 'se';
            case 'se': return 'nw';
            case 'sw': return 'ne';
        };
    };
    /*}}}*/
    function createDragger(ord)/*{{{*/
    {
        return function(e) {
            if (options.disabled) return false;
            if ((ord == 'move') && !options.allowMove) return false;
            btndown = true;
            startDragMode(ord,mouseAbs(e));
            e.stopPropagation();
            e.preventDefault();
            return false;
        };
    };
    /*}}}*/
    function presize($obj,w,h)/*{{{*/
    {
        var nw = $obj.width(), nh = $obj.height();
        if ((nw > w) && w > 0)
        {
            nw = w;
            nh = (w/$obj.width()) * $obj.height();
        }
        if ((nh > h) && h > 0)
        {
            nh = h;
            nw = (h/$obj.height()) * $obj.width();
        }
        xscale = $obj.width() / nw;
        yscale = $obj.height() / nh;
        $obj.width(nw).height(nh);
    };
    /*}}}*/
    function unscale(c)/*{{{*/
    {
        return {
            x: parseInt(c.x * xscale), y: parseInt(c.y * yscale), 
            x2: parseInt(c.x2 * xscale), y2: parseInt(c.y2 * yscale), 
            w: parseInt(c.w * xscale), h: parseInt(c.h * yscale)
        };
    };
    /*}}}*/
    function doneSelect(pos)/*{{{*/
    {
        var c = Coords.getFixed();
        if (c.w > options.minSelect[0] && c.h > options.minSelect[1])
        {
            Selection.enableHandles();
            Selection.done();
        }
        else
        {
            Selection.release();
        }
        Tracker.setCursor( options.allowSelect?'crosshair':'default' );
    };
    /*}}}*/
    function newSelection(e)/*{{{*/
    {
        if (options.disabled) return false;
        if (!options.allowSelect) return false;
        btndown = true;
        docOffset = getPos($img);
        Selection.disableHandles();
        myCursor('crosshair');
        var pos = mouseAbs(e);
        Coords.setPressed(pos);
        Tracker.activateHandlers(selectDrag,doneSelect);
        KeyManager.watchKeys();
        Selection.update();

        e.stopPropagation();
        e.preventDefault();
        return false;
    };
    /*}}}*/
    function selectDrag(pos)/*{{{*/
    {
        Coords.setCurrent(pos);
        Selection.update();
    };
    /*}}}*/
    function newTracker()
    {
        var trk = $('<div></div>').addClass(cssClass('tracker'));
        $.browser.msie && trk.css({ opacity: 0, backgroundColor: 'white' });
        return trk;
    };

    // }}}
    // API methods {{{
        
    function animateTo(a)/*{{{*/
    {
        var x1 = a[0] / xscale,
            y1 = a[1] / yscale,
            x2 = a[2] / xscale,
            y2 = a[3] / yscale;

        if (animating) return;

        var animto = Coords.flipCoords(x1,y1,x2,y2);
        var c = Coords.getFixed();
        var animat = initcr = [ c.x, c.y, c.x2, c.y2 ];
        var interv = options.animationDelay;

        var x = animat[0];
        var y = animat[1];
        var x2 = animat[2];
        var y2 = animat[3];
        var ix1 = animto[0] - initcr[0];
        var iy1 = animto[1] - initcr[1];
        var ix2 = animto[2] - initcr[2];
        var iy2 = animto[3] - initcr[3];
        var pcent = 0;
        var velocity = options.swingSpeed;

        Selection.animMode(true);

        var animator = function()
        {
            return function()
            {
                pcent += (100 - pcent) / velocity;

                animat[0] = x + ((pcent / 100) * ix1);
                animat[1] = y + ((pcent / 100) * iy1);
                animat[2] = x2 + ((pcent / 100) * ix2);
                animat[3] = y2 + ((pcent / 100) * iy2);

                if (pcent < 100) animateStart();
                    else Selection.done();

                if (pcent >= 99.8) pcent = 100;

                setSelectRaw(animat);
            };
        }();

        function animateStart()
            { window.setTimeout(animator,interv); };

        animateStart();
    };
    /*}}}*/
    function setSelect(rect)//{{{
    {
        setSelectRaw([rect[0]/xscale,rect[1]/yscale,rect[2]/xscale,rect[3]/yscale]);
    };
    //}}}
    function setSelectRaw(l) /*{{{*/
    {
        Coords.setPressed([l[0],l[1]]);
        Coords.setCurrent([l[2],l[3]]);
        Selection.update();
    };
    /*}}}*/
    function setOptions(opt)/*{{{*/
    {
        if (typeof(opt) != 'object') opt = { };
        options = $.extend(options,opt);

        if (typeof(options.onChange)!=='function')
            options.onChange = function() { };

        if (typeof(options.onSelect)!=='function')
            options.onSelect = function() { };

    };
    /*}}}*/
    function tellSelect()/*{{{*/
    {
        return unscale(Coords.getFixed());
    };
    /*}}}*/
    function tellScaled()/*{{{*/
    {
        return Coords.getFixed();
    };
    /*}}}*/
    function setOptionsNew(opt)/*{{{*/
    {
        setOptions(opt);
        interfaceUpdate();
    };
    /*}}}*/
    function disableCrop()//{{{
    {
        options.disabled = true;
        Selection.disableHandles();
        Selection.setCursor('default');
        Tracker.setCursor('default');
    };
    //}}}
    function enableCrop()//{{{
    {
        options.disabled = false;
        interfaceUpdate();
    };
    //}}}
    function cancelCrop()//{{{
    {
        Selection.done();
        Tracker.activateHandlers(null,null);
    };
    //}}}
    function destroy()//{{{
    {
        $div.remove();
        $origimg.show();
    };
    //}}}

    function interfaceUpdate(alt)//{{{
    // This method tweaks the interface based on options object.
    // Called when options are changed and at end of initialization.
    {
        options.allowResize ?
            alt?Selection.enableOnly():Selection.enableHandles():
            Selection.disableHandles();

        Tracker.setCursor( options.allowSelect? 'crosshair': 'default' );
        Selection.setCursor( options.allowMove? 'move': 'default' );

        $div.css('backgroundColor',options.bgColor);

        if ('setSelect' in options) {
            setSelect(opt.setSelect);
            Selection.done();
            delete(options.setSelect);
        }

        if ('trueSize' in options) {
            xscale = options.trueSize[0] / boundx;
            yscale = options.trueSize[1] / boundy;
        }

        xlimit = options.maxSize[0] || 0;
        ylimit = options.maxSize[1] || 0;
        xmin = options.minSize[0] || 0;
        ymin = options.minSize[1] || 0;

        if ('outerImage' in options)
        {
            $img.attr('src',options.outerImage);
            delete(options.outerImage);
        }

        Selection.refresh();
    };
    //}}}

    // }}}

    $hdl_holder.hide();
    interfaceUpdate(true);
    
    var api = {
        animateTo: animateTo,
        setSelect: setSelect,
        setOptions: setOptionsNew,
        tellSelect: tellSelect,
        tellScaled: tellScaled,

        disable: disableCrop,
        enable: enableCrop,
        cancel: cancelCrop,

        focus: KeyManager.watchKeys,

        getBounds: function() { return [ boundx * xscale, boundy * yscale ]; },
        getWidgetSize: function() { return [ boundx, boundy ]; },

        release: Selection.release,
        destroy: destroy

    };

    $origimg.data('Jcrop',api);

    return api;
};

$.fn.Jcrop = function(options)/*{{{*/
{
    function attachWhenDone(from)/*{{{*/
    {
        var loadsrc = options.useImg || from.src;
        var img = new Image();
        img.onload = function() { $.Jcrop(from,options); };
        img.src = loadsrc;
    };
    /*}}}*/
    if (typeof(options) !== 'object') options = { };

    // Iterate over each object, attach Jcrop
    this.each(function()
    {
        // If we've already attached to this object
        if ($(this).data('Jcrop'))
        {
            // The API can be requested this way (undocumented)
            if (options == 'api') return $(this).data('Jcrop');
            // Otherwise, we just reset the options...
            else $(this).data('Jcrop').setOptions(options);
        }
        // If we haven't been attached, preload and attach
        else attachWhenDone(this);
    });

    // Return "this" so we're chainable a la jQuery plugin-style!
    return this;
};
/*}}}*/

})(jQuery);
