// **************************************************************************
// Copyright Tavs Dokkedahl
// Contact: http://www.jslab.dk/contact.php
//
// JSLab Carousel is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// any later version.
//
// JSLab Carousel is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// ***************************************************************************

// JavaScript carousel for inline elements

// Namespace
if (!window.JSL)
  JSL = {};

// Carousel 'constructor'
// px: number of pixels to show
// s: speed factor of carousel
// is: smoothness of animation - lower is better
JSL.carousel =
  function(px, s, is) {
    // Save for later
    JSL.carousel.speed = s;
    JSL.carousel.invSpeed = s;
    // Container
    // Add styles to suite your needs
    var div = document.createElement('div');
    // Don't show overflow
    div.style.overflow = 'hidden';
    // Render all elements on single line
    div.style.whiteSpace = 'nowrap';
    // View area in px
    div.style.width = px + 'px';
    // Handle mouseover event
    div.onmouseover = JSL.carousel.mouseover;
    return div;
  };

// Start moving on mouseover
JSL.carousel.mouseover =
  function(e) {
    // If IE
    if (!e)
      e = event;
    // If x coordinate of container is not calculated do it now
    if (this.pos == undefined) {
      this.posX = 0;
      var n = this;
      do {
        this.posX += n.offsetLeft;
        n = n.offsetParent;
      }
      while(n)
    }
    // Initialize mouepointer to 0 movement
    this.x = 0;
    // Clear mouseover
    this.onmouseover = null;
    // Change speed on mousemove
    this.onmousemove = JSL.carousel.mousemove;
    // Stop moving on mouseout
    this.onmouseout = JSL.carousel.mouseout;
    // For closure
    var that = this;
    // Start moving
    this.inv = window.setInterval(function(){JSL.carousel.rotate.call(that)}, JSL.carousel.invSpeed); 
  };

// Change speed when moving mouse
JSL.carousel.mousemove =
  function(e) {
    // If IE
    if (!e)
      e = event;
    // Detect speed - move faster when closer to border of container
    this.x = e.clientX - this.posX;
    this.x = (this.x / this.offsetWidth) * -2 + 1;
    };

// Stop moving on mouseout - buggy
JSL.carousel.mouseout =
  function(e) {
    // If IE
    if (!e) {
      e = event;
      e.target = e.srcElement;
      e.relatedTarget = e.toElement;
    }
    /*
    // If within container
    var x = parseInt(this.style.left);
    var y = parseInt(this.style.top);
    if (x <= e.clientX && e.clientX <= x + this.offsetWidth && y <= e.clientY && e.clientY <= y + this.offsetHeight)
      return;
    */
    // If mouseout and target is notan element within container
    if (e.target == this && e.relatedTarget.parentNode != this) {
      // Stop listetning for mousemove
      this.onmousemove = null;
      // Reattach mouseover
      this.onmouseover = JSL.carousel.mouseover;
      // Clear animation
      window.clearInterval(this.inv);  
    }
  };

// Rotate elements in carousel
JSL.carousel.rotate =
  function() {
    // Get new left margin for first element
    var ml = parseInt(this.firstChild.style.marginLeft) + this.x * JSL.carousel.speed;
    // If greater than zero move last element making it firstchild
    if (ml > 0) {
      // Reset left margin on element before moving
      this.firstChild.style.marginLeft = 0;
      // Change element positions
      this.insertBefore(this.removeChild(this.lastChild), this.firstChild);
      // Hide element outside of container
      this.firstChild.style.marginLeft = -1 * this.firstChild.offsetWidth + 'px';
    }
    // If left margin is less than width of element move
    // first element making it last
    else if (ml < -1 * this.firstChild.offsetWidth) {
    // Reset left margin on element before moving
      this.firstChild.style.marginLeft = 0;
      // Change element positions
      this.appendChild(this.removeChild(this.firstChild));
      // Reset margin of new first element
      this.firstChild.style.marginLeft = 0;
    }
    // Just move the element by shifting its left margin
    else
      this.firstChild.style.marginLeft = ml + 'px';
  };
