﻿/*
 * KWP jQuery library
 *
 * Copyright (c) 2011 Michael Stamm, KWP Marketing (kwp-marketing.de)
 *
 *
 */

(function($){

 // box slider
 $.fn.boxSlider = function(config){

  var settings = jQuery.extend({
   "firstSlide": 0,
   "selectorNest": "ul",
   "selectorItem": "li",
   "dynamicHeight": false, // not used yet
   "windowWidth": -1,
   "windowHeight": -1,
   "nestWidth": -1,
   "nestHeight": -1,
   "itemWidth": -1,
   "itemHeight": -1,
   "visibleItems": 1,
   "sliderSpeed": 500,
   "sliderEffect": "swing",
   "autoSlide": true,
   "autoSlideStart": 7500,
   "autoSlideDuration": 5000,
   "swipeOffset": 30,
   "showMenu": true,
   "menuItem": "&#9679;"
  }, config);
  
  $(this).each(function(){
   
   var silderObj = this;
   
   var numberOfSlides = $(silderObj).find(settings.selectorNest).eq(0).children(settings.selectorItem).length;
   
   if(numberOfSlides > settings.visibleItems){
    
    var itemWidth    = (settings.itemWidth == -1)    ? $(silderObj).find(settings.selectorNest).eq(0).find(settings.selectorItem).eq(settings.firstSlide).outerWidth() : settings.itemWidth;
    var itemHeight   = (settings.itemHeight == -1)   ? $(silderObj).find(settings.selectorNest).eq(0).find(settings.selectorItem).eq(settings.firstSlide).outerHeight() : settings.itemHeight;
    var nestWidth    = (settings.nestWidth == -1)    ? itemWidth * numberOfSlides : settings.nestWidth;
    var nestHeight   = (settings.nestHeight == -1)   ? itemHeight : settings.nestHeight;
    var windowWidth  = (settings.windowWidth == -1)  ? itemWidth * settings.visibleItems : settings.windowWidth;
    var windowHeight = (settings.windowHeight == -1) ? itemHeight : settings.windowHeight;
    
    var swipeCoords = {"startX":0, "startY":0, "endX":0, "endY":0};
    
    $(silderObj).append("<div class=\"slider_window\"></div>");
    $(silderObj).children(".slider_window:eq(0)").append($(this).find(settings.selectorNest).eq(0).detach());
    
    // setting up window box
    var windowObj = $(silderObj).children(".slider_window:eq(0)");
    $(windowObj).width(windowWidth).height(windowHeight).css({"overflow": "hidden"});
    // setting up nest
    var nestObj = $(windowObj).find(settings.selectorNest).eq(0);
    $(nestObj).width(nestWidth).height(nestHeight);
    // set current slide
    var currentSlideIndex = settings.firstSlide;
    // jump to first slide (firstSlide)
    $(nestObj).css({"margin-left": "-" + (getSlidePosition(currentSlideIndex) * itemWidth) + "px"});
    
    // Touch Events
    // not optimized for more than one itme in viewport
    if(document.addEventListener){
     $(nestObj).children(settings.selectorItem).each(function(){
     	var itemObj = this;
    	
	    	this.addEventListener("touchstart", function(event){
       if(typeof sliderTimer != "undefined") {
         window.clearTimeout(sliderTimer);
       }
						 swipeCoords.startX = event.targetTouches[0].pageX;
				 		swipeCoords.startY = event.targetTouches[0].pageY;
					 }, false);
					 
	    	this.addEventListener("touchmove", function(event){
							event.preventDefault();
							swipeCoords.EndX = event.targetTouches[0].pageX;
							swipeCoords.EndY = event.targetTouches[0].pageY;
					 }, false);
					 
	    	this.addEventListener("touchend", function(event){
							var diffX = swipeCoords.startX - swipeCoords.EndX;
							var diffY = swipeCoords.startY - swipeCoords.EndY;
							
							var currentIndex = $(itemObj).index();
							var sliderItemsLength = $(itemObj).parent().children(settings.selectorItem).length;
							
							// right swipe
							if(diffX < -1 * settings.swipeOffset){
								var prevIndex = (currentIndex - 1 < 0) ? 0 : currentIndex - 1;
								if(currentIndex != prevIndex){
	 							moveSliderToIndex(prevIndex);
	 						}
							}
							// left swipe
							else if(diffX > settings.swipeOffset){
								var nextIndex = (currentIndex + 1 >= sliderItemsLength) ? sliderItemsLength - 1 : currentIndex + 1;
								if(currentIndex != nextIndex){
	 							moveSliderToIndex(nextIndex);
	 						}
							}
						}, false);
						
	    	this.addEventListener("touchcancel", function(event){ 
					  //console.log('Canceling swipe gesture...')
			  	}, false);
			  	
     });
    }
 			
 
    // generate menu if set true
    if(settings.showMenu){
     $(silderObj).append("<ul class=\"slider_menu\"></ul>");
     var menuObj = $(silderObj).children(".slider_menu").eq(0);
     for(var menuCounter = 0; menuCounter < numberOfSlides; menuCounter++){
      $(menuObj).append("<li><a href=\"#\">" + settings.menuItem + "</a></li>");
     }
     $(menuObj).find("li>a").each(function(){
      $(this).bind("click", function(event){
       event.preventDefault();
       if(typeof sliderTimer != "undefined") {
         window.clearTimeout(sliderTimer);
       }
       moveSliderToIndex($(this).parent().index());
      });
     });
     setMenuClasses();
    }
    
    // start autoslide if set true
    if(settings.autoSlide){
     var sliderTimer = window.setTimeout(function(){autoSlide();}, settings.autoSlideStart);
    }
    
   }
   
   // autoslide loop
   function autoSlide(){
    moveSliderToIndex(getNextSlide());
    sliderTimer = window.setTimeout(function(){autoSlide();}, settings.autoSlideDuration + settings.sliderSpeed);
   }
   
   // getting index of next slide
   function getNextSlide(){
    var viewportArray = getWindowViewport();
    var nextSlideIndex = 0;
    for(var viewportCounter = viewportArray.length; viewportCounter > 0; viewportCounter--){
     if(viewportArray[viewportCounter - 1] == true){
      nextSlideIndex = viewportCounter;
      break;
     }
    }
    if(nextSlideIndex >= numberOfSlides){
     nextSlideIndex = 0;
    }
    else if(nextSlideIndex < settings.visibleItems - 1){
     nextSlideIndex = settings.visibleItems - 1;
    }
    return nextSlideIndex;
   }
   
   // setting menü classes
   function setMenuClasses(viewportArray){
    var viewportArray = (viewportArray == null) ? getWindowViewport() : viewportArray;
    $(menuObj).children("li").each(function(){
     $(this).removeClass("active").removeClass("current");
     if($(this).index() == currentSlideIndex){
      $(this).addClass("current");
     }
     else if(viewportArray[$(this).index()]){
      $(this).addClass("active");
     }
    });
   }
   
   // moving the window box to a new slide. if index = 2 and slide number = 8 and visible slides = 3 -> [0,0,1,1,1,0,0,0]
   function moveSliderToIndex(newSlideItemIndex){
    var newSlidePositionIndex = getSlidePosition(newSlideItemIndex);
    var currentSlidePositionIndex = getSlidePosition(currentSlideIndex);
    if(newSlidePositionIndex != currentSlidePositionIndex){
     $(nestObj).stop();
     $(nestObj).animate(
    	 {
    	  "margin-left": (itemWidth * newSlidePositionIndex * -1) + "px"
    	 },
    	 {
    	  "duration": settings.sliderSpeed,
    	  "easing": settings.sliderEffect,
    	  "complete": function(){
    	   // do nothing
       }
    	 }
    	);
    }
    currentSlideIndex = newSlideItemIndex;
    if(settings.showMenu){
     var viewportArray = getWindowViewport(itemWidth * newSlidePositionIndex);
     setMenuClasses(viewportArray);
    }
   }
   
   // getting index for moveSliderToIndex function
   function getSlidePosition(newSlideItemIndex){
    var viewportArray = getWindowViewport();
    var currentWindowPositionIndex = 0;
    var newWindowPositionIndex = 0;
    for(var viewportCounter = 0; viewportCounter < viewportArray.length; viewportCounter++){
     if(viewportArray[viewportCounter] == true){
      currentWindowPositionIndex = viewportCounter;
      break;
     }
    }
    if(viewportArray[newSlideItemIndex] == true){
     //item is already shown
     newWindowPositionIndex = currentWindowPositionIndex;
    }
    else{
     if(newSlideItemIndex < currentWindowPositionIndex){
      //item is hidden left
      newWindowPositionIndex = newSlideItemIndex;
     }
     else if(newSlideItemIndex > currentWindowPositionIndex + settings.visibleItems - 1){
      //item is hidden right
      newWindowPositionIndex = newSlideItemIndex - (settings.visibleItems - 1);
     }     
    }
    return newWindowPositionIndex;
   }
   
   // returning array of visible and invisible slides
   function getWindowViewport(marginOverride){
    var marginOverride = (marginOverride == null) ? -1 : marginOverride;
    var marginOffset = (marginOverride == -1) ? parseInt($(nestObj).css("margin-left")) * -1 : marginOverride;
    var firstSliderIndex = -1;
    if(marginOffset == 0){
     firstSliderIndex = 0;
    }
    else{
     firstSliderIndex = marginOffset / itemWidth;
    }
    var viewportArray = [];
    for(var viewportCounter = 0; viewportCounter < numberOfSlides; viewportCounter++){
     if(viewportCounter >= firstSliderIndex && viewportCounter < firstSliderIndex + settings.visibleItems){
      viewportArray[viewportCounter] = true;
     }
     else{
      viewportArray[viewportCounter] = false;
     }
    }
    return viewportArray;
   }
    
  });

 };
 
})(jQuery);
