/* Galleria v 1.2 prerelease 1.1 2010-11-23, http://galleria.aino.se, Copyright (c) 2010, Aino, Licensed under the MIT license. */
(function($){
  var undef,window=this,doc=document,$doc=$(doc);
  var DEBUG=false,
  NAV=navigator.userAgent.toLowerCase(),
  HASH=window.location.hash.replace(/#\//,''),
  CLICK=function(){return Galleria.TOUCH?'touchstart':'click';},
  IE=(function(){
    var v=3,div=doc.createElement('div');
    while(div.innerHTML='<!--[if gt IE '+(++v)+']><i></i><![endif]-->',div.getElementsByTagName('i')[0]);
    return v>4?v:undef;
  }()),
  DOM=function(){
    return {html:doc.documentElement,body:doc.body,head:doc.getElementsByTagName('head')[0],title:doc.title};
  },
  _timeouts={
    trunk:{},
    add:function(id,fn,delay,loop){
      loop=loop||false;
      this.clear(id);
      if(loop){
        var old=fn;
        fn=function(){old();_timeouts.add(id,fn,delay);};
      }
      this.trunk[id]=window.setTimeout(fn,delay);
    },
    clear:function(id){
      var del=function(i){window.clearTimeout(this.trunk[i]);delete this.trunk[i];};
      if(!!id&&id in this.trunk){del.call(_timeouts,id);}
      else if(typeof id=='undefined'){for(var i in this.trunk){del.call(_timeouts,i);}}
    }
  },
  _galleries=[],
  _transitions={
    fade:function(params,complete){
      $(params.next).css('opacity',0).show().animate({opacity:1},params.speed,complete);
      if(params.prev){$(params.prev).css('opacity',1).show().animate({opacity:0},params.speed);}
    },
    flash:function(params,complete){
      $(params.next).css('opacity',0);
      if(params.prev){
        $(params.prev).animate({opacity:0},(params.speed/2),function(){$(params.next).animate({opacity:1},params.speed,complete);});
      }
      else{$(params.next).animate({opacity:1},params.speed,complete);}
    },
    pulse:function(params,complete){
      if(params.prev){$(params.prev).hide();}
      $(params.next).css('opacity',0).animate({opacity:1},params.speed,complete);
    },
    slide:function(params,complete){
      var image=$(params.next).parent(),
      images=this.$('images'),
      width=this._stageWidth,
      easing=this.getOptions('easing');
      image.css({left:width*(params.rewind?-1:1)});
      images.animate({left:width*(params.rewind?1:-1)},{duration:params.speed,queue:false,easing:easing,complete:function(){images.css('left',0);image.css('left',0);complete();}});
    },
    fadeslide:function(params,complete){
      var x=0,
      easing=this.getOptions('easing'),
      distance=this.getStageWidth();
      if(params.prev){
        x=Utils.parseValue($(params.prev).css('left'));
        $(params.prev).css({opacity:1,left:x}).animate({opacity:0,left:x+(distance*(params.rewind?1:-1))},{duration:params.speed,queue:false,easing:easing});
      }
      x=Utils.parseValue($(params.next).css('left'));
      $(params.next).css({left:x+(distance*(params.rewind?-1:1)),opacity:0}).animate({opacity:1,left:x},{duration:params.speed,complete:complete,queue:false,easing:easing});
    }
  },
  Utils=(function(){
    return {
      array:function(obj){return Array.prototype.slice.call(obj);},
      create:function(className,nodeName){
        nodeName=nodeName||'div';
        var elem=doc.createElement(nodeName);
        elem.className=className;
        return elem;
      },
      forceStyles:function(elem,styles){
        elem=$(elem);
        if(elem.attr('style')){elem.data('styles',elem.attr('style')).removeAttr('style');}
        elem.css(styles);
      },
      revertStyles:function(){
        $.each(Utils.array(arguments),function(i,elem){
          elem=$(elem).removeAttr('style');
          if(elem.data('styles')){elem.attr('style',elem.data('styles')).data('styles',null);}
        });
      },
      moveOut:function(elem){Utils.forceStyles(elem,{position:'absolute',left:-10000});},
      moveIn:function(){Utils.revertStyles.apply(Utils,Utils.array(arguments));},
      hide:function(elem,speed,callback){
        elem=$(elem);
        if(!elem.data('opacity')){elem.data('opacity',elem.css('opacity'));}
        var style={opacity:0};
        if(speed){elem.stop().animate(style,speed,callback);}
        else{elem.css(style);};
      },
      show:function(elem,speed,callback){
        elem=$(elem);
        var saved=parseFloat(elem.data('opacity'))||1,style={opacity:saved};
        if(saved==1){elem.data('opacity',null);}
        if(speed){elem.stop().animate(style,speed,callback);}
        else{elem.css(style);};
      },
      addTimer:function(){_timeouts.add.apply(_timeouts,Utils.array(arguments));return this;},
      clearTimer:function(){_timeouts.clear.apply(_timeouts,Utils.array(arguments));return this;},
      wait:function(options){
        options=$.extend({
          until:function(){return false;},
          success:function(){},
          error:function(){Galleria.raise('Could not complete wait function.');},
          timeout:3000
        },options);
        var start=Utils.timestamp(),elapsed,now;
        window.setTimeout(function(){
          now=Utils.timestamp();
          elapsed=now-start;
          if(options.until(elapsed)){options.success();return false;}
          if(now>=start+options.timeout){options.error();return false;}
          window.setTimeout(arguments.callee,2);
        },2);
      },
      toggleQuality:function(img,force){
        if(!(IE==7||IE==8)||!!img===false){return;}
        if(typeof force==='undefined'){force=img.style.msInterpolationMode=='nearest-neighbor';}
        img.style.msInterpolationMode=force?'bicubic':'nearest-neighbor';
      },
      insertStyleTag:function(styles){
        var style=doc.createElement('style');
        DOM().head.appendChild(style);
        if(style.styleSheet){style.styleSheet.cssText=styles;}
        else{var cssText=doc.createTextNode(styles);style.appendChild(cssText);}
      },
      loadScript:function(url,callback){
        var done=false,script=$('<scr'+'ipt>').attr({src:url,async:true}).get(0);
        script.onload=script.onreadystatechange=function(){
          if(!done&&(!this.readyState||this.readyState=='loaded'||this.readyState=='complete')){
            done=true;
            if(typeof callback=='function'){callback.call(this,this);}
            script.onload=script.onreadystatechange=null;
          }
        };
        var s=doc.getElementsByTagName('script')[0];
        s.parentNode.insertBefore(script,s);
      },
      parseValue:function(val){
        if(typeof val=='number'){return val;}
        else if(typeof val=='string'){var arr=val.match(/\-?\d/g);return arr&&arr.constructor==Array?arr.join('')*1:0;}
        else{return 0;}
      },
      timestamp:function(){return new Date().getTime();},
      loadCSS:function(href,id,callback){
        var link,ready=false,length;
        $('link[rel=stylesheet]').each(function(){
          if(new RegExp(href).test(this.href)){link=this;return false;}
        });
        if(typeof id=='function'){callback=id;id=undef;}
        callback=callback||function(){};
        if(link){callback.call(link,link);return link;}
        length=doc.styleSheets.length;
        if(DEBUG){href+='?'+Utils.timestamp();}
        if($('#'+id).length){$('#'+id).attr('href',href);length--;ready=true;}
        else{
          link=$('<link>').attr({rel:'stylesheet',href:href,id:id}).get(0);
          window.setTimeout(function(){
            var styles=$('link[rel="stylesheet"],style');
            if(styles.length){styles.get(0).parentNode.insertBefore(link,styles[0]);}
            else{DOM().head.appendChild(link);}
            if(IE){
              link.attachEvent('onreadystatechange',function(e){
                if(link.readyState=='complete'){ready=true;}
              });
            }
            else{ready=true;}
          },10);
        }
        if(typeof callback=='function'){
          Utils.wait({
            until:function(){return ready&&doc.styleSheets.length>length;},
            success:function(){Utils.addTimer('css',function(){callback.call(link,link);},100);},
            error:function(){Galleria.raise('Theme CSS could not load');},
            timeout:1000
          });
        }
        return link;
      }
    };
  })();
  Galleria=function(){
    var self=this;
    this._theme=undef;
    this._options={};
    this._playing=false;
    this._playtime=5000;
    this._active=null;
    this._queue={length:0};
    this._data=[];
    this._dom={};
    this._thumbnails=[];
    this._initialized=false;
    this._stageWidth=0;
    this._stageHeight=0;
    this._target=undef;
    this._id=Utils.timestamp();
    var divs='container stage images image-nav image-nav-left image-nav-right '+
    'info info-text info-title info-description info-author '+
    'thumbnails thumbnails-list thumbnails-container thumb-nav-left thumb-nav-right '+
    'loader counter tooltip',
    spans='current total';
    $.each(divs.split(' '),function(i,elemId){self._dom[ elemId ]=Utils.create('galleria-'+elemId);});
    $.each(spans.split(' '),function(i,elemId){self._dom[elemId]=Utils.create('galleria-'+elemId,'span');});
    var keyboard=this._keyboard={
      keys:{'UP':38,'DOWN':40,'LEFT':37,'RIGHT':39,'RETURN':13,'ESCAPE':27,'BACKSPACE':8,'SPACE':32},
      map:{},
      bound:false,
      press:function(e){
        var key=e.keyCode||e.which;
        if(key in keyboard.map&&typeof keyboard.map[key]=='function'){keyboard.map[key].call(self,e);}
      },
      attach:function(map){
        for(var key in map){
          var up=key.toUpperCase();
          if(up in keyboard.keys){keyboard.map[keyboard.keys[up]]=map[key];}
        }
        if(!keyboard.bound){keyboard.bound=true;$doc.bind('keydown',keyboard.press);}
      },
      detach:function(){keyboard.bound=false;$doc.unbind('keydown',keyboard.press);}
    };
    var controls=this._controls={
      0:undef,
      1:undef,
      active:0,
      swap:function(){controls.active=controls.active?0:1;},
      getActive:function(){return controls[controls.active];},
      getNext:function(){return controls[1-controls.active];}
    };
    var carousel=this._carousel={
      next:self.$('thumb-nav-right'),
      prev:self.$('thumb-nav-left'),
      width:0,
      current:0,
      max:0,
      hooks:[],
      update:function(){
        var w=0,h=0,hooks=[0];
        $.each(self._thumbnails,function(i,thumb){
          if(thumb.ready){
            w+=thumb.outerWidth||$(thumb.container).outerWidth(true);
            hooks[i+1]=w;
            h=Math.max(h,thumb.outerHeight||$(thumb.container).outerHeight(true));
          }
        });
        self.$('thumbnails').css({width:w,height:h});
        carousel.max=w;
        carousel.hooks=hooks;
        carousel.width=self.$('thumbnails-list').width();
        carousel.setClasses();
        self.$('thumbnails-container').toggleClass('galleria-carousel',w>carousel.width);
      },
      bindControls:function(){
        carousel.next.bind(CLICK(),function(e){
          e.preventDefault();
          if(self._options.carousel_steps=='auto'){
            for(var i=carousel.current;i<carousel.hooks.length;i++){
              if(carousel.hooks[i]-carousel.hooks[carousel.current]>carousel.width){carousel.set(i-2);break;}
            }
          }
          else{carousel.set(carousel.current+self._options.carousel_steps);}
        });
        carousel.prev.bind(CLICK(),function(e){
          e.preventDefault();
          if(self._options.carousel_steps=='auto'){
            for(var i=carousel.current;i>=0;i--){
              if(carousel.hooks[carousel.current]-carousel.hooks[i]>carousel.width){carousel.set(i+2);break;}
              else if(i==0){carousel.set(0);break;}
            }
          }
          else{carousel.set(carousel.current-self._options.carousel_steps);}
        });
      },
      set:function(i){
        i=Math.max(i,0);
        while(carousel.hooks[i-1]+carousel.width>carousel.max&&i>=0){i--;}
        carousel.current=i;
        carousel.animate();
      },
      getLast:function(i){
        return (i||carousel.current)-1;
      },
      follow:function(i){
        if(i==0||i==carousel.hooks.length-2){carousel.set(i);return;}
        var last=carousel.current;
        while(carousel.hooks[last]-carousel.hooks[carousel.current]<carousel.width&&last<=carousel.hooks.length){last++;}
        if(i-1<carousel.current){carousel.set(i-1);}
        else if(i+2>last){carousel.set(i-last+carousel.current+2);}
      },
      setClasses:function(){
        carousel.prev.toggleClass('disabled',!carousel.current);
        carousel.next.toggleClass('disabled',carousel.hooks[carousel.current]+carousel.width>carousel.max);
      },
      animate:function(to){
        carousel.setClasses();
        var num=carousel.hooks[carousel.current]*-1;
        if(isNaN(num)){return;}
        self.$('thumbnails').animate({left:num},{duration: self._options.carousel_speed,easing:self._options.easing,queue:false});
      }
    };
    var tooltip=this._tooltip={
      initialized:false,
      open:false,
      init:function(){
        tooltip.initialized=true;
        var css='.galleria-tooltip{padding:3px 8px;max-width:50%;background:#ffe;color:#000;z-index:20003;position:absolute;font-size:11px;line-height:1.3' +
        'opacity:0;box-shadow:0 0 2px rgba(0,0,0,.4);-moz-box-shadow:0 0 2px rgba(0,0,0,.4);-webkit-box-shadow:0 0 2px rgba(0,0,0,.4);}';
        Utils.insertStyleTag(css);
        self.$('tooltip').css('opacity',.8);
        Utils.hide(self.get('tooltip'));
      },
      move:function(e){
        var mouseX=self.getMousePosition(e).x,
        mouseY=self.getMousePosition(e).y,
        $elem=self.$('tooltip'),
        x=mouseX,
        y=mouseY,
        height=$elem.outerHeight(true)+1,
        width=$elem.outerWidth(true),
        limitY=height+15;
        var maxX=self.$('container').width()-width-2,
        maxY=self.$('container').height()-height-2;
        if(!isNaN(x)&&!isNaN(y)){
          x+=10;
          y-=30;
          x=Math.max(0,Math.min(maxX,x));
          y=Math.max(0,Math.min(maxY,y));
          if(mouseY<limitY){y=limitY;}
          $elem.css({left:x,top:y});
        }
      },
      bind:function(elem,value){
        if(!tooltip.initialized){tooltip.init();}
        var hover=function(elem,value){
          tooltip.define(elem,value);
          $(elem).hover(function(){
            Utils.clearTimer('switch_tooltip');
            self.$('container').unbind('mousemove',tooltip.move).bind('mousemove',tooltip.move).trigger('mousemove');
            tooltip.show(elem);
            Galleria.utils.addTimer('tooltip',function(){
              self.$('tooltip').stop();
              Utils.show(self.get('tooltip'),400);
              tooltip.open=true;
            },tooltip.open?0:1000);
          },function(){
            self.$('container').unbind('mousemove',tooltip.move);
            Utils.clearTimer('tooltip');
            self.$('tooltip').stop();
            Utils.hide( self.get('tooltip'),200,function(){
              Utils.addTimer('switch_tooltip',function(){tooltip.open=false;},1000);
            });
          });
        };
        if(typeof value=='string'){hover((elem in self._dom?self.get(elem):elem),value);}
        else{$.each(elem,function(elemID,val){hover(self.get(elemID),val);});}
      },
      show:function(elem){
        elem=$(elem in self._dom?self.get(elem):elem);
        var text=elem.data('tt');
        if(!text){return;}
        text=typeof text=='function'?text():text;
        self.$('tooltip').html(text.replace(/\s/,'&nbsp;'));
        elem.bind('mouseup',function(e){
          window.setTimeout((function(ev){return function(){tooltip.move(ev);}})(e),10);
          elem.unbind('mouseup',arguments.callee);
        });
      },
      define:function(elem,value){
        if(typeof value!=='function'){
          var s=value;
          value=function(){return s;};
        }
        elem=$(elem in self._dom?self.get(elem):elem).data('tt',value);
        tooltip.show(elem);
      }
    };
    var fullscreen=this._fullscreen={
      scrolled:0,
      enter:function(callback){
        Utils.hide(self.getActiveImage());
        self.$('container').addClass('fullscreen');
        fullscreen.scrolled=$(window).scrollTop();
        Utils.forceStyles(self.get('container'),{position:'fixed',top:0,left:0,width:'100%',height:'100%',zIndex:20000});
        var htmlbody={height:'100%',overflow:'hidden',margin:0,padding:0};
        Utils.forceStyles(DOM().html,htmlbody);
        Utils.forceStyles(DOM().body,htmlbody);
        self.attachKeyboard({escape:self.exitFullscreen,right:self.next,left:self.prev});
        self.rescale(function(){
          Utils.addTimer('fullscreen_enter',function(){
            Utils.show(self.getActiveImage());
            if(typeof callback=='function'){callback.call(self);}
          },100);
          self.trigger(Galleria.FULLSCREEN_ENTER);
        });
        $(window).resize(function(){fullscreen.scale();});
      },
      scale:function(){self.rescale();},
      exit:function(callback){
        Utils.hide(self.getActiveImage());
        self.$('container').removeClass('fullscreen');
        Utils.revertStyles(self.get('container'),DOM().html,DOM().body);
        window.scrollTo(0,fullscreen.scrolled);
        self.detachKeyboard();
        self.rescale(function(){
          Utils.addTimer('fullscreen_exit',function(){
            Utils.show(self.getActiveImage());
            if(typeof callback=='function'){callback.call(self);}
          },50);
          self.trigger(Galleria.FULLSCREEN_EXIT);
        });
        $(window).unbind('resize',fullscreen.scale);
      }
    };
    var idle=this._idle={
      trunk:[],
      bound:false,
      add:function(elem,to){
        if(!elem){return;}
        if(!idle.bound){idle.addEvent();}
        elem=$(elem);
        var from={};
        for(var style in to){from[style]=elem.css(style);}
        elem.data('idle',{from:from,to:to,complete:true,busy:false});
        idle.addTimer();
        idle.trunk.push(elem);
      },
      remove:function(elem){
        elem=jQuery(elem);
        $.each(idle.trunk,function(i,el){
          if(el.length&&!el.not(elem).length){self._idle.show(elem);self._idle.trunk.splice(i,1);}
        });
        if(!idle.trunk.length){idle.removeEvent();Utils.clearTimer('idle');}
      },
      addEvent:function(){idle.bound=true;self.$('container').bind('mousemove click',idle.showAll);},
      removeEvent:function(){idle.bound=false;self.$('container').unbind('mousemove click',idle.showAll);},
      addTimer:function(){Utils.addTimer('idle',function(){self._idle.hide();},self._options.idle_time);},
      hide:function(){
        self.trigger(Galleria.IDLE_ENTER);
        $.each(idle.trunk,function(i,elem){
          var data=elem.data('idle');
          if(!data){return;}
          elem.data('idle').complete=false;
          elem.stop().animate(data.to,{duration:600,queue:false,easing:'swing'});
        });
      },
      showAll:function(){
        Utils.clearTimer('idle');
        $.each(self._idle.trunk,function(i,elem){self._idle.show(elem);});
      },
      show:function(elem){
        var data=elem.data('idle');
        if(!data.busy&&!data.complete){
          data.busy=true;
          self.trigger(Galleria.IDLE_EXIT);
          Utils.clearTimer('idle');
          elem.stop().animate(data.from,{
            duration:300,
            queue:false,
            easing:'swing',
            complete:function(){$(this).data('idle').busy=false;$(this).data('idle').complete=true;}
          });
        }
        idle.addTimer();
      }
    };
    var lightbox=this._lightbox={
      width:0,
      height:0,
      initialized:false,
      active:null,
      image:null,
      elems:{},
      init:function(){
        self.trigger(Galleria.LIGHTBOX_OPEN);
        if(lightbox.initialized){return;}
        lightbox.initialized=true;
        var elems='overlay box content shadow title info close prevholder prev nextholder next counter image',
        el={},
        op=self._options,
        css='',
        cssMap={
          overlay:'position:fixed;display:none;opacity:'+op.overlay_opacity+';top:0;left:0;width:100%;height:100%;background:'+op.overlay_background+';z-index:99990',
          box:'position:fixed;display:none;width:400px;height:400px;top:50%;left:50%;margin-top:-200px;margin-left:-200px;z-index:99991',
          shadow:'position:absolute;background:#000;width:100%;height:100%;',
          content:'position:absolute;background-color:#fff;top:10px;left:10px;right:10px;bottom:10px;overflow:hidden',
          info:'position:absolute;bottom:10px;left:10px;right:10px;color:#444;font:11px/13px arial,sans-serif;height:13px',
          close:'position:absolute;top:10px;right:10px;height:20px;width:20px;background:#fff;text-align:center;cursor:pointer;color:#444;font:16px/22px arial,sans-serif;z-index:99999',
          image:'position:absolute;top:10px;left:10px;right:10px;bottom:30px;overflow:hidden',
          prevholder:'position:absolute;width:50%;height:100%;cursor:pointer',
          nextholder:'position:absolute;width:50%;height:100%;right:0;cursor:pointer',
          prev:'position:absolute;top:50%;margin-top:-20px;height:40px;width:30px;background:#fff;left:20px;display:none;line-height:40px;text-align:center;color:#000',
          next:'position:absolute;top:50%;margin-top:-20px;height:40px;width:30px;background:#fff;right:20px;left:auto;display:none;line-height:40px;text-align:center;color:#000',
          title:'float:left',
          counter:'float:right;margin-left:8px'
        },
        hover=function(elem){return elem.hover(function(){$(this).css('color','#bbb');},function(){$(this).css('color','#444');});};
        $.each(cssMap,function(key,value){css+='.galleria-lightbox-'+key+'{'+value+'}';});
        Utils.insertStyleTag(css);
        $.each(elems.split(' '),function(i,elemId){
          self.addElement('lightbox-'+elemId);
          el[elemId]=lightbox.elems[elemId]=self.get('lightbox-'+elemId);
        });
        lightbox.image=new Galleria.Picture();
        self.append({
          'lightbox-box':['lightbox-shadow','lightbox-content', 'lightbox-close','lightbox-prevholder','lightbox-nextholder'],
          'lightbox-info':['lightbox-title','lightbox-counter'],
          'lightbox-content':['lightbox-info', 'lightbox-image'],
          'lightbox-prevholder':'lightbox-prev',
          'lightbox-nextholder':'lightbox-next'
        });
        $(el.image).append(lightbox.image.container);
        $(DOM().body).append(el.overlay,el.box);
        hover($(el.close).bind(CLICK(),lightbox.hide).html('&#215;'));
        $.each(['Prev','Next'],function(i,dir){
          var $d=$(el[dir.toLowerCase()]).html(/v/.test(dir)?'‹&nbsp;':'&nbsp;›');
          $(el[dir.toLowerCase()+'holder']).hover(function(){$d.show();
          },function(){$d.fadeOut(200);}).bind(CLICK(),function(){lightbox['show'+dir]();});
        });
        $(el.overlay).bind(CLICK(),lightbox.hide);
      },
      rescale:function(event){
        var width=Math.min($(window).width()-40,lightbox.width),
        height=Math.min($(window).height()-60,lightbox.height),
        ratio=Math.min(width/lightbox.width,height/lightbox.height),
        destWidth=(lightbox.width*ratio)+40,
        destHeight=(lightbox.height*ratio)+60,
        to={width:destWidth,height:destHeight,marginTop:Math.ceil(destHeight/2)*-1,marginLeft:Math.ceil(destWidth/2)*-1};
        if(event){$(lightbox.elems.box).css(to);}
        else{
          $(lightbox.elems.box).animate(
            to,
            self._options.lightbox_transition_speed,
            self._options.easing,
            function(){
              var image=lightbox.image,
              speed=self._options.lightbox_fade_speed;
              self.trigger({type:Galleria.LIGHTBOX_IMAGE,imageTarget:image.image});
              image.show();
              Utils.show(image.image,speed);
              Utils.show(lightbox.elems.info,speed);
            }
          );
        }
      },
      hide:function(){
        lightbox.image.image=null;
        $(window).unbind('resize',lightbox.rescale);
        $(lightbox.elems.box).hide();
        Utils.hide(lightbox.elems.info);
        Utils.hide(lightbox.elems.overlay,200,function(){
          $(this).hide().css('opacity',self._options.overlay_opacity);
          self.trigger(Galleria.LIGHTBOX_CLOSE);
        });
      },
      showNext:function(){lightbox.show(self.getNext(lightbox.active));},
      showPrev:function(){lightbox.show(self.getPrev(lightbox.active));},
      show:function(index){
        lightbox.active=index=typeof index=='number'?index:self.getIndex();
        if(!lightbox.initialized){lightbox.init();}
        $(window).unbind('resize',lightbox.rescale);
        var data=self.getData(index),
        total=self.getDataLength();
        Utils.hide(lightbox.elems.info);
        lightbox.image.load(data.image,function(image){
          lightbox.width=image.original.width;
          lightbox.height=image.original.height;
          $(image.image).css({width:'100.5%',height:'100.5%',top:0,zIndex:99998,opacity:0});
          lightbox.elems.title.innerHTML=data.title;
          lightbox.elems.counter.innerHTML=(index+1)+' / '+total;
          $(window).resize(lightbox.rescale);
          lightbox.rescale();
        });
        $(lightbox.elems.overlay).show();
        $(lightbox.elems.box).show();
      }
    };
    return this;
  };
  Galleria.prototype={
    constructor:Galleria,
    init:function(target,options){
      var self=this;
      _galleries.push(this);
      this._original={target:target,options:options,data:null};
      this._target=this._dom.target=target.nodeName?target:$(target).get(0);
      if(!this._target){Galleria.raise('Target not found.');return;}
      this._options={
        autoplay:false,
        carousel:true,
        carousel_follow:true,
        carousel_speed:400,
        carousel_steps:'auto',
        clicknext:false,
        data_config:function(elem){return {};},
        data_selector:'img',
        data_source:this._target,
        debug:undef,
        easing:'galleria',
        extend:function(options) {},
        height:'auto',
        idle_time:3000,
        image_crop:false,
        image_margin:0,
        image_pan:false,
        image_pan_smoothness:12,
        image_position:'50%',
        keep_source:false,
        lightbox_fade_speed:200,
        lightbox_transition_speed:500,
        link_source_images:true,
        max_scale_ratio:undef,
        min_scale_ratio:undef,
        on_image:function(img,thumb){},
        overlay_opacity:.85,
        overlay_background:'#0b0b0b',
        pause_on_interaction:true,
        popup_links:false,
        preload:2,
        queue:true,
        show:0,
        show_info:true,
        show_counter:true,
        show_imagenav:true,
        thumb_crop:true,
        thumb_event_type:CLICK(),
        thumb_fit:true,
        thumb_margin:0,
        thumb_quality:'auto',
        thumbnails:true,
        transition:'fade',
        transition_initial:undef,
        transition_speed:400,
        width:'auto',
		logo:''
      };
      if(options&&options.debug===true){DEBUG=true;}
      $(this._target).children().hide();
      if(Galleria.theme){this._init();}
      else{
        Utils.addTimer('themeload',function(){Galleria.raise('No theme found.',true);},2000);
        $doc.one(Galleria.THEMELOAD,function(){Utils.clearTimer('themeload');self._init.call(self);});
      }
    },
    _init:function(){
      var self=this;
      if(this._initialized){Galleria.raise('Init failed: Gallery instance already initialized.');return this;}
      this._initialized=true;
      if(!Galleria.theme){Galleria.raise('Init failed: No theme found.');return this;}
      $.extend(true,this._options,Galleria.theme.defaults,this._original.options);
      this.bind(Galleria.DATA,function(){
        this._original.data=this._data;
        this.get('total').innerHTML=this.getDataLength();
        var $container=this.$('container');
        var num={width:0,height:0};
        var testElem=Utils.create('galleria-image');
        Utils.wait({
          until:function(){
            $.each(['width','height'],function(i,m){
              if(self._options[m]&&typeof self._options[m]=='number'){num[m]=self._options[m];}
              else{
                num[m]=Utils.parseValue($container.css(m))||Utils.parseValue(self.$('target').css(m))||$container[m]()||self.$('target')[m]();
              }
            });
            var thumbHeight=function(){return true;};
            if(self._options.thumbnails){
              self.$('thumbnails').append(testElem);
              thumbHeight=function(){return !!$(testElem).height();};
            }
            return thumbHeight()&&num.width&&num.height>50;
          },
          success:function(){
            $(testElem).remove();
            $container.width(num.width);
            $container.height(num.height);
            if(Galleria.WEBKIT){window.setTimeout(function(){self._run();},1);}
            else{self._run();}
          },
          error: function(){Galleria.raise('Width & Height not found.',true);},
          timeout:2000
        });
      });
      var one=false;
      this.bind(Galleria.READY,function(){
        Utils.show(this.get('counter'));
        if(this._options.clicknext){
          $.each(this._data,function(i,data){delete data.link;});
          this.$('stage').css({cursor:'pointer'}).bind(CLICK(),function(e){self.next();});
        }
        if(this._options.carousel){this._carousel.bindControls();}
        if(this._options.autoplay){
          this.pause();
          if(typeof this._options.autoplay=='number'){this._playtime=this._options.autoplay;}
          this.trigger(Galleria.PLAY);
          this._playing=true;
        }
        if(one){
          if(typeof this._options.show=='number'){this.show(this._options.show);}
          return;
        }
        one=true;
        if(Galleria.History){
          Galleria.History.change(function(e){
            var val=parseInt(e.value.replace(/\//,''));
            if(isNaN(val)){window.history.go(-1);}
            else{self.show(val,undef,true);}
          });
        }
        Galleria.theme.init.call(this,this._options);
        this._options.extend.call(this,this._options);
        if(/^[0-9]{1,4}$/.test(HASH)&&Galleria.History){this.show(HASH,undef,true);}
        else{this.show(this._options.show);}
      });
      this.append({
        'info-text':['info-title','info-description','info-author'],
        'info':['info-text'],
        'image-nav':['image-nav-right','image-nav-left'],
        'stage':['images','loader','counter','image-nav'],
        'thumbnails-list':['thumbnails'],
        'thumbnails-container':['thumbnails-list'],
        'container':['stage','thumbnails-container','info','tooltip']
      });
      Utils.hide(this.$('counter').append(this.get('current'),' / ',this.get('total')));
      this.setCounter('&#8211;');
      $.each(new Array(2),function(i){
        var image=new Galleria.Picture();
        $(image.container).css({position:'absolute',top:0,left:0});
        self.$('images').append(image.container);
        self._controls[i]=image;
      });
      this.$('images').css({position:'relative',top:0,left:0,width:'100%',height:'100%'});
      this.$('thumbnails,thumbnails-list').css({position:'relative'});
      this.$('image-nav-right,image-nav-left').bind(CLICK(),function(e){
        if(self._options.clicknext){e.stopPropagation();}
        if(self._options.pause_on_interaction){self.pause();}
        var fn=/right/.test(this.className)?'next':'prev';
        self[fn]();
      });
      $.each(['info','counter','image-nav'],function(i,el){
        if(self._options['show_'+el.replace(/-/,'')]===false){Utils.moveOut(self.get(el));}
      });
      this.load();
      if(!this._options.keep_source&&!IE){this._target.innerHTML='';}
      this.$('target').append(this.get('container'));
      if(this._options.carousel){this.bind(Galleria.THUMBNAIL,function(){this.updateCarousel();});}
      this.bind(Galleria.IMAGE,function(e){this._options.on_image.call(this,e.imageTarget,e.thumbTarget);});
      return this;
    },
    _run:function(){
      var self=this,o=this._options,width=0,height=0,optval=typeof o.thumbnails=='string'?o.thumbnails.toLowerCase():null;
      for(var i=0;this._data[i];i++){
        var thumb,data=this._data[i],$container;
        if(o.thumbnails===true){
          thumb=new Galleria.Picture(i);
          var src=data.thumb||data.image;
          this.$('thumbnails').append(thumb.container);
          $container=$(thumb.container);
          var getStyle=function(prop){
            return doc.defaultView&&doc.defaultView.getComputedStyle?
              doc.defaultView.getComputedStyle(thumb.container,null)[prop]:$container.css(prop);
          };
          thumb.data={width:Utils.parseValue(getStyle('width')),height:Utils.parseValue(getStyle('height')),order:i};
		  $container.css((o.thumb_fit&&o.thumb_crop!==true)?{width:0,height:0}:{width:thumb.data.width,height:thumb.data.height});
          thumb.load(src,function(thumb){
            thumb.scale({
              width:thumb.data.width,
              height:thumb.data.height,
              crop:o.thumb_crop,
              margin:o.thumb_margin,
              complete:function(thumb){
                var top=['left','top'];
                var arr=['Width','Height'];
                $.each(arr,function(i,meassure){
                  var m=meassure.toLowerCase();
                  if((o.thumb_crop!==true||o.thumb_crop==m)&&o.thumb_fit){
                    var css={};
					if(m=='height'){css[m]=100;}
                    else{css[m]=thumb[m];}
                    $(thumb.container).css(css);
                    css={};
                    css[top[i]]=0;
                    $(thumb.image).css(css);
                  }
                  thumb['outer'+meassure]=$(thumb.container)['outer'+meassure](true);
                });
                Utils.toggleQuality(thumb.image,o.thumb_quality===true||(o.thumb_quality=='auto'&&thumb.original.width<thumb.width*3));
                self.trigger({type:Galleria.THUMBNAIL,thumbTarget:thumb.image,index:thumb.data.order});
              }
            });
          });
          if(o.preload=='all'){thumb.add(data.image);}
        }
        else if(optval=='empty'||optval=='numbers'){
          thumb={container:Utils.create('galleria-image'),image:Utils.create('img','span'),ready:true};
          if(optval=='numbers'){$(thumb.image).text(i+1);}
          this.$('thumbnails').append(thumb.container);
          window.setTimeout((function(image,index,container){
            return function(){
              $(container).append(image);
              self.trigger({type:Galleria.THUMBNAIL,thumbTarget:image,index:index});
            }
          })(thumb.image,i,thumb.container),50+(i*20));
        }
        else{thumb={container:null,image:null};}
        $(thumb.container).add(o.keep_source&&o.link_source_images?data.original:null)
          .data('index',i).bind(o.thumb_event_type,function(e){
            if(o.pause_on_interaction){self.pause();}
            var index=$(e.currentTarget).data('index');
            //if(self.getIndex()!==index){
			  self.show(index);
			//}
            e.preventDefault();
        });
        this._thumbnails.push(thumb);
      }
      Utils.wait({
        until:function(){
          self._stageWidth=self.$('stage').width();
          self._stageHeight=self.$('stage').height();
          return(self._stageWidth&&self._stageHeight>50);
        },
        success:function(){self.trigger(Galleria.READY);},
        error:function(){Galleria.raise('stage meassures not found');}
      });
    },
    load:function(source,selector,config){
      var self=this;
      this._data=[];
      this._thumbnails=[];
      this.$('thumbnails').empty();
      if(typeof selector=='function'){config=selector;selector=null;}
      source=source||this._options.data_source;
      selector=selector||this._options.data_selector;
      config=config||this._options.data_config;
      if(source.constructor==Array){
        if(this.validate(source)){this._data=source;this.trigger(Galleria.DATA);}
        else{Galleria.raise('Load failed: JSON Array not valid.');}
        return this;
      }
      $(source).find(selector).each(function(i,img){
        var data={},
        img=$(img),
        parent=img.parent(),
        href=parent.attr('href');
        if(/\.(png|gif|jpg|jpeg)(\?.*)?$/i.test(href)){data.image=href;}
        else if(href){data.link=href;}
        self._data.push( $.extend({
          title:img.attr('title'),thumb:img.attr('src'),image:img.attr('src'),
          description:img.attr('alt'),author:img.attr('name'),link:img.attr('longdesc'),original:img.get(0)
        },data,config(img)));
      });
      if(this.getDataLength()){this.trigger(Galleria.DATA);}
      else{Galleria.raise('Load failed: no data found.');}
      return this;
    },
    _getActive:function(){return this._controls.getActive();},
    validate:function(data){return true;},
    bind:function(type,fn){this.$('container').bind(type,this.proxy(fn));return this;},
    unbind:function(type){this.$('container').unbind(type);return this;},
    trigger:function(type){
      type=typeof type=='object'?$.extend(type,{scope:this}):{type:type,scope:this};
      this.$('container').trigger(type);
      return this;
    },
    addIdleState:function(elem,styles){this._idle.add.apply(this._idle,Utils.array(arguments));return this;},
    removeIdleState:function(elem){this._idle.remove.apply(this._idle,Utils.array(arguments));return this;},
    enterIdleMode:function(){this._idle.hide();return this;},
    exitIdleMode:function(){this.idle._show();return this;},
    enterFullscreen:function(callback){this._fullscreen.enter.apply(this,Utils.array(arguments));return this;},
    exitFullscreen:function(callback){this._fullscreen.exit.apply(this,Utils.array(arguments));return this;},
    bindTooltip:function(elem,value){this._tooltip.bind.apply(this._tooltip,Utils.array(arguments));return this;},
    defineTooltip:function(elem,value){this._tooltip.define.apply(this._tooltip,Utils.array(arguments));return this;},
    refreshTooltip:function(){this._tooltip.show.apply(this._tooltip,Utils.array(arguments));return this;},
    openLightbox:function(){this._lightbox.show.apply(this._lightbox,Utils.array(arguments));return this;},
    closeLightbox:function(){this._lightbox.hide.apply(this._lightbox,Utils.array(arguments));return this;},
    getActiveImage:function(){return this._getActive().image||undef;},
    getActiveThumb:function(){return this._thumbnails[this._active].image||undef;},
    getMousePosition:function(e){return {x:e.pageX-this.$('container').offset().left,y:e.pageY-this.$('container').offset().top};},
    addPan:function(img){
      if(this._options.image_crop===false){return;}
      img=$(img||this.getActiveImage());
      var self=this,
      x=img.width()/2,
      y=img.height()/2,
      curX=destX=parseInt(img.css('left'))||0,
      curY=destY=parseInt(img.css('top'))||0,
      distX=0,
      distY=0,
      active=false,
      ts=Utils.timestamp(),
      cache=0,
      move=0,
      position=function(dist,cur,pos){
        if(dist>0){
          move=Math.round(Math.max(dist*-1,Math.min(0,cur)));
          if(cache!=move){
            cache=move;
            if(IE==8){img.parent()['scroll'+pos](move*-1);}
            else{var css={};css[pos.toLowerCase()]=move;img.css(css);}
          }
        }
      },
      calculate=function(e){
        if(Utils.timestamp()-ts<50){return;}
        active=true;
        x=self.getMousePosition(e).x;
        y=self.getMousePosition(e).y;
      },
      loop=function(e){
        if(!active){return;}
        distX=img.width()-self._stageWidth;
        distY=img.height()-self._stageHeight;
        destX=x/self._stageWidth*distX*-1;
        destY=y/self._stageHeight*distY*-1;
        curX+=(destX-curX)/self._options.image_pan_smoothness;
        curY+=(destY-curY)/self._options.image_pan_smoothness;
        position(distY,curY,'Top');
        position(distX,curX,'Left');
      };
      if(IE==8){img.parent().scrollTop(curY*-1).scrollLeft(curX*-1);img.css({top:0,left:0});}
      this.$('stage').unbind('mousemove',calculate).bind('mousemove',calculate);
      Utils.addTimer('pan',loop,50,true);
      return this;
    },
    proxy:function(fn,scope){
      if(typeof fn!=='function'){return function(){};}
      scope=scope||this;
      return function(){return fn.apply(scope,Utils.array(arguments));};
    },
    removePan:function(){
      if(IE==8){}
      this.$('stage').unbind('mousemove');
      Utils.clearTimer('pan');
      return this;
    },
    addElement:function(id){
      var dom=this._dom;
      $.each(Utils.array(arguments),function(i,blueprint){dom[blueprint]=Utils.create('galleria-'+blueprint);});
      return this;
    },
    attachKeyboard:function(map){this._keyboard.attach.apply(this._keyboard,Utils.array(arguments));return this;},
    detachKeyboard:function(){this._keyboard.detach.apply(this._keyboard,Utils.array(arguments));return this;},
    appendChild :function(parentID,childID){this.$(parentID).append(this.get(childID)||childID);return this;},
    prependChild:function(parentID,childID){this.$(parentID).prepend(this.get(childID)||childID);return this;},
    remove:function(elemID){this.$(Utils.array(arguments).join(',')).remove();return this;},
    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;
    },
    _scaleImage:function(image,options){
      options=$.extend({
        width:this._stageWidth,
        height:this._stageHeight,
        crop:this._options.image_crop,
        max:this._options.max_scale_ratio,
        min:this._options.min_scale_ratio,
        margin:this._options.image_margin,
        position:this._options.image_position
      },options);
     (image||this._controls.getActive()).scale(options);
      return this;
    },
    updateCarousel:function(){this._carousel.update();return this;},
    rescale:function(width,height,complete){
      var self=this;
      if(typeof width=='function'){complete=width;width=undef;}
      var scale=function(){
        var o=self._options;
        self._stageWidth=width||self.$('stage').width();
        self._stageHeight=height||self.$('stage').height();
        self._scaleImage();
        if(self._options.carousel){self.updateCarousel();}
        self.trigger(Galleria.RESCALE);
        if(typeof complete=='function'){complete.call(self);}
      };
      if(Galleria.WEBKIT&&!width&&!height){Utils.addTimer('scale',scale,5);}
      else{scale.call(self);}
      return this;
    },
    refreshImage:function(){
      this._scaleImage();
      if(this._options.image_pan){this.addPan();}
      return this;
    },
    show:function(index,rewind,_history){
      if(index===false||!this._options.queue&&this._queue.stalled){return;}
      index=Math.max(0,Math.min(parseInt(index),this.getDataLength()-1));
      rewind=typeof rewind!='undefined'?!!rewind:index<this.getIndex();
      _history=_history||false;
      if(!_history&&Galleria.History){Galleria.History.value(index.toString());return;}
      this._active=index;
      Array.prototype.push.call(this._queue,{index:index,rewind:rewind});
      if(!this._queue.stalled){this._show();}
      return this;
    },
    _show:function(){
      var self=this,queue=this._queue[0],data=this.getData(queue.index);
      if(!data){return;}
      var src=data.image,
      active=this._controls.getActive(),
      next=this._controls.getNext(),
      cached=next.isCached(src),
      thumb=this._thumbnails[queue.index];
      var complete=function(){
        self._queue.stalled=false;
        Utils.toggleQuality(next.image,self._options.image_quality);
        $(active.container).css({zIndex:0,opacity:0});
        $(next.container).css({zIndex:1,opacity:1});
        self._controls.swap();
        if(self._options.image_pan){self.addPan(next.image);}
        if(data.link){
          $(next.image).css({
            cursor:'pointer'
          }).bind(CLICK(),function(){
            if(self._options.popup_links){var win=window.open(data.link,'_blank');}
            else{window.location.href=data.link;}
          });
        }
        Array.prototype.shift.call(self._queue);
        if(self._queue.length){self._show();}
        self._playCheck();
        self.trigger({type:Galleria.IMAGE,index:queue.index,imageTarget:next.image,thumbTarget:thumb.image});
      };
      if(this._options.carousel&&this._options.carousel_follow){this._carousel.follow(queue.index);}
      if(this._options.preload){
        var p,n=this.getNext();
        try{
          for(var i=this._options.preload;i>0;i--){
            p=new Galleria.Picture();
            p.add(self.getData(n).image);
            n=self.getNext(n);
          }
        }catch(e){}
      }
      Utils.show(next.container);
      $(self._thumbnails[queue.index].container).addClass('active').siblings('.active').removeClass('active');
      self.trigger({type:Galleria.LOADSTART,cached:cached,index:queue.index,imageTarget:next.image,thumbTarget:thumb.image});
      next.load(src,function(next){
        self._scaleImage(next,{
          complete:function(next){
            Utils.show(next.container);
            if('image' in active){Utils.toggleQuality(active.image,false);}
            Utils.toggleQuality(next.image,false);
            self._queue.stalled=true;
            self.removePan();
            self.setInfo(queue.index);
            self.setCounter(queue.index);
            self.trigger({
              type:Galleria.LOADFINISH,
              cached:cached,
              index:queue.index,
              imageTarget:next.image,
              thumbTarget:self._thumbnails[ queue.index ].image
            });
            var transition=active.image===null&&self._options.transition_initial?self._options.transition_initial:self._options.transition;
            if(transition in _transitions===false){complete();self.setOptions('transition','fade');}
            else{
              var params={prev:active.image,next:next.image,rewind:queue.rewind,speed:self._options.transition_speed||400};
              _transitions[transition].call(self,params,complete);
            }
          }
        });
      });
    },
    getNext:function(base){
      base=typeof base=='number'?base:this.getIndex();
      return base==this.getDataLength()-1?0:base+1;
    },
    getPrev:function(base){
      base=typeof base=='number'?base:this.getIndex();
      return base===0?this.getDataLength()-1:base-1;
    },
    next:function(){
      if(this.getDataLength()>1){this.show(this.getNext(),false);}
      return this;
    },
    prev:function(){
      if(this.getDataLength()>1){this.show(this.getPrev(),true);}
      return this;
    },
    get:function(elemId){return elemId in this._dom?this._dom[elemId]:null;},
    getData:function(index){return index in this._data?this._data[index]:this._data[this._active];},
    getDataLength:function(){return this._data.length;},
    getIndex:function(){return typeof this._active==='number'?this._active:false;},
    getStageHeight:function(){return this._stageHeight;},
    getStageWidth:function(){return this._stageWidth;},
    getOptions:function(key){return typeof key=='undefined'?this._options:this._options[key];},
    setOptions:function(key,value){
      if(typeof key=='object'){$.extend(this._options,key);}
      else{this._options[key]=value;}
      return this;
    },
    play:function(delay){
      this._playing=true;
      this._playtime=delay||this._playtime;
      this._playCheck();
      this.trigger(Galleria.PLAY);
      this.$('info-play').removeClass('playing');
      return this;
    },
    pause:function(){
      this._playing=false;
      this.trigger(Galleria.PAUSE);
      this.$('info-play').addClass('playing');
      return this;
    },
    playToggle:function(delay){
      if(this._playing){return this.pause();}
      else{return this.play(delay);}
    },
    isPlaying:function(){return this._playing;},
    _playCheck:function(){
      var self=this,played=0,interval=20,now=Utils.timestamp();
      if(this._playing){
        Utils.clearTimer('play');
        var fn=function(){
          played=Utils.timestamp()-now;
          if(played>=self._playtime&&self._playing){Utils.clearTimer('play');self.next();return;}
          if(self._playing){
            self.trigger({
              type:Galleria.PROGRESS,
              percent:Math.ceil(played/self._playtime*100),
              seconds:Math.floor(played/1000),
              milliseconds:played
            });
            Utils.addTimer('play',fn,interval);
          }
        };
        Utils.addTimer('play',fn,interval);
      }
    },
    setIndex:function(val){this._active=val;return this;},
    setCounter: function( index ) {
      if(typeof index=='number'){index++;}
      else if(typeof index=='undefined'){index=this.getIndex()+1;}
      this.get('current').innerHTML=index;
      if(IE==8){var opacity=this.$('counter').css('opacity');this.$('counter').css('opacity',opacity);}
      return this;
    },
    setInfo:function(index){
      var self=this,data=this.getData(index);
      $.each(['title','description','author'],function(i,type){
        var elem=self.$('info-'+type);
        if(!!data[type]){elem.show().html(data[type]);}
        else{elem.show().html(' ');}
      });
      self.$('info').removeClass('thumbs');
      return this;
    },
    hasInfo:function(index){return true;},
    jQuery:function(str){
      var self=this,ret=[];
      $.each(str.split(','),function(i,elemId){
        elemId=$.trim(elemId);
        if(self.get(elemId)){ret.push(elemId);}
      });
      var jQ=$(self.get(ret.shift()));
      $.each(ret,function(i,elemId){jQ=jQ.add(self.get(elemId));});
      return jQ;
    },
    $:function(){return this.jQuery.apply(this,Utils.array(arguments));}
  };
  $.extend(Galleria,{
    DATA:'g_data',
    READY:'g_ready',
    THUMBNAIL:'g_thumbnail',
    LOADSTART:'g_loadstart',
    LOADFINISH:'g_loadfinish',
    IMAGE:'g_image',
    THEMELOAD:'g_themeload',
    PLAY:'g_play',
    PAUSE:'g_pause',
    PROGRESS:'g_progress',
    FULLSCREEN_ENTER:'g_fullscreen_enter',
    FULLSCREEN_EXIT:'g_fullscreen_exit',
    IDLE_ENTER:'g_idle_enter',
    IDLE_EXIT:'g_idle_exit',
    RESCALE:'g_rescale',
    LIGHTBOX_OPEN:'g_lightbox_open',
    LIGHTBOX_CLOSE:'g_lightbox_close',
    LIGHTBOX_IMAGE:'g_lightbox_image',
    IE9:IE==9,
    IE8:IE==8,
    IE7:IE==7,
    IE6:IE==6,
    IE:!!IE,
    WEBKIT:/webkit/.test(NAV),
    SAFARI:/safari/.test(NAV),
    CHROME:/chrome/.test(NAV),
    QUIRK:(IE&&doc.compatMode&&doc.compatMode=="BackCompat"),
    MAC:/mac/.test( navigator.platform.toLowerCase() ),
    OPERA:!!window.opera,
    IPHONE:/iphone/.test(NAV),
    IPAD:/ipad/.test(NAV),
    ANDROID:/android/.test(NAV),
    TOUCH:!!(/iphone/.test(NAV)||/ipad/.test(NAV)||/android/.test(NAV))
  });
  Galleria.addTheme=function(theme){
    if(!!theme['name']===false){Galleria.raise('No theme name specified');}
    if(typeof theme.defaults!='object'){theme.defaults={};}
    if(typeof theme.css=='string'){
      var css;
      $('script').each(function(i,script){
        var reg=new RegExp('galleria\\.'+theme.name.toLowerCase()+'\\.');
        if(reg.test(script.src)){
          css=script.src.replace(/[^\/]*$/,'')+theme.css;
          Utils.addTimer("css",function(){
            Utils.loadCSS(css,'galleria-theme',function(){Galleria.theme=theme;$doc.trigger(Galleria.THEMELOAD);});
          },1);
        }
      });
      if(!css){Galleria.raise('No theme CSS loaded');}
    }
    else{Galleria.theme=theme;$doc.trigger(Galleria.THEMELOAD);}
    return theme;
  };
  Galleria.loadTheme=function(src,options){
    var loaded=false,
    length=_galleries.length;
    Galleria.theme=undef;
    Utils.loadScript(src,function(){loaded=true;});
    Utils.wait({
      until:function(){return loaded;},
      error:function(){Galleria.raise("Theme at "+src+" could not load, check theme path.",true);},
      success:function(){
        if(length){
          var refreshed=[];
          $.each(Galleria.get(),function(i,instance){
            var op=$.extend(instance._original.options,{data_source:instance._data},options);
            instance.$('container').remove();
            var g=new Galleria();
            g._id=instance._id;
            g.init(instance._original.target,op);
            refreshed.push(g);
          });
          _galleries=refreshed;
        }
      },
      timeout:2000
    });
  };
  Galleria.get=function(index){
    if(!!_galleries[index]){return _galleries[index];}
    else if(typeof index!=='number'){return _galleries;}
    else{Galleria.raise('Gallery index '+index+' not found');}
  };
  Galleria.addTransition=function(name,fn){_transitions[name]=fn;};
  Galleria.utils=Utils;
  Galleria.log=function(){
    try{window.console.log.apply(window.console,Utils.array(arguments));}
    catch(e){
      try{opera.postError.apply(opera,arguments);}
      catch(er){alert(Utils.array(arguments).split(', '));}
    }
  };
  Galleria.raise=function(msg,fatal){
    if(DEBUG||fatal){var type=fatal?'Fatal error':'Error';throw new Error(type+': '+msg);}
  };
  Galleria.Picture=function(id){
    this.id=id||null;
    this.image=null;
    this.container=Utils.create('galleria-image');
    $(this.container).css({overflow:'hidden',position:'relative'});
    this.original={width:0,height:0};
    this.ready=false;
    this.loaded=false;
  };
  Galleria.Picture.prototype={
    cache:{},
    add:function(src){
      var self=this;
      var image=new Image();
      $(image).css('display','block');
      if(self.cache[src]){
        image.src=src;
        self.loaded=true;
        self.original={height:image.height,width:image.width};
        return image;
      }
      image.onload=function(){
        self.original={height:this.height,width:this.width};
        self.cache[src]=src;
        self.loaded=true;
      };
      image.src=src;
      return image;
    },
    show:function(){Utils.show(this.image);},
    hide:function(){Utils.moveOut(this.image);},
    clear:function(){this.image=null;},
    isCached:function(src){return !!this.cache[src];},
    load:function(src,callback){
      var self=this;
      $(this.container).empty(true);
      this.image=this.add(src);
      Utils.hide(this.image);
      $(this.container).append(this.image);
      Utils.wait({
        until:function(){return self.loaded&&self.image.complete&&self.image.width;},
        success:function(){
          window.setTimeout(function(){callback.call(self,self);},50);},
        error:function(){
          window.setTimeout(function(){callback.call(self,self);},50 );
          Galleria.raise('image not loaded in 10 seconds: '+src);
        },
        timeout:10000
      });
      return this.container;
    },
    scale:function(options){
      options=$.extend({
        width:0,height:0,min:undef,max:undef,margin:0,complete:function(){},position:'center',crop:false
      },options);
      if(!this.image){return this.container;}
      var width,height,self=this,
      $container=$(self.container);
      Utils.wait({
        until:function(){
          width=options.width||$container.width()||Utils.parseValue($container.css('width'));
          height=options.height||$container.height()||Utils.parseValue($container.css('height'));
          return width&&height;
        },
        success:function(){
          var newWidth=(width-options.margin*2)/self.original.width,
          newHeight=(height-options.margin*2)/self.original.height,
          cropMap={'true':Math.max(newWidth,newHeight),'width':newWidth,'height':newHeight,'false':Math.min(newWidth,newHeight)},
          ratio=cropMap[options.crop.toString()];
          if(options.max){ratio=Math.min(options.max,ratio);}
          if(options.min){ratio=Math.max(options.min,ratio);}
          $(self.container).width(width).height(height);
          $.each(['width','height'],function(i,m){$(self.image)[m](self[m]=Math.ceil(self.original[m]*ratio));});
          var pos ={},mix={},
          getPosition=function(value,meassure,margin){
            var result=0;
            if(/\%/.test(value)){
              var flt=parseInt(value)/100;
              result=Math.ceil($(self.image)[meassure]()*-1*flt+margin*flt);
            }
            else{result=Utils.parseValue(value);}
            return result;
          },
          positionMap={'top':{top:0},'left':{left:0},'right':{left:'100%'},'bottom':{top:'100%'}};
          $.each(options.position.toLowerCase().split(' '),function(i,value){
            if(value=='center'){value='50%';}
            pos[i?'top':'left']=value;
          });
          $.each(pos,function(i,value){
            if(positionMap.hasOwnProperty(value)){$.extend(mix,positionMap[value]);}
          });
          pos=pos.top?$.extend(pos,mix):mix;
          pos=$.extend({top:'50%',left:'50%'},pos);
          $(self.image).css({
            position:'relative',
            top:getPosition(pos.top,'height',height)-options.margin,
            left:getPosition(pos.left,'width',width)-options.margin
          });
          self.show();
          self.ready=true;
          options.complete.call(self,self);
        },
        error:function(){Galleria.raise('Could not scale image: '+self.image.src);},
        timeout:1000
      });
      return this;
    }
  };
  $.extend($.easing,{
    galleria:function(_,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;
    },
    galleriaIn:function(_,t,b,c,d){return c*(t/=d)*t*t*t+b;},
    galleriaOut:function(_,t,b,c,d){return -c*((t=t/d-1)*t*t*t-1)+b;}
  });
  $.fn.galleria=function(options){
    return this.each(function(){var gallery=new Galleria();gallery.init(this,options);});
  };
  window.Galleria=Galleria;
})(jQuery);
