 /*
* scrollingTouchCarousel 1.0 - jQuery plugin
* Written by Jason Doucette/Thrust Labs
* Based on Adam Lafene's Scrolling Carousel - www.convergent-evolution.co.uk
*
* Copyright (c) 2010 Adam Lafene - www.convergent-evolution.co.uk
* Copyright (c) 2011 Thrust Labs - www.thrustlabs.com
*
* Licensed under the terms of the MIT and GPL licenses:
*   http://www.opensource.org/licenses/mit-license.php
*   http://www.gnu.org/licenses/gpl.html
*
* Options:
* scrollerOffset: an integer or an array of offsets (in pixels or percentages)
*/

(function ($) {
  var cursorPosition;
  $.fn.scrollingTouchCarousel = function (options) {
    var method;
    var lastTouchX = 0;
    var startX = 0;
    var startY = 0;
    var velocity = 0;
    var isTouch = true;
    try {
      document.createEvent("TouchEvent");
    } catch(e) {
      isTouch = false;
    }
    if ((typeof options).toLowerCase() === 'object' || !options) {
      var defaults = {
        scrollerOffset: 0,
        scrollSpeed: 'medium',
        looped: true
      };
      options = $.extend(defaults, options)
    } else {
      method = options
    }
    var functions = new Object();
    
    functions.getData = function (index, obj) {      
      if (!obj.attr('id')) {
        obj.attr('id', 'scrollingTouchCarouselElement_' + touchCarouselCount)
      }
      var objId = obj.attr('id');
      
      var scrollerContent;
      var scrollerPosition = 0;
      var sMultiplier;
      var scrollerChildren;
      var offsetDistance;
            
      var objId = obj.attr('id');
      var scrollContainer = obj[0];
      scrollContainer.style.paddingLeft = '0';
      scrollContainer.style.paddingRight = '0';
      var scrollContainerWidth = scrollContainer.offsetWidth;
      var childType = obj.children()[0].nodeName.toLowerCase();
      switch (childType) {
      case 'div':
        if (!method) {
          scrollContainer.innerHTML = '<div class="sc_scrollContent">' + obj[0].innerHTML + '</div>';
          scrollContainer.innerHTML += scrollContainer.innerHTML
        }
        scrollerContent = obj.find('div.sc_scrollContent');
        scrollerChildren = obj.find('div.sc_scrollContent:first').find('div');
        break;
      case 'ul':
        if (!method) {
          scrollContainer.innerHTML += scrollContainer.innerHTML
        }
        scrollerContent = obj.find('ul');
        scrollerChildren = obj.find('ul:first').find('li');
        break;
      case 'ol':
        if (!method) {
          scrollContainer.innerHTML += scrollContainer.innerHTML
        }
        scrollerContent = obj.find('ol');
        scrollerChildren = obj.find('ol:first').find('li');
        break;
      default:
        alert('unable to initialise scroller - please ensure contents are either in a UL, an OL or in DIVs');
        return
      }
      switch (options.scrollSpeed) {
      case 'slow':
        sMultiplier = 1;
        break;
      case 'fast':
        sMultiplier = 4;
        break;
      case 'medium':
      default:
        sMultiplier = 2
      }
      var scrollContentWidth = 0;
      var scrollerHeight = 0;
      var itemPadding;
      var itemMargin;
      $(scrollerChildren).each(function (i) {
        scrollContentWidth += $(this, obj)[0].offsetWidth + parseInt($(this, obj).css('marginLeft')) + parseInt($(this, obj).css('marginRight'));
        if ($(this, obj)[0].offsetHeight > scrollerHeight) {
          scrollerHeight = $(this, obj)[0].offsetHeight
        }
      });
      if (scrollContentWidth > obj[0].offsetWidth) {
        var scrollerOffset = options.scrollerOffset;
        if(scrollerOffset.length > 1) {
          scrollerOffset = options.scrollerOffset[index < scrollerOffset.length ? index : index % scrollerOffset.length];
        }
        var offSetPoint = 0;
        if(options.scrollerOffset != null && (scrollerOffset + '').indexOf('%') > 0) {
          var offSetPoint = Math.round((scrollContentWidth / 100) * parseInt(scrollerOffset));        
          offsetDistance = offSetPoint - (Math.round(scrollContainerWidth / 2));
        } else {
          offsetDistance = scrollerOffset;
        }
        if (offsetDistance > (scrollContentWidth - scrollContainerWidth)) {
          offsetDistance = scrollContentWidth - scrollContainerWidth
        }
      } else {
        $(scrollerContent[1]).remove();
        return
      }
      scrollContainer.style.overflow = 'hidden';
      scrollContainer.style.position = 'relative';
      scrollContainer.style.height = scrollerHeight + 'px';
      var itemPadding;
      scrollerContent.each(function () {
        $(this, obj)[0].style.position = 'absolute';
        $(this, obj)[0].style.top = '0';
        $(this, obj)[0].style.width = scrollContentWidth + 'px';
        $(this).children().each(function (i) {
          $(this, obj)[0].style.cssFloat = 'left';
          $(this, obj)[0].style.position = 'static'
        })
      });
      scrollerContent[0].style.left = (offsetDistance > 0) ? '-' + offsetDistance + 'px' : '0';
      scrollerPosition = -parseInt(scrollerContent[0].style.left);
      if (options.looped == true) {
        scrollerContent[1].style.left = scrollerContent[0].offsetLeft - scrollContentWidth + 'px'
      } else {
        scrollerContent[1].style.display = 'none';
        scrollerContent[1].style.top = '-1000px'
      }

      return {'id': objId,      
      'scrollerContent' : scrollerContent,
      'scrollerPosition' : scrollerPosition,
      'scrollContainer' : scrollContainer,
      'scrollContentWidth' : scrollContentWidth,
      'scrollContainerWidth' : scrollContainerWidth,
      'sMultiplier' : sMultiplier,
      'offsetDistance' : offsetDistance};
    };
          
    if(!method) {
      var touchCarouselCount = 0;
      var scrollers = $(this).map(function(i, o) {        
        return functions.getData(i, $(this));      
      });
      $.each(scrollers, function(index, scroller) { 
        var obj = $('#' + scroller.id);
        if(isTouch) {
          obj.bind('touchstart', function(event) {
            var e = event.originalEvent;
            e.preventDefault();
            startX = e.touches[0].clientX;
            startY = e.touches[0].clientY;
            var activeScrollerIndex = 0;
            for(var i = 0; i < scrollers.length; i++) {
              if(obj.attr('id') == scrollers[i].id) {
                scrollers[i].lastPosition = null;                
              }                
              if(scrollers[i].trailInterval != null) {
                clearInterval(scrollers[i].trailInterval);
                scrollers[i].trailInterval = null;
              }
            }            
            lastTouchX = null;
          }, "true");
          obj.bind('touchend', function(event) {
            var e = event.originalEvent;
            e.preventDefault();
            if(velocity != 0) {
              var activeScrollerIndex = 0;
              for(var i = 0; i < scrollers.length; i++) {
                if(obj.attr('id') == scrollers[i].id) {
                  scrollers[i].trailInterval = setInterval(functions.stopCarousel, 50);
                  return;
                }                
              }            
            }
            if(lastTouchX == null) { // no move, just a tap
              // need to find the object I clicked on.
              obj.find('a').each(function(i, o) {
                if($(this).offset().left <= startX &&
                    $(this).offset().left + $(this).width() >= startX) {
                    window.open($(this).attr('href'));
                  //$(this).click();
                  return;                    
                }
              });
            }
          }, "true");
          obj.bind('touchmove', function(event) {
            var e = event.originalEvent;
            e.preventDefault();
            var cursor = {
              x: 0,
              y: 0
            };
            if (e.touches[0].pageX || e.touches[0].pageY) {
              cursor.x = e.touches[0].pageX;
              cursor.y = e.touches[0].pageY
            } else {
              var de = document.documentElement;
              var b = document.body;
              cursor.x = e.clientX + ((de.scrollLeft || b.scrollLeft) - (de.clientLeft || 0));
              cursor.y = e.clientY + ((de.scrollTop || b.scrollTop) - (de.clientTop || 0))
            }
            cursorPosition = cursor;
            if(lastTouchX == null) {
              lastTouchX = cursorPosition.x;
            }
            velocity = cursorPosition.x - lastTouchX;
            lastTouchX = cursorPosition.x;
            
            functions.swipeCarousels();            
          }, "true");        
        } else {
          obj.mouseenter(function (e) {
            for(var i = 0; i < scrollers.length; i++) {
              if(scrollers[i].trailInterval != null) {
                clearInterval(scrollers[i].trailInterval);
                scrollers[i].trailInterval = null;
              }
              if(scrollers[i].scrollInterval != null) {              
                clearInterval(scrollers[i].scrollInterval);
                scrollers[i].scrollInterval = null;
              }
            }            
            var cursor = {
              x: 0,
              y: 0
            };
            if (e.pageX || e.pageY) {
              cursor.x = e.pageX;
              cursor.y = e.pageY
            } else {
              var de = document.documentElement;
              var b = document.body;
              cursor.x = e.clientX + ((de.scrollLeft || b.scrollLeft) - (de.clientLeft || 0));
              cursor.y = e.clientY + ((de.scrollTop || b.scrollTop) - (de.clientTop || 0))
            }
            cursorPosition = cursor;            
            functions.startCarousel();
          });
          obj.mouseleave(function () {          
            for(var i = 0; i < scrollers.length; i++) {
              if(obj.attr('id') == scrollers[i].id) {
                scrollers[i].trailInterval = setInterval(functions.stopCarousel, 50);
              }                
              if(scrollers[i].scrollInterval != null) {              
                clearInterval(scrollers[i].scrollInterval);
                scrollers[i].scrollInterval = null;
              }              
            }            
          });
          obj.mousemove(function (e) {
            var cursor = {
              x: 0,
              y: 0
            };
            if (e.pageX || e.pageY) {
              cursor.x = e.pageX;
              cursor.y = e.pageY
            } else {
              var de = document.documentElement;
              var b = document.body;
              cursor.x = e.clientX + ((de.scrollLeft || b.scrollLeft) - (de.clientLeft || 0));
              cursor.y = e.clientY + ((de.scrollTop || b.scrollTop) - (de.clientTop || 0))
            }
            cursorPosition = cursor;
          });
        }                    
      });
    }
    
    functions.swipeCarousels = function() {
      var activeScrollerIndex = 0;
      for(var i = 0; i < scrollers.length; i++) {
        var obj = $('#' + scrollers[i].id);
        if(obj.offset().top <= cursorPosition.y && obj.offset().top + obj.height() >= cursorPosition.y) {          
          activeScrollerIndex = i;
          break;
        }        
      }
      var activeScroller = scrollers[activeScrollerIndex];
      if(activeScroller.lastPosition == null) {
        activeScroller.lastPosition = cursorPosition.x;
      } else {
        var scrollDistance = cursorPosition.x - activeScroller.lastPosition;
        var isScrollingRight = (scrollDistance > 0);
        activeScroller.lastPosition = cursorPosition.x;

        for(var i = 0; i < scrollers.length; i++) {
          var adjustedDistance = scrollDistance;
          if(Math.abs(i - activeScrollerIndex) % 2 == 1) {
            adjustedDistance *= -1;
          }
          functions.positionCarousel(scrollers[i], adjustedDistance);
        }
      }
    
    }
    
    functions.positionCarousel = function(scroller, distance) {
      scroller.scrollerPosition += distance;      
      scroller.scrollerPosition = scroller.scrollerPosition % scroller.scrollContentWidth;
      if(document.body.style.WebkitTransform !== undefined) {            
        
        var leftEdgePosition = scroller.scrollerPosition - scroller.offsetDistance*2;
        var rightEdgePosition = leftEdgePosition + scroller.scrollContentWidth;
        if(leftEdgePosition > 0 && leftEdgePosition < scroller.scrollContainerWidth) {
          // left edge is in frame
          scroller.scrollerContent[0].style.webkitTransform = "translateX(" + (scroller.scrollerPosition - scroller.offsetDistance) + "px)";
          scroller.scrollerContent[1].style.webkitTransform = "translateX(" + (scroller.scrollerPosition - scroller.offsetDistance) + "px)";
                  if(scroller.offsetDistance == 0) {  
                    $('#debug').html('left edge in frame, position = ' + scroller.scrollerPosition +
                                      ', trans1 = ' + scroller.scrollerContent[0].style.webkitTransform +
                                      ', trans2 = ' + scroller.scrollerContent[1].style.webkitTransform + ", XXX = " + scroller.scrollContentWidth
                                      ); 
                  }          
                  if(scroller.offsetDistance > 0) {  
                    $('#debug2').html('left edge in frame, position = ' + scroller.scrollerPosition +
                                      ', trans1 = ' + scroller.scrollerContent[0].style.webkitTransform +
                                      ', trans2 = ' + scroller.scrollerContent[1].style.webkitTransform + ", XXX = " + scroller.scrollContentWidth
                                      ); 
                  }                  
        } else if((rightEdgePosition > 0 && rightEdgePosition < scroller.scrollContainerWidth) || 
                  (rightEdgePosition < 0 && rightEdgePosition  + scroller.scrollContentWidth < scroller.scrollContainerWidth)) {
                  
          if(rightEdgePosition > 0) {                 
            scroller.scrollerContent[0].style.webkitTransform = "translateX(" + (scroller.scrollerPosition - scroller.offsetDistance) + "px)";
            scroller.scrollerContent[1].style.webkitTransform = "translateX(" + (scroller.scrollContentWidth * 2 + scroller.scrollerPosition - scroller.offsetDistance) + "px)";
                  if(scroller.offsetDistance == 0) {  
                    $('#debug').html('right edge in frame, position = ' + scroller.scrollerPosition +
                                      'right = ' + rightEdgePosition +
                                      'left = ' + leftEdgePosition +
                                      ', trans1 = ' + scroller.scrollerContent[0].style.webkitTransform +
                                      ', trans2 = ' + scroller.scrollerContent[1].style.webkitTransform
                                      ); 
                  }          
                  if(scroller.offsetDistance > 0) {  
                    $('#debug2').html('right edge in frame, position = ' + scroller.scrollerPosition +
                                      'right = ' + rightEdgePosition +
                                      'left = ' + leftEdgePosition +
                                      ', trans1 = ' + scroller.scrollerContent[0].style.webkitTransform +
                                      ', trans2 = ' + scroller.scrollerContent[1].style.webkitTransform
                                      ); 
                  }          
          } else {
            scroller.scrollerContent[0].style.webkitTransform = "translateX(" + (scroller.scrollerPosition + scroller.scrollContentWidth - scroller.offsetDistance) + "px)";
            scroller.scrollerContent[1].style.webkitTransform = "translateX(" + (scroller.scrollContentWidth * 3 + scroller.scrollerPosition - scroller.offsetDistance) + "px)";          
                  if(scroller.offsetDistance == 0) {  
                    $('#debug').html('right edge in frame b, position = ' + scroller.scrollerPosition +
                                      'right = ' + rightEdgePosition +
                                      'left = ' + leftEdgePosition +
                                      ', trans1 = ' + scroller.scrollerContent[0].style.webkitTransform +
                                      ', trans2 = ' + scroller.scrollerContent[1].style.webkitTransform
                                      ); 
                  }          
                  if(scroller.offsetDistance > 0) {  
                    $('#debug2').html('right edge in frame b, position = ' + scroller.scrollerPosition +
                                      'right = ' + rightEdgePosition +
                                      'left = ' + leftEdgePosition +
                                      ', trans1 = ' + scroller.scrollerContent[0].style.webkitTransform +
                                      ', trans2 = ' + scroller.scrollerContent[1].style.webkitTransform
                                      ); 
                  }          
          }          
        } else {
          // Just draw, edges are fine
          scroller.scrollerContent[1].style.webkitTransform = "translateX(0px)";
          if(leftEdgePosition <= 0) {
            if(scroller.offsetDistance > 0 && scroller.scrollerPosition - scroller.offsetDistance < -scroller.scrollContentWidth + scroller.offsetDistance) {
              scroller.scrollerContent[0].style.webkitTransform = "translateX(" + (scroller.scrollerPosition - scroller.offsetDistance + scroller.scrollContentWidth) + "px)";
                    if(scroller.offsetDistance == 0) {  
                      $('#debug').html('Simple1a, position = ' + scroller.scrollerPosition +
                                      'right = ' + rightEdgePosition +
                                      'left = ' + leftEdgePosition +
                                      ', trans1 = ' + scroller.scrollerContent[0].style.webkitTransform +
                                      ', trans2 = ' + scroller.scrollerContent[1].style.webkitTransform
                                      ); 
                    }          
                    if(scroller.offsetDistance > 0) {  
                      $('#debug2').html('Simple1a, position = ' + scroller.scrollerPosition +
                                      'right = ' + rightEdgePosition +
                                      'left = ' + leftEdgePosition +
                                      ', trans1 = ' + scroller.scrollerContent[0].style.webkitTransform +
                                      ', trans2 = ' + scroller.scrollerContent[1].style.webkitTransform
                                      ); 
                    }             
            } else {
            scroller.scrollerContent[0].style.webkitTransform = "translateX(" + (scroller.scrollerPosition - scroller.offsetDistance) + "px)";
                  if(scroller.offsetDistance == 0) {  
                    $('#debug').html('Simple1b, position = ' + scroller.scrollerPosition +
                                    'right = ' + rightEdgePosition +
                                    'left = ' + leftEdgePosition +
                                    ', trans1 = ' + scroller.scrollerContent[0].style.webkitTransform +
                                    ', trans2 = ' + scroller.scrollerContent[1].style.webkitTransform
                                    ); 
                  }          
                  if(scroller.offsetDistance > 0) {  
                    $('#debug2').html('Simple1b, position = ' + scroller.scrollerPosition +
                                    'right = ' + rightEdgePosition +
                                    'left = ' + leftEdgePosition +
                                    ', trans1 = ' + scroller.scrollerContent[0].style.webkitTransform +
                                    ', trans2 = ' + scroller.scrollerContent[1].style.webkitTransform
                                    ); 
                  } 
            }
          } else {
            scroller.scrollerContent[0].style.webkitTransform = "translateX(" + (scroller.scrollerPosition - scroller.scrollContentWidth - scroller.offsetDistance) + "px)";          
                  if(scroller.offsetDistance == 0) {  
                    $('#debug').html('Simple2, position = ' + scroller.scrollerPosition +
                                    'right = ' + rightEdgePosition +
                                    'left = ' + leftEdgePosition +
                                    ', trans1 = ' + scroller.scrollerContent[0].style.webkitTransform +
                                    ', trans2 = ' + scroller.scrollerContent[1].style.webkitTransform +
                                    ', content = ' + scroller.scrollContentWidth
                                    ); 
                  }          
                  if(scroller.offsetDistance > 0) {  
                    $('#debug2').html('Simple2, position = ' + scroller.scrollerPosition +
                                    'right = ' + rightEdgePosition +
                                    'left = ' + leftEdgePosition +
                                    ', trans1 = ' + scroller.scrollerContent[0].style.webkitTransform +
                                    ', trans2 = ' + scroller.scrollerContent[1].style.webkitTransform +
                                    ', content = ' + scroller.scrollContentWidth
                                    ); 
                  }          
          }
        
        }                

      } else {
        scroller.scrollerContent[0].style.left = (scroller.scrollerPosition - scroller.offsetDistance *2) + 'px';
        if(scroller.scrollerPosition - scroller.offsetDistance > 0) {
          scroller.scrollerContent[1].style.left = (scroller.scrollerPosition - scroller.offsetDistance*2) - scroller.scrollContentWidth + 'px';
        } else {
          scroller.scrollerContent[1].style.left = (scroller.scrollerPosition - scroller.offsetDistance*2) + scroller.scrollContentWidth + 'px';
        }
      }    
    
      if(!isTouch && options.hoverClass) {
        var imgs0 = $(scroller.scrollerContent[0]).find('img');
        var imgs1 = $(scroller.scrollerContent[1]).find('img');
        for(var i = 0; i < imgs0.length; i++ ) {
          if(($(imgs0[i]).offset().left <= cursorPosition.x &&
              $(imgs0[i]).offset().left + $(imgs0[i]).width() >= cursorPosition.x && 
              $(imgs0[i]).offset().top <= cursorPosition.y &&
              $(imgs0[i]).offset().top + $(imgs0[i]).height() >= cursorPosition.y)
              ||
              ($(imgs1[i]).offset().left <= cursorPosition.x &&
              $(imgs1[i]).offset().left + $(imgs1[i]).width() >= cursorPosition.x && 
              $(imgs1[i]).offset().top <= cursorPosition.y &&
              $(imgs1[i]).offset().top + $(imgs1[i]).height() >= cursorPosition.y)
            ) {
            //$('#debug').html(cursorPosition.x + "," + cursorPosition.y + " // " + scroller.scrollerContent[0].style.left + "," + scroller.scrollerContent[1].style.left + " // " + i + " // " + ($(imgs0[i]).hasClass('highlighted') ? 'TRUE' : 'FALSE') + "," + ($(imgs1[i]).hasClass('highlighted') ? 'TRUE' : 'FALSE'));
            $(imgs0[i]).attr('class', options.hoverClass);
            $(imgs1[i]).attr('class', options.hoverClass);
          } else {
            $(imgs0[i]).removeClass(options.hoverClass);
            $(imgs1[i]).removeClass(options.hoverClass);
          }
        }
      }
    }
      
    functions.startCarousel = function () {      

      var activeScrollerIndex = -1;
      for(var i = 0; i < scrollers.length; i++) {
        var obj = $('#' + scrollers[i].id);
        if(obj.offset().top <= cursorPosition.y && obj.offset().top + obj.height() >= cursorPosition.y) {          
          activeScrollerIndex = i;
          break;
        }        
      }
      if(activeScrollerIndex >= 0) {
        var activeScroller = scrollers[activeScrollerIndex];
        activeScroller.scrollInterval = setInterval(function() {
          var activeScrollerIndex = -1;          
          for(var i = 0; i < scrollers.length; i++) {
            if(scrollers[i].scrollInterval != null) {
              activeScrollerIndex = i;
              break;
            }        
          }  
          if(activeScrollerIndex >= 0) {
            scroller = scrollers[activeScrollerIndex];
            var centerPoint = Math.round($(scroller.scrollContainer).offset().left + (scroller.scrollContainer.offsetWidth / 2));
            var cursorDistance;
            var cursor = cursorPosition.x;
            var halfContainer = scroller.scrollContainerWidth / 2;
            cursorDistance = (cursor < centerPoint) ? centerPoint - cursor : cursor - centerPoint;
            var scrollDistance = (cursorDistance < (Math.ceil((halfContainer / 100) * 30))) ? 1 : ((cursorDistance < (Math.ceil((halfContainer / 100) * 50))) ? 2 * scroller.sMultiplier : ((cursorDistance < (Math.ceil((halfContainer / 100) * 70))) ? 3 * scroller.sMultiplier : ((cursorDistance < (Math.ceil((halfContainer / 100) * 90))) ? 4 * scroller.sMultiplier : 6 * scroller.sMultiplier)));
            if(cursor > centerPoint) { scrollDistance *= -1; }
            for(var i = 0; i < scrollers.length; i++) {
              var adjustedDistance = scrollDistance;
              if(Math.abs(i - activeScrollerIndex) % 2 == 1) {
                adjustedDistance *= -1;
              }
              functions.positionCarousel(scrollers[i], adjustedDistance);
            } 
            velocity = scrollDistance;

          }
        }, 40);    
      }
    };

    functions.stopCarousel = function () {      
      var activeScrollerIndex = -1;
      for(var i = 0; i < scrollers.length; i++) {
        if(scrollers[i].trailInterval != null) {
          activeScrollerIndex = i;
          break;
        }        
      }        
      if(velocity == 0) {
        clearInterval(scrollers[activeScrollerIndex].trailInterval);
        scrollers[activeScrollerIndex].trailInterval = null;
      } else if(activeScrollerIndex >= 0) {
        velocity = velocity - (velocity > 0 ? 1 : -1);
        for(var i = 0; i < scrollers.length; i++) {
          var adjustedDistance = velocity;
          if(Math.abs(i - activeScrollerIndex) % 2 == 1) {
            adjustedDistance *= -1;
          }
          functions.positionCarousel(scrollers[i], adjustedDistance);
        }       
      }
    };
          
    if (!method) {
      return
    }
    switch (method) {
    default:
      $.error('Method ' + method + ' does not exist on jQuery.scrollingTouchCarousel')
    }
  };
})(jQuery);
