| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467 |
- (function( window, $, undefined ) {
-
- // http://www.netcu.de/jquery-touchwipe-iphone-ipad-library
- $.fn.touchwipe = function(settings) {
-
- var config = {
- min_move_x: 20,
- min_move_y: 20,
- wipeLeft: function() { },
- wipeRight: function() { },
- wipeUp: function() { },
- wipeDown: function() { },
- preventDefaultEvents: true
- };
-
- if (settings) $.extend(config, settings);
-
- this.each(function() {
- var startX;
- var startY;
- var isMoving = false;
-
- function cancelTouch() {
- this.removeEventListener('touchmove', onTouchMove);
- startX = null;
- isMoving = false;
- }
-
- function onTouchMove(e) {
- if(config.preventDefaultEvents) {
- e.preventDefault();
- }
- if(isMoving) {
- var x = e.touches[0].pageX;
- var y = e.touches[0].pageY;
- var dx = startX - x;
- var dy = startY - y;
- if(Math.abs(dx) >= config.min_move_x) {
- cancelTouch();
- if(dx > 0) {
- config.wipeLeft();
- }
- else {
- config.wipeRight();
- }
- }
- else if(Math.abs(dy) >= config.min_move_y) {
- cancelTouch();
- if(dy > 0) {
- config.wipeDown();
- }
- else {
- config.wipeUp();
- }
- }
- }
- }
-
- function onTouchStart(e)
- {
- if (e.touches.length == 1) {
- startX = e.touches[0].pageX;
- startY = e.touches[0].pageY;
- isMoving = true;
- this.addEventListener('touchmove', onTouchMove, false);
- }
- }
- if ('ontouchstart' in document.documentElement) {
- this.addEventListener('touchstart', onTouchStart, false);
- }
- });
-
- return this;
- };
-
- $.elastislide = function( options, element ) {
- this.$el = $( element );
- this._init( options );
- };
-
- $.elastislide.defaults = {
- speed : 450, // animation speed
- easing : '', // animation easing effect
- imageW : 190, // the images width
- margin : 3, // image margin right
- border : 2, // image border
- minItems : 1, // the minimum number of items to show.
- // when we resize the window, this will make sure minItems are always shown
- // (unless of course minItems is higher than the total number of elements)
- current : 0, // index of the current item
- // when we resize the window, the carousel will make sure this item is visible
- onClick : function() { return false; } // click item callback
- };
-
- $.elastislide.prototype = {
- _init : function( options ) {
-
- this.options = $.extend( true, {}, $.elastislide.defaults, options );
-
- // <ul>
- this.$slider = this.$el.find('ul');
-
- // <li>
- this.$items = this.$slider.children('li');
-
- // total number of elements / images
- this.itemsCount = this.$items.length;
-
- // cache the <ul>'s parent, since we will eventually need to recalculate its width on window resize
- this.$esCarousel = this.$slider.parent();
-
- // validate options
- this._validateOptions();
-
- // set sizes and initialize some vars...
- this._configure();
-
- // add navigation buttons
- this._addControls();
-
- // initialize the events
- this._initEvents();
-
- // show the <ul>
- this.$slider.show();
-
- // slide to current's position
- this._slideToCurrent( false );
-
- },
- _validateOptions : function() {
-
- if( this.options.speed < 0 )
- this.options.speed = 450;
- if( this.options.margin < 0 )
- this.options.margin = 4;
- if( this.options.border < 0 )
- this.options.border = 1;
- if( this.options.minItems < 1 || this.options.minItems > this.itemsCount )
- this.options.minItems = 1;
- if( this.options.current > this.itemsCount - 1 )
- this.options.current = 0;
-
- },
- _configure : function() {
-
- // current item's index
- this.current = this.options.current;
-
- // the ul's parent's (div.es-carousel) width is the "visible" width
- this.visibleWidth = this.$esCarousel.width();
-
- // test to see if we need to initially resize the items
- if( this.visibleWidth < this.options.minItems * ( this.options.imageW + 2 * this.options.border ) + ( this.options.minItems - 1 ) * this.options.margin ) {
- this._setDim( ( this.visibleWidth - ( this.options.minItems - 1 ) * this.options.margin ) / this.options.minItems );
- this._setCurrentValues();
- // how many items fit with the current width
- this.fitCount = this.options.minItems;
- }
- else {
- this._setDim();
- this._setCurrentValues();
- }
-
- // set the <ul> width
- this.$slider.css({
- width : this.sliderW
- });
-
- },
- _setDim : function( elW ) {
-
- // <li> style
- this.$items.css({
- marginRight : this.options.margin,
- width : ( elW ) ? elW : this.options.imageW + 2 * this.options.border
- }).children('a').css({ // <a> style
- borderWidth : this.options.border
- });
-
- },
- _setCurrentValues : function() {
-
- // the total space occupied by one item
- this.itemW = this.$items.outerWidth(true);
-
- // total width of the slider / <ul>
- // this will eventually change on window resize
- this.sliderW = this.itemW * this.itemsCount;
-
- // the ul parent's (div.es-carousel) width is the "visible" width
- this.visibleWidth = this.$esCarousel.width();
-
- // how many items fit with the current width
- this.fitCount = Math.floor( this.visibleWidth / this.itemW );
-
- },
- _addControls : function() {
-
- this.$navNext = $('<span class="es-nav-next">Next</span>');
- this.$navPrev = $('<span class="es-nav-prev">Previous</span>');
- $('<div class="es-nav"/>')
- .append( this.$navPrev )
- .append( this.$navNext )
- .appendTo( this.$el );
-
- //this._toggleControls();
-
- },
- _toggleControls : function( dir, status ) {
-
- // show / hide navigation buttons
- if( dir && status ) {
- if( status === 1 )
- ( dir === 'right' ) ? this.$navNext.show() : this.$navPrev.show();
- else
- ( dir === 'right' ) ? this.$navNext.hide() : this.$navPrev.hide();
- }
- else if( this.current === this.itemsCount - 1 || this.fitCount >= this.itemsCount )
- this.$navNext.hide();
-
- },
- _initEvents : function() {
-
- var instance = this;
-
- // window resize
- $(window).bind('resize.elastislide', function( event ) {
-
- instance._reload();
-
- // slide to the current element
- clearTimeout( instance.resetTimeout );
- instance.resetTimeout = setTimeout(function() {
- instance._slideToCurrent();
- }, 200);
-
- });
-
- // navigation buttons events
- this.$navNext.bind('click.elastislide', function( event ) {
- instance._slide('right');
- });
-
- this.$navPrev.bind('click.elastislide', function( event ) {
- instance._slide('left');
- });
-
- // item click event
- this.$items.bind('click.elastislide', function( event ) {
- instance.options.onClick( $(this) );
- return false;
- });
-
- // touch events
- instance.$slider.touchwipe({
- wipeLeft : function() {
- instance._slide('right');
- },
- wipeRight : function() {
- instance._slide('left');
- }
- });
-
- },
- reload : function( callback ) {
- this._reload();
- if ( callback ) callback.call();
-
- },
- _reload : function() {
-
- var instance = this;
-
- // set values again
- instance._setCurrentValues();
-
- // need to resize items
- if( instance.visibleWidth < instance.options.minItems * ( instance.options.imageW + 2 * instance.options.border ) + ( instance.options.minItems - 1 ) * instance.options.margin ) {
- instance._setDim( ( instance.visibleWidth - ( instance.options.minItems - 1 ) * instance.options.margin ) / instance.options.minItems );
- instance._setCurrentValues();
- instance.fitCount = instance.options.minItems;
- }
- else{
- instance._setDim();
- instance._setCurrentValues();
- }
-
- instance.$slider.css({
- width : instance.sliderW + 10 // TODO: +10px seems to solve a firefox "bug" :S
- });
-
- },
- _slide : function( dir, val, anim, callback ) {
-
- // if animating return
- //if( this.$slider.is(':animated') )
- //return false;
-
- // current margin left
- var ml = parseFloat( this.$slider.css('margin-left') );
-
- // val is just passed when we want an exact value for the margin left (used in the _slideToCurrent function)
- if( val === undefined ) {
-
- // how much to slide?
- var amount = this.fitCount * this.itemW, val;
-
- if( amount < 0 ) return false;
-
- // make sure not to leave a space between the last item / first item and the end / beggining of the slider available width
- if( dir === 'right' && this.sliderW - ( Math.abs( ml ) + amount ) < this.visibleWidth ) {
- amount = this.sliderW - ( Math.abs( ml ) + this.visibleWidth ) - this.options.margin; // decrease the margin left
- // show / hide navigation buttons
- this._toggleControls( 'right', -1 );
- this._toggleControls( 'left', 1 );
- }
- else if( dir === 'left' && Math.abs( ml ) - amount < 0 ) {
- amount = Math.abs( ml );
- // show / hide navigation buttons
- this._toggleControls( 'left', -1 );
- this._toggleControls( 'right', 1 );
- }
- else {
- var fml; // future margin left
- ( dir === 'right' )
- ? fml = Math.abs( ml ) + this.options.margin + Math.abs( amount )
- : fml = Math.abs( ml ) - this.options.margin - Math.abs( amount );
-
- // show / hide navigation buttons
- if( fml > 0 )
- this._toggleControls( 'left', 1 );
- else
- this._toggleControls( 'left', -1 );
-
- if( fml < this.sliderW - this.visibleWidth )
- this._toggleControls( 'right', 1 );
- else
- this._toggleControls( 'right', -1 );
-
- }
-
- ( dir === 'right' ) ? val = '-=' + amount : val = '+=' + amount
-
- }
- else {
- var fml = Math.abs( val ); // future margin left
-
- if( Math.max( this.sliderW, this.visibleWidth ) - fml < this.visibleWidth ) {
- val = - ( Math.max( this.sliderW, this.visibleWidth ) - this.visibleWidth );
- if( val !== 0 )
- val += this.options.margin; // decrease the margin left if not on the first position
-
- // show / hide navigation buttons
- this._toggleControls( 'right', -1 );
- fml = Math.abs( val );
- }
-
- // show / hide navigation buttons
- if( fml > 0 )
- this._toggleControls( 'left', 1 );
- else
- this._toggleControls( 'left', -1 );
-
- if( Math.max( this.sliderW, this.visibleWidth ) - this.visibleWidth > fml + this.options.margin )
- this._toggleControls( 'right', 1 );
- else
- this._toggleControls( 'right', -1 );
-
- }
-
- $.fn.applyStyle = ( anim === undefined ) ? $.fn.animate : $.fn.css;
-
- var sliderCSS = { marginLeft : val };
-
- var instance = this;
-
- this.$slider.stop().applyStyle( sliderCSS, $.extend( true, [], { duration : this.options.speed, easing : this.options.easing, complete : function() {
- if( callback ) callback.call();
- } } ) );
-
- },
- _slideToCurrent : function( anim ) {
-
- // how much to slide?
- var amount = this.current * this.itemW;
- this._slide('', -amount, anim );
-
- },
- add : function( $newelems, callback ) {
-
- // adds new items to the carousel
- this.$items = this.$items.add( $newelems );
- this.itemsCount = this.$items.length;
- this._setDim();
- this._setCurrentValues();
- this.$slider.css({
- width : this.sliderW
- });
- this._slideToCurrent();
-
- if ( callback ) callback.call( $newelems );
-
- },
- setCurrent : function( idx, callback ) {
-
- this.current = idx;
-
- var ml = Math.abs( parseFloat( this.$slider.css('margin-left') ) ),
- posR = ml + this.visibleWidth,
- fml = Math.abs( this.current * this.itemW );
-
- if( fml + this.itemW > posR || fml < ml ) {
- this._slideToCurrent();
- }
-
- if ( callback ) callback.call();
-
- },
- destroy : function( callback ) {
-
- this._destroy( callback );
-
- },
- _destroy : function( callback ) {
- this.$el.unbind('.elastislide').removeData('elastislide');
- $(window).unbind('.elastislide');
- if ( callback ) callback.call();
- }
- };
-
- var logError = function( message ) {
- if ( this.console ) {
- console.error( message );
- }
- };
-
- $.fn.elastislide = function( options ) {
- if ( typeof options === 'string' ) {
- var args = Array.prototype.slice.call( arguments, 1 );
-
- this.each(function() {
- var instance = $.data( this, 'elastislide' );
- if ( !instance ) {
- logError( "cannot call methods on elastislide prior to initialization; " +
- "attempted to call method '" + options + "'" );
- return;
- }
- if ( !$.isFunction( instance[options] ) || options.charAt(0) === "_" ) {
- logError( "no such method '" + options + "' for elastislide instance" );
- return;
- }
- instance[ options ].apply( instance, args );
- });
- }
- else {
- this.each(function() {
- var instance = $.data( this, 'elastislide' );
- if ( !instance ) {
- $.data( this, 'elastislide', new $.elastislide( options, this ) );
- }
- });
- }
- return this;
- };
-
- })( window, jQuery );
|