
var gallery = {
  initialize : function(element, options) {
    this.setOptions( {
      showArrows : true,
      showCarousel : true,
      showInfopane : true,
      embedLinks : true,
      fadeDuration : 500,
      timed : false,
      delay : 9000,
      preloader : true,
      preloaderImage : true,
      preloaderErrorImage : true,
      manualData : [],
      populateFrom : false,
      populateData : true,
      destroyAfterPopulate : true,
      elementSelector : "div.imageElement",
      titleSelector : "h3",
      subtitleSelector : "p",
      linkSelector : "a.open",
      imageSelector : "img.full",
      thumbnailSelector : "img.thumbnail",
      defaultTransition : "fade",
      slideInfoZoneOpacity : 0.7,
      slideInfoZoneSlide : true,
      carouselMinimizedOpacity : 0.4,
      carouselMinimizedHeight : 20,
      carouselMaximizedOpacity : 0.9,
      thumbHeight : 75,
      thumbWidth : 100,
      thumbSpacing : 10,
      thumbIdleOpacity : 0.2,
      textShowCarousel : 'Pictures',
      showCarouselLabel : true,
      thumbCloseCarousel : true,
      useThumbGenerator : false,
      thumbGenerator : 'resizer.php',
      useExternalCarousel : false,
      carouselElement : false,
      carouselHorizontal : true,
      activateCarouselScroller : true,
      carouselPreloader : true,
      textPreloadingCarousel : 'Loading...',
      baseClass : 'jdGallery',
      withArrowsClass : 'withArrows',
      useHistoryManager : false,
      customHistoryKey : false
    }
    , options);
    this.fireEvent('onInit');
    this.currentIter = 0;
    this.lastIter = 0;
    this.maxIter = 0;
    this.galleryElement = element;
    this.galleryData = this.options.manualData;
    this.galleryInit = 1;
    this.galleryElements = Array();
    this.thumbnailElements = Array();
    this.galleryElement.addClass(this.options.baseClass);
    this.populateFrom = element;
    if(this.options.populateFrom)this.populateFrom = this.options.populateFrom;
    if(this.options.populateData)this.populateData();
    element.style.display = "block";
    if(this.options.useHistoryManager)this.initHistory();
    if(this.options.embedLinks) {
      this.currentLink = new Element('a').addClass('open').setProperties( {
        href : 'http://+++',
        title : ''
      }
      ).injectInside(element);
      if((!this.options.showArrows) && (!this.options.showCarousel))this.galleryElement = element = this.currentLink;
      else this.currentLink.setStyle('display', 'none')
        }
    this.constructElements();
    if((this.galleryData.length > 1) && (this.options.showArrows)) {
      var leftArrow = new Element('a').addClass('left').addEvent('click', this.prevItem.bind(this)).injectInside(element);
      var rightArrow = new Element('a').addClass('right').addEvent('click', this.nextItem.bind(this)).injectInside(element);
      this.galleryElement.addClass(this.options.withArrowsClass)
      }
    this.loadingElement = new Element('div').addClass('loadingElement').injectInside(element);
    if(this.options.showInfopane)this.initInfoSlideshow();
    if(this.options.showCarousel)this.initCarousel();
    this.doSlideShow(1)
    }
  ,
  populateData : function() {
    currentArrayPlace = this.galleryData.length;
    options = this.options;
    var a = $A(this.galleryData);
    a.extend(this.populateGallery(this.populateFrom, currentArrayPlace));
    this.galleryData = a;
    this.fireEvent('onPopulated')
    }
  ,
  populateGallery : function(element, startNumber) {
    var data = [];
    options = this.options;
    currentArrayPlace = startNumber;
    element.getElements(options.elementSelector).each(function(el) {
      elementDict = {
        image : el.getElement(options.imageSelector).getProperty('src'),
        number : currentArrayPlace,
        transition : this.options.defaultTransition
        }; elementDict.extend = $extend; if((options.showInfopane) | (options.showCarousel))elementDict.extend( {
        title : el.getElement(options.titleSelector).innerHTML,
        description : el.getElement(options.subtitleSelector).innerHTML
        }
      ); if(options.embedLinks)elementDict.extend( {
        link : el.getElement(options.linkSelector).href || false,
        linkTitle : el.getElement(options.linkSelector).title || false,
        linkTarget : el.getElement(options.linkSelector).getProperty('target') || false
        }
      ); if((!options.useThumbGenerator) && (options.showCarousel))elementDict.extend( {
        thumbnail : el.getElement(options.thumbnailSelector).getProperty('src')
        }
      ); else if(options.useThumbGenerator)elementDict.extend( {
        thumbnail : options.thumbGenerator + '?imgfile=' + elementDict.image + '&max_width=' + options.thumbWidth + '&max_height=' + options.thumbHeight
        }
      ); data.extend([elementDict]); currentArrayPlace++; if(this.options.destroyAfterPopulate)el.remove()
        }
    );
    return data
    }
  ,
  constructElements : function() {
    el = this.galleryElement;
    this.maxIter = this.galleryData.length;
    var currentImg;
    for(i = 0; i < this.galleryData.length; i++) {
      currentImg = new Fx.Styles(new Element('div').addClass('slideElement').setStyles( {
        'position':'absolute',
        'left':'0px',
        'right':'0px',
        'margin':'0px',
        'padding':'0px',
        'backgroundPosition':"center center",
        'opacity':'0'
      }
      ).injectInside(el), 'opacity', {
        duration : this.options.fadeDuration
        }
      );
      if(this.options.preloader) {
        currentImg.source = this.galleryData[i].image;
        currentImg.loaded = false;
        currentImg.load = function(imageStyle) {
          if(!imageStyle.loaded) {
            new Asset.image(imageStyle.source, {
              'onload':function(img) {
                img.element.setStyle('backgroundImage', "url('" + img.source + "')"); img.loaded = true
                }
              .bind(this, imageStyle)
              }
            )
            }
        }
        .pass(currentImg, this)
        }
      else {
        currentImg.element.setStyle('backgroundImage', "url('" + this.galleryData[i].image + "')")
        }
      this.galleryElements[parseInt(i)] = currentImg
      }
  }
  ,
  destroySlideShow : function(a) {
    var b = a.className;
    var c = new Element('div').addClass('myClassName');
    a.parentNode.replaceChild(c, a)
    }
  ,
  startSlideShow : function() {
    this.fireEvent('onStart');
    this.loadingElement.style.display = "none";
    this.lastIter = this.maxIter - 1;
    this.currentIter = 0;
    this.galleryInit = 0;
    this.galleryElements[parseInt(this.currentIter)].set( {
      opacity : 1
    }
    );
    if(this.options.showInfopane)this.showInfoSlideShow.delay(1000, this);
    var a = formatString(this.options.textShowCarousel, this.currentIter + 1, this.maxIter);
    if(this.options.showCarousel && (!this.options.carouselPreloader))this.carouselBtn.setHTML(a).setProperty('title', a);
    this.prepareTimer();
    if(this.options.embedLinks)this.makeLink(this.currentIter)
      }
  ,
  nextItem : function() {
    this.fireEvent('onNextCalled');
    this.nextIter = this.currentIter + 1;
    if(this.nextIter >= this.maxIter)this.nextIter = 0;
    this.galleryInit = 0;
    this.goTo(this.nextIter)
    }
  ,
  prevItem : function() {
    this.fireEvent('onPreviousCalled');
    this.nextIter = this.currentIter - 1;
    if(this.nextIter <=- 1)this.nextIter = this.maxIter - 1;
    this.galleryInit = 0;
    this.goTo(this.nextIter)
    }
  ,
  goTo : function(num) {
    this.clearTimer();
    if(this.options.preloader) {
      this.galleryElements[num].load();
      if(num == 0)this.galleryElements[this.maxIter - 1].load();
      else this.galleryElements[num - 1].load();
      if(num == (this.maxIter - 1))this.galleryElements[0].load();
      else this.galleryElements[num + 1].load()
        }
    if(this.options.embedLinks)this.clearLink();
    if(this.options.showInfopane) {
      this.slideInfoZone.clearChain();
      this.hideInfoSlideShow().chain(this.changeItem.pass(num, this))
      }
    else this.currentChangeDelay = this.changeItem.delay(500, this, num);
    if(this.options.embedLinks)this.makeLink(num);
    this.prepareTimer()
    }
  ,
  changeItem : function(a) {
    this.fireEvent('onStartChanging');
    this.galleryInit = 0;
    if(this.currentIter != a) {
      for(i = 0; i < this.maxIter; i++) {
        if((i != this.currentIter))this.galleryElements[i].set( {
          opacity : 0
        }
        )
        }
      gallery.Transitions[this.galleryData[a].transition].pass([this.galleryElements[this.currentIter], this.galleryElements[a], this.currentIter, a], this)();
      this.currentIter = a
      }
    var b = formatString(this.options.textShowCarousel, a + 1, this.maxIter);
    if(this.options.showCarousel)this.carouselBtn.setHTML(b).setProperty('title', b);
    this.doSlideShow.bind(this)();
    this.fireEvent('onChanged')
    }
  ,
  clearTimer : function() {
    if(this.options.timed)$clear(this.timer)
      }
  ,
  prepareTimer : function() {
    if(this.options.timed)this.timer = this.nextItem.delay(this.options.delay, this)
      }
  ,
  doSlideShow : function(a) {
    if(this.galleryInit == 1) {
      imgPreloader = new Image();
      imgPreloader.onload = function() {
        this.startSlideShow.delay(10, this)
        }
      .bind(this);
      imgPreloader.src = this.galleryData[0].image;
      if(this.options.preloader)this.galleryElements[0].load()
        }
    else {
      if(this.options.showInfopane) {
        if(this.options.showInfopane) {
          this.showInfoSlideShow.delay((500 + this.options.fadeDuration), this)
          }
        else if((this.options.showCarousel) && (this.options.activateCarouselScroller))this.centerCarouselOn(a)
          }
    }
  }
  ,
  createCarousel : function() {
    var carouselElement;
    if(!this.options.useExternalCarousel) {
      var carouselContainerElement = new Element('div').addClass('carouselContainer').injectInside(this.galleryElement);
      this.carouselContainer = new Fx.Styles(carouselContainerElement, {
        transition : Fx.Transitions.expoOut
        }
      );
      this.carouselContainer.normalHeight = carouselContainerElement.offsetHeight;
      this.carouselContainer.set( {
        'opacity':this.options.carouselMinimizedOpacity,
        'top':(this.options.carouselMinimizedHeight - this.carouselContainer.normalHeight)
        }
      );
      this.carouselBtn = new Element('a').addClass('carouselBtn').setProperties( {
        title : this.options.textShowCarousel
        }
      ).injectInside(carouselContainerElement);
      if(this.options.carouselPreloader)this.carouselBtn.setHTML(this.options.textPreloadingCarousel);
      else this.carouselBtn.setHTML(this.options.textShowCarousel);
      this.carouselBtn.addEvent('click', function() {
        this.carouselContainer.clearTimer(); this.toggleCarousel()
        }
      .bind(this));
      this.carouselActive = false;
      carouselElement = new Element('div').addClass('carousel').injectInside(carouselContainerElement);
      this.carousel = new Fx.Styles(carouselElement)
      }
    else {
      carouselElement = $(this.options.carouselElement).addClass('jdExtCarousel')
      }
    this.carouselElement = new Fx.Styles(carouselElement, {
      transition : Fx.Transitions.expoOut
      }
    );
    this.carouselElement.normalHeight = carouselElement.offsetHeight;
    if(this.options.showCarouselLabel)this.carouselLabel = new Element('p').addClass('label').injectInside(carouselElement);
    carouselWrapper = new Element('div').addClass('carouselWrapper').injectInside(carouselElement);
    this.carouselWrapper = new Fx.Styles(carouselWrapper, {
      transition : Fx.Transitions.expoOut
      }
    );
    this.carouselWrapper.normalHeight = carouselWrapper.offsetHeight;
    this.carouselInner = new Element('div').addClass('carouselInner').injectInside(carouselWrapper);
    if(this.options.activateCarouselScroller) {
      this.carouselWrapper.scroller = new Scroller(carouselWrapper, {
        area : 100,
        velocity : 0.2
      }
      );
      this.carouselWrapper.elementScroller = new Fx.Scroll(carouselWrapper, {
        duration : 400,
        onStart : this.carouselWrapper.scroller.stop.bind(this.carouselWrapper.scroller),
        onComplete : this.carouselWrapper.scroller.start.bind(this.carouselWrapper.scroller)
        }
      )
      }
  }
  ,
  fillCarousel : function() {
    this.constructThumbnails();
    this.carouselInner.normalWidth = ((this.maxIter * (this.options.thumbWidth + this.options.thumbSpacing + 2)) + this.options.thumbSpacing) + "px";
    this.carouselInner.style.width = this.carouselInner.normalWidth
    }
  ,
  initCarousel : function() {
    this.createCarousel();
    this.fillCarousel();
    if(this.options.carouselPreloader)this.preloadThumbnails()
      }
  ,
  flushCarousel : function() {
    this.thumbnailElements.each(function(a) {
      a.element.remove(); a = a.element = null
      }
    );
    this.thumbnailElements = []
    }
  ,
  toggleCarousel : function() {
    if(this.carouselActive)this.hideCarousel();
    else this.showCarousel()
      }
  ,
  showCarousel : function() {
    this.fireEvent('onShowCarousel');
    this.carouselContainer.start( {
      'opacity':this.options.carouselMaximizedOpacity,
      'top':0
    }
    ).chain(function() {
      this.carouselActive = true; this.carouselWrapper.scroller.start(); this.fireEvent('onCarouselShown'); this.carouselContainer.options.onComplete = null
      }
    .bind(this))
    }
  ,
  hideCarousel : function() {
    this.fireEvent('onHideCarousel');
    var a = this.options.carouselMinimizedHeight - this.carouselContainer.normalHeight;
    this.carouselContainer.start( {
      'opacity':this.options.carouselMinimizedOpacity,
      'top':a
    }
    ).chain(function() {
      this.carouselActive = false; this.carouselWrapper.scroller.stop(); this.fireEvent('onCarouselHidden'); this.carouselContainer.options.onComplete = null
      }
    .bind(this))
    }
  ,
  constructThumbnails : function() {
    element = this.carouselInner;
    for(i = 0; i < this.galleryData.length; i++) {
      var currentImg = new Fx.Style(new Element('div').addClass("thumbnail").setStyles( {
        backgroundImage : "url('" + this.galleryData[i].thumbnail + "')",
        backgroundPosition : "center center",
        backgroundRepeat : 'no-repeat',
        marginLeft : this.options.thumbSpacing + "px",
        width : this.options.thumbWidth + "px",
        height : this.options.thumbHeight + "px"
        }
      ).injectInside(element), "opacity", {
        duration : 200
      }
      ).set(this.options.thumbIdleOpacity);
      currentImg.element.addEvents( {
        'mouseover':function(a) {
          a.clearTimer(); a.start(0.99); if(this.options.showCarouselLabel)$(this.carouselLabel).setHTML('<span class="number">' + (a.relatedImage.number + 1) + "/" + this.maxIter + ":</span> " + a.relatedImage.title)
            }
        .pass(currentImg, this),
        'mouseout':function(a) {
          a.clearTimer(); a.start(this.options.thumbIdleOpacity)
          }
        .pass(currentImg, this),
        'click':function(a) {
          this.goTo(a.relatedImage.number); if(this.options.thumbCloseCarousel)this.hideCarousel()
            }
        .pass(currentImg, this)
        }
      );
      currentImg.relatedImage = this.galleryData[i];
      this.thumbnailElements[parseInt(i)] = currentImg
      }
  }
  ,
  log : function(a) {
    if(console.log)console.log(a)
      }
  ,
  preloadThumbnails : function() {
    var b = [];
    for(i = 0; i < this.galleryData.length; i++) {
      b[parseInt(i)] = this.galleryData[i].thumbnail
      }
    this.thumbnailPreloader = new Preloader();
    this.thumbnailPreloader.addEvent('onComplete', function() {
      var a = formatString(this.options.textShowCarousel, this.currentIter + 1, this.maxIter); this.carouselBtn.setHTML(a).setProperty('title', a)
      }
    .bind(this));
    this.thumbnailPreloader.load(b)
    }
  ,
  clearThumbnailsHighlights : function() {
    for(i = 0; i < this.galleryData.length; i++) {
      this.thumbnailElements[i].clearTimer();
      this.thumbnailElements[i].start(0.2)
      }
  }
  ,
  changeThumbnailsSize : function(a, b) {
    for(i = 0; i < this.galleryData.length; i++) {
      this.thumbnailElements[i].clearTimer();
      this.thumbnailElements[i].element.setStyles( {
        'width':a + "px",
        'height':b + "px"
        }
      )
      }
  }
  ,
  centerCarouselOn : function(a) {
    if(!this.carouselWallMode) {
      var b = this.thumbnailElements[a];
      var c = b.element.offsetLeft + (b.element.offsetWidth / 2);
      var d = this.carouselWrapper.element.offsetWidth;
      var e = this.carouselInner.offsetWidth;
      var f = d / 2;
      var g = c - f;
      this.carouselWrapper.elementScroller.scrollTo(g, 0)
      }
  }
  ,
  initInfoSlideshow : function() {
    this.slideInfoZone = new Fx.Styles(new Element('div').addClass('slideInfoZone').injectInside($(this.galleryElement))).set( {
      'opacity':0
    }
    );
    var a = new Element('h2').injectInside(this.slideInfoZone.element);
    var b = new Element('p').injectInside(this.slideInfoZone.element);
    this.slideInfoZone.normalHeight = this.slideInfoZone.element.offsetHeight;
    this.slideInfoZone.element.setStyle('opacity', 0)
    }
  ,
  changeInfoSlideShow : function() {
    this.hideInfoSlideShow.delay(10, this);
    this.showInfoSlideShow.delay(500, this)
    }
  ,
  showInfoSlideShow : function() {
    if (this.galleryData[this.currentIter].title.length == 0) {
      return this.slideInfoZone; 
    }
    this.fireEvent('onShowInfopane');
    this.slideInfoZone.clearTimer();
    element = this.slideInfoZone.element;
    element.getElement('h2').setHTML(this.galleryData[this.currentIter].title);
    element.getElement('p').setHTML(this.galleryData[this.currentIter].description);
    if(this.options.slideInfoZoneSlide)this.slideInfoZone.start( {
      'opacity':[0, this.options.slideInfoZoneOpacity],
      'height':[0, this.slideInfoZone.normalHeight]
      }
    );
    else this.slideInfoZone.start( {
      'opacity':[0, this.options.slideInfoZoneOpacity]
      }
    );
    if(this.options.showCarousel)this.slideInfoZone.chain(this.centerCarouselOn.pass(this.currentIter, this));
    return this.slideInfoZone
    }
  ,
  hideInfoSlideShow : function() {
    this.fireEvent('onHideInfopane');
    this.slideInfoZone.clearTimer();
    if(this.options.slideInfoZoneSlide)this.slideInfoZone.start( {
      'opacity':0,
      'height':0
    }
    );
    else this.slideInfoZone.start( {
      'opacity':0
    }
    );
    return this.slideInfoZone
    }
  ,
  makeLink : function(a) {
    if (this.galleryData[a].title.length == 0 || this.galleryData[a].link == false || this.galleryData[a].link.length == 0 || this.galleryData[a].link.indexOf('http://+++')>0) {
     return;
    }
    this.currentLink.setProperties( {
      href : this.galleryData[a].link,
      title : this.galleryData[a].linkTitle
      }
    );
    if(!((this.options.embedLinks) && (!this.options.showArrows) && (!this.options.showCarousel)))this.currentLink.setStyle('display', 'block')
      }
  ,
  clearLink : function() {
    this.currentLink.setProperties( {
      href : '',
      title : ''
    }
    );
    if(!((this.options.embedLinks) && (!this.options.showArrows) && (!this.options.showCarousel)))this.currentLink.setStyle('display', 'none')
      }
  ,
  flushGallery : function() {
    this.galleryElements.each(function(a) {
      a.element.remove(); a = a.element = null
      }
    );
    this.galleryElements = []
    }
  ,
  changeData : function(a) {
    this.galleryData = a;
    this.clearTimer();
    this.flushGallery();
    if(this.options.showCarousel)this.flushCarousel();
    this.constructElements();
    if(this.options.showCarousel)this.fillCarousel();
    if(this.options.showInfopane)this.hideInfoSlideShow();
    this.galleryInit = 1;
    this.lastIter = 0;
    this.currentIter = 0;
    this.doSlideShow(1)
    }
  ,
  initHistory : function() {
    this.fireEvent('onHistoryInit');
    this.historyKey = this.galleryElement.id + '-picture';
    if(this.options.customHistoryKey)this.historyKey = this.options.customHistoryKey();
    this.history = HistoryManager.register(this.historyKey, [1], function(a) {
      if(parseInt(a[0]) - 1 < this.maxIter)this.goTo(parseInt(a[0]) - 1)
        }
    .bind(this), function(a) {
      return[this.historyKey, '(', a[0], ')'].join('')
      }
    .bind(this), this.historyKey + '\\((\\d+)\\)');
    this.addEvent('onChanged', function() {
      this.history.setValue(0, this.currentIter + 1)
      }
    .bind(this));
    this.fireEvent('onHistoryInited')
    }
};
gallery = new Class(gallery);
gallery.implement(new Events);
gallery.implement(new Options);
gallery.Transitions = new Abstract( {
  fade : function(a, b, c, d) {
    a.options.transition = b.options.transition = Fx.Transitions.linear; a.options.duration = b.options.duration = this.options.fadeDuration; if(d > c)b.start( {
      opacity : 1
    }
    ); else {
      b.set( {
        opacity : 1
      }
      ); a.start( {
        opacity : 0
      }
      )
      }
  }
  ,
  crossfade : function(a, b, c, d) {
    a.options.transition = b.options.transition = Fx.Transitions.linear; a.options.duration = b.options.duration = this.options.fadeDuration; b.start( {
      opacity : 1
    }
    ); a.start( {
      opacity : 0
    }
    )
    }
  ,
  fadebg : function(a, b, c, d) {
    a.options.transition = b.options.transition = Fx.Transitions.linear; a.options.duration = b.options.duration = this.options.fadeDuration / 2; a.start( {
      opacity : 0
    }
    ).chain(b.start.pass([ {
      opacity : 1
    }
    ], b))
    }
}
);
var Preloader = new Class( {
  Implements : [Events, Options],
  options : {
    root : '',
    period : 100
  }
  ,
  initialize : function(a) {
    this.setOptions(a)
    }
  ,
  load : function(c) {
    this.index = 0; this.images = []; this.sources = this.temps = c; this.total = this.sources.length; this.fireEvent('onStart', [this.index, this.total]); this.timer = this.progress.periodical(this.options.period, this); this.sources.each(function(a, b) {
      this.images[b] = new Asset.image(this.options.root + a, {
        'onload':function() {
          this.index++; if(this.images[b])this.fireEvent('onLoad', [this.images[b], b, a])
            }
        .bind(this),
        'onerror':function() {
          this.index++; this.fireEvent('onError', [this.images.splice(b, 1), b, a])
          }
        .bind(this),
        'onabort':function() {
          this.index++; this.fireEvent('onError', [this.images.splice(b, 1), b, a])
          }
        .bind(this)
        }
      )
      }
    , this)
    }
  ,
  progress : function() {
    this.fireEvent('onProgress', [Math.min(this.index, this.total), this.total]); if(this.index >= this.total)this.complete()
      }
  ,
  complete : function() {
    $clear(this.timer); this.fireEvent('onComplete', [this.images])
    }
  ,
  cancel : function() {
    $clear(this.timer)
    }
}
);
Preloader.implement(new Events, new Options);
function formatString() {
  var a = arguments.length;
  var b = arguments[0];
  for(var i = 1; i < a; i++) {
    var c = "\\{" + (i - 1) + "\\}";
    var d = new RegExp(c, "g");
    b = b.replace(d, arguments[i])
    }
  return b
  }
