Created
January 9, 2015 01:49
-
-
Save ginlime/1c3899aea48ca29cc80f to your computer and use it in GitHub Desktop.
jQuery UI widget version of jCarouselLite
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*! | |
* jQuery UI jCarouselLite | |
* | |
* Copyright 2015, Startia Lab | |
* Dual licensed under the MIT or GPL Version 2 licenses. | |
* http://jquery.org/license | |
* | |
* Ported from jCarouselLite v1.1 to UI widget | |
* http://www.gmarwaha.com/jquery/jcarousellite/ | |
* | |
* Depends: | |
* jquery.ui.core.js | |
* jquery.ui.widget.js | |
*/ | |
(function($) { | |
var nameSpaceCnt = 0, | |
elemBaseCSSProp = ['visibility','overflow','position','z-index','left'], | |
ulBaseCSSProp = ['margin','padding','position','list-style','z-index'], | |
liBaseCSSProp = ['overflow','float','width','height']; | |
$.widget('ui.jCarouselLite', { | |
version: '1.0.0', | |
options: { | |
disableClass: 'disabled', // Class Selector which prevents button action | |
btnPrev: null, // CSS Selector for the previous button | |
btnNext: null, // CSS Selector for the next button | |
btnGo: null, // CSS Selector for the go button | |
mouseWheel: false, // Set "true" if you want the carousel scrolled using mouse wheel | |
auto: null, // Set to a numeric value (800) in millis. Time period between auto scrolls | |
speed: 200, // Set to a numeric value in millis. Speed of scroll | |
easing: null, // Set to easing (bounceout) to specify the animation easing | |
vertical: false, // Set to "true" to make the carousel scroll vertically | |
circular: true, // Set to "true" to make it an infinite carousel | |
visible: 3, // Set to a numeric value to specify the number of visible elements at a time | |
start: 0, // Set to a numeric value to specify which item to start from | |
scroll: 1, // Set to a numeric value to specify how many items to scroll for one scroll event | |
beforeStart: null, // Set to a function to receive a callback before every scroll start | |
afterEnd: null // Set to a function to receive a callback after every scroll end | |
}, | |
isRunning: false, | |
animCss: 'left', | |
sizeCss: 'width', | |
initialItemLength: 0, | |
numVisible: 0, | |
li: null, | |
calculatedTo: 0, | |
itemLength: 0, | |
liSize: 0, | |
nameSpace: '', | |
autoTimeout: null, | |
elemCss: {}, | |
ulCss: {}, | |
liCss: {}, | |
_create: function(){ | |
var self = this, | |
options = self.options, | |
elem = self.element, | |
ul = elem.find('>ul'); | |
self.nameSpace = 'jCarouselLite' + nameSpaceCnt; | |
nameSpaceCnt++; | |
/* initVariables */ | |
if(options.vertical) { | |
self.animCss = 'top'; | |
self.sizeCss = 'height'; | |
} | |
if(ul.length == 0){ | |
return false; /* Not valid */ | |
} | |
var _initialLI = ul.find('>li'); | |
self.initialItemLength = _initialLI.length; | |
self.numVisible = self.initialItemLength < options.visible ? self.initialItemLength : options.visible; | |
if(options.circular) { | |
var $lastItemSet = _initialLI.slice(self.initialItemLength-self.numVisible).clone(); | |
var $firstItemSet = _initialLI.slice(0,self.numVisible).clone(); | |
_initialLI.each(function(){ | |
$(this).attr('data-default','1') | |
}); | |
ul.prepend($lastItemSet) | |
.append($firstItemSet); | |
options.start += self.numVisible; | |
} | |
self.li = $('li', ul); | |
self.itemLength = self.li.length; | |
self.calculatedTo = options.start; | |
/* initStyles */ | |
var _elemCSSLen = elemBaseCSSProp.length; | |
self.elemCss[self.sizeCss] = elem.css(self.sizeCss); | |
for(var i = 0; i < _elemCSSLen; i++){ | |
self.elemCss[elemBaseCSSProp[i]] = elem.css(elemBaseCSSProp[i]); | |
} | |
elem.css('visibility', 'visible'); | |
var _ulCSSLen = ulBaseCSSProp.length; | |
self.ulCss[self.sizeCss] = ul.css(self.sizeCss); | |
self.ulCss[self.animCss] = ul.css(self.animCss); | |
for(var i = 0; i < _ulCSSLen; i++){ | |
self.ulCss[ulBaseCSSProp[i]] = ul.css(ulBaseCSSProp[i]); | |
} | |
var _liCSSLen = liBaseCSSProp.length; | |
self.liCss[self.sizeCss] = self.li.css(self.sizeCss); | |
self.liCss[self.animCss] = self.li.css(self.animCss); | |
for(var i = 0; i < _liCSSLen; i++){ | |
self.liCss[liBaseCSSProp[i]] = self.li.css(liBaseCSSProp[i]); | |
} | |
self.li.css({ | |
'overflow':'hidden', | |
'float':options.vertical ? 'none':'left' | |
}); | |
ul.css({ | |
'margin':'0', | |
'padding':'0', | |
'position':'relative', | |
'list-style':'none', | |
'z-index':'1' | |
}); | |
elem.css({ | |
'overflow':'hidden', | |
'position':'relative', | |
'z-index':'2', | |
'left':'0px' | |
}); | |
if(!options.circular && options.btnPrev && options.start == 0) { | |
$(options.btnPrev).addClass('disabled'); | |
} | |
/* initSizes */ | |
self.liSize = options.vertical ? self.li.outerHeight(true) : self.li.outerWidth(true); | |
var ulSize = self.liSize * self.itemLength, | |
divSize = self.liSize * self.numVisible; | |
self.li.css({ | |
width: self.li.width(), | |
height: self.li.height() | |
}); | |
ul.css(self.sizeCss, ulSize+'px') | |
.css(self.animCss, -(self.calculatedTo * self.liSize)); | |
elem.css(self.sizeCss, divSize+'px'); | |
/* attachEventHandlers */ | |
if(options.btnPrev && $(options.btnPrev).length > 0) { | |
$(options.btnPrev).on('click.'+self.nameSpace,function() { | |
if(!$(this).hasClass(options.disableClass)){ | |
return self._go(self.calculatedTo - options.scroll); | |
} | |
}); | |
} | |
if(options.btnNext && $(options.btnNext).length > 0) { | |
$(options.btnNext).on('click.'+self.nameSpace,function() { | |
if(!$(this).hasClass(options.disableClass)){ | |
return self._go(self.calculatedTo + options.scroll); | |
} | |
}); | |
} | |
if(options.btnGo && $(options.btnGo).length > 0) { | |
$.each(options.btnGo, function(i, val) { | |
$(val).on('click.'+self.nameSpace,function() { | |
return self._go(options.circular ? self.numVisible + i : i); | |
}); | |
}); | |
} | |
if(options.mouseWheel && elem.mousewheel) { | |
elem.on('mousewheel.'+self.nameSpace,function(e, d) { | |
console.log('moving'); | |
return d > 0 ? | |
self._go(self.calculatedTo - options.scroll) : | |
self._go(self.calculatedTo + options.scroll); | |
}); | |
} | |
if(options.auto) { | |
self._setupAutoScroll(); | |
} | |
}, | |
_init: function(){ | |
}, | |
_destroy: function(){ | |
var self = this, | |
elem = self.element, | |
options = self.options; | |
elem.css(self.elemCss) | |
.find('>ul').css(self.ulCss) | |
.find('>li').css(self.liCss).each(function(){ | |
if($(this).attr('data-default') === undefined){ | |
$(this).remove(); | |
} else { | |
$(this).removeAttr('data-default'); | |
} | |
}); | |
if(options.btnPrev && $(options.btnPrev).length > 0) { | |
$(options.btnPrev).off('click.'+self.nameSpace); | |
} | |
if(options.btnNext && $(options.btnNext).length > 0) { | |
$(options.btnNext).off('click.'+self.nameSpace); | |
} | |
if(options.btnGo && $(options.btnGo).length > 0) { | |
$.each(options.btnGo, function(i, val) { | |
$(val).off('click.'+self.nameSpace); | |
}); | |
} | |
return self; | |
}, | |
widget: function(){ | |
return this.element; | |
}, | |
ver: function(){ | |
return this.version; | |
}, | |
visibleItems: function(){ | |
return this.options.visible; | |
}, | |
_refreshView: function(){ | |
var self = this; | |
self._destroy(); | |
self._create(); | |
}, | |
_setOptions: function(options){ | |
var self = this; | |
if(options['visible'] !== undefined && options['start'] === undefined){ | |
options['start'] = 0; | |
} | |
$.each(options, function(key, value){ | |
self._setOption(key, value); | |
}); | |
self._refreshView(); | |
}, | |
_setOption: function(key, value){ | |
var self = this; | |
$.Widget.prototype._setOption.apply(self, arguments); | |
}, | |
_setupAutoScroll: function(){ | |
var self = this; | |
self.autoTimeout = setTimeout(function() { | |
self._go(self.calculatedTo + options.scroll); | |
}, self.options.auto); | |
}, | |
_visibleItems: function(){ | |
var self = this; | |
return self.li.slice(self.calculatedTo).slice(0,self.numVisible); | |
}, | |
_go: function(to){ | |
var self = this, | |
options = self.options; | |
if(!self.isRunning) { | |
clearTimeout(self.autoTimeout); | |
self.calculatedTo = to; | |
if(options.beforeStart) { | |
options.beforeStart.call(this, self._visibleItems()); | |
} | |
if(options.circular) { | |
self._adjustOobForCircular(to); | |
} else { | |
self._adjustOobForNonCircular(to); | |
} | |
self._animateToPosition({ | |
start: function() { | |
self.isRunning = true; | |
}, | |
done: function() { | |
if(options.afterEnd) { | |
options.afterEnd.call(this, self._visibleItems()); | |
} | |
if(options.auto) { | |
self._setupAutoScroll(); | |
} | |
self.isRunning = false; | |
} | |
}); | |
if(!options.circular) { | |
self._disableOrEnableButtons(); | |
} | |
} | |
return false; | |
}, | |
_adjustOobForCircular: function(to){ | |
var self = this, | |
elem = self.element, | |
ul = elem.find('>ul'), | |
options = self.options, | |
newPosition; | |
// If first, then goto last | |
if(to <= options.start - self.numVisible - 1) { | |
newPosition = to + self.initialItemLength + options.scroll; | |
ul.css(self.animCss, -(newPosition * self.liSize) + 'px'); | |
self.calculatedTo = newPosition - options.scroll; | |
/* console.log('Before - Positioned at: ' + newPosition + ' and Moving to: ' + self.calculatedTo); */ | |
} | |
// If last, then goto first | |
else if(to >= self.itemLength - self.numVisible + 1) { | |
newPosition = to - self.initialItemLength - options.scroll; | |
ul.css(self.animCss, -(newPosition * self.liSize) + 'px'); | |
self.calculatedTo = newPosition + options.scroll; | |
/* console.log('After - Positioned at: ' + newPosition + ' and Moving to: ' + self.calculatedTo); */ | |
} | |
}, | |
_adjustOobForNonCircular: function(to){ | |
var self = this; | |
// If user clicks "prev" and tries to go before the first element, reset it to first element. | |
if(to < 0) { | |
self.calculatedTo = 0; | |
} | |
// If "to" is greater than the max index that we can use to show another set of elements | |
// it means that we will have to reset "to" to a smallest possible index that can show it | |
else if(to > self.itemLength - self.numVisible) { | |
self.calculatedTo = self.itemLength - self.numVisible; | |
} | |
/* console.log('Item Length: ' + self.itemLength + '; ' + | |
'To: ' + to + '; ' + | |
'CalculatedTo: ' + self.calculatedTo + '; ' + | |
'Num Visible: ' + self.numVisible); */ | |
}, | |
_disableOrEnableButtons: function(){ | |
var self = this, | |
options = self.options; | |
$(options.btnPrev + ',' + options.btnNext).removeClass('disabled'); | |
$( (self.calculatedTo - options.scroll < 0 && options.btnPrev) | |
|| | |
(self.calculatedTo + options.scroll > self.itemLength - self.numVisible && options.btnNext) | |
|| | |
[] | |
).addClass('disabled'); | |
}, | |
_animateToPosition: function(animationOptions){ | |
var self = this, | |
options = self.options; | |
self.isRunning = true; | |
self.element.find('>ul').animate( | |
self.animCss == 'left' ? | |
{ left: -(self.calculatedTo * self.liSize) } : | |
{ top: -(self.calculatedTo * self.liSize) }, | |
$.extend({ | |
duration: options.speed, | |
easing: options.easing | |
}, animationOptions) | |
); | |
} | |
}); | |
})(jQuery); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment