
  /*
  * Slider
  * Etopia BV
  */
  
  /*
  * Utils
  * Utils object, adding extra things to the libs
  */
  
  var utils = {
          scope: function( target, func ) {
                  return function(){
                          return func.apply( target, arguments ); 
                  }
          }
  };
  
  $.fn.slider = function( options ) {
            // iterate the matched nodeset
            var slider;
            return this.each(function() {
                    $( this ).data( 'slider', ( slider = new Slider(this, ( options ? options : {} )) ) );
            });
  };
  
  // Settings
  //  - steps (1 <-> 999), 1px default
  //  - interval (ms) (1 <-> 999), 40ms default
  //  - next (selector e.g. #next), none default
  //  - prev (selector e.g. #prev), none default
  //  - selector (selector e.g. img), 'img' default
  //  - maxElements (1 <-> 999), 4 default (how many elements to show)
  //  - position (absolute), none default
  var Slider = function( obj, options ){
          // The slide object
          this.elem = $( obj );
          this.options = options;
          this.slider;
          
          // Interval loader
          this.interval;
          this.prev;
          this.next;
          
          // Pager
          this.current = 0;
          this.max     = 1;
          
          // Position management
          this.position= 0;
          this.selector;
          this.viewSelectors;
          
          // Init. it
          this.init = function() {
                  // Insert div
                  this.elem.append(
                          ( this.slider = $( '<div />' ).css({
                               'margin': '0px',
                               'padding': ( 'padding' in this.options ? this.options.padding : '0px' ),
                               'overflow': 'hidden',
                               'height': this.elem.height() + 'px',
                               'width': 'auto'
                          }).addClass( 'slider' ) )
                  );
                  
                  // Abs?
                  if( 'position' in this.options ) {
                          if( this.options.position.toLowerCase() == 'absolute' ) {
                                  this.slider.css({
                                        'position': 'absolute',
                                        'top': '0px',
                                        'left': '0px',
                                        'zindex': '5px'
                                  });
                          }
                  }
                  
                  // Set all images in the new view
                  if( this.slider ) {
                          var width = 0, max = 0;
                          this.elem.find( ( this.selector = ( ( 'selector' in this.options ) ? this.options.selector : 'img' ) ) ).appendTo( this.slider ).each(function(){
                                  width += $(this).width();
                                  max++;
                          });
                          
                          // View selector
                          if( 'maxElements' in this.options )
                                  this.viewSelectors = this.options.maxElements;
                          else
                                  this.viewSelectors = 4;
                          
                          // Max elems.
                          this.max = max;
                          
                          // Init settings
                          this.elem.find( this.selector + ':first-child' ).addClass( 'first' );
                          this.elem.find( this.selector + ':eq(' + (this.viewSelectors-1) + ')' ).addClass( 'last' );
                          
                          // Get width
                          this.slider.css({
                                'width': ( width - 2 ) + 'px'
                          });
                  }
                  
                  // Add event handlers
                  if( 'prev' in this.options ) {
                          this.prev = $( this.options.prev ).bind( 'click', utils.scope( this, this.prev ) );
                          if( this.current == 0 )
                                  this.prev.css({ 'visibility': 'hidden' });
                  }
                  
                  if( 'next' in this.options ) {
                          this.next = $( this.options.next ).bind( 'click', utils.scope( this, this.next ) );
                          if( this.current >= ( this.max - this.viewSelectors ) )
                                  this.next.css({ 'visibility': 'hidden' });
                  }
          };
          
          this.checkPager = function() {
                  if( this.current > 0 && this.prev ) {
                          this.prev.css({ 'visibility': 'visible' }); 
                          if( this.current >= ( this.max - this.viewSelectors ) )
                                  this.next.css({ 'visibility': 'hidden' });   
                  }
                  else if( this.current == 0 && this.prev ) {
                          this.prev.css({ 'visibility': 'hidden' });   
                  }
          };
          
          this.prevRunning = false;
          this.prev = function() {
                  // Add last image to the front
                  if( this.current <= 0 || this.prevRunning ) return;
                  if( this.nextRunning ) {
                          // Cancel it
                          this.interval = clearInterval( this.interval );
                  }
                  
                  this.prevRunning = true;
                  var lastElem = this.slider.find( this.selector + ':last-child' );
                  if( lastElem.length ) {
                          var cp = lastElem.clone();
                          
                          // Delete from position
                          this.position += lastElem.width();
                          
                          // Delete node
                          lastElem.remove();
                          
                          // Append in the front
                          this.slider.find( this.selector ).removeClass( 'last' );
                          this.slider.find( this.selector + ':first-child' ).removeClass( 'first' );
                          cp.insertBefore( this.slider.find( this.selector + ':first-child' ) ).addClass( 'first' );
                          this.slider.find( this.selector + ':eq(' + (this.viewSelectors-1) + ')' ).addClass( 'last' );
                          
                          // Update margin
                          this.slider.css( 'margin-left', '-' + this.position + 'px' );
                  }
          
                  // Set interval to delete the first image
                  this.interval = setInterval(utils.scope( this, function(){
                          // Alloc it
                          var firstElem = this.slider.find( this.selector + ':first-child' ), fw;
                          if( firstElem.length ) {
                                  // Just to be sure it still exists
                                  if( this.position <= 0 ) {
                                          this.position = 0;
                                          
                                          // Done
                                          this.interval = clearInterval( this.interval );
                                          
                                          // Update current position
                                          this.current--;
                                          this.checkPager();
                                          
                                          // Done
                                          this.prevRunning = false;
                                  }
                                  else {
                                          this.position -= ( 'steps' in this.options ? this.options.steps : 1 );
                                  }
                                  
                                  // Update position
                                  this.slider.css( 'margin-left', '-' + this.position + 'px' );
                          }
                          else
                                  this.interval = clearInterval( this.interval );
                          
                  }), ( 'interval' in this.options ? this.options.interval : 40 ));
          };
          
          this.nextRunning = false;
          this.next = function() {
                  if( this.nextRunning ) return;
                  if( this.prevRunning ) {
                          // Cancel it
                          this.interval = clearInterval( this.interval );
                  }
                  
                                    this.nextRunning = true;
                  // Set interval to delete the first image
                  this.interval = setInterval(utils.scope( this, function(){
                          // Alloc it
                          var firstElem = this.slider.find( this.selector + ':first-child' ), fw;
                          if( firstElem.length ) {
                                  // Just to be sure it still exists
                                  if( Math.abs( this.position ) >= ( fw = firstElem.width() ) ) {
                                          // Delete it
                                          var cp = firstElem.clone().removeClass( 'first' );
                                          
                                          // Delete from position
                                          this.position -= fw;
                                          
                                          // Delete node
                                          firstElem.remove();
                                          
                                          // Append after last-child
                                          cp.insertAfter( this.slider.find( this.selector + ':last-child' ) );
                                          
                                          // Done
                                          this.interval = clearInterval( this.interval );
                                          
                                          // Update current position
                                          this.current++;
                                          this.checkPager();
                                          
                                          // Update first elem
                                          this.slider.find( this.selector + ':first-child' ).addClass( 'first' );
                                          this.slider.find( this.selector ).removeClass( 'last' );
                                          this.slider.find( this.selector + ':eq(' + (this.viewSelectors-1) + ')' ).addClass( 'last' );
                                          
                                          // Done
                                          this.nextRunning = false;
                                  }
                                  else {
                                          this.position += ( 'steps' in this.options ? this.options.steps : 1 );
                                  }
                                  
                                  // Update position
                                  this.slider.css( 'margin-left', ( this.position > 0 ? '-' : '' ) + this.position + 'px' );
                          }
                          else
                                  this.interval = clearInterval( this.interval );
                          
                  }), ( 'interval' in this.options ? this.options.interval : 40 ));
          };
          
          // Init it
          this.init();
  };
