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