text: /**
  * @author Alexander Farkas
  * v. 1.22
  */
  (function ($)
  {
      if (!document.defaultView || !document.defaultView.getComputedStyle)
      { // IE6-IE8
          var oldCurCSS = $.curCSS;
          $.curCSS = function (elem, name, force)
          {
              if (name === 'background-position')
              {
                  name = 'backgroundPosition';
              }
              if (name !== 'backgroundPosition' || !elem.currentStyle || elem.currentStyle[name])
              {
                  return oldCurCSS.apply(this, arguments);
              }
              var style = elem.style;
              if (!force && style && style[name])
              {
                  return style[name];
              }
              return oldCurCSS(elem, 'backgroundPositionX', force) + ' ' + oldCurCSS(elem, 'backgroundPositionY', force);
          };
      }
  
      var oldAnim = $.fn.animate;
      $.fn.animate = function (prop)
      {
          if ('background-position' in prop)
          {
              prop.backgroundPosition = prop['background-position'];
              delete prop['background-position'];
          }
          if ('backgroundPosition' in prop)
          {
              prop.backgroundPosition = '(' + prop.backgroundPosition;
          }
          return oldAnim.apply(this, arguments);
      };
  
      function toArray(strg)
      {
          strg = strg.replace(/left|top/g, '0px');
          strg = strg.replace(/right|bottom/g, '100%');
          strg = strg.replace(/([0-9\.]+)(\s|\)|$)/g, "$1px$2");
          var res = strg.match(/(-?[0-9\.]+)(px|\%|em|pt)\s(-?[0-9\.]+)(px|\%|em|pt)/);
          return [parseFloat(res[1], 10), res[2], parseFloat(res[3], 10), res[3]];
      }
  
      $.fx.step.backgroundPosition = function (fx)
      {
          if (!fx.bgPosReady)
          {
              var start = $.curCSS(fx.elem, 'backgroundPosition');
              if (!start)
              {//FF2 no inline-style fallback
                  start = '0px 0px';
              }
  
              start = toArray(start);
              fx.start = [start[0], start[2]];
              var end = toArray(fx.end);
              fx.end = [end[0], end[2]];
  
              fx.unit = [end[1], end[3]];
              fx.bgPosReady = true;
          }
          //return;
          var nowPosX = [];
          nowPosX[0] = ((fx.end[0] - fx.start[0]) * fx.pos) + fx.start[0] + fx.unit[0];
          nowPosX[1] = ((fx.end[1] - fx.start[1]) * fx.pos) + fx.start[1] + fx.unit[1];
          fx.elem.style.backgroundPosition = nowPosX[0] + ' ' + nowPosX[1];
  
      };
  })(jQuery);
  
  
  
  /*
  tlrkSlider
    
    example usage:
   
      $("#slider").tlrkSlider({
        autoStart: false,
        elements: {
          "img": {delay: 10},
          "h2": {delay: 500},
          ".copy": {delay: 800},
          ".button": {delay: 1000}
        }
      });
  
    to go to a specific frame:
      $("#slider").tlrkSlider("go", position);
      "position" can have one of the following values:
      "next", "prev", "first", "last", "+1", "-1" or a numeric value
    
    to start/stop the automatic loop:
      $("#slider").tlrkSlider("start");
      $("#slider").tlrkSlider("stop");
    
    to change the delay between automatic transitions:
      $("#slider").tlrkSlider("option", "delayAnimation", 1000);
   
    to change any option:
      $("#slider").tlrkSlider("option", option_name, option_value);
      
    Changing the "elements" object is not tested.
    
    Changing the following options: "navigation", "navigationClass", "framesSelector", "autoStart" won't have any effect for now.
    They are used only during the initialization.
    
    $("#slider").data("tlrkSlider") will return the plugin instance and the methods/properties can be accessed from there.
    
    The plugin contructor defaults are accessable through TlrkSlider.defaults
    
    The function that actually sweep the elements in/out can be overriden from
      TlrkSlider.prototype._animationIn and TlrkSlider.prototype._animationOut
     
      See sweepIn/sweepOut 
    
   */
  
  
  
  ;(function( $, window, document, undefined ){
    
    // utility function that generates the "dots" navigation
    function generateNavigation($el, count, config) {
      var i, html = "",
          width = count * 24;
      
      html += "<ol class='" + config.navigationClass + "' style='margin-left: -" + width/2 + "px; width: " + width + "px'>";
      for (i = 0; i < count; i++) {
        html += "<li><a " + (i === 0 ? "class='selected'" : "" ) + " href='#" + (i) + "'>slide</a></li>";
      }
      html += "</ol>";
      
      $el.append(html);
    }
    
    function sweepOut($el, windowWidth) {
      var dfr = $.Deferred(),
          pos = $el.position(),
          width = $el.width(),
          delta, final,
          options = $el.data("tlrkAnimOptions");
      
      windowWidth = windowWidth || $(window).width(); // check if the windowWidth is passed, if not - get it
      
      delta = windowWidth - pos.left;
      final = -(delta);
      
      setTimeout(function(){
        $el.animate({left: final, opacity: "toggle"}, options.speed, options.easing, function(){
          dfr.resolve();
        });
      }, options.delay);
      
      return dfr.promise();
    }
    
    function sweepIn($el, windowWidth, frameLeft) {
      var dfr = $.Deferred(),
          options = $el.data("tlrkAnimOptions"),
          positionData = $el.data("tlrkOriginalPos"),
          final = positionData.position.left,
          rightEdge;
      
      windowWidth = windowWidth || $(window).width(); // check if the windowWidth is passed, if not - get it
      
      $el.css({opacity: 0, display: "block"}); // move it outside the right edge of the screen
      $el.css("left", function(current){
        return current + windowWidth - frameLeft;
      });
      
      setTimeout(function(){
        $el.animate({left: final, opacity: 1}, options.speed, options.easing, function(){
          dfr.resolve();
        });
      }, options.delay);
      
      return dfr.promise();
    }
    
    
    // two pass function that first iterates all the elements and gets their position/width/height
    // and then sets their position to absolute
    function absolutize($elements) {
      
      // todo - move it to separate function and do it just once
      // gather the original position/dimension data for all elements
      $elements.each(function(){
        var $t = $(this);
        
        if ($t.data("tlrkOriginalPos")) return
        
        $t.data("tlrkOriginalPos", {
          position: $t.position(),
          width: $t.width(),
          height: $t.height(),
          css_pos: $t.css("position"),
          css_left: $t.css("left"),
          css_top: $t.css("top"),
          css_width: $t.css("width") || "auto",
          css_height: $t.css("height") || "auto"
        });
        
      });
      
      // set the absolute position
      $elements.each(function(){
        var $t = $(this),
            opos = $t.data("tlrkOriginalPos");
           
        $t.css({
          position: "absolute",
          left: opos.position.left,
          top: opos.position.top,
          width: opos.width,
          height: opos.height
        });
      });
    }
    
    function restoreFrameElements($elements) {
      $elements.each(function(){
        var $t = $(this),
            opos = $t.data("tlrkOriginalPos");
            
        if (!opos) return
            
        $t.css({
          position: opos.css_pos,
          left: opos.css_left,
          top: opos.css_top,
          width: opos.css_width,
          height: opos.css_height
        });
      });
      
    }
  
    var TlrkSlider = function( elem, options ){
        this.elem = elem;
        this.$elem = $(elem);
        this.options = options;
      };
  
    // the plugin prototype
    TlrkSlider.prototype = {
      defaults: {
  
  
        defaultElementOptions: {
          speed: 1200,
          easing: "easeInOutBack",
          // interval before the element starts moving when the fadeIn/Out functions are called
          // it's a good idea to give different delays for the different elements
          // if all have the same delay they'll start moving all together
          delay: 100 
        },
        
        // dispose elements are these that are not included in the elements object
        // but affect the document flow and will be fadedIn/Out
        disposeDelay: 100, // delay for the dispose elements
        disposeSpeed: 1000, // how quickly they'll fadeOut/In
        
        delayBetweenTransition: 1000, // time between starting fadeOut and fadeIn
        delayAnimation: 7000, // time between auto changing the current frame
        
        loop: true, // if true when clicking next on the last frame the slider jumps to the first one
        
        autoStart: true, // start the automatic looping through the frames on init
        
        framesSelector: "section", // selector for the frames inside the slider
        
        elements: {
          "p": {delay: 100, speed: 1000, easing: "easeInOutBack"}
        },
        
        navigation: true, // the dots navigation on the bottom
        navigationClass: "slider-nav",
       
        // callbacks
        // another way to "catch" these events is with
        // $(-slider-element-).bind("animationStart")
        animationStart: null,
        animationEnd: null
      },
  
      init: function() {
        var c, e, element, $element,
            that = this,
            $firstFrame;
        
        c = this.config = $.extend({}, this.defaults, this.options);
        
        this.elem.style.position = "relative"; // make the wrapping element relative
        
        // basics
        this.$frames = this.$elem.find(c.framesSelector);
        this.framesCount = this.$frames.length;
        this.currentFrame = 0;
        this.queue = [];
        
        this._$elementsByFrame = {};
        this._$disposeElementsByFrame = {};
        
        for (i = 0; i < this.framesCount; i++) {
          this._$elementsByFrame[i] = this._getFrameElements(i); // cache the $elements by frame
          this._$disposeElementsByFrame[i] = this._getDisposeFrameElements(i); // cache the rest of the tree for each frame
        }
        
        if (c.navigation) {
          generateNavigation(this.$elem, this.framesCount, c);
          this.$navigation = this.$elem.find("."+c.navigationClass);
        }
        
        // bindings
        this.$elem.find(".slider-nav").delegate("a", "click", function(e){
          var frame = this.getAttribute("href").split("#")[1];
          that.go.call(that, frame);
          return false;
        });
        
        this.$elem // internal bindings for the callbacks
          .bind("animationStart", function(){
            if ($.isFunction(c.animationStart)) {c.animationStart.apply(that, arguments);}
          })
          .bind("animationEnd", function(){
            if ($.isFunction(c.animationEnd)) {c.animationEnd.apply(that, arguments);}
          })
        ;
        
        // start animation?
        if (c.autoStart) {
          this.start();
        } else {
          this.running = false;
        }
  
        return this;
      },
      
      start: function(instant) {
        var that = this;
        
        if (this.timer) { // we'll clear the current timer
          window.clearTimeout(this.timer);
        }
        
        this.running = true;
        
        if (instant) {
          that.nextFrame();
        } else {
          this.timer = window.setTimeout(function(){ that.nextFrame.call(that) }, that.config.delayAnimation);
        }
      },
      
      stop: function() {
        if (!this.running) return; // we are not running
        
        this.running = false;
        window.clearTimeout(this.timer);
      },
  
      // main function for changing frames
      selectFrame: function(frame, dfr) {
        var c = this.config, // shorthand for the config
            that = this,
            dfr = dfr || $.Deferred(),
            dFadeIn = $.Deferred(),
            dFadeOut = $.Deferred();
            
        if (isNaN(frame) || frame < 0 || frame > this.framesCount || frame === this.currentFrame) {
          dfr.reject();
          return dfr.promise();
        }
  
        // clear the animation loop interval if the animation is running
        if (this.running && this.timer) { 
          window.clearTimeout(this.timer);
        }
  
        // check if we are currenly running an animation.
        if (this.animated && this.queue.length > 0) {
          // wait for the last item in the queue to finish
          this.queue[this.queue.length-1].done(function(){
            that.selectFrame(frame, dfr); // and call again the selectFrame
          })
          return dfr.promise();
        }
        
        this.animated = true;
        this.$elem.trigger("animationStart", [this, frame]);
        
        this.queue.push(dfr);
        
        // fade the frames
        dFadeOut = this._fadeOutFrame(this.currentFrame);
        
        // hide the fadetout frame
        dFadeOut.done(function(){
          that.$frames.eq(that.currentFrame).hide();
        });
        
        window.setTimeout(function(){ // then wait delayBetweenTransition and fadeIn the new frame
          dFadeIn = that._fadeInFrame.call(that, frame).done(function(){
            // when both the fadeIn and fadeOut are done we'll resolve the selectFrame promise
            $.when(dFadeOut, dFadeIn).done(function(){
              that.animated = false;
              that.queue.shift();
              that.$elem.trigger("animationEnd", [that]);
              that.currentFrame = frame;
              dfr.resolve();
            });
          });
        }, c.delayBetweenTransition);
        
        // navigation html change
        if (this.config.navigation) {
          this.$navigation.find(".selected").removeClass("selected").end()
            .find("a").eq(frame).addClass("selected");
        }
          
        dfr.done(function(){ // we'll resume the loop animation after the transitions are done
          if (that.running) {
            that.start();
          }
        });
        
        return dfr.promise();
      },
      
      _fadeFrame: function(frame, callback, direction) {
        var dfr = $.Deferred(),
            $frame = this.$frames.eq(frame),
            $elements = this._$elementsByFrame[frame],
            windowWidth = $(window).width(), // cache it before the animations, so we don't have to check it for each element 
            i, len,
            that = this,
            elementAnimations = [],
            $disposeElements = this._$disposeElementsByFrame[frame],
            $affectedElements,
            frameLeft = $frame.offset().left;
            
        direction = direction || "out";
            
        if (!$.isFunction(callback)) return; // do nothing if there's no callback passed
        
        $affectedElements = $elements.add($disposeElements);
        
        // position absolute the animation and dispose elements
        absolutize($affectedElements);
        
        // toggle the dispose elements
        if ($disposeElements.length > 0) {
          window.setTimeout(function(){
            $disposeElements[direction === "out" ? "fadeOut" : "fadeIn"](that.config.disposeSpeed);
          }, this.config.disposeDelay);
        }
        
        // invoke the callback for each element
        // the callback must return a promise
        $elements.each(function(){
          elementAnimations.push( callback.call(that, $(this), windowWidth, frameLeft) );
        });
        
        // wait for all the elements to finish their animation
        $.when.apply(this, elementAnimations).done(function(){
          //restoreFrameElements($affectedElements); // and restore the elements' position
          dfr.resolve(); // resolve the fade function
        });
        
        return dfr.promise();
      },
  
      _fadeOutFrame: function(frame) {
        var dfr = $.Deferred(),
            $frame = this.$frames.eq(frame),
            $disposeElements = this._$disposeElementsByFrame[frame];
        
        this._fadeFrame(frame, this._animationOut, "out").done(function(){
          dfr.resolve();
        })
        
        return dfr.promise();
      },
      
      _fadeInFrame: function(frame) {
        var dfr = $.Deferred(),
            $frame = this.$frames.eq(frame),
            $elements = this._$elementsByFrame[frame];
        
        this._restoreFrame(frame);
        
        $frame.show();
        
        this._fadeFrame(frame, this._animationIn, "in").done(function(){
          dfr.resolve();
        });
        
        return dfr.promise();
      },
      
      _restoreFrame: function(frame){
        if (!frame) return
        restoreFrameElements( this._$elementsByFrame[frame].add(this._$disposeElementsByFrame[frame]) );
      },
      
      nextFrame: function() {
        var frame = this.currentFrame+1,
            dfr = $.Deferred();
            
        if (frame > this.framesCount-1) {
          if (this.config.loop) {
            frame = 0;
          } else {
            dfr.reject();
          }
        };
        
        this.selectFrame(frame).done(function(){
          dfr.resolve();
        });
        
        return dfr.promise();
      },
      
      prevFrame: function() {
        var frame = this.currentFrame-1,
            dfr = $.Deferred();
            
        if (frame < 0) {
          if (this.config.loop) {
            frame = this.framesCount-1;
          } else {
            dfr.reject();
            return dfr.promise();
          }
        }
        
        this.selectFrame(frame).done(function(){
          dfr.resolve();
        });
        
        return dfr.promise();
      },
      
      go: function(str) { // shorthand
        switch (str) {
          case "next":
          case "+1":
            this.nextFrame();
            break;
  
          case "prev":
          case "-1":
            this.prevFrame();
            break;
          
          case "first":
            this.selectFrame(0);
            break;
          
          case "last":
            this.selectFrame(this.framesCount-1);
            break;
          
          default:
            if (isNaN(str)) return;
            this.selectFrame(Number(str));
        }
      },
      
      // returns jquery collection of animation elements
      _getFrameElements: function(frame) { 
        var $frame = this.$frames.eq(frame),
            elements = this.config.elements,
            e, elementOptions,
            $found, $frameElements = $([]);
            
        for (e in elements) {
          elementOptions = elements[e];
          $found = $frame.find(e);
          $found.addClass("t-frame-element").data("tlrkAnimOptions", $.extend({}, this.defaults.defaultElementOptions, elementOptions ));
          $frameElements = $frameElements.add($found);
        }
        
        return $frameElements;
      },
  
      // returns jquery collection of elements that have to be faded out
      // i.e. elements on the same level as the animation elements
      // that doesn't contain other animation elements
      _getDisposeFrameElements: function(frame) {
        var $disposeElements = $([]),
            $frame = this.$frames.eq(frame),
            $elements = this._$elementsByFrame[frame];
  
        $elements.each(function(){
          var $t = $(this),
              $siblings = $t.siblings().not(".t-frame-element");
          
          $siblings.each(function(){
            var $t = $(this);
            // check if the node is not already marked and doesn't contains other frame elements
            if (!$t.hasClass("t-frame-dispose") && $t.find(".t-frame-element").length === 0) {
              $t.addClass("t-frame-dispose");
              $disposeElements = $disposeElements.add($t);
            }
          });
          
        });
        return $disposeElements;
      },
      
      
      // expose the internal animationIn/Out functions that are called for each element in the frame
      // two arguments are passed - the $element which have to be animated and the window width
      _animationIn: sweepIn,
      _animationOut: sweepOut
      
    }
  
    TlrkSlider.defaults = TlrkSlider.prototype.defaults;
  
    $.fn.tlrkSlider = function(options) {
      var otherArgs = Array.prototype.slice.call(arguments, 1);
          
      return this.each(function() {
        var $el = $(this),
            pluginData = $el.data("tlrkSlider");
        
        if (!pluginData) { // check if the slider is already attached
          pluginData = new TlrkSlider(this, options).init();
          $el.data("tlrkSlider", pluginData);
          return;
        }
        
        //change the options or call a method
        if (typeof options === "string") {
          
          // setting / getting option(s)
          if (options === "option") {
            
            if (typeof otherArgs[0] === "string" && typeof otherArgs[1] !== "undefined") { // set an option value
              pluginData.config[otherArgs[0]] = otherArgs[1]; 
            }
            
            if (typeof otherArgs[0] === "object") { // extend the config with new options
              pluginData.config = $.extend(pluginData.config, otherArgs[0]);
            }
            
          } else { // call a method?
            try {
              pluginData[options].apply(pluginData, otherArgs);
            } catch(ex) {
              throw "Error calling a plugin method (" + ex + ")";
            }
          }
        }
      });
    };
  
    window.TlrkSlider = TlrkSlider;
  
  })( jQuery, window , document );