/*!
 * Galleria v 1.1.4 2010-05-30
 * http://galleria.aino.se
 *
 * Copyright (c) 2010, Aino
 * Licensed under the MIT license.
 */

(function() {

var initializing = false,
    fnTest = /xyz/.test(function(){xyz;}) ? /\b__super\b/ : /.*/,
    Class = function(){},
    window = this;

Class.extend = function(prop) {
    var __super = this.prototype;
    initializing = true;
    var proto = new this();
    initializing = false;
    for (var name in prop) {
        if (name) {
            proto[name] = typeof prop[name] == "function" && 
                typeof __super[name] == "function" && fnTest.test(prop[name]) ? 
                (function(name, fn) { 
                    return function() { 
                        var tmp = this.__super; 
                        this.__super = __super[name]; 
                        var ret = fn.apply(this, arguments);       
                        this.__super = tmp; 
                        return ret; 
                    }; 
                })(name, prop[name]) : prop[name]; 
        } 
    }

    function Class() {
        if ( !initializing && this.__constructor ) {
            this.__constructor.apply(this, arguments);
        }
    }
    Class.prototype = proto;
    Class.constructor = Class;
    Class.extend = arguments.callee;
    return Class;
};

var Base = Class.extend({
    loop : function( elem, fn) {
        var scope = this;
        if (typeof elem == 'number') {
            elem = new Array(elem);
        }
        jQuery.each(elem, function() {
            fn.call(scope, arguments[1], arguments[0]);
        });
        return elem;
    },
    create : function( elem, className ) {
        elem = elem || 'div';
        var el = document.createElement(elem);
        if (className) {
            el.className = className;
        }
        return el;
    },
    getElements : function( selector ) {
        var elems = {};
        this.loop( jQuery(selector), this.proxy(function( elem ) {
            this.push(elem, elems);
        }));
        return elems;
    },
    setStyle : function( elem, css ) {
        jQuery(elem).css(css);
        return this;
    },
    cssText : function( string ) {
        var style = document.createElement('style');
        this.getElements('head')[0].appendChild(style);
        if (style.styleSheet) { // IE
            style.styleSheet.cssText = string;
        } else {
            var cssText = document.createTextNode(string);
            style.appendChild(cssText);
        }
        return this;
    },
    cssFile : function(src) {
        var link = document.createElement('link');
        link.media = 'all';
        link.rel = 'stylesheet';
        link.href = src;
        document.getElementsByTagName('head')[0].appendChild(link);
    },
    moveOut : function( elem ) {
        return this.setStyle(elem, {
            position: 'absolute',
            left: '-10000px'
        });
    },
    moveIn : function( elem ) {
        return this.setStyle(elem, {
            left: '0'
        }); 
    },
    reveal : function( elem ) {
        return jQuery( elem ).show();
    },
    hide : function( elem ) {
        return jQuery( elem ).hide();
    },
    mix : function( obj, ext ) {
        return jQuery.extend(obj, ext);
    },
    proxy : function( fn, scope ) {
        if ( typeof fn !== 'function' ) {
            return function() {};
        }
        scope = scope || this;
        return function() {
            return fn.apply( scope, Array.prototype.slice.call(arguments) );
        };
    },
    listen : function( elem, type, fn ) {
        jQuery(elem).bind( type, fn );
    },
    forget : function( elem, type ) {
        jQuery(elem).unbind(type);
    },
    dispatch : function( elem, type ) {
        jQuery(elem).trigger(type);
    },
    clone : function( elem, keepEvents ) {
        keepEvents = keepEvents || false;
        return jQuery(elem).clone(keepEvents)[0];
    },
    removeAttr : function( elem, attributes ) {
        this.loop( attributes.split(' '), function(attr) {
            jQuery(elem).removeAttr(attr);
        });
    },
    push : function( elem, obj ) {
        if (typeof obj.length == 'undefined') {
            obj.length = 0;
        }
        Array.prototype.push.call( obj, elem );
        return elem;
    },
    width : function( elem, outer ) {
        return this.meassure(elem, outer, 'Width');
    },
    height : function( elem, outer ) {
        return this.meassure(elem, outer, 'Height');
    },
    meassure : function(el, outer, meassure) {
        var elem = jQuery( el );
        var ret = outer ? elem['outer'+meassure](true) : elem[meassure.toLowerCase()]();
        // fix quirks mode
        if (G.QUIRK) {
            var which = meassure == "Width" ? [ "left", "right" ] : [ "top", "bottom" ];
            this.loop(which, function(s) {
                ret += elem.css('border-' + s + '-width').replace(/[^\d]/g,'') * 1;
                ret += elem.css('padding-' + s).replace(/[^\d]/g,'') * 1;
            });
        }
        return ret;
    },
    toggleClass : function( elem, className, arg ) {
        if (typeof arg !== 'undefined') {
            var fn = arg ? 'addClass' : 'removeClass';
            jQuery(elem)[fn](className);
            return this;
        }
        jQuery(elem).toggleClass(className);
        return this;
    },
    hideAll : function( el ) {
        jQuery(el).find('*').hide();
    },
    animate : function( el, options ) {
        var elem = jQuery(el);
        if (!elem.length) {
            return;
        }
        if (options.from) {
            elem.css(from);
        }
        elem.animate(options.to, {
            duration: options.duration || 400,
            complete: options.complete || function(){}
        });
    },
    wait : function(fn, callback, err, max) {
        fn = this.proxy(fn);
        callback = this.proxy(callback);
        err = this.proxy(err);
        var ts = new Date().getTime() + (max || 3000);
        window.setTimeout(function() {
            if (fn()) {
                callback();
                return false;
            }
            if (new Date().getTime() >= ts) {
                err();
                callback();
                return false;
            }
            window.setTimeout(arguments.callee, 1);
        }, 1);
        return this;
    },
    getScript: function(url, callback) {
       var script = document.createElement('script');
       script.src = url;
       script.async = true; // HTML5
       callback = this.proxy(callback);

       // Handle Script loading
       {
          var done = false;

          // Attach handlers for all browsers
          script.onload = script.onreadystatechange = function(){
             if ( !done && (!this.readyState ||
                   this.readyState == "loaded" || this.readyState == "complete") ) {
                done = true;
                callback();

                // Handle memory leak in IE
                script.onload = script.onreadystatechange = null;
             }
          };
       }
       
       var ex = document.getElementsByTagName('script');
       ex = ex[ex.length-1];
       ex.parentNode.insertBefore(script, ex.nextSibling);
       return this;
    }
});

var Picture = Base.extend({
    __constructor : function(order) {
        this.image = null;
        this.elem = this.create('div', 'galleria-image');
        this.setStyle( this.elem, {
            overflow: 'hidden',
            position: 'relative' // for IE Standards mode
        } );
        this.order = order;
        this.orig = { w:0, h:0, r:1 };
    },
    
    cache: {},
    
    add: function(src) {
        if (this.cache[src]) {
            return this.cache[src];
        }
        var image = new Image();
        image.src = src;
        this.setStyle(image, {display: 'block'});
        if (image.complete && image.width) {
            this.cache[src] = image;
            return image;
        }
        image.onload = (function(scope) {
            return function() {
                scope.cache[src] = image;
            };
        })(this);
        return image;
    },
    
    isCached: function(src) {
        return this.cache[src] ? this.cache[src].complete : false;
    },
    
    make: function(src) {
        var i = this.cache[src] || this.add(src);
        return this.clone(i);
    },
    
    load: function(src, callback) {
        callback = this.proxy( callback );
        this.elem.innerHTML = '';
        this.image = this.make( src );
        this.moveOut( this.image );
        this.elem.appendChild( this.image );
        this.wait(function() {
            return (this.image.complete && this.image.width);
        }, function() {
            this.orig = {
                h: this.image.height,
                w: this.image.width
            };
            callback( {target: this.image, scope: this} );
        }, function() {
            G.raise('image not loaded in 10 seconds: '+ src);
        }, 10000);
        return this;
    },
    
    scale: function(w, h, crop, max, margin, complete) {
        margin = margin || 0;
        complete = complete || function() {};
        if (!this.image) {
            return this;
        }
        this.wait(function() {
            width  = w || this.width(this.elem);
            height = h || this.height(this.elem);
            return width && height;
        }, function() {
            var ratio = Math[ (crop ? 'max' : 'min') ](width / this.orig.w, height / this.orig.h);
            if (max) {
                ratio = Math.min(max, ratio);
            }
            this.setStyle(this.elem, {
                width: width,
                height: height
            });
            this.image.width = Math.ceil(this.orig.w * ratio) - margin*2;
            this.image.height = Math.ceil(this.orig.h * ratio) - margin*2;
            this.setStyle(this.image, {
                position : 'relative',
                top :  Math.round(this.image.height * -1 / 2 + (height / 2)) - margin,
                left : Math.round(this.image.width * -1 / 2 + (width / 2)) - margin
            });
            complete.call(this);
        });
        return this;
    }
});

var tID; // the private timeout handler

var G = window.Galleria = Base.extend({
    
    __constructor : function(options) {
        if (typeof options.target === 'undefined' ) {
            G.raise('No target.');
        }
        this.playing = false;
        this.playtime = 3000;
        this.active = null;
        this.queue = {};
        this.data = {};
        this.dom = {};
        this.controls = {
            active : 0,
            swap : function() {
                this.active = this.active ? 0 : 1;
            },
            getActive : function() {
                return this[this.active];
            },
            getNext : function() {
                return this[Math.abs(this.active - 1)];
            }
        };
        this.thumbnails = {};
        this.options = this.mix({
            autoplay: false,
            carousel: true,
            carousel_follow: true,
            carousel_speed: 200,
            carousel_steps: 'auto',
            data_config : function( elem ) { return {}; },
            data_image_selector: 'img',
            data_source: options.target,
            data_type: 'auto',
            debug: false,
            extend: function(options) {},
            height: undefined,
            image_crop: false,
            image_margin: 0,
            keep_source: false,
            link_source_images: true,
            max_scale_ratio: undefined,
            popup_links: false,
            preload: 2,
            queue: true,
            show: 0,
            thumb_crop: true,
            thumb_margin: 0,
            thumb_quality: 'auto',
            thumbnails: true,
            transition: G.transitions.fade,
            transition_speed: 400
        }, options);
        
        this.target = this.dom.target = this.getElements(this.options.target)[0];
        if (!this.target) {
             G.raise('Target not found.');
        }
        
        this.stageWidth = 0;
        this.stageHeight = 0;
        
        var elems = 'container stage images image-nav image-nav-left image-nav-right ' + 
                    'info info-link info-text info-title info-description info-author info-close ' +
                    'thumbnails thumbnails-list thumbnails-container thumb-nav-left thumb-nav-right ' +
                    'loader counter';
        elems = elems.split(' ');
        
        this.loop(elems, function(blueprint) {
            this.dom[ blueprint ] = this.create('div', 'galleria-' + blueprint);
        });
    },
    
    bind : function(type, fn) {
        this.listen( this.get('container'), type, this.proxy(fn) );
        return this;
    },
    
    trigger : function( type ) {
        type = typeof type == 'object' ? 
            this.mix( type, { scope: this } ) : 
            { type: type, scope: this };
        this.dispatch( this.get('container'), type );
        return this;
    },
    run : function() {
        
        var o = this.options;
        if (!this.data.length) {
            G.raise('Data is empty.');
        }
        if (!o.keep_source) {
            this.target.innerHTML = '';
        }
        this.loop(2, function() {
            var image = new Picture();
            this.setStyle( image.elem, {
                position: 'absolute',
                top: 0,
                left: 0
            });
            this.setStyle(this.get( 'images' ), {
                position: 'relative',
                top: 0,
                left: 0,
                width: '100%',
                height: '100%'
            });
            this.get( 'images' ).appendChild( image.elem );
            this.push(image, this.controls);
        }, this);
        
        for( var i=0; this.data[i]; i++ ) {
            var thumb;
            if (o.thumbnails === true) {
                thumb = new Picture(i);
                var src = this.data[i].thumb || this.data[i].image;
                this.get( 'thumbnails' ).appendChild( thumb.elem );
                thumb.load(src, this.proxy(function(e) {
                    var orig = this.width(e.target);
                    e.scope.scale(null, null, o.thumb_crop, null, o.thumb_margin, this.proxy(function() {
                        // set high quality if downscale is moderate
                        this.toggleQuality(e.target, o.thumb_quality === true || ( o.thumb_quality == 'auto' && orig < e.target.width * 3 ));
                        this.trigger({
                            type: G.THUMBNAIL,
                            thumbTarget: e.target,
                            thumbOrder: e.scope.order
                        });
                    }));
                }));
                if (o.preload == 'all') {
                    thumb.add(this.data[i].image);
                }
            } else if (o.thumbnails == 'empty') {
                thumb = {
                    elem:  this.create('div','galleria-image'),
                    image: this.create('span','img')
                };
                thumb.elem.appendChild(thumb.image);
                this.get( 'thumbnails' ).appendChild( thumb.elem );
            } else {
                thumb = {
                    elem: false,
                    image: false
                }
            }
            var activate = this.proxy(function(e) {
                e.preventDefault();
                var ind = e.currentTarget.rel;
                if (this.active !== ind) {
                    this.show( ind );
                }
            });
            if (o.thumbnails !== false) {
                thumb.elem.rel = i;
                this.listen(thumb.elem, 'click', activate);
            }
            if (o.link_source_images && o.keep_source && this.data[i].elem) {
                this.data[i].elem.rel = i;
                this.listen(this.data[i].elem, 'click', activate);
            }
            this.push(thumb, this.thumbnails );
        }
        this.build();
        this.target.appendChild(this.get('container'));
        this.wait(function() {
            this.stageWidth = this.width(this.get( 'stage' ));
            this.stageHeight = this.height( this.get( 'stage' ));
            if (!this.stageHeight && this.stageWidth) { // no height in css, set reasonable ratio (16/9)
                this.setStyle( this.get( 'container' ),  { 
                    height: this.options.height || Math.round( this.stageWidth*9/16 ) 
                } );
                this.stageHeight = this.height( this.get( 'stage' ));
            }
            return this.stageHeight && this.stageWidth;
        }, function() {
            var thumbWidth = this.thumbnails[0] ? this.width(this.thumbnails[0].elem, true) : 0;
            
            var thumbsWidth = thumbWidth * this.thumbnails.length;
            if (thumbsWidth < this.stageWidth) {
                o.carousel = false;
            }

            if (o.carousel) {
                this.toggleClass(this.get('thumbnails-container'), 'galleria-carousel');
                this.carousel = {
                    right: this.get('thumb-nav-right'),
                    left: this.get('thumb-nav-left'),
                    overflow: 0,
                    setOverflow: this.proxy(function(newWidth) {
                        newWidth = newWidth || this.width(this.get('thumbnails-list'));
                        this.carousel.overflow = Math.ceil( ( (thumbsWidth - newWidth) / thumbWidth ) + 1 ) * -1;
                    }),
                    pos: 0,
                    setClasses: this.proxy(function() {
                        this.toggleClass( this.carousel.left, 'disabled', this.carousel.pos === 0);
                        this.toggleClass( this.carousel.right, 'disabled', this.carousel.pos == this.carousel.overflow + 1);
                    }),
                    animate: this.proxy(function() {
                        this.carousel.setClasses();
                        this.animate( this.get('thumbnails'), {
                            to: { left: thumbWidth * this.carousel.pos },
                            duration: o.carousel_speed
                        });
                    })
                };
                this.carousel.setOverflow();
            
                this.setStyle(this.get('thumbnails-list'), {
                    overflow:'hidden',
                    position: 'relative' // for IE Standards mode
                });
                this.setStyle(this.get('thumbnails'), {
                    width: thumbsWidth,
                    position: 'relative'
                });
                
                this.proxy(function(c, steps) {
                    steps = (typeof steps == 'string' && steps.toLowerCase() == 'auto') ? this.thumbnails.length + c.overflow : steps;
                    c.setClasses();
                    this.loop(['left','right'], this.proxy(function(dir) {
                        this.listen(c[dir], 'click', function(e) {
                            if (c.pos === ( dir == 'right' ? c.overflow : 0 ) ) {
                                return;
                            }
                            c.pos = dir == 'right' ? Math.max(c.overflow + 1, c.pos - steps) : Math.min(0, c.pos + steps);
                            c.animate();
                        });
                    }));
                })(this.carousel, o.carousel_steps);
            }
            this.listen(this.get('image-nav-right'), 'click', this.proxy(function() {
                this.next();
            }));
            this.listen(this.get('image-nav-left'), 'click', this.proxy(function() {
                this.prev();
            }));
            this.trigger( G.READY );
        }, function() {
            G.raise('Galleria could not load. Make sure stage has a height and width.');
        }, 5000);
    },
    addElement : function() {
        this.loop(arguments, function(b) {
            this.dom[b] = this.create('div', 'galleria-' + b );
        });
        return this;
    },
    getDimensions: function(i) {
        return {
            w: i.width,
            h: i.height,
            cw: this.stageWidth,
            ch: this.stageHeight,
            top: (this.stageHeight - i.height) / 2,
            left: (this.stageWidth - i.width) / 2
        };
    },
    attachKeyboard : function(map) {
        jQuery(document).bind('keydown', {map: map, scope: this}, this.keyNav);
        return this;
    },
    detachKeyboard : function() {
        jQuery(document).unbind('keydown', this.keyNav);
        return this;
    },
    keyNav : function(e) {
        var key = e.keyCode || e.which;
        var map = e.data.map;
        var scope = e.data.scope;
        var keymap = {
            UP: 38,
            DOWN: 40,
            LEFT: 37,
            RIGHT: 39,
            RETURN: 13,
            ESCAPE: 27,
            BACKSPACE: 8
        };
        for( var i in map ) {
            var k = i.toUpperCase();
            if ( keymap[k] ) {
                map[keymap[k]] = map[i];
            }
        }
        if (typeof map[key] == 'function') {
            map[key].call(scope, e);
        }
    },
    build : function() {
        this.append({
            'info-text' :
                ['info-title', 'info-description', 'info-author'],
            'info' : 
                ['info-link', 'info-text', 'info-close'],
            'image-nav' : 
                ['image-nav-right', 'image-nav-left'],
            'stage' : 
                ['images', 'loader', 'counter', 'image-nav'],
            'thumbnails-list' :
                ['thumbnails'],
            'thumbnails-container' : 
                ['thumb-nav-left', 'thumbnails-list', 'thumb-nav-right'],
            'container' : 
                ['stage', 'thumbnails-container', 'info']
        });
    },
    
    appendChild : function(parent, child) {
        try {
            this.get(parent).appendChild(this.get(child));
        } catch(e) {}
    },
    
    append : function(data) {
        for( var i in data) {
            if (data[i].constructor == Array) {
                for(var j=0; data[i][j]; j++) {
                    this.appendChild(i, data[i][j]);
                }
            } else {
                this.appendChild(i, data[i]);
            }
        }
        return this;
    },
    
    rescale : function(width, height) {
        
        var check = this.proxy(function() {
            this.stageWidth = width || this.width(this.get('stage'));
            this.stageHeight = height || this.height(this.get('stage'));
            return this.stageWidth && this.stageHeight;
        });
        if ( G.WEBKIT ) {
            this.wait(check);// wekit is too fast
        } else {
            check.call(this); 
        }
        this.controls.getActive().scale(this.stageWidth, this.stageHeight, this.options.image_crop, this.options.max_scale_ratio, this.options.image_margin);
        if (this.carousel) {
            this.carousel.setOverflow();
        }
        
    },
    
    show : function(index, rewind, history) {
        if (!this.options.queue && this.queue.stalled) {
            return;
        }
        rewind = typeof rewind != 'undefined' ? !!rewind : index < this.active;
        history = history || false;
        index = parseInt(index);
        if (!history && G.History) {
            G.History.value(index.toString());
            return;
        }
        this.active = index;
        this.push([index,rewind], this.queue);
        if (!this.queue.stalled) {
            this.showImage();
        }
        return this;
    },
    
    showImage : function() {
        var o = this.options;
        var args = this.queue[0];
        var index = args[0];
        var rewind = !!args[1];
        if (o.carousel && this.carousel && o.carousel_follow) {
            this.proxy(function(c) {
                if (index <= Math.abs(c.pos)) {
                    c.pos = Math.max(0, (index-1))*-1;
                    c.animate();
                } else if ( index >= this.thumbnails.length + c.overflow + Math.abs(c.pos)) {
                    c.pos = this.thumbnails.length + c.overflow - index - 1 + (index == this.thumbnails.length-1 ? 1 : 0);
                    c.animate();
                }
            })(this.carousel);
        }
        
        var src = this.getData(index).image;
        var active = this.controls.getActive();
        var next = this.controls.getNext();
        var cached = next.isCached(src);
        if (active.image) {
            this.toggleQuality(active.image, false);
        }
        var complete = this.proxy(function() {
            this.queue.stalled = false;
            this.toggleQuality(next.image, o.image_quality);
            this.setStyle( active.elem, { zIndex : 0 } );
            this.setStyle( next.elem, { zIndex : 1 } );
            this.moveOut( active.image );
            this.controls.swap();
            if (this.getData( index ).link) {
                this.setStyle( next.image, { cursor: 'pointer' } );
                this.listen( next.image, 'click', this.proxy(function() {
                    if (o.popup_links) {
                        var win = window.open(this.getData( index ).link, '_blank');
                    } else {
                        window.location.href = this.getData( index ).link;
                    }
                }));
            }
            Array.prototype.shift.call( this.queue );
            if (this.queue.length) {
                this.showImage();
            }
            this.playCheck();
        });
        if (typeof o.preload == 'number' && o.preload > 0) {
            var p,n = this.getNext();
            try {
                for (var i = o.preload; i>0; i--) {
                    p = new Picture();
                    p.add(this.getData(n).image);
                    n = this.getNext(n);
                }
            } catch(e) {}
        }
        this.trigger( {
            type: G.LOADSTART,
            cached: cached,
            imageTarget: next.image,
            thumbTarget: this.thumbnails[index].image
        } );
        next.load( src, this.proxy(function(e) {
            next.scale(this.stageWidth, this.stageHeight, o.image_crop, o.max_scale_ratio, o.image_margin, this.proxy(function(e) {
                this.toggleQuality(next.image, false);
                this.trigger({
                    type: G.LOADFINISH,
                    cached: cached,
                    imageTarget: next.image,
                    thumbTarget: this.thumbnails[index].image
                });
                this.queue.stalled = true;
                var transition = G.transitions[o.transition] || o.transition;
                if (typeof transition == 'function') {
                    transition.call(this, {
                        prev: active.image,
                        next: next.image,
                        rewind: rewind,
                        speed: o.transition_speed || 400
                    }, complete );
                } else {
                    complete();
                }
            }));
            this.setInfo(index);
            this.get('counter').innerHTML = '<span class="current">' + (index+1) + 
                '</span> / <span class="total">' + this.thumbnails.length + '</span>';
        }));
    },
    
    getNext : function(base) {
        base = base || this.active;
        return base == this.data.length - 1 ? 0 : base + 1;
    },
    
    getPrev : function(base) {
        base = base || this.active;
        return base === 0 ? this.data.length - 1 : base - 1;
    },
    
    next : function() {
        if (this.data.length > 1) {
            this.show(this.getNext(), false);
        }
        return this;
    },
    
    prev : function() {
        if (this.data.length > 1) {
            this.show(this.getPrev(), true);
        }
        return this;
    },
    
    get : function( elem ) {
        return this.dom[ elem ] || false;
    },
    
    getData : function( index ) {
        return this.data[index] || this.data[this.active];
    },
    
    play : function(delay) {
        this.playing = true;
        this.playtime = delay || this.playtime;
        this.playCheck();
        return this;
    },
    
    pause : function() {
        this.playing = false;
        return this;
    },
    
    playCheck : function() {
        if (this.playing) {
            window.clearInterval(tID);
            tID = window.setTimeout(this.proxy(function() {
                if (this.playing) {
                    this.next();
                }
            }), this.playtime);
        }
    },
    
    setActive: function(val) {
        this.active = val;
        return this;
    },
    
    setInfo : function(index) {
        var data = this.getData(index);
        var set = this.proxy(function() {
            this.loop(arguments, function(type) {
                var elem = this.get('info-'+type);
                var fn = data[type] && data[type].length ? 'reveal' : 'hide';
                this[fn](elem);
                elem.innerHTML = data[type];
            });
        });
        set('title','description','author');
        return this;
    },
    
    hasInfo : function(index) {
        var d = this.getData(index);
        var l = d.title + d.description + d.author;
        return !!l.length;
    },
    
    getDataObject : function(o) {
        var obj = {
            image: '',
            thumb: '',
            title: '',
            description: '',
            author: '',
            link: ''
        };
        return o ? this.mix(obj,o) : obj;
    },
    
    jQuery : function( str ) {
        var ret = [];
        this.loop(str.split(','), this.proxy(function(elem) {
            elem = elem.replace(/^\s\s*/, "").replace(/\s\s*$/, "");
            if (this.get(elem)) {
                ret.push(elem);
            }
        }));
        var jQ = jQuery(this.get(ret.shift()));
        this.loop(ret, this.proxy(function(elem) {
            jQ = jQ.add(this.get(elem));
        }));
        return jQ;
    },
    
    $ : function( str ) {
        return this.jQuery( str );
    },
    
    toggleQuality : function(img, force) {
        if (!G.IE7 || typeof img == 'undefined' || !img) {
            return this;
        }
        if (typeof force === 'undefined') {
            force = img.style.msInterpolationMode == 'nearest-neighbor';
        }
        img.style.msInterpolationMode = force ? 'bicubic' : 'nearest-neighbor';

        return this;
    },
    
    load : function() {
        var loaded = 0;
        var o = this.options;
        if (
            (o.data_type == 'auto' && 
                typeof o.data_source == 'object' && 
                !(o.data_source instanceof jQuery) && 
                !o.data_source.tagName
            ) || o.data_type == 'json' || o.data_source.constructor == 'Array' ) {
            this.data = o.data_source;
            this.trigger( G.DATA );
            
        } else { // assume selector
            var images = jQuery(o.data_source).find(o.data_image_selector);
            var getData = this.proxy(function( elem ) {
                var i,j,anchor = elem.parentNode;
                if (anchor && anchor.nodeName == 'A') {
                    if (anchor.href.match(/\.(png|gif|jpg)/i)) {
                        i = anchor.href;
                    } else {
                        j = anchor.href;
                    }
                }
                var obj = this.getDataObject({
                    title: elem.title,
                    thumb: elem.src,
                    image: i || elem.src,
                    description: elem.alt,
                    link: j || elem.getAttribute('longdesc'),
                    elem: elem
                });
                return this.mix(obj, o.data_config( elem ) );
            });
            
            this.loop(images, function( elem ) {
                loaded++;
                this.push( getData( elem ), this.data );
                if (!o.keep_source) {
                    elem.parentNode.removeChild(elem);
                }
                if ( loaded == images.length ) {
                    this.trigger( G.DATA );
                }
            });
        }
    }
});

G.log = function() {
    try { 
        console.log.apply( console, Array.prototype.slice.call(arguments) ); 
    } catch(e) {
        try {
            opera.postError.apply( opera, arguments ); 
        } catch(er) { 
              alert( Array.prototype.join.call( arguments, " " ) ); 
        } 
    }
};

G.DATA = 'data';
G.READY = 'ready';
G.THUMBNAIL = 'thumbnail';
G.LOADSTART = 'loadstart';
G.LOADFINISH = 'loadfinish';

var nav = navigator.userAgent.toLowerCase();

G.IE7 = (window.XMLHttpRequest && document.expando);
G.IE6 = (!window.XMLHttpRequest);
G.IE = !!(G.IE6 || G.IE7);
G.WEBKIT = /webkit/.test( nav );
G.SAFARI = /safari/.test( nav );
G.CHROME = /chrome/.test( nav );
G.QUIRK = (G.IE && document.compatMode && document.compatMode == "BackCompat");
G.MAC = /mac/.test(navigator.platform.toLowerCase());

var tempPath = ''; // we need to save this in a global private variable later
var tempName = ''; // the last loaded theme
var tempLoading = false; // we need to manually check if script has loaded
var tempFile = ''; // the theme file
var hash = window.location.hash.replace(/#\//,'');

G.themes = {
    create: function(obj) {
        var orig = ['name','author','version','defaults','init'];
        var proto = G.prototype;
        proto.loop(orig, function(val) {
            if (!obj[ val ]) {
                G.raise(val+' not specified in theme.');
            }
            if ( typeof G.themes[obj.name] == 'undefined') {
                G.themes[obj.name] = {};
            }
            if (val != 'name' && val != 'init') {
                G.themes[obj.name][val] = obj[val];
            }
        });
        if (obj.css) {
            if (!tempPath.length) { // try to find the script tag to determine tempPath
                var theme_src = proto.getElements('script');
                proto.loop(theme_src, function(el) {
                    var reg = new RegExp('galleria.'+obj.name+'.js');
                    if(reg.test(el.src)) {
                        tempPath = el.src.replace(/[^\/]*$/, "");
                    }
                });
            }
            obj.cssPath = tempPath + obj.css;
            tempPath = '';
        }
        tempName = obj.name;
        G.themes[obj.name].init = function(o) {
            if (obj.cssPath) {
                var link = proto.getElements('#galleria-styles');
                if (link.length) {
                    link = link[0];
                } else {
                    link = proto.create('link');
                    link.id = 'galleria-styles';
                    link.rel = 'stylesheet';
                    link.media = 'all';
                    var li = document.getElementsByTagName('link').length ?
                        document.getElementsByTagName('link') : document.getElementsByTagName('style');
                    if (li[0]) {
                        li[0].parentNode.insertBefore(link, li[0]);
                    } else {
                        document.getElementsByTagName('head')[0].appendChild(link);
                    }
                }
                link.href = obj.cssPath;
            }
            if (obj.cssText) {
                proto.cssText(obj.cssText);
            }
            o = proto.mix( G.themes[obj.name].defaults, o );
            var gallery = new G( o );
            o = gallery.options;
            gallery.bind(G.DATA, function() {
                gallery.run();
            });
            gallery.bind(G.READY, function() {
                if (G.History) {
                    G.History.change(function(e) {
                        var val = parseInt(e.value.replace(/\//,''));
                        if (isNaN(val)) {
                            window.history.go(-1);
                        } else {
                            gallery.show(val, undefined, true);
                        }
                    });
                }
                obj.init.call(gallery, o);
                o.extend.call(gallery, o);
                if (/^[0-9]{1,4}$/.test(hash) && G.History) {
                    gallery.show(hash, undefined, true);
                } else if (typeof o.show == 'number') {
                    gallery.show(o.show);
                }
                if (o.autoplay) {
                    if (typeof o.autoplay == 'number') {
                        gallery.play(o.autoplay);
                    } else {
                        gallery.play();
                    }
                }
            });
            gallery.load();
            return gallery;
        };
    }
};

G.raise = function(msg) {
    if ( G.debug ) {
        throw new Error( msg );
    }
},

G.loadTheme = function(src, callback) {
    tempLoading = true;
    tempPath = src.replace(/[^\/]*$/, "");
    tempFile = src;
    G.prototype.getScript(src, function() {
        tempLoading = false;
        if (typeof callback == 'function') {
            callback();
        }
    });
};

jQuery.easing.galleria = 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;
};

G.transitions = {
    add: function(name, fn) {
        if (name != arguments.callee.name ) {
            this[name] = fn;
        }
    },
    fade: function(params, complete) {
        jQuery(params.next).show().css('opacity',0).animate({
            opacity: 1
        }, params.speed, complete);
        if (params.prev) {
            jQuery(params.prev).css('opacity',1).animate({
                opacity: 0
            }, params.speed);
        }
    },
    flash: function(params, complete) {
        jQuery(params.next).css('opacity',0);
        if (params.prev) {
            jQuery(params.prev).animate({
                opacity: 0
            }, (params.speed/2), function() {
                jQuery(params.next).animate({
                    opacity: 1
                }, params.speed, complete);
            });
        } else {
            jQuery(params.next).animate({
                opacity: 1
            }, params.speed, complete);
        }
    },
    slide: function(params, complete) {
        var image = jQuery(params.next).parent();
        var images =  this.$('images');
        var width = this.stageWidth;
        image.css({
            left: width * ( params.rewind ? -1 : 1 )
        });
        images.animate({
            left: width * ( params.rewind ? 1 : -1 )
        }, {
            duration: params.speed,
            queue: false,
            easing: 'galleria',
            complete: function() {
                images.css('left',0);
                image.css('left',0);
                complete();
            }
        });
    },
    fadeslide: function(params, complete) {
        if (params.prev) {
            jQuery(params.prev).css({
                opacity: 1,
                left: 0
            }).animate({
                opacity: 0,
                left: 50 * ( params.rewind ? 1 : -1 )
            },{
                duration: params.speed,
                queue: false,
                easing: 'swing'
            });
        }
        jQuery(params.next).css({
            left: 50 * ( params.rewind ? -1 : 1 ), 
            opacity: 0
        }).animate({
            opacity: 1,
            left:0
        }, {
            duration: params.speed,
            complete: complete,
            queue: false,
            easing: 'swing'
        });
    }
};

jQuery.fn.galleria = function() {
    var selector = this.selector;
    var a = arguments;
    var hasTheme = typeof a[0] == 'string';
    var options = hasTheme ? a[1] || {} : a[0] || {};

    if ( !options.keep_source ) {
        jQuery(this).find('*').hide();
    }

    G.prototype.wait(function() {
        return !tempLoading;
    }, function() {
        var theme = hasTheme ? a[0] : tempName;
        options = G.prototype.mix(options, { target: selector } );
        G.debug = !!options.debug; 
        if (typeof G.themes[theme] == 'undefined') {
            var err = theme ? 'Theme '+theme+' not found.' : 'No theme specified';
            G.raise(err);
            return null;
        } else {
            return G.themes[theme].init(options);
        }
    }, function() {
        G.raise('Theme file '+tempFile+' not found.');
    });
};

})();

/*!
 * Galleria History Plugin v 1.0
 * http://galleria.aino.se
 *
 * Original Copyright (c) 2009-2010 Rostislav Hristov
 * Modified by Aino (c) 2010
 *
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 */
(function($) {
    
    var G = window.Galleria; 
    if (typeof G == 'undefined') {
        return;
    }

    G.History = (function () {

        var _trigger = function(name) {
                $(G.History).trigger(
                    $.extend($.Event(name), 
                        (function() {
                            var parameters = {},
                                parameterNames = G.History.parameterNames();
                            for (var i = 0, l = parameterNames.length; i < l; i++) {
                                parameters[parameterNames[i]] = G.History.parameter(parameterNames[i]);
                            }
                            return {
                                value: G.History.value(),
                                path: G.History.path(),
                                pathNames: G.History.pathNames(),
                                parameterNames: parameterNames,
                                parameters: parameters,
                                queryString: G.History.queryString()
                            };
                        }).call(G.History)
                    )
                );
            },
            _bind = function(value, data, fn) {
                fn = fn || function(){};
                $(G.History).bind(value, data, fn);
                return G.History;
            },
            _hash = function() {
                var index = _l.href.indexOf('#');
                return index != -1 ? _ec(_dc(_crawl(_l.href.substr(index + 1), FALSE))) : '';
            },
            _window = function() {
                try {
                    return top.document !== undefined ? top : window;
                } catch (e) { 
                    return window;
                }
            },
            _js = function() {
                return 'javascript';
            },
            _strict = function(value, force) {
                if (_opts.strict) {
                    value = force ? (value.substr(0, 1) != '/' ? '/' + value : value) : (value == '' ? '/' : value);
                }
                return value;
            },
            _local = function(value, direction) {
                return (_msie && _l.protocol == 'file:') ? 
                    (direction ? _value.replace(/\?/, '%3F') : _value.replace(/%253F/, '?')) : value;
            },
            _crawl = function(value, direction) {
                if (_opts.crawlable && direction) {
                    return (value != '' ? '!' : '') + value;
                }
                return value.replace(/^\!/, '');
            },
            _cssint = function(el, value) {
                return parseInt(el.css(value), 10);
            },
            _search = function(el) {
                var url, s;
                for (var i = 0, l = el.childNodes.length; i < l; i++) {
                    if (el.childNodes[i].src) {
                        url = String(el.childNodes[i].src);
                    }
                    s = _search(el.childNodes[i]);
                    if (s) {
                        url = s;
                    }
                }
                return url;
            },
            _listen = function() {
                if (!_silent) {
                    var hash = _hash(),
                        diff = _value != hash;
                    if (_safari && _version < 523) {
                        if (_length != _h.length) {
                            _length = _h.length;
                            if (typeof _stack[_length - 1] != UNDEFINED) {
                                _value = _stack[_length - 1];
                            }
                            _update(FALSE);
                        }
                    } else if (_msie && _version < 7 && diff) {
                        _l.reload();
                    } else if (diff) {
                        _value = hash;
                        _update(FALSE);
                    }
                }
            },
            _update = function(internal) {
                _trigger(CHANGE);
                _trigger(internal ? INTERNAL_CHANGE : EXTERNAL_CHANGE);
                _st(_track, 10);
            },
            _track = function() {
                var value = (_l.pathname + (/\/$/.test(_l.pathname) ? '' : '/') + 
                    (G.History ? G.History.value() : '')).replace(/\/\//, '/').replace(/^\/$/, ''),
                    fn = _t[_opts.tracker];
                if (typeof fn == FUNCTION) {
                    fn(value);
                } else if (typeof urchinTracker == FUNCTION) {
                    urchinTracker(value);
                } else if (typeof pageTracker != UNDEFINED && typeof pageTracker._trackPageview == FUNCTION) {
                    pageTracker._trackPageview(value);
                } else if (typeof _gaq != UNDEFINED && typeof _gaq.push == FUNCTION) {
                    _gaq.push(['_trackPageview', value]);
                }
            },
            _html = function() {
                var doc = _frame.contentWindow.document;
                doc.open();
                doc.write('<html><head><title>' + _d.title + '</title><script>var ' + ID + ' = "' + _hash() + '";</' + 'script></head></html>');
                doc.close();
            },
            _load = function() {
                if (!_loaded) {
                    _loaded = TRUE;
                    var body = $('body').ajaxComplete(function() {
                        _unescape.call(this);
                    }).trigger('ajaxComplete');
                    if (_opts.wrap) {
                        var wrap = $('body > *')
                            .wrapAll('<div style="padding:' + 
                                (_cssint(body, 'marginTop') + _cssint(body, 'paddingTop')) + 'px ' + 
                                (_cssint(body, 'marginRight') + _cssint(body, 'paddingRight')) + 'px ' + 
                                (_cssint(body, 'marginBottom') + _cssint(body, 'paddingBottom')) + 'px ' + 
                                (_cssint(body, 'marginLeft') + _cssint(body, 'paddingLeft')) + 'px;" />')
                            .parent()
                            .wrap('<div id="' + ID + '" style="height:100%; overflow:auto;' + 
                                (_safari ? (window.statusbar.visible && !/chrome/i.test(_agent) ? '' : ' resize:both;') : '') + '" />');
                        $('html, body')
                            .css({
                                height: '100%',
                                margin: 0,
                                padding: 0,
                                overflow: 'hidden'
                            });
                        if (_safari) {
                            $('<style type="text/css" />')
                                .appendTo('head')
                                .text('#' + ID + '::-webkit-resizer { background-color: #fff; }');
                        }
                    }
                    if (_msie && _version < 8) {
                        var frameset = _d.getElementsByTagName('frameset')[0];
                        _frame = _d.createElement((frameset ? '' : 'i') + 'frame');
                        if (frameset) {
                            frameset.insertAdjacentElement('beforeEnd', _frame);
                            frameset[frameset.cols ? 'cols' : 'rows'] += ',0';
                            _frame.src = _js() + ':' + FALSE;
                            _frame.noResize = TRUE;
                            _frame.frameBorder = _frame.frameSpacing = 0;
                        } else {
                            _frame.src = _js() + ':' + FALSE;
                            _frame.style.display = 'none';
                            _d.body.insertAdjacentElement('afterBegin', _frame);
                        }
                        _st(function() {
                            $(_frame).bind('load', function() {
                                var win = _frame.contentWindow;
                                var src = win.location.href;
                                _value = (typeof win[ID] != UNDEFINED ? win[ID] : '');
                                if (_value != _hash()) {
                                    _update(FALSE);
                                    _l.hash = _local(_crawl(_value, TRUE), TRUE);
                                }
                            });
                            if (typeof _frame.contentWindow[ID] == UNDEFINED) {
                                _html();
                            }
                        }, 50);
                    } else if (_safari) {
                        if (_version < 418) {
                            $(_d.body).append('<form id="' + ID + '" style="position:absolute;top:-9999px;" method="get"></form>');
                            _form = _d.getElementById(ID);
                        }
                        if (typeof _l[ID] == UNDEFINED) {
                            _l[ID] = {};
                        }
                        if (typeof _l[ID][_l.pathname] != UNDEFINED) {
                            _stack = _l[ID][_l.pathname].split(',');
                        }
                    }

                    _st(function() {
                        _trigger('init');
                        _update(FALSE);
                    }, 1);
                    
                    if ((_msie && _version > 7) || (!_msie && ('on' + HASH_CHANGE) in _t)) {
                        if (_t.addEventListener) {
                            _t.addEventListener(HASH_CHANGE, _listen, false);
                        } else if (_t.attachEvent) {
                            _t.attachEvent('on' + HASH_CHANGE, _listen);
                        }
                    } else {
                        _si(_listen, 50);
                    }
                    
                    //$('a').filter('[rel*=address:]').address();
                }
            },
            _unload = function() {
                if (_t.removeEventListener) {
                    _t.removeEventListener(HASH_CHANGE, _listen, false);
                } else if (_t.detachEvent) {
                    _t.detachEvent('on' + HASH_CHANGE, _listen);
                }
            },
            _unescape = function() {
                var base = _l.pathname.replace(/\/$/, ''),
                    fragment = '_escaped_fragment_';
                if ($('body').html().indexOf(fragment) != -1) {
                    $('a[href]:not([href^=http])', this).each(function() {
                        var href = $(this).attr('href').replace(new RegExp(base + '/?$'), '');
                        if (href == '' || href.indexOf(fragment) != -1) {
                            $(this).attr('href', '#' + decodeURIComponent(href.replace(new RegExp('/(.*)\\?' + fragment + '=(.*)$'), '!$2')));
                        }
                    });
                }
            },
            ID = 'jQueryAddress',
            FUNCTION = 'function',
            UNDEFINED = 'undefined',
            HASH_CHANGE = 'hashchange',
            INIT = 'init',
            CHANGE = 'change',
            INTERNAL_CHANGE = 'internalChange',
            EXTERNAL_CHANGE = 'externalChange',
            TRUE = true,
            FALSE = false,
            _opts = {
                autoUpdate: TRUE, 
                crawlable: FALSE,
                history: TRUE, 
                strict: TRUE,
                wrap: FALSE
            },
            _browser = $.browser, 
            _version = parseFloat($.browser.version),
            _mozilla = _browser.mozilla,
            _msie = _browser.msie,
            _opera = _browser.opera,
            _safari = _browser.safari,
            _supported = FALSE,
            _t = _window(),
            _d = _t.document,
            _h = _t.history, 
            _l = _t.location,
            _si = setInterval,
            _st = setTimeout, 
            _dc = decodeURI,
            _ec = encodeURI,
            _agent = navigator.userAgent,            
            _frame,
            _form,
            _url = _search(document),
            _qi = _url ? _url.indexOf('?') : -1,
            _title = _d.title, 
            _length = _h.length, 
            _silent = FALSE,
            _loaded = FALSE,
            _justset = TRUE,
            _juststart = TRUE,
            _updating = FALSE,
            _stack = [], 
            _listeners = {}, 
            _value = _hash();
            
        if (_msie) {
            _version = parseFloat(_agent.substr(_agent.indexOf('MSIE') + 4));
            if (_d.documentMode && _d.documentMode != _version) {
                _version = _d.documentMode != 8 ? 7 : 8;
            }
            $(document).bind('propertychange', function() {
                if (_d.title != _title && _d.title.indexOf('#' + _hash()) != -1) {
                    _d.title = _title;
                }
            });
        }
        
        _supported = 
            (_mozilla && _version >= 1) || 
            (_msie && _version >= 6) ||
            (_opera && _version >= 9.5) ||
            (_safari && _version >= 312);
            
        if (_supported) {
        
            for (var i = 1; i < _length; i++) {
                _stack.push('');
            }
            
            _stack.push(_value);
        
            if (_msie && _l.hash != _value) {
                _l.hash = '#' + _local(_crawl(_value, TRUE), TRUE);
            }
            
            if (_opera) {
                history.navigationMode = 'compatible'; 
            }
            
            if (_url && _qi != -1) {
                var param, params = _url.substr(_qi + 1).split('&');
                for (i = 0; i < params.length; i++) {
                    param = params[i].split('=');
                    if (/^(autoUpdate|crawlable|history|strict|wrap)$/.test(param[0])) {
                        _opts[param[0]] = (isNaN(param[1]) ? /^(true|yes)$/i.test(param[1]) : (parseInt(param[1], 10) !== 0));
                    }
                    if (/^tracker$/.test(param[0])) {
                        _opts[param[0]] = param[1];
                    }
                }
            }

            if (document.readyState == 'complete') {
                _load();
            }
            $(_load);
            $(window).bind('unload', _unload);
            
        } else if ((!_supported && _hash() != '') || 
            (_safari && _version < 418 && _hash() != '' && _l.search != '')) {
            _d.open();
            _d.write('<html><head><meta http-equiv="refresh" content="0;url=' + 
                encodeURI(_l.href.substr(0, _l.href.indexOf('#'))) + '" /></head></html>');
            _d.close();
        } else {
            _track();
        }

        return {
            bind: function(type, data, fn) {
                return _bind(type, data, fn);
            },
            init: function(fn) {
                return _bind(INIT, fn);
            },
            change: function(fn) {
                return _bind(CHANGE, fn);
            },
            internalChange: function(fn) {
                return _bind(INTERNAL_CHANGE, fn);
            },
            externalChange: function(fn) {
                return _bind(EXTERNAL_CHANGE, fn);
            },
            baseURL: function() {
                var url = _l.href;
                if (url.indexOf('#') != -1) {
                    url = url.substr(0, url.indexOf('#'));
                }
                if (/\/$/.test(url)) {
                    url = url.substr(0, url.length - 1);
                }
                return url;
            },
            autoUpdate: function(value) {
                if (value !== undefined) {
                    _opts.autoUpdate = value;
                    return this;
                }
                return _opts.autoUpdate;
            },
            crawlable: function(value) {
                if (value !== undefined) {
                    _opts.crawlable = value;
                    return this;
                }
                return _opts.crawlable;
            },
            history: function(value) {
                if (value !== undefined) {
                    _opts.history = value;
                    return this;
                }
                return _opts.history;
            },
            strict: function(value) {
                if (value !== undefined) {
                    _opts.strict = value;
                    return this;
                }
                return _opts.strict;
            },
            tracker: function(value) {
                if (value !== undefined) {
                    _opts.tracker = value;
                    return this;
                }
                return _opts.tracker;
            },
            wrap: function(value) {
                if (value !== undefined) {
                    _opts.wrap = value;
                    return this;
                }
                return _opts.wrap;
            },
            update: function() {
                _updating = TRUE;
                this.value(_value);
                _updating = FALSE;
                return this;
            },
            title: function(value) {
                if (value !== undefined) {
                    value = _dc(value);
                    _st(function() {
                        _title = _d.title = value;
                        if (_juststart && _frame && _frame.contentWindow && _frame.contentWindow.document) {
                            _frame.contentWindow.document.title = value;
                            _juststart = FALSE;
                        }
                        if (!_justset && _mozilla) {
                            _l.replace(_l.href.indexOf('#') != -1 ? _l.href : _l.href + '#');
                        }
                        _justset = FALSE;
                    }, 50);
                    return this;
                }
                return _d.title;
            },
            value: function(value) {
                if (value !== undefined) {
                    value = _ec(_dc(_strict(value, TRUE)));
                    if (value == '/') {
                        value = '';
                    }
                    if (_value == value && !_updating) {
                        return;
                    }
                    _justset = TRUE;
                    _value = value;
                    if (_opts.autoUpdate || _updating) {
                        _silent = TRUE;
                        _update(TRUE);
                        _stack[_h.length] = _value;
                        if (_safari) {
                            if (_opts.history) {
                                _l[ID][_l.pathname] = _stack.toString();
                                _length = _h.length + 1;
                                if (_version < 418) {
                                    if (_l.search == '') {
                                        _form.action = '#' + _crawl(_value, TRUE);
                                        _form.submit();
                                    }
                                } else if (_version < 523 || _value == '') {
                                    var evt = _d.createEvent('MouseEvents');
                                    evt.initEvent('click', TRUE, TRUE);
                                    var anchor = _d.createElement('a');
                                    anchor.href = '#' + _crawl(_value, TRUE);
                                    anchor.dispatchEvent(evt);                
                                } else {
                                    _l.hash = '#' + _crawl(_value, TRUE);
                                }
                            } else {
                                _l.replace('#' + _crawl(_value, TRUE));
                            }
                        } else if (_value != _hash()) {
                            if (_opts.history) {
                                _l.hash = '#' + _local(_crawl(_value, TRUE), TRUE);
                            } else {
                                _l.replace('#' + _crawl(_value, TRUE));
                            }
                        }
                        if ((_msie && _version < 8) && _opts.history) {
                            _st(_html, 50);
                        }
                        if (_safari) {
                            _st(function(){ _silent = FALSE; }, 1);
                        } else {
                            _silent = FALSE;
                        }
                    }
                    return this;
                }
                if (!_supported) {
                    return null;
                }
                return _dc(_strict(_local(_value, FALSE), FALSE));
            },
            path: function(value) {
                if (value !== undefined) {
                    var qs = this.queryString(),
                        hash = this.hash();
                    this.value(value + (qs ? '?' + qs : '') + (hash ? '#' + hash : ''));
                    return this;
                }
                return this.value().split('#')[0].split('?')[0];
            },
            queryString: function(value) {
                if (value !== undefined) {
                    var hash = this.hash();
                    this.value(this.path() + (value ? '?' + value : '') + (hash ? '#' + hash : ''));
                    return this;
                }
                var arr = this.value().split('?');
                return arr.slice(1, arr.length).join('?').split('#')[0];
            },
            parameter: function(name, value, append) {
                var i, params;
                if (value !== undefined) {
                    var names = this.parameterNames();
                    params = [];
                    for (i = 0; i < names.length; i++) {
                        var n = names[i],
                            v = this.parameter(n);
                        if (typeof v == 'string') {
                            v = [v];
                        }
                        if (n == name) {
                            v = (value === null || value === '') ? [] : 
                                (append ? v.concat([value]) : [value]);
                        }
                        for (var j = 0; j < v.length; j++) {
                            params.push(n + '=' + v[j]);
                        }
                    }
                    if ($.inArray(name, names) == -1 && value !== null && value !== '') {
                        params.push(name + '=' + value);
                    }
                    this.queryString(params.join('&'));
                    return this;
                }
                value = this.queryString();
                if (value) {
                    params = value.split('&');
                    var r = [];
                    for (i = 0; i < params.length; i++) {
                        var p = params[i].split('=');
                        if (p[0] == name) {
                            r.push(p[1]);
                        }
                    }
                    if (r.length !== 0) {
                        return r.length != 1 ? r : r[0];
                    }
                }
            },
            pathNames: function() {
                var path = this.path(),
                    names = path.replace(/\/{2,9}/g, '/').split('/');
                if (path.substr(0, 1) == '/' || path.length === 0) {
                    names.splice(0, 1);
                }
                if (path.substr(path.length - 1, 1) == '/') {
                    names.splice(names.length - 1, 1);
                }
                return names;
            },
            parameterNames: function() {
                var qs = this.queryString(),
                    names = [];
                if (qs && qs.indexOf('=') != -1) {
                    var params = qs.split('&');
                    for (var i = 0; i < params.length; i++) {
                        var name = params[i].split('=')[0];
                        if ($.inArray(name, names) == -1) {
                            names.push(name);
                        }
                    }
                }
                return names;
            },
            hash: function(value) {
                if (value !== undefined) {
                    this.value(this.value().split('#')[0] + (value ? '#' + value : ''));
                    return this;
                }
                var arr = this.value().split('#');
                return arr.slice(1, arr.length).join('#');
            }            
        };
        
    })();
    
}(jQuery));