1(function( window, $, undefined ) { 2 3 $.fn.touchwipe = function(settings) { 4 5 var config = { 6 min_move_x: 20, 7 min_move_y: 20, 8 wipeLeft: function() { }, 9 wipeRight: function() { }, 10 wipeUp: function() { }, 11 wipeDown: function() { }, 12 preventDefaultEvents: true 13 }; 14 15 if (settings) $.extend(config, settings); 16 17 this.each(function() { 18 var startX; 19 var startY; 20 var isMoving = false; 21 22 function cancelTouch() { 23 this.removeEventListener('touchmove', onTouchMove); 24 startX = null; 25 isMoving = false; 26 } 27 28 function onTouchMove(e) { 29 if(config.preventDefaultEvents) { 30 e.preventDefault(); 31 } 32 if(isMoving) { 33 var x = e.touches[0].pageX; 34 var y = e.touches[0].pageY; 35 var dx = startX - x; 36 var dy = startY - y; 37 if(Math.abs(dx) >= config.min_move_x) { 38 cancelTouch(); 39 if(dx > 0) { 40 config.wipeLeft(); 41 } 42 else { 43 config.wipeRight(); 44 } 45 } 46 else if(Math.abs(dy) >= config.min_move_y) { 47 cancelTouch(); 48 if(dy > 0) { 49 config.wipeDown(); 50 } 51 else { 52 config.wipeUp(); 53 } 54 } 55 } 56 } 57 58 function onTouchStart(e) 59 { 60 if (e.touches.length == 1) { 61 startX = e.touches[0].pageX; 62 startY = e.touches[0].pageY; 63 isMoving = true; 64 this.addEventListener('touchmove', onTouchMove, false); 65 } 66 } 67 if ('ontouchstart' in document.documentElement) { 68 this.addEventListener('touchstart', onTouchStart, false); 69 } 70 }); 71 72 return this; 73 }; 74 75 $.elastislide = function( options, element ) { 76 this.$el = $( element ); 77 this._init( options ); 78 }; 79 80 $.elastislide.defaults = { 81 speed : 450, // animation speed 82 easing : '', // animation easing effect 83 imageW : 190, // the images width 84 margin : 0, // image margin right 85 border : 0, // image border 86 minItems : 1, // the minimum number of items to show. 87 // when we resize the window, this will make sure minItems are always shown 88 // (unless of course minItems is higher than the total number of elements) 89 current : 0, // index of the current item 90 // when we resize the window, the carousel will make sure this item is visible 91 onClick : function() { return false; } // click item callback 92 }; 93 94 $.elastislide.prototype = { 95 _init : function( options ) { 96 97 this.options = $.extend( true, {}, $.elastislide.defaults, options ); 98 99 // <ul> 100 this.$slider = this.$el.find('ul'); 101 102 // <li> 103 this.$items = this.$slider.children('li'); 104 105 // total number of elements / images 106 this.itemsCount = this.$items.length; 107 108 // cache the <ul>'s parent, since we will eventually need to recalculate its width on window resize 109 this.$esCarousel = this.$slider.parent(); 110 111 // validate options 112 this._validateOptions(); 113 114 // set sizes and initialize some vars... 115 this._configure(); 116 117 // add navigation buttons 118 this._addControls(); 119 120 // initialize the events 121 this._initEvents(); 122 123 // show the <ul> 124 this.$slider.show(); 125 126 // slide to current's position 127 this._slideToCurrent( false ); 128 129 }, 130 _validateOptions : function() { 131 132 if( this.options.speed < 0 ) 133 this.options.speed = 450; 134 if( this.options.margin < 0 ) 135 this.options.margin = 4; 136 if( this.options.border < 0 ) 137 this.options.border = 1; 138 if( this.options.minItems < 1 || this.options.minItems > this.itemsCount ) 139 this.options.minItems = 1; 140 if( this.options.current > this.itemsCount - 1 ) 141 this.options.current = 0; 142 143 }, 144 _configure : function() { 145 146 // current item's index 147 this.current = this.options.current; 148 149 // the ul's parent's (div.es-carousel) width is the "visible" width 150 this.visibleWidth = this.$esCarousel.width(); 151 152 // test to see if we need to initially resize the items 153 if( this.visibleWidth < this.options.minItems * ( this.options.imageW + 2 * this.options.border ) + ( this.options.minItems - 1 ) * this.options.margin ) { 154 this._setDim( ( this.visibleWidth - ( this.options.minItems - 1 ) * this.options.margin ) / this.options.minItems ); 155 this._setCurrentValues();
156 // how many items fit with the current width 157 this.fitCount = this.options.minItems; 158 } 159 else { 160 this._setDim(); 161 this._setCurrentValues(); 162 } 163 164 // set the <ul> width 165 this.$slider.css({ 166 width : this.sliderW 167 }); 168 169 }, 170 _setDim : function( elW ) { 171 172 // <li> style 173 this.$items.css({ 174 marginRight : this.options.margin, 175 width : ( elW ) ? elW : this.options.imageW + 2 * this.options.border 176 }).children('a').css({ // <a> style 177 borderWidth : this.options.border 178 }); 179 180 }, 181 _setCurrentValues : function() { 182 183 // the total space occupied by one item 184 this.itemW = this.$items.outerWidth(true); 185 186 // total width of the slider / <ul> 187 // this will eventually change on window resize 188 this.sliderW = this.itemW * this.itemsCount; 189 190 // the ul parent's (div.es-carousel) width is the "visible" width 191 this.visibleWidth = this.$esCarousel.width(); 192 193 // how many items fit with the current width 194 this.fitCount = Math.floor( this.visibleWidth / this.itemW ); 195 196 }, 197 _addControls : function() { 198 199 this.$navNext = $('<span class="es-nav-next"><a>></a></span>'); 200 this.$navPrev = $('<span class="es-nav-prev"><a><</a></span>'); 201 $('<div class="es-nav"/>') 202 .append( this.$navPrev ) 203 .append( this.$navNext ) 204 .appendTo( this.$el ); 205 206 //this._toggleControls(); 207 208 }, 209 _toggleControls : function( dir, status ) { 210 211 // show / hide navigation buttons 212 if( dir && status ) { 213 if( status === 1 ) 214 ( dir === 'right' ) ? this.$navNext.show() : this.$navPrev.show(); 215 else 216 ( dir === 'right' ) ? this.$navNext.hide() : this.$navPrev.hide(); 217 } 218 else if( this.current === this.itemsCount - 1 || this.fitCount >= this.itemsCount ) 219 this.$navNext.hide(); 220 221 }, 222 _initEvents : function() { 223 224 var instance = this; 225 226 // window resize 227 $(window).bind('resize.elastislide', function( event ) { 228 229 // set values again 230 instance._setCurrentValues();
231 232 // need to resize items 233 if( instance.visibleWidth < instance.options.minItems * ( instance.options.imageW + 2 * instance.options.border ) + ( instance.options.minItems - 1 ) * instance.options.margin ) { 234 instance._setDim( ( instance.visibleWidth - ( instance.options.minItems - 1 ) * instance.options.margin ) / instance.options.minItems ); 235 instance._setCurrentValues(); 236 instance.fitCount = instance.options.minItems; 237 } 238 else{ 239 instance._setDim(); 240 instance._setCurrentValues(); 241 } 242 243 instance.$slider.css({ 244 width : instance.sliderW + 10 // TODO: +10px seems to solve a firefox "bug" :S 245 }); 246 247 // slide to the current element 248 clearTimeout( instance.resetTimeout ); 249 instance.resetTimeout = setTimeout(function() { 250 instance._slideToCurrent(); 251 }, 200); 252 253 }); 254 255 // navigation buttons events 256 this.$navNext.bind('click.elastislide', function( event ) { 257 instance._slide('right'); 258 }); 259 260 this.$navPrev.bind('click.elastislide', function( event ) { 261 instance._slide('left'); 262 }); 263 264 // item click event 265 this.$items.bind('click.elastislide', function( event ) { 266 instance.options.onClick( $(this) ); 267 //return false; 268 }); 269 270 // touch events 271 instance.$slider.touchwipe({ 272 wipeLeft : function() { 273 instance._slide('right'); 274 }, 275 wipeRight : function() { 276 instance._slide('left'); 277 } 278 }); 279 280 }, 281 _slide : function( dir, val, anim, callback ) { 282 283 // if animating return 284 if( this.$slider.is(':animated') ) 285 return false; 286 287 // current margin left 288 var ml = parseFloat( this.$slider.css('margin-left') ); 289 290 // val is just passed when we want an exact value for the margin left (used in the _slideToCurrent function) 291 if( val === undefined ) { 292 293 // how much to slide? 294 var amount = this.fitCount * this.itemW, val; 295 296 if( amount < 0 ) return false; 297 298 // make sure not to leave a space between the last item / first item and the end / beggining of the slider available width 299 if( dir === 'right' && this.sliderW - ( Math.abs( ml ) + amount ) < this.visibleWidth ) { 300 amount = this.sliderW - ( Math.abs( ml ) + this.visibleWidth ) - this.options.margin; // decrease the margin left 301 // show / hide navigation buttons 302 this._toggleControls( 'right', -1 ); 303 this._toggleControls( 'left', 1 ); 304 } 305 else if( dir === 'left' && Math.abs( ml ) - amount < 0 ) { 306 amount = Math.abs( ml ); 307 // show / hide navigation buttons 308 this._toggleControls( 'left', -1 ); 309 this._toggleControls( 'right', 1 ); 310 } 311 else { 312 var fml; // future margin left 313 ( dir === 'right' ) 314 ? fml = Math.abs( ml ) + this.options.margin + Math.abs( amount ) 315 : fml = Math.abs( ml ) - this.options.margin - Math.abs( amount ); 316 317 // show / hide navigation buttons 318 if( fml > 0 ) 319 this._toggleControls( 'left', 1 ); 320 else 321 this._toggleControls( 'left', -1 ); 322 323 if( fml < this.sliderW - this.visibleWidth ) 324 this._toggleControls( 'right', 1 ); 325 else 326 this._toggleControls( 'right', -1 ); 327 328 } 329 330 ( dir === 'right' ) ? val = '-=' + amount : val = '+=' + amount 331 332 } 333 else { 334 var fml = Math.abs( val ); // future margin left 335 336 if( Math.max( this.sliderW, this.visibleWidth ) - fml < this.visibleWidth ) { 337 val = - ( Math.max( this.sliderW, this.visibleWidth ) - this.visibleWidth ); 338 if( val !== 0 ) 339 val += this.options.margin; // decrease the margin left if not on the first position 340 341 // show / hide navigation buttons 342 this._toggleControls( 'right', -1 ); 343 fml = Math.abs( val ); 344 } 345 346 // show / hide navigation buttons 347 if( fml > 0 ) 348 this._toggleControls( 'left', 1 ); 349 else 350 this._toggleControls( 'left', -1 ); 351 352 if( Math.max( this.sliderW, this.visibleWidth ) - this.visibleWidth > fml + this.options.margin ) 353 this._toggleControls( 'right', 1 ); 354 else 355 this._toggleControls( 'right', -1 ); 356 357 } 358 359 $.fn.applyStyle = ( anim === undefined ) ? $.fn.animate : $.fn.css; 360 361 var sliderCSS = { marginLeft : val }; 362 363 var instance = this; 364 365 this.$slider.applyStyle( sliderCSS, $.extend( true, [], { duration : this.options.speed, easing : this.options.easing, complete : function() { 366 if( callback ) callback.call(); 367 } } ) ); 368 369 }, 370 _slideToCurrent : function( anim ) { 371 372 // how much to slide? 373 var amount = this.current * this.itemW; 374 this._slide('', -amount, anim ); 375 376 },
377 add : function( $newelems, callback ) { 378 379 // adds new items to the carousel 380 this.$items = this.$items.add( $newelems ); 381 this.itemsCount = this.$items.length; 382 this._setDim(); 383 this._setCurrentValues(); 384 this.$slider.css({ 385 width : this.sliderW 386 }); 387 this._slideToCurrent(); 388 389 if ( callback ) callback.call( $newelems ); 390 391 }, 392 destroy : function( callback ) { 393 this._destroy( callback ); 394 }, 395 _destroy : function( callback ) { 396 this.$el.unbind('.elastislide').removeData('elastislide'); 397 $(window).unbind('.elastislide'); 398 if ( callback ) callback.call(); 399 } 400 }; 401 402 var logError = function( message ) { 403 if ( this.console ) { 404 console.error( message ); 405 } 406 }; 407 408 $.fn.elastislide = function( options ) { 409 if ( typeof options === 'string' ) { 410 var args = Array.prototype.slice.call( arguments, 1 ); 411 412 this.each(function() { 413 var instance = $.data( this, 'elastislide' ); 414 if ( !instance ) { 415 logError( "cannot call methods on elastislide prior to initialization; " + 416 "attempted to call method '" + options + "'" ); 417 return; 418 } 419 if ( !$.isFunction( instance[options] ) || options.charAt(0) === "_" ) { 420 logError( "no such method '" + options + "' for elastislide instance" ); 421 return; 422 } 423 instance[ options ].apply( instance, args ); 424 }); 425 } 426 else { 427 this.each(function() { 428 var instance = $.data( this, 'elastislide' ); 429 if ( !instance ) { 430 $.data( this, 'elastislide', new $.elastislide( options, this ) ); 431 } 432 }); 433 } 434 return this; 435 }; 436 437})( window, jQuery );
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.