function SlidingGallery(params){
/**
*
*	@param container{jQuery Selector}			The container element for the gallery to slide in; used for finding/managing children
*	@param nextButton{jQuery Selector}			Handle clicks
*	@param prevButton{jQuery Selector}			Handle clicks
*	@param navItem{jQuery Selector}				Will attach "goTo" handlers to any matching items
*	@param hideBtnsAfterLoad{Boolean}			Next/Prev buttons will fade out after initial load and come back on hover
*	@param inifiniteLoop{Boolean}				Whether going from last-item to first-item will feel infinite or go-back.
*	@param allowPinchZoom{Boolean}				Will e.preventDefault() on multi-touch (read:pinch zoom) events.
**/

/* Params */
var _container = params.container != null ? params.container : "";
var _nextBtn = params.nextButton != null ? params.nextButton : "";
var _prevBtn = params.prevButton != null ? params.prevButton :"";
var _navItem = params.navItem != null ? params.navItem : "";
var _navItemCallback = params.navItemCallback;
var _hideBtnsAfterLoad = params.hideBtnsAfterLoad != null ? params.hideBtnsAfterLoad : true;
var _infiniteLoop = params.infiniteLoop != null ? params.infiniteLoop : true;
var _allowPinchZoom = params.allowPinchZoom != null ? params.allowPinchZoom : true;
var _autoScroll = params.autoScroll != null ? params.autoScroll : false;
var _preloadDiv = params.preloadDiv != null ? params.preloadDiv : "";


/* App Vars */
var _this = this;
var _autoScrollDuration = 8500;
var _autoScrollTimer;
var _animationDuration = 750;
var	_animationTimer;
var _buttonFadeTimer;
var _queIntens = true;
var _quedIntent;
var _pageScroll;
var _touch;


/*********************************************************************************
*	Init && Set
**********************************************************************************/

this.init = function () {
	
    _this.setVariables();
    _this.setListeners();
    _this.setNavListeners();
    _this.setClasses();
    _this.setBtnVisibility();
    _this.setHoverFix();
	_this.setAutoScrollTimer();
	_this.clearPreloadDiv();
}

this.setVariables = function(){
   _container = $(_container);
   _nextBtn = $(_nextBtn);
   _prevBtn = $(_prevBtn);
}

this.setListeners = function(){
   _container.bind("touchmove", _this.handleTouchMove);
   _container.bind("mouseover", _this.handleContainerOver);
   _container.bind("mouseleave", _this.handleContainerLeave);
   _container.bind("swipeRight", _this.handleSwipeRight);
   _container.bind("swipeLeft", _this.handleSwipeLeft);
   _container.bind("doubleTap", _this.handleDoubleTap);
   _nextBtn.bind("mousedown", _this.handleNextMouseDown);
   _prevBtn.bind("mousedown", _this.handlePreviousMouseDown);
}

this.setNavListeners = function(){
	if(_navItem)
	{
		$(_navItem).each(function()
		{
			$(this).bind("mousedown", _this.handleNavItemIntent);
		});
	}
}

this.setAutoScrollTimer = function(){
	if(_autoScroll){
		_autoScrollTimer = setInterval(_this.handleAutoCompleteTimeout, _autoScrollDuration);
	}
}

this.clearAutoScrollTimer = function(){
	clearInterval(_autoScrollTimer);
}

this.setClasses = function() {
	for(var i = 0; i < _container.find(".sliderItem").length; i++)
	{
		if( i < 1){ _container.find(".sliderItem").eq(i).addClass("current"); }

		else if( i == _container.find(".sliderItem").length - 1){ 
			if(Modernizr.csstransitions) { _container.find(".sliderItem").eq(i).addClass("left"); }
			else { _container.find(".sliderItem").eq(i).addClass("leftIE").css({left:"-100%"}); }
		}
		else { 
			if(Modernizr.csstransitions) { _container.find(".sliderItem").eq(i).addClass("right"); }
			else{ 
				_container.find(".sliderItem").eq(i).addClass("rightIE").css({left:"100%"});
			}
		}
	}
}

this.setBtnVisibility = function(){
	if(_container.find(".sliderItem").length != $(_navItem).length && _navItem != ""){
		trace("###### ERROR:SlidingGallery.js:Case 1");
	}
	if(_hideBtnsAfterLoad)
	{
		_this.setButtonFadeTime(2000);
	}
}

this.setHoverFix = function () {
    var arrows = $('.sliderArrow');
    var $sliderItems = _container.find('.sliderItem');

    // show/hide arrows
    if (!Modernizr.csstransitions) {
        _container.hover(function () {
            arrows.stop().animate({
                opacity: 1
            }, 200);
        }, function () {
            arrows.stop().animate({
                opacity: 0
            }, 200);
        });
    } else {
        _container.hover(function () {
            _container.addClass('hover');
        }, function () {
            _container.removeClass('hover');
        });
    }

    // show/hide captions
    if (!Modernizr.csstransitions) {
        $sliderItems.hover(function () {
            $(this).find('.caption').stop().animate({
                bottom: 0
            }, 200);
        }, function () {
            $(this).find('.caption').stop().animate({
                bottom: -55
            }, 200);
        });
    } else {
        $sliderItems.hover(function () {
            $(this).addClass('hover');
        }, function () {
            $(this).removeClass('hover');
        });
    }
	
}

this.clearPreloadDiv = function(){
	trace("@remove");
	if(_preloadDiv == "") { return; }
	$(_preloadDiv).css({zIndex:"-1000000",display:"none"}).remove();
}

/*********************************************************************************
*	Handlers
**********************************************************************************/

this.handleAutoCompleteTimeout = function(){
	_this.GoToNext();
}

this.handleTouchMove = function(e) {
	if(!_allowPinchZoom && _TOUCH_EVENT_MULIT_TOUCH){
		e.preventDefault();
	}
}

this.handleDoubleTap = function(e) {
	e.preventDefault();	
}

this.handleCurrentChange = function(targetIndex){
	$(_navItem).each(function(i){
		if(i != targetIndex){
			$(this).removeClass("active").addClass("inactive");
		}
		else{
			$(this).removeClass("inactive").addClass("active");	
		}
	});
	if(_navItemCallback)
	{
		var t = $(_navItem).eq(targetIndex);
		_navItemCallback(t);
	}
}

this.handleNavItemIntent = function (e) {

    var target = $(e.target);
    var checkCount = 0;
    function checkParent() {
        checkCount++;
        if (target.hasClass('navWrapperInner') && checkCount < 5) {
            target = target.parent();
            checkParent();
        }
        else {
            _this.GoTo(target.index());
        }
    }
    checkParent();
	
	if(_autoScrollTimer){ _this.clearAutoScrollTimer(); }
}

this.handleNextMouseDown = function(){
	_this.GoToNext();
	if(_autoScrollTimer){ _this.clearAutoScrollTimer(); }
}

this.handlePreviousMouseDown = function() {
	_this.GoToPrevious();
	if(_autoScrollTimer){ _this.clearAutoScrollTimer(); }
}

this.handleSwipeRight = function() {
	_this.GoToPrevious();
	if(_autoScrollTimer){ _this.clearAutoScrollTimer(); }
}

this.handleSwipeLeft = function() {
	_this.GoToNext();
	if(_autoScrollTimer){ _this.clearAutoScrollTimer(); }
}

this.handleContainerOver = function () {
    if (!_hideBtnsAfterLoad) { return; }
    clearTimeout(_buttonFadeTimer);
    _nextBtn.stop().animate({ opacity: 1 }, 800);
    _prevBtn.stop().animate({ opacity: 1 }, 800);
}

this.handleContainerLeave = function(){
	if(!_hideBtnsAfterLoad){ return; }
	_nextBtn.stop().animate({opacity:0}, 1200);
	_prevBtn.stop().animate({opacity:0}, 1200);
}

/*********************************************************************************
*	Utility Methods
**********************************************************************************/

this.setButtonFadeTime = function(timeout){
	if(!_hideBtnsAfterLoad){ return; }
	_buttonFadeTimer = setTimeout(function(){
		_this.handleContainerLeave();
	}, timeout);
}

this.setIntentTimer = function(){
	_animationTimer = setTimeout(function(){
		if(_quedIntent && _queIntens){
			clearTimeout(_animationTimer);
			_animationTimer = null;
			_quedIntent();
			_quedIntent = null;
		}
		else {
		_this.clearIntentTimer();
		}
	}, _animationDuration);
}

this.clearIntentTimer = function(){
	clearTimeout(_animationTimer);
	_animationTimer = null;
}

this.GoToNext = function() {
	if(_animationTimer){ 
		_quedIntent = _this.GoToNext;
		return; 
	}
	else{ _this.setIntentTimer(); }
	
	var currentIndex = _container.find(".current").index();
	var goToIndex = currentIndex >= _container.find(".sliderItem").length - 1 ? 0 : currentIndex + 1;
	_this.Animate(goToIndex);
}

this.GoToPrevious = function () {
    if (_animationTimer) {
        _quedIntent = _this.GoToPrevious; 
        return;
    }
    else { _this.setIntentTimer(); }

    var currentIndex = _container.find(".current").index();
    var goToIndex = currentIndex <= 0 ? _container.find(".sliderItem").length - 1 : currentIndex - 1;
	
	var goLeftJustBecause = currentIndex == 0;
    _this.Animate(goToIndex, false, goLeftJustBecause);
}

this.GoTo = function(targetIndex) {
	if(_animationTimer){return;}
	else{ _this.setIntentTimer(); }
	_this.Animate(targetIndex, false);
}

this.RectifySorting = function(targetIndex, goLeftJustBecause){
	var limitIndex = _container.find(".sliderItem").length - 1;
	
	if(targetIndex == limitIndex){
		var target = _container.find(".sliderItem").eq(limitIndex);
		if(goLeftJustBecause){
			if (Modernizr.csstransitions) { target.removeClass("next").removeClass("previous").removeClass("right").addClass("left").stop(); }
			else { target.removeClass("next").removeClass("previous").removeClass("rightIE").addClass("leftIE").css({ left: "-100%" }).stop(); }
		}
		else{
			if(Modernizr.csstransitions){ target.removeClass("next").removeClass("previous").removeClass("left").addClass("right"); }
			else{ target.removeClass("next").removeClass("previous").removeClass("leftIE").addClass("rightIE").css({ left: "100%" }); }		
		}
		return true;
	}
	
	
	return false;
}

this.Animate = function (targetIndex, overrideLoopingLogic, goLeftJustBecause) {
	
    var current = _container.find(".current");
	var limit = _container.find(".sliderItem").length - 1;
    var firstItem, lastItem, loopToFirst, loopToLast;

	if(overrideLoopingLogic != true){
		if(_this.RectifySorting(targetIndex, goLeftJustBecause) && (current.index() == 0 && targetIndex == _container.find(".sliderItem").length - 1)){
			setTimeout(function () { 
			    _this.clearIntentTimer();
				_this.Animate(targetIndex, true, goLeftJustBecause); }, 10);
			return;
		}
	}
	
    // False as different than null -> used by _this.GoTo() to handle _navItem.click()
    if (overrideLoopingLogic != false) {
        loopToFirst = targetIndex == 0 && (current.index() == limit) && _infiniteLoop;
        loopToLast = targetIndex == limit && (current.index() == 0) && _infiniteLoop;
    }
	
	

    // Looping logic to wrap items around.
    // Check for null overrideLoopingLogic as way to handle jquery/browser animation threading.
    if (!overrideLoopingLogic) {
        if (loopToFirst) {
            firstItem = _container.find(".sliderItem").eq(0);
            if (Modernizr.csstransitions) { firstItem.removeClass("next").removeClass("previous").removeClass("left").addClass("right").stop(); }
            else { firstItem.removeClass("next").removeClass("previous").removeClass("leftIE").addClass("rightIE").css({ left: "100%" }).stop(); };
            setTimeout(function () { 
				_this.clearIntentTimer();
				_this.Animate(0, true, goLeftJustBecause); 
				}, 10);
            return;
        }
		
        if (loopToLast) {
            lastItem = _container.find(".sliderItem").eq(limit);
            if (Modernizr.csstransitions) { lastItem.removeClass("next").removeClass("previous").removeClass("right").addClass("left").stop(); }
            else { lastItem.removeClass("next").removeClass("previous").removeClass("rightIE").addClass("leftIE").css({ left: "-100%" }).stop(); }
            setTimeout(function () { 
				_this.clearIntentTimer();
				_this.Animate(_container.find(".sliderItem").length - 1, true, goLeftJustBecause); 
			}, 10);
            return;
        }
    }

    // Reset all items and push to ends (left or right)
    for (var i = 0; i < targetIndex; i++) {
        var left = _container.find(".sliderItem").eq(i);
        if (!left.hasClass("current") && !loopToFirst) {
            if (Modernizr.csstransitions) { left.removeClass("next").removeClass("previous").removeClass("right").addClass("left").stop(); }
            else { left.removeClass("next").removeClass("previous").removeClass("rightIE").addClass("leftIE").css({ left: "-100%" }).stop(); }
        }
    }

    for (var j = targetIndex + 1; j < _container.find(".sliderItem").length; j++) {
        var right = _container.find(".sliderItem").eq(j);
        if (!right.hasClass("current") && !loopToLast) {
            if (Modernizr.csstransitions) { right.removeClass("next").removeClass("previous").removeClass("left").addClass("right").stop(); }
            else { right.removeClass("next").removeClass("previous").removeClass("leftIE").addClass("rightIE").css({ left: "100%" }).stop(); }
        }
    }

    // Now apply CSS animations to only the visible elements; handle loop cases first
    if (((targetIndex > current.index() || loopToFirst) && !loopToLast) ||(current.index() == 0 && targetIndex == limit) && !goLeftJustBecause) {
        current.removeClass("current").addClass("previous");
		if (!Modernizr.csstransitions) {
            current.addClass("previousIE");
        }
    }
    else {
        current.removeClass("current").addClass("next");
        if (!Modernizr.csstransitions) {
            current.addClass("nextIE");
        }
    }

    // Apply to browsers without CSS animations by using the classes we just assinged to direct jQuery.animate()
    if (!Modernizr.csstransitions) {
        _container.find(".sliderItem.next").removeClass("rightIE").removeClass("leftIE").stop(true, false).animate({ left: "100%" }, 1000, 'easeInOutCubic');
        _container.find(".sliderItem.previous").removeClass("leftIE").removeClass("rightIE").stop(true, false).animate({ left: "-100%" }, 1000, 'easeInOutCubic');
        _container.find(".sliderItem").eq(targetIndex).removeClass("next").removeClass("previous").addClass("current").stop().animate({ left: "0" }, 1000, 'easeInOutCubic', function () {
            $(this).removeClass("leftIE").removeClass("rightIE");
            _container.find(".sliderItem.leftIE").css({ left: "-100%" });
            _container.find(".sliderItem.rightIE").css({ left: "100%" });
        });
    }
    else {
        _container.find(".sliderItem").eq(targetIndex).removeClass("next").removeClass("previous").removeClass("left").removeClass("right").addClass("current");
    }

    // Just to update _navItems  if they exist	
    _this.handleCurrentChange(targetIndex);
}



// Ready
$(document).ready(function () { _this.init(); });
}	// Ends Object
