/* DhoniShow Rock Summer, version 2
 *
 * http://dhonishow.de
 *
 * (c) 2009 Stanislav Müller <stanislav@lifedraft.de>
 * Distributed under the terms of an MIT-style license */


(function($){

  $.DhoniShow = function(element, options, index) {
    var _this = jQuery(element);

    /* To avoid double initialization */
    if(element.className.indexOf("dhonishowproceeded") == -1) {
      _this.addClass("dhonishowproceeded");
    } else {
      return;
    }

    var Class = function() {

      var events = {};

      this.share = function(name, property) {
          var ret = _this.data("dhonishow."+name, property);
          return (property != undefined) ? property : ret;
      };

      this.addEventListener = function(event, method) {
          var args = []; for (var i = 2; i < arguments.length; i++) args.push(arguments[i]);

          if(!(event in events)) {
            events[event] = [];
          }

          events[event].push({
            method: method,
            args: args
          });

      };

      this.dispatchEvent = function(event /*, n args */) {
          if(!(event in events)) return false;

          var _args = []; for (var i = 1; i < arguments.length; i++) _args.push(arguments[i]);

          var eventsList = events[event];
          var eventsListLength = eventsList.length;

          for (var i=0; i < eventsListLength; i++) {
            var eventScope = eventsList[i];
            if(arguments.length > 1) { var args = [].concat(eventScope.args).concat(_args); }
            eventScope.method.apply(eventScope.method, args || eventScope.args);
          };
          return true;
      };
    };

    var events = new Class();

    events.share(".dhonishow", _this);
    events.share("current", 0);


    options = options || {};
    if(options.constructor == String) {
      options = new $.DhoniShow.options(options);
    } else {
      options = DhoniShow.mixin({}, options);
    }
    options = events.share("options", DhoniShow.mixin(options, new $.DhoniShow.options(_this.attr("class"))));

    for (var moduleName in DhoniShow.fn) {
      var ModuleInstance = DhoniShow.fn[moduleName];
      ModuleInstance.prototype = DhoniShow.mixin({}, events, ModuleInstance.prototype);
      ModuleInstance.prototype.options = DhoniShow.mixin({}, ModuleInstance.defaults, options[moduleName]);
      new ModuleInstance();
      ModuleInstance = undefined;
    };

    events.dispatchEvent("dhonishow.initialize");
    events.dispatchEvent("trigger.update", 0, 0);
  };

  $.DhoniShow.bind = function(_this, method) {
    return function() {
      return method.apply(_this, arguments);
    };
  };

  $.DhoniShow.mixin = function (root) {
    var isFlat = function(smth){ return (smth.constructor === String || smth.constructor === Number ||
      smth.constructor === Array || smth.constructor === Boolean); };
    var obj = root;

    for (var i=1; i < arguments.length; i++) {
      var extender = arguments[i];

      for(var prop in extender){
        if(!(prop in obj) || isFlat(extender[prop])){ obj[prop] = extender[prop]; continue; }
        obj[prop] = this.mixin(obj[prop], extender[prop]);
      }
    };
    return obj;
  };

  $.DhoniShow.options = function(string) {

    var recognizeValue = function(value) {
      if(value == "true") return true;
      if(value == "false") return false;
      if( value.indexOf("dot") != -1 ) {
        return value = value.split("dot").join(".");
      }
      return value;
    };

    var names = string.toLowerCase().split(" ");

    for(var i = 0; i < names.length; i++) {
      if(names[i].indexOf("_") != -1) {
        var destination = this,
        option = names[i].split("_"),
        value = recognizeValue(option[1]),
        path = option[0],
        name = option[0];

        if(path.indexOf("-") != -1) {
          var path = path.split("-");

          for(var j = 0; j < path.length; j++ ) {
            name = path[j];

            if(!(name in destination)) {
              if(j == path.length-1){
                destination[name] = value;
              } else {
                destination = destination[name] = {};
              }
            } else {
              destination = destination[name];
            }
          }
        } else {
          this[name] = value;
        }
      }
    }

    return;
  };

  $.DhoniShow.contains = function(a, b) {
    /* source: http://ejohn.org/blog/comparing-document-position/ */
    return a.contains ? a != b && a.contains(b) : !!(a.compareDocumentPosition(b) & 16);
  };

  $.DhoniShow.fn = {};


})(window);

(function(){

  var autoplay = DhoniShow.fn.autoplay = function() {
    this.state = "stop";
    this.stepsLeft = 0;

    if(this.options.each) {
      this.addEventListener("preloader.elementsLoaded", DhoniShow.bind(this, this.initialize));
    }
  };

  autoplay.defaults = {
    each: 0,
    random: false,
    iterations: false

    /* in element option
     * autoplay-wait_5
     */
  };

  autoplay.prototype = {

    initialize: function() {
      if(this.options.iterations > 0) {
        this.stepsLeft = this.share("elements").length * this.options.iterations;
      }
      this.addEventListener("trigger.update", DhoniShow.bind(this, this.play), 0, 0);
      
      var wrapper = this.share(".dhonishow"),
          _this = this;

      wrapper.click(function(event) {

        if (jQuery(event.target).hasClass("pause")) {
          _this.stop(true);
          return false;
        };

        if (jQuery(event.target).hasClass("play")) {
          _this.share(".dhonishow").removeClass("dhonishow-stop");
          _this.play();
          return false;
        };

      });
      
      this.cache_wait();
      this.play();
    },

    play: function(fake, each) {
      var _this = this;
      var each = each || this.options.each * 1000;

      this.stop(false);

      var timeout_function = function() {

        _this.share(".dhonishow").removeClass("dhonishow-stop");

        if(_this.stepsLeft > -1 && !fake) _this.stepsLeft--;

        var current = _this.share("current");
        var total = _this.share("elements").length-1;

        if(_this.stepsLeft == 0 || total == 0) {
          _this.stop(false); return;
        }

        if(_this.options.random) {

          var next = Math.round(Math.random() * total);
          if(current == next) { _this.play(true); return; }

          _this.dispatchEvent("trigger.next", next);

        } else {

          if(current == total) {
            _this.dispatchEvent("trigger.next", 0);
          } else {
            _this.dispatchEvent("trigger.next");
          }

        }

        var wait = _this.share("elements")[_this.share("current")].wait;
        if(wait) {
          _this.play(false, wait);
        }
      };


      this.timeout = setTimeout(timeout_function, each);

      return this.state = "play";
    },

    stop: function(hardstop) {
      if (hardstop) {
        this.share(".dhonishow").addClass("dhonishow-stop");
      };

      clearTimeout(this.timeout);
      return this.state = "stop";
    },

    cache_wait: function() {
      var elements = this.share("elements");

      for (var i=0; i < elements.length; i++) {
        var autoplay = new DhoniShow.options(elements[i].element[0].className).autoplay;
        if(autoplay && autoplay.wait) {
          elements[i].wait = autoplay.wait * 1000;
        }
      };

      this.share("elements", elements);
    }
  };

})();

(function(){

  var center = DhoniShow.fn.center = function(parent) {
    this.share("center", this);

    this.max = { width: 0, height: 0 };

    this.addEventListener("preloader.elementsLoaded", DhoniShow.bind(this, this.center));
  };

  center.defaults = {
    elements: true,
    fullwidth: false,
    width: "auto",
    height: "auto",
    container: "fluid"
  };

  center.prototype = {
    center: function() {
      var elements = this.share("elements");

      for (var i=0; i < elements.length; i++) {
        var dimensions = elements[i].dimensions;

        if(!elements[i].center) continue;
        if(this.max.width < dimensions.width) this.max.width = dimensions.width;
        if(this.max.height < dimensions.height) this.max.height = dimensions.height;
      };

      elements.container = this.options.container == "fixed";

      var width;
      if(this.options.fullwidth) {
        width = this.share(".dhonishow").width();
      } else if(this.options.width && this.options.width != "auto") {
        width = this.options.width;
      } else {
        width = this.max.width;
      }

      var height;
      if(this.options.height && this.options.height != "auto") {
        height = this.options.height;
      } else {
        height = this.max.height;
      }

      this.share("width", Number(width));
      this.share("height", Number(height));

      for (var i=0; i < elements.length; i++) {

        if(this.options.elements == true && elements[i].center) {
          elements[i].offsets =
          this.calculateOffsets(width, height, elements[i].dimensions.width, elements[i].dimensions.height);
        } else {
          elements[i].offsets = {};
        }
      }

    },

    calculateOffsets: function(outerWidth, outerHeight, innerWidth, innerHeight) {
      var dimensions = {};

      var offsetWidth = (innerWidth - outerWidth) / 2;
      var offsetHeight = (innerHeight - outerHeight) / 2;

      if(offsetWidth > 0 ) {
        dimensions.paddingLeft = 0;
        dimensions.marginLeft = -offsetWidth;
      } else dimensions.paddingLeft = -offsetWidth;

      if(offsetHeight > 0 ) {
        dimensions.paddingTop = 0;
        dimensions.marginTop = -offsetHeight;
      } else dimensions.paddingTop = -offsetHeight;

      return dimensions;
    }
  };
})();

(function(){

  var effect = DhoniShow.fn.effect = function(parent) {

    var EffectClass = function(){};
    EffectClass.prototype = {
      easing: function(string) {
        if(string == "swing") return "swing";
        if(!jQuery.easing.easeInOutCubic || string == "linear") return "linear";
        return "easeInOut"+string[0].toUpperCase()+(string.substring(1).toLowerCase());
      }
    };

    var EffectInstance = DhoniShow.fn.effect.fn[this.options.name];
    EffectInstance.prototype = DhoniShow.mixin({}, this, new EffectClass(), EffectInstance.prototype);
    EffectInstance.prototype.options = DhoniShow.mixin({}, EffectInstance.defaults, this.options);
    new EffectInstance(this);

    this.addEventListener("effect.update", DhoniShow.bind(this, function(current, next) {

      var _this = this;
      var between = this.options.between*1000;
      var before = this.options.before*1000;
      var duration = this.options.duration*1000;
      var after = this.options.after*1000;

      if(between || before || after) {

        if( between ) {
          this.dispatchEvent("effect.between", current, next, between, "before");
        } else if( before ) {
          this.dispatchEvent("effect.before", current, next, before, "before");
        }

        if( between || before ) {
          setTimeout(function() {
            _this.dispatchEvent("trigger.update", current, next);
            _this.dispatchEvent("effect.change", current, next, duration);
          }, between || before);
        } else {
          this.dispatchEvent("trigger.update", current, next);
          this.dispatchEvent("effect.change", current, next, duration);
        }

        if( between ) {
          setTimeout(function() {
            _this.dispatchEvent("effect.between", current, next, between, "after");
          }, duration);
        } else if (after) {
          setTimeout(function() {
            _this.dispatchEvent("effect.after", current, next, after, "after");
          }, duration);
        }

        return;

      }

      this.dispatchEvent("trigger.update", current, next);
      this.dispatchEvent("effect.change", current, next, duration);

    }));

  };

  effect.defaults = {
    name: "appear",
    duration: 0.6,
    /* Easing Plugin could be included http://gsgd.co.uk/sandbox/jquery/easing/ */
    easing: "linear", /* quad, cubic, quart, quint, sine, expo, circ, elastic, back, bounce */
    between: false,
    before: false,
    after: false
  };


  effect.fn = {};

})();


(function(){

  var accordion = DhoniShow.fn.effect.fn.accordion = function() {
    this.addEventListener("preloader.elementsLoaded", DhoniShow.bind(this, this.center));
    this.addEventListener("effect.change", DhoniShow.bind(this, this.change));
    if(this.options.trigger.enable) {
      this.addEventListener("preloader.elementsLoaded", DhoniShow.bind(this, this.trigger));
    }
  };

  accordion.defaults = {
    barwidth: 20,
    trigger: {
      enable: false,
      event: "click"
    }
  };

  accordion.prototype = {
    trigger: function() {
      var elements = this.share("elements");
      var _this = this;

      jQuery.each(elements, function(index, element) {

        var a = jQuery("<a class='effect-accordion_trigger' title='"+element.description+"'>"+element.description+"</a>");
        element.element.append(a);

        a[_this.options.trigger.event](function() {
          _this.dispatchEvent("trigger.next", index);
        });

      });
    },

    change: function(current, next, duration) {

      var elements = this.share("elements");

      var nextOff = elements[next].offsets;
      var barwidth = this.options.barwidth;
      var width = this.share("width");
      var height = this.share("height");

      elements[current].element.stop(true, true).animate({
        paddingLeft: 0,
        width: barwidth+"px"
      }, duration, this.easing(this.options.easing));

      elements[next].element.animate({
        paddingLeft: (nextOff.paddingLeft || 0),
        width: width - (nextOff.paddingLeft || 0)
      }, duration, this.easing(this.options.easing));

    },

    center: function() {
      var elements = this.share("elements");
      var currenIndex = this.share("current");


      var barwidth = this.options.barwidth;
      var totalElements = elements.length;
      var width = this.share("width");
      var height = this.share("height");
      var totalWidth = ((totalElements - 1) * barwidth) + width;

      this.share(".dhonishow-template-base_elements").css({
        height: height,
        width: totalWidth
      });

      if(elements.container) {
        this.share(".dhonishow").css("width", totalWidth);
      }

      for (var i=0; i < elements.length; i++) {
        elements[i].element.css(elements[i].offsets);

        if(i != currenIndex) {
          elements[i].element.css({
            paddingLeft: 0,
            width: barwidth+"px",
            height: (height - (elements[i].offsets.paddingTop || 0))+"px"
          });
        } else {
          elements[i].element.css({
            width: width+"px",
            height: (height - (elements[i].offsets.paddingTop || 0))+"px"
          });
        }

      }

    }

  };
})();


(function(){

  var appear = DhoniShow.fn.effect.fn.appear = function() {
    this.addEventListener("preloader.elementsLoaded", DhoniShow.bind(this, this.center));
    this.addEventListener("effect.change", DhoniShow.bind(this, this.change));
  };


  appear.prototype = {
    change: function(current, next, duration) {

      var elements = this.share("elements");
      elements[current].element.animate({ opacity: "toggle" }, duration, this.easing(this.options.easing));
      elements[next].element.animate({ opacity: "toggle" }, duration, this.easing(this.options.easing));

    },

    center: function() {
      var elements = this.share("elements");
      var currenIndex = this.share("current");

      this.share(".dhonishow-template-base_elements").css({
        "height": this.share("height"),
        "width": this.share("width")
      });
      
      if(elements.container) {
        // this.share(".dhonishow").css("width", this.share("width"));
      }

      for (var i=0; i < elements.length; i++) {
        elements[i].element.css(elements[i].offsets);
        if(i != currenIndex) elements[i].element.hide();
      }

    }

  };
})();

(function() {
  var btexxmiddle = DhoniShow.fn.effect.fn.btexxmiddle = function() {

    this.addEventListener("preloader.elementsLoaded", DhoniShow.bind(this, this.center));
    this.addEventListener("effect.change", DhoniShow.bind(this, this.change));
  };
  
  btexxmiddle.prototype = {
    change: function(current, next, duration) {

      var elements = this.share("elements");
      elements[current].element.animate({ opacity: "toggle" }, duration, this.easing(this.options.easing));
      elements[next].element.animate({ opacity: "toggle" }, duration, this.easing(this.options.easing));

    },
    
    center: function() {
      
      var elements = this.share("elements");
      var currenIndex = this.share("current");

      this.share(".dhonishow-template-base_elements").css({
         "height": this.share("height") + 40,
         "width": this.share("width")
      });

      if(elements.container) {
        // this.share(".dhonishow").css("width", this.share("width"));
      }

      for (var i=0; i < elements.length; i++) {
        // console.log(elements[i].element);
        // elements[i].element.css(elements[i].offsets);
        if(i != currenIndex) elements[i].element.hide();
      }

    }
  };
  
})();


(function(){

  var frame = DhoniShow.fn.effect.fn.frame = function() {
    this.addEventListener("preloader.elementsLoaded", DhoniShow.bind(this, this.initialize));
    this.addEventListener("effect.change", DhoniShow.bind(this, this.change));

  };

  frame.defaults = {
    cols: 3,
    direction: "fly"
  };

  frame.prototype = {

    initialize: function() {
      this.themehelper = this.share(".dhonishow-template-base_elements").wrapAll("<div class='dhonishow-effect-slide_themehelper'></div>").parent();
      this.offsets = [];
      this.center();
    },

    change: function(current, next, duration) {
      var elements = this.share(".dhonishow-template-base_elements");
      var offsets = this.offsets;
      var easing = this.easing(this.options.easing);

      if(this.options.direction == "fly"){

        elements.animate({
          top: -offsets[next].top,
          left: -offsets[next].left
        }, duration, easing);

      } else {

        elements.animate({
          left: -offsets[next].left
        }, duration, this.easing(this.options.easing), function(){
          elements.animate({
            top: -offsets[next].top
          }, duration, easing);
        });

      }


    },

    center: function() {
      var elements = this.share("elements");
      var currenIndex = this.share("current");
      var cols = this.options.cols;
      var width = this.share("width");
      var height = this.share("height");

      this.themehelper.css({
        width: width,
        height: height
      });

      this.share(".dhonishow-template-base_elements").css({
        width: (cols)*width
      });

      if(elements.container) {
        this.share(".dhonishow").css("width", this.share("width"));
      }

      var left = 0;
      var top = 0;

      for (var i=0; i < elements.length; i++) {
        var element = elements[i];

        element.element.css(element.offsets);
        element.element.css({
          width: width - (element.offsets.paddingLeft || 0),
          height: height - (element.offsets.paddingTop || 0)
        });

        var position = {
          left: left,
          top: top
        };

        left += width;

        if(i % (cols) == 0 && i != 0) {
          element.element.css("clear", "both");
        }

        if((i+1) % (cols) == 0 && (i+1) != 1) {
          left = 0;
          top += height;
        }

        this.offsets.push(position);

      };

    }

  };
})();


(function(){

  var resize = DhoniShow.fn.effect.fn.resize = function(parent) {
    this.addEventListener("preloader.elementsLoaded", DhoniShow.bind(this, this.center));
    this.addEventListener("effect.change", DhoniShow.bind(this, this.change));
  };

  resize.prototype = {

    change: function(current, next, duration) {
      var elements = this.share("elements");

      elements[current].element.animate({ opacity: "toggle" }, duration);
      elements[next].element.animate({ opacity: "toggle" }, duration);

      this.share(".dhonishow-template-base_elements").animate( {
        width: elements[next].dimensions.width,
        height: elements[next].dimensions.height
      }, duration, this.easing(this.options.easing));

      if(elements.container) {
        this.share(".dhonishow").animate({
          "width": elements[next].dimensions.width
        }, duration, this.easing(this.options.easing));
      };

    },

    center: function() {
      var elements = this.share("elements");
      var reversed = [].concat(elements).reverse(); /* Ugly, we want to break the reference */
      var current = this.share("current");

      for (var i=0; i < reversed.length; i++) {
        reversed[i].element.css( "z-index", i + 1 );
        if(i != (reversed.length-1 - current)) reversed[i].element.hide();
      }

      this.share(".dhonishow-template-base_elements").css({
        "width": elements[current].dimensions.width,
        "height": elements[current].dimensions.height
      });

      if(elements.container) {
        this.share(".dhonishow").css("width", elements[current].dimensions.width);
      }
    }

  };
})();


(function(){

  var slide = DhoniShow.fn.effect.fn.slide = function() {
    if(!this.options.direction) this.options.direction = "left";

    this.addEventListener("preloader.elementsLoaded", DhoniShow.bind(this, this.initialize));
    this.addEventListener("preloader.elementsLoaded", DhoniShow.bind(this, this.center));
    this.addEventListener("effect.change", DhoniShow.bind(this, this.change));

  };

  slide.defaults = {
    direction: "left"
  };

  slide.prototype = {
    initialize: function() {

      if(this.options.direction == "left") {
        this.updateHelper = { dimension: "width", side: "left", position: "left", prefix: "" };
      } else if (this.options.direction == "top") {
        this.updateHelper = { dimension: "height", side: "top", position: "top", prefix: ""};
      } else if (this.options.direction == "right") {
        this.updateHelper = { dimension: "width", side: "right", position: "left", prefix: "-" };
      } else if (this.options.direction == "bottom") {
        this.updateHelper = { dimension: "height", side: "bottom", position: "top", prefix: "-" };
      }

      this.themehelper = this.share(".dhonishow-template-base_elements").wrapAll("<div class='dhonishow-effect-slide_themehelper'></div>").parent();
      this.share("effect.slide", this);

    },

    change: function(current, next) {

      var total = this.share("elements").length-1;
      var _this = this;
      var css = {};

      if(total == next && current == 0) {
        css[this.updateHelper.side] = this.share(this.updateHelper.dimension);

        var complete = function(){
          var css = {};
          css[_this.updateHelper.side] = -(_this.share(_this.updateHelper.dimension) * next);
          jQuery(this).css(css);
        };

      } else if(next == 0 && current == total) {
        css[this.updateHelper.side] = -((this.share(this.updateHelper.dimension) * current) + this.share(this.updateHelper.dimension));

        var complete = function() {
          var css = {};
          css[_this.updateHelper.side] = 0;
          jQuery(this).css(css);
        };

      } else {
        css[this.updateHelper.side] = -(this.share(this.updateHelper.dimension) * next);
        var complete = function(){};
      }

      this.share(".dhonishow-template-base_elements").animate(css, this.options.duration*1000, this.easing(this.options.easing), complete);

    },

    center: function() {

      var elements = this.share("elements");

      var dimensions = this.dimensions = {
        width: this.share("width"),
        height: this.share("height")
      };

      if(elements.container) {
        this.share(".dhonishow").css("width", dimensions.width);
      };


      var dimensionsWrapperCSS = {};
      if(this.updateHelper.dimension == "width") {
        dimensionsWrapperCSS.width = dimensions.width*elements.length;
        dimensionsWrapperCSS.height = dimensions.height;
      } else {
        dimensionsWrapperCSS.width = dimensions.width;
        dimensionsWrapperCSS.height = dimensions.height*elements.length;
      }

      this.share(".dhonishow-template-base_elements").css(dimensionsWrapperCSS);
      this.themehelper.css({width: dimensions.width, height: dimensions.height});

      var currenIndex = this.share("current");
      var offset = 0;

      for (var i=0; i < elements.length; i++) {
        var css = {
          paddingLeft: elements[i].offsets.paddingLeft,
          paddingTop: elements[i].offsets.paddingTop,
          marginLeft: elements[i].offsets.marginLeft,
          marginTop: elements[i].offsets.marginTop
        };
        css[this.updateHelper.position] = (this.updateHelper.prefix == "-") ? -offset : offset;
        css.width = dimensions.width - (css.paddingLeft || 0);
        elements[i].element.css(css);
        offset += dimensions[this.updateHelper.dimension];
      };

      if(this.options.endless) {
        var first = elements[0].element.clone();
        elements[elements.length-1].element.after(first);
        first.css(this.updateHelper.position, (this.updateHelper.prefix == "-") ? -offset : offset);

        var last = elements[elements.length-1].element.clone();
        elements[0].element.before(last);
        last.css(this.updateHelper.position, (this.updateHelper.prefix == "-") ? dimensions[this.updateHelper.dimension] : -dimensions[this.updateHelper.dimension]);
      }

    }
  };

})();


(function(){

  var gestures = DhoniShow.fn.gestures = function() {
    this.addEventListener("preloader.elementsLoaded", DhoniShow.bind(this, this.initialize));
  };

  gestures.defaults = {
    enable: false
  };

  gestures.prototype = {
    initialize: function() {

      var effectSlide = this.share("effect.slide");

      if(!effectSlide || !this.options.enable) return;

      this.width = this.share("width");
      this.height = this.share("height");
      this.origin = 0;
      this.startX = 0;
      this.startY = 0;

      this.direction = effectSlide.options.direction;

      if(navigator.userAgent.indexOf("iPhone") != -1) {
        this.iphone();
      } else {
        this.desktop();
      }
    },

    touchstart: function(startX, startY){ // mousedown
      this.moving = false;
      this.startX = startX;
      this.startY = startY;

      if(isNaN(this.origin = Number(this.share(".dhonishow-template-base_elements").css(this.direction).split("px")[0])))
        this.origin = 0;

      this.dispatchEvent("gestures.start", startX, startY);
      return false;
    },

    touchmove: function(endX, endY){ // mousemove
      this.moving = true;
      this.endX = endX;
      this.endY = endY;
      var elements = this.share(".dhonishow-template-base_elements");
      var offset;

      switch(this.direction) {
        case "left":
          offset = this.origin+(this.endX-this.startX);
        break;
        case "top":
          offset = this.origin+(this.endY-this.startY);
        break;
        case "right":
          offset = this.origin+(this.startX-this.endX);
        break;
        case "bottom":
          offset = this.origin+(this.startY-this.endY);
        break;
      }

      elements.css(this.direction, offset);
      this.dispatchEvent("gestures.move", this.direction, offset);

      return false;
    },

    touchend: function(){ // mouseup
      if(!this.moving) return;
      this.moving = false;
      var offsetX = this.endX-this.startX;
      var offsetY = this.endY-this.startY;

      var factorX = this.width/16;
      var factorY = this.height/16;

      if(offsetX < 0) offsetX = -offsetX;
      if(offsetY < 0) offsetY = -offsetY;

      var ret = false;
      var next = false;
      var previous = false;

      if(this.direction == "left" || this.direction == "right") {

        if(this.endX < this.startX && offsetX >= factorX) {
          /* right to left */
          this.direction == "left" ? next = true : previous = true;
        } else if(offsetX >= factorX) {
          /* left to right */
          this.direction == "right" ? next = true : previous = true;
        }

      }

      if(this.direction == "top" || this.direction == "bottom") {
        if(this.endY < this.startY && offsetY >= factorY) {
          /* top to bottom */
          this.direction == "top" ? next = true : previous = true;
        } else if(offsetY >= factorY) {
          /* bottom to top */
          this.direction == "bottom" ? next = true : previous = true;
        }
      }

      if(next) {
        ret = this.next();
      } else if(previous) {
        ret = this.previous();
      }

      if(!ret || ret == undefined) {
        var animate = {};
        animate[this.direction] = this.origin;
        this.share(".dhonishow-template-base_elements").animate(animate, 200);
      }

      this.startX = 0;
      this.startY = 0;
    },

    next: function() {
      var endless = this.share("trigger").options.endless;
      var current = this.share("current");
      var total = this.share("elements").length-1;

      if(current+1 <= total){
        return this.dispatchEvent("trigger.next");
      } else {
        return false;
      }
    },
    previous: function() {
      var endless = this.share("trigger").options.endless;
      var current = this.share("current");
      if(current-1 >= 0){
        return this.dispatchEvent("trigger.previous");
      } else {
        return false;
      }
    },

    iphone: function() {
      var _this = this;
      var element = this.share(".dhonishow")[0];

      element.ontouchstart = function(event) {
        if(event.touches.length == 1) {
          var target = event.touches[0];
          return _this.touchstart(target.pageX, target.pageY);
        }
      };

      element.ontouchmove = function(event) {
        if(event.touches.length == 1) {
          _this.touchmove(event.touches[0].pageX, event.touches[0].pageY);
        }
      };

      element.ontouchend = function(event) {
        _this.touchend();
      };
    },

    desktop: function() {

      var element = this.share(".dhonishow");
      var _this = this;
      var active = false;

      element.bind("mousedown.dhonishow", function(event){
        active = true;
        return _this.touchstart(event.pageX, event.pageY);
      });

      element.bind("mousemove.dhonishow", function(event){
        if(active) {
          return _this.touchmove(event.pageX, event.pageY);
        }
      });

      element.bind("mouseout.dhonishow", function(event){
        if(active) jQuery(this).trigger("mouseup");
      });

      element.bind("mouseup.dhonishow", function(event){
        if(active){
          active = false;
          _this.touchend();
        }
      });

    }
  };

})();

(function() {

  var inelementoptions = DhoniShow.fn.inelementoptions = function() {
    this.addEventListener("template.base.ready", DhoniShow.bind(this, this.initialize));
  };

  inelementoptions.prototype = {
    initialize: function() {
      var elements = this.share("elements");

      for (var i=0; i < elements.length; i++) {
        var element = elements[i];

      };
    }
  };

})();

jQuery.fn.dhonishow = function(options) {
  return jQuery.each(this, function(index) {
    new DhoniShow(this, options, index);
  });
};


jQuery.fn.flickrdhonishow = function(){
  return this.each(function(index){
    var element = jQuery(this);
    var href = element.find("link[rel=flickrdhonishow]").attr("href");
    var functionName = "flickrdhonishow_"+index;
    var data = {};

    window[functionName] = function(json) {
      data = json;
      buildDom();
    };

    jQuery.getScript(href+"&format=json&jsoncallback="+functionName);

    var buildDom = function() {
      element.text("");

      var items = data.items;
      for (var i=0; i < items.length; i++) {
        var item = items[i];
        element.append('<a href="'+item.link+'" title="'+item.title+'"><img src="'+item.media.m+'" title="'+item.title+'"/></a>');
      };

      element.removeClass("flickrdhonishow").addClass("dhonishow").dhonishow();
    };

  });
};


(function() {

  var keyboard = DhoniShow.fn.keyboard = function(){
    if(!this.options.enable) return;

    this.addEventListener("preloader.elementsLoaded", DhoniShow.bind(this, this.initialize));
  };

  keyboard.defaults = {
    enable: true
  };

  keyboard.prototype = {
    initialize: function() {

      var element = this.share(".dhonishow")[0];
      var _this = this;

      this.keyboardActive = false;

      jQuery("body").live("click.dhonishow_keyboard", function(event) {
        _this.keyboardActive = DhoniShow.contains(element, event.target);
      });

      jQuery(document).bind("keyup", function(event) {
        if(!_this.keyboardActive) return;

        switch(event.keyCode) {
          case 37: /* left */
            _this.dispatchEvent("trigger.previous");
          break;
          case 39: /* right */
            _this.dispatchEvent("trigger.next");
          break;
        }

        event.stopPropagation();
        event.preventDefault();
        return false;
      });

    }
  };

})();


(function() {

  var preloader = DhoniShow.fn.preloader = function() {
    this.addEventListener("preloader.elementLoaded", DhoniShow.bind(this, this.elementLoaded));
    this.addEventListener("preloader.elementsLoaded", DhoniShow.bind(this, this.elementsLoaded));
    this.addEventListener("template.ready", DhoniShow.bind(this, this.templateReady));

  };

  preloader.prototype = {
    templateReady: function() {
      var _this = this;

      this.fixWidth();
      this.createLoading();
      this.loadedElements = this.share("elements").length;

      jQuery.each(this.share("elements"), function(index, element) {

        var domElement = jQuery(element.element);
        element.children = [];

        var childrenElements = domElement.find("*").length;

        var images = domElement.find("img");
        var allImagesLoaded = 0;

        element.center = domElement.find(".center-element_false").length ? false : true;

        if(images.length > 0) {

          element.dimensions = {};

          if(childrenElements != images.length) {
            domElement.addClass("dhonishow-template-base_image-text-element");
          } else {
            domElement.addClass("dhonishow-template-base_image");
          }

          for (var i=0; i < images.length; i++) {
            element.children[i] = {
              width: 0,
              height: 0,
              image: images[i]
            };

            if(images[i].width > 0 && images[i].height > 0) {
              _this.dispatchEvent("preloader.elementLoaded", images.length-1, allImagesLoaded++, images[i], i, index);
            } else {
              var src = images[i].src;
              images[i].src = "";
              var imageIndex = i;
              images[i].onload = function() {
                _this.dispatchEvent("preloader.elementLoaded", images.length-1, allImagesLoaded++, this, imageIndex, index);
              };

              images[i].src = src;
            }
          }

        } else {

          domElement.addClass("dhonishow-template-base_text-element");
          element.dimensions = {
            width: domElement.width(),
            height: domElement.height()
          };

          _this.loadedTextElement(index);

        }
      });
    },

    elementLoaded: function(totalImages, loadedImages, image, currentImageIndex, currentElementIndex) {
      var dimensions = this.share("elements");

      dimensions[currentElementIndex].children[currentImageIndex] = {
        width: image.width,
        height: image.height
      };

      var wrapperElement = dimensions[currentElementIndex].element;

      dimensions[currentElementIndex].dimensions = {
        width: wrapperElement.width(),
        height: wrapperElement.height()
      };

      this.share("elements", dimensions);

      if(totalImages == loadedImages) {
        this.loadedElements--;

        if(this.loadedElements <= 0) {
          this.dispatchEvent("preloader.elementsLoaded");
        }
      }
    },

    loadedTextElement: function(index) {
      this.loadedElements--;

      if(this.loadedElements <= 0) {
        this.dispatchEvent("preloader.elementsLoaded");
      }
    },

    createLoading: function() {
      this.loading = this.share(".dhonishow").prev('.dhonishow-module_preloader');
    },

    fixWidth: function() {
      var parent = this.share(".dhonishow").parent();

      var width = /\d*/.exec(parent.css("width"));
      var paddingLeft = /\d*/.exec(parent.css("padding-left"));
      var paddingRight = /\d*/.exec(parent.css("padding-right"));

      this.share(".dhonishow").width(width - paddingLeft - paddingRight);
    },

    elementsLoaded: function() {

      if(this.loading) {
        this.loading.fadeOut(1000);
      }

      this.share(".dhonishow").css({
        position: "relative",
        top: 0,
        left: 0,
        width: ""
      });

    }
  };

})();


(function(){

  var template = DhoniShow.fn.template = function(parent) {

    var TemplateClass = function() {};

    TemplateClass.prototype = {

      placeholders: function() {
        var modulePlaceholders = {};
        var moduleName = this._moduleName;
        this.template = this.template().replace(/@(\w*)/g, function(searchResultWithExpression, searchResult){
          modulePlaceholders[searchResult] = "dhonishow-template-"+moduleName+"_"+searchResult;
          return '<span class="'+modulePlaceholders[searchResult]+'"></span>';
        });
        return this._modulePlaceholders = modulePlaceholders;
      },

      invokeModules: function() {
        for(var module in this._modulePlaceholders)
          this[module](this.giveModluePlaceholder(module));
      },

      giveModluePlaceholder: function(name) {
        return this.share(".dhonishow").find("."+this._modulePlaceholders[name]);
      }
    };


    this.addEventListener("dhonishow.initialize", DhoniShow.bind(this, function() {

      var Class = new TemplateClass();

      for(var module in DhoniShow.fn.template.fn) {
        var ModuleInstance = DhoniShow.fn.template.fn[module];
        ModuleInstance.prototype = DhoniShow.mixin({}, this, Class, ModuleInstance.prototype, { _moduleName: module });
        ModuleInstance.prototype.options = DhoniShow.mixin({}, ModuleInstance.defaults, this.options);
        new ModuleInstance();
      }

      this.dispatchEvent("template.initialize");
      this.dispatchEvent("template.ready");

    }));
  };


  template.fn = {};

})();

(function(){

  var base = DhoniShow.fn.template.fn.base = function(parent) {
    this.addEventListener("template.initialize", DhoniShow.bind(this, this.initialize));
  };

  base.prototype = {
    initialize: function() {
      var element = this.share(".dhonishow");
      var tagName = element[0].tagName;
      var classNames = element[0].className;
      var id = element[0].id;
      var elements = [];

      if(tagName == "OL") {

        if(id) { id = ' id="'+id+'"'; element.removeAttr("id");}

        var newParent = jQuery("<div class='"+classNames+"'"+id+"></div>");
        element.wrap(newParent);
        elements = element.children();

        jQuery.each(elements, function(){
          this.firstChild.className += " "+this.className;
        });

        elements.addClass("dhonishow-template-base_element");
        element[0].className = "dhonishow-template-base_elements";
        this.share(".dhonishow", element.parent());

      } else {

        elements = this.share(".dhonishow").children().wrap("<li></li>").each(function(){
          this.parentNode.className += this.className;
        }).parent();
        elements.wrapAll('<div class="dhonishow-template_base"><ol class="dhonishow-template-base_elements"></ol></div>');

      }

      this.share(".dhonishow-template-base_elements", this.share(".dhonishow").find(".dhonishow-template-base_elements"));
      this.setElements(elements);

      this.dispatchEvent("template.base.ready");
    },

    setElements: function(elements) {

      var domElements = [];
      for (var i=0; i < elements.length; i++) {
        domElements.push({ element: jQuery(elements[i]) });
      };

      this.share("elements", domElements);
    }
  };

})();

(function(){

  var navigation = DhoniShow.fn.template.fn.navigation = function(parent) {
    this.addEventListener("template.base.ready", DhoniShow.bind(this, this.initialize));
  };

  DhoniShow.fn.template.fn.navigation.pagingDelimiter = "/";

  navigation.prototype = {
    initialize: function() {

      this.placeholders();
      this.share(".dhonishow").append(this.template);

      this.addEventListener("trigger.update", DhoniShow.bind(this, this.current), this.share("template.navigation.current", this.giveModluePlaceholder("current")));
      this.addEventListener("trigger.update", DhoniShow.bind(this, this.allpages), this.share("template.navigation.allpages", this.giveModluePlaceholder("allpages")));
      this.addEventListener("trigger.update", DhoniShow.bind(this, this.description), this.share("template.navigation.description", this.giveModluePlaceholder("description")));
      this.addEventListener("trigger.update", DhoniShow.bind(this, this.next), this.share("template.navigation.next", this.share(".dhonishow").find(".next")));
      this.addEventListener("trigger.update", DhoniShow.bind(this, this.previous), this.share("template.navigation.previous", this.share(".dhonishow").find(".previous")));
      this.cache_description();

      this.dispatchEvent("template.navigation.ready");
    },

    template: function(){ return '<div class="dhonishow-template-navigation"> \
        <p class="dhonishow-template-navigation_wrapper-description">@description</p> \
        <div class="dhonishow-template-navigation_paging-buttons"> \
          <div class="dhonishow-template-navigation_theme-helper"> \
            <a class="next dhonishow-template-navigaton_next-button" title="Next"><span>Next</span></a> \
            <p class="dhonishow-template-navigation_paging">@current'+DhoniShow.fn.template.fn.navigation.pagingDelimiter+'@allpages</p> \
            <a class="previous dhonishow-template-navigaton_previous-button" title="Previous"><span>Previous</span></a> \
          </div> \
        </div> \
      </div>';},

    current: function(placeholder) {
      placeholder.text(this.share("current")+1);
    },

    allpages: function(placeholder) {
      placeholder.text(this.share("elements").length);
    },

    cache_description: function() {
      var elements = this.share("elements");
      var description, alt, title;

      for (var i=0; i < elements.length; i++) {
        var description = elements[i].element.find(".description");
        if(description.length) {
          elements[i].description = description.html();
          description.remove();
          description = undefined;
          continue;
        }

        var alt = elements[i].element.find("*[alt]");
        if(alt.length) {
          elements[i].description = alt.attr("alt");
          alt = undefined;
          continue;
        }

        var title = elements[i].element.find("*[title]");
        if(title.length) {
          elements[i].description = title.attr("title");
          title = undefined;
          continue;
        }

        elements[i].description = i + 1;
      };

      this.share("elements", elements);
    },

    description: function(placeholder) {
      placeholder.html(this.share("elements")[this.share("current")].description);
    },

    previous: function(placeholder, current, next) {
      var options = this.share("options");
      var endless = false;
      if(options.trigger && options.trigger.endless) {
        endless = true;
      }

      if(!endless && (next == 0 || next == undefined)) {
        placeholder.addClass("dhonishow-template-navigaton-previous-button_disabled");
      } else {
        placeholder.removeClass("dhonishow-template-navigaton-previous-button_disabled");
      }
    },

    next: function(placeholder, current, next) {
      var options = this.share("options");
      var endless = false;
      if(options.trigger && options.trigger.endless) {
        endless = true;
      }

      if(!endless && this.share("elements").length-1 == next) {
        placeholder.addClass("dhonishow-template-navigaton-next-button_disabled");
      } else {
        placeholder.removeClass("dhonishow-template-navigaton-next-button_disabled");
      }
    }
  };

})();

(function(){

  var thumbnails = DhoniShow.fn.thumbnails = function(parent) {
    if(this.options.show) {
      this.addEventListener("preloader.elementsLoaded", DhoniShow.bind(this, this.elementsLoaded));
      this.addEventListener("effect.change", DhoniShow.bind(this, this.update));
    }
  };

  thumbnails.defaults = {
    cols: 4,
    gap: 10,
    height: 0,
    show: false,
    position: "after",
    center: true,
    style: true,
    prepend: false
  };

  thumbnails.prototype = {
    elementsLoaded: function() {
      this.elements = this.share("elements");

      this.ol = jQuery("<ol class='dhonishow-module_thumbnails'></ol>");
      this.wrapper = jQuery("<div class='dhonishow-module-thumbnails_wrapper'></div>");
      this.share(".dhonishow").find(".dhonishow-template-base_elements")[this.options.position](this.wrapper);
      this.wrapper.append(this.ol);

      this.insertElements();
      this.addEventListeners();
      this.update(this.share("current"), this.share("current"));
      
      if(this.options.prepend) {
        this.ol.before('<h2>Bilder:</h2>');
      }
    },

    insertElements: function() {

      this.thumbnails = [];
      var dimension = (this.share("width") - (this.options.gap * (this.options.cols - 1))) / this.options.cols;

      var cols = this.options.cols;
      
      this.ol.append("<li class='dhonishow_module_autoplay_play'><a rel='next' class='play'><span>Play</span></a></li>");
      this.ol.append("<li class='dhonishow_module_autoplay_pause'><a rel='next' class='pause'><span>Pause</span></a></li>");
      

      for (var i=0; i < this.elements.length; i++) {

        var thumb = this.get_thumb(this.elements[i].element);
        var element = this.thumbnails[i] = jQuery("<li></li>");
        var a = jQuery("<a rel='"+i+"' class='dhonishow_change'>"+(i+1)+"</a>");

        element.append(a);

        if(this.options.center) {
          var offsets = this.share("center").calculateOffsets(dimension, dimension, this.elements[i].dimensions.width, this.elements[i].dimensions.height);
          element.children().css(offsets);
        }

        this.ol.append(element);
        var dimensions = this.elements[i].dimensions;

        if(this.options.style) {

          element.css({
            width: dimension,
            height: Number(this.options.height) || dimension,
            marginBottom: this.options.gap + "px",
            padding: 0,
            left: 0,
            top: 0,
            display: "block",
            marginRight: ((i+1) % cols != 0) ? this.options.gap + "px" : 0,
            clear: (i % cols == 0 && i != 0) ? "both" : ""
          });

        }

      };

    },

    addEventListeners: function() {
      var _this = this;
      this.wrapper.find("a.dhonishow_change").bind("click.dhonishow", function(event) {
        var rel = jQuery(this).attr("rel");
        _this.dispatchEvent("trigger.next", Number(rel));
        
        return false;
      });
    },

    get_thumb: function(element) {
      var clone = element.children().clone();
      var thumb = clone.filter(".dhonishow-thumbnail");
      if(thumb.length) {
        return thumb;
      }
      
      thumb = clone.find(".dhonishow-thumbnail");
      if(thumb.length) {
        return thumb;
      }

      return clone;
    },

    update: function(current, next) {
      this.thumbnails[current].removeClass("thumbnail_active");
      this.thumbnails[next].addClass("thumbnail_active");
    }
  };
})();

(function() {

  var trigger = DhoniShow.fn.trigger = function(parent) {
    this.addEventListener("preloader.elementsLoaded", DhoniShow.bind(this, this.addListeners));
    this.addEventListener("trigger.next", DhoniShow.bind(this, this.next), {});
    this.addEventListener("trigger.previous", DhoniShow.bind(this, this.previous), {});
    this.share("trigger", this);
  };

  trigger.defaults = {
    endless: false
  };


  trigger.prototype = {

    addListeners: function() {
      var element = this.share(".dhonishow");

      this.bind(".next", "click.dhonishow", DhoniShow.bind(this, this.next));
      this.bind(".previous", "click.dhonishow", DhoniShow.bind(this, this.previous));
      this.bind(".goto", "click.dhonishow", DhoniShow.bind(this, this.go_to));
    },

    next: function(event, next) {
      var current = this.share("current");
      var total = this.share("elements").length;

      if(next && next.constructor != String || next == 0) {
        next = next;
      } else if(!(current+1 < total) && this.options.endless) {
        next = 0;
      } else if (current+1 < total) {
        next = current+1;
      }

      if((current == next) || next == undefined) return false;
      var next = this.share("current", next);
      this.dispatchEvent("effect.update", current, next);
      return true;
    },

    previous: function(event, next) {
      var current = this.share("current");
      var total = this.share("elements").length;

      if(next && next.constructor != String || next == 0) {
        next = next;
      } else if(!(current > 0) && this.options.endless) {
        next = total-1;
      } else if(current > 0) {
        next = current-1;
      }

      if((current == next) || next == undefined) return false;
      var next = this.share("current", next);
      this.dispatchEvent("effect.update", current, next);
      return true;
    },

    go_to: function(event) {
      var next = jQuery(event.target).attr("rel") - 1;
      this.next(event, next);
      return false;
    },

    bind: function(selector, event, func) {
      var element = this.share(".dhonishow");

      element.find(selector).bind(event, function(e) {
        e.target = this;
        func(e);
      });
    }

  };

})();


(function() {
  
  var slider = DhoniShow.fn.slider = function(parent) {
    if (this.options.enabled) {
      this.addEventListener("preloader.elementsLoaded", DhoniShow.bind(this, this.loaded));
      
    };
  };
  
  slider.defaults = {
    enabled: false
  };
  
  slider.prototype = {
    loaded: function() {
      var _this = this;
      var elements = this.share("elements");
      
      var wrapper = this.share(".dhonishow");
      
      wrapper.append("<div class='dhonishow-slider-wrapper'><div class='dhonishow-slider'></div></div>");
      var slider = wrapper.find(".dhonishow-slider");
      this.share(".dhonishow-slider", slider);
      
      var total = elements.length - 1;
      
      slider.slider({
        min: 0,
        max: total,
        step: 1,
        value: 0,
        animate: true,
        slide: function(event, ui) {
          _this.dispatchEvent("trigger.next", ui.value);
        }
      });
      
      var step = 100 / total;
      
      for (var i=0; i < total+1; i++) {
        slider.append("<div class='dhonishow-slidershow-marker' style='left:"+(step*i)+"%'>"+(i+1)+"</div>");
      };

      var slider_wrapper = slider.parent();
      
      var marker = jQuery('<span class="dhonishow-slidershow-marker-arrow"></span>');
      slider.append(marker);
      
      this.share("slider-marker", marker);
      
      var descriptions = [];
      
      for (var i=0; i < elements.length; i++) {
        var description = jQuery('<div style="display:none;" class="dhonishow-slidershow-description">'+elements[i].description+'</div>');        
        descriptions.push(description);
        
        slider_wrapper.append(description);
        
      };
      
      this.share("slider-descriptions", descriptions);
      
      
      this.addEventListener("trigger.update", function(current, next) {
        
        if (current == next) {
          descriptions[next].show();
        } else {
          descriptions[current].hide();
          descriptions[next].show();
        };
        
        slider.slider("value", next);
        
        marker.css("left", (next*step - 1) + "%");
        
      });
    }
    
    
  };
  
})();

