1/** 2 * jquery.flipshow.js v1.0.0 3 * http://www.codrops.com 4 * 5 * Licensed under the MIT license. 6 * http://www.opensource.org/licenses/mit-license.php 7 * 8 * Copyright 2013, Codrops 9 * http://www.codrops.com 10 */ 11;( function( $, window, undefined ) { 12 13 'use strict'; 14 15 // ======================= imagesLoaded Plugin =============================== 16 // https://github.com/desandro/imagesloaded 17 18 // $('#my-container').imagesLoaded(myFunction) 19 // execute a callback when all images have loaded. 20 // needed because .load() doesn't work on cached images 21 22 // callback function gets image collection as argument 23 // this is the container 24 25 // original: mit license. paul irish. 2010. 26 // contributors: Oren Solomianik, David DeSandro, Yiannis Chatzikonstantinou 27 28 // blank image data-uri bypasses webkit log warning (thx doug jones) 29 // blank image data-uri bypasses webkit log warning (thx doug jones) 30 var BLANK = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw=='; 31 32 $.fn.imagesLoaded = function( callback ) { 33 var $this = this, 34 deferred = $.isFunction($.Deferred) ? $.Deferred() : 0, 35 hasNotify = $.isFunction(deferred.notify), 36 $images = $this.find('img').add( $this.filter('img') ), 37 loaded = [], 38 proper = [], 39 broken = []; 40 41 // Register deferred callbacks 42 if ($.isPlainObject(callback)) { 43 $.each(callback, function (key, value) { 44 if (key === 'callback') { 45 callback = value; 46 } else if (deferred) { 47 deferred[key](value); 48 } 49 }); 50 } 51 52 function doneLoading() { 53 var $proper = $(proper), 54 $broken = $(broken); 55 56 if ( deferred ) { 57 if ( broken.length ) { 58 deferred.reject( $images, $proper, $broken ); 59 } else { 60 deferred.resolve( $images ); 61 } 62 } 63 64 if ( $.isFunction( callback ) ) { 65 callback.call( $this, $images, $proper, $broken ); 66 } 67 } 68 69 function imgLoadedHandler( event ) { 70 imgLoaded( event.target, event.type === 'error' ); 71 } 72 73 function imgLoaded( img, isBroken ) { 74 // don't proceed if BLANK image, or image is already loaded 75 if ( img.src === BLANK || $.inArray( img, loaded ) !== -1 ) { 76 return; 77 } 78 79 // store element in loaded images array 80 loaded.push( img ); 81 82 // keep track of broken and properly loaded images 83 if ( isBroken ) { 84 broken.push( img ); 85 } else { 86 proper.push( img ); 87 } 88 89 // cache image and its state for future calls 90 $.data( img, 'imagesLoaded', { isBroken: isBroken, src: img.src } ); 91 92 // trigger deferred progress method if present 93 if ( hasNotify ) { 94 deferred.notifyWith( $(img), [ isBroken, $images, $(proper), $(broken) ] ); 95 } 96 97 // call doneLoading and clean listeners if all images are loaded 98 if ( $images.length === loaded.length ) { 99 setTimeout( doneLoading ); 100 $images.unbind( '.imagesLoaded', imgLoadedHandler ); 101 } 102 } 103 104 // if no images, trigger immediately 105 if ( !$images.length ) { 106 doneLoading(); 107 } else { 108 $images.bind( 'load.imagesLoaded error.imagesLoaded', imgLoadedHandler ) 109 .each( function( i, el ) { 110 var src = el.src; 111 112 // find out if this image has been already checked for status 113 // if it was, and src has not changed, call imgLoaded on it 114 var cached = $.data( el, 'imagesLoaded' ); 115 if ( cached && cached.src === src ) { 116 imgLoaded( el, cached.isBroken ); 117 return; 118 } 119 120 // if complete is true and browser supports natural sizes, try 121 // to check for image status manually 122 if ( el.complete && el.naturalWidth !== undefined ) { 123 imgLoaded( el, el.naturalWidth === 0 || el.naturalHeight === 0 ); 124 return; 125 } 126 127 // cached images don't fire load sometimes, so we reset src, but only when 128 // dealing with IE, or image is complete (loaded) and failed manual check 129 // webkit hack from http://groups.google.com/group/jquery-dev/browse_thread/thread/eee6ab7b2da50e1f 130 if ( el.readyState || el.complete ) { 131 el.src = BLANK; 132 el.src = src; 133 } 134 }); 135 } 136 137 return deferred ? deferred.promise( $this ) : $this; 138 }; 139 140 // global 141 var Modernizr = window.Modernizr; 142 143 $.Flipshow = function( options, element ) { 144 this.$el = $( element ); 145 this._init( options ); 146 }; 147 148 // the options 149 $.Flipshow.defaults = { 150 // default transition speed (ms) 151 speed : 700, 152 // default transition easing 153 easing : 'cubic-bezier(.29,1.44,.86,1.06)' 154 }; 155 156 $.Flipshow.prototype = { 157 _init : function( options ) { 158 159 // options 160 this.options = $.extend( true, {}, $.Flipshow.defaults, options ); 161 // support for CSS Transitions & 3D transforms 162 this.support = Modernizr.csstransitions && Modernizr.csstransforms3d; 163 // transition end event name and transform name 164 var transEndEventNames = { 165 'WebkitTransition' : 'webkitTransitionEnd', 166 'MozTransition' : 'transitionend', 167 'OTransition' : 'oTransitionEnd', 168 'msTransition' : 'MSTransitionEnd', 169 'transition' : 'transitionend' 170 }, 171 transformNames = { 172 'WebkitTransform' : '-webkit-transform', 173 'MozTransform' : '-moz-transform', 174 'OTransform' : '-o-transform', 175 'msTransform' : '-ms-transform', 176 'transform' : 'transform' 177 }; 178 179 if( this.support ) { 180 this.transEndEventName = transEndEventNames[ Modernizr.prefixed( 'transition' ) ] + '.cbpFWSlider'; 181 this.transformName = transformNames[ Modernizr.prefixed( 'transform' ) ]; 182 } 183 this.transitionProperties = this.transformName + ' ' + this.options.speed + 'ms ' + this.options.easing; 184 185 // the list of items 186 this.$listItems = this.$el.children( 'ul.fc-slides' ); 187 // the items 188 this.$items = this.$listItems.children( 'li' ).hide(); 189 // total number of items 190 this.itemsCount = this.$items.length; 191 // current item´s index 192 this.current = 0; 193 this.$listItems.imagesLoaded( $.proxy( function() { 194 // show first item 195 this.$items.eq( this.current ).show(); 196 // add navigation and flipping structure 197 if( this.itemsCount > 0 ) { 198 this._addNav(); 199 if( this.support ) { 200 this._layout(); 201 } 202 } 203 }, this ) ); 204 205 }, 206 _addNav : function() { 207 208 var self = this, 209 $navLeft = $( '<div class="fc-left"><span></span><span></span><span></span><i class="icon-arrow-left"></i></div>' ), 210 $navRight = $( '<div class="fc-right"><span></span><span></span><span></span><i class="icon-arrow-right"></i></div>' ); 211 212 $( '<nav></nav>' ).append( $navLeft, $navRight ).appendTo( this.$el ); 213 214 $navLeft.find( 'span' ).on( 'click.flipshow touchstart.flipshow', function() { 215 self._navigate( $( this ), 'left' ); 216 } ); 217 218 $navRight.find( 'span' ).on( 'click.flipshow touchstart.flipshow', function() { 219 self._navigate( $( this ), 'right' ); 220 } ); 221 222 }, 223 _layout : function( $current, $next ) { 224 225 this.$flipFront = $( '<div class="fc-front"><div></div></div>' ); 226 this.$frontContent = this.$flipFront.children( 'div:first' ); 227 this.$flipBack = $( '<div class="fc-back"><div></div></div>' ); 228 this.$backContent = this.$flipBack.children( 'div:first' ); 229 this.$flipEl = $( '<div class="fc-flip"></div>' ).append( this.$flipFront, this.$flipBack ).hide().appendTo( this.$el ); 230 231 }, 232 _navigate : function( $nav, dir ) { 233 234 if( this.isAnimating && this.support ) { 235 return false;
236 } 237 this.isAnimating = true; 238 239 var $currentItem = this.$items.eq( this.current ).hide(); 240 241 if( dir === 'right' ) { 242 this.current < this.itemsCount - 1 ? ++this.current : this.current = 0; 243 } 244 else if( dir === 'left' ) { 245 this.current > 0 ? --this.current : this.current = this.itemsCount - 1; 246 } 247 248 var $nextItem = this.$items.eq( this.current ); 249 250 if( this.support ) { 251 this._flip( $currentItem, $nextItem, dir, $nav.index() ); 252 } 253 else { 254 $nextItem.show(); 255 } 256 257 }, 258 _flip : function( $currentItem, $nextItem, dir, angle ) { 259 260 var transformProperties = '', 261 // overlays 262 $overlayLight = $( '<div class="fc-overlay-light"></div>' ), 263 $overlayDark = $( '<div class="fc-overlay-dark"></div>' ); 264 265 this.$flipEl.css( 'transition', this.transitionProperties ); 266 267 this.$flipFront.find( 'div.fc-overlay-light, div.fc-overlay-dark' ).remove(); 268 this.$flipBack.find( 'div.fc-overlay-light, div.fc-overlay-dark' ).remove(); 269 270 if( dir === 'right' ) { 271 this.$flipFront.append( $overlayLight ); 272 this.$flipBack.append( $overlayDark ); 273 $overlayDark.css( 'opacity', 1 ); 274 } 275 else if( dir === 'left' ) { 276 this.$flipFront.append( $overlayDark ); 277 this.$flipBack.append( $overlayLight ); 278 $overlayLight.css( 'opacity', 1 ); 279 } 280 var overlayStyle = { transition : 'opacity ' + ( this.options.speed / 1.3 ) + 'ms' }; 281 $overlayLight.css( overlayStyle ); 282 $overlayDark.css( overlayStyle ); 283 284 switch( angle ) { 285 case 0 : 286 transformProperties = dir === 'left' ? 'rotate3d(-1,1,0,-179deg) rotate3d(-1,1,0,-1deg)' : 'rotate3d(1,1,0,180deg)'; 287 break; 288 case 1 : 289 transformProperties = dir === 'left' ? 'rotate3d(0,1,0,-179deg) rotate3d(0,1,0,-1deg)' : 'rotate3d(0,1,0,180deg)'; 290 break; 291 case 2 : 292 transformProperties = dir === 'left' ? 'rotate3d(1,1,0,-179deg) rotate3d(1,1,0,-1deg)' : 'rotate3d(-1,1,0,179deg) rotate3d(-1,1,0,1deg)'; 293 break; 294 } 295 296 this.$flipBack.css( 'transform', transformProperties ); 297 298 this.$frontContent.empty().html( $currentItem.html() ); 299 this.$backContent.empty().html( $nextItem.html() ); 300 this.$flipEl.show(); 301 302 var self = this; 303 setTimeout( function() { 304 305 self.$flipEl.css( 'transform', transformProperties ); 306 $overlayLight.css( 'opacity', dir === 'right' ? 1 : 0 ); 307 $overlayDark.css( 'opacity', dir === 'right' ? 0 : 1 ); 308 self.$flipEl.on( self.transEndEventName, function( event ) { 309 if( event.target.className === 'fc-overlay-light' || event.target.className === 'fc-overlay-dark' ) return; 310 self._ontransitionend( $nextItem ); 311 } ); 312 313 }, 25 ); 314 315 }, 316 _ontransitionend : function( $nextItem ) { 317 $nextItem.show(); 318 this.$flipEl.off( this.transEndEventName ).css( { 319 transition : 'none', 320 transform : 'none' 321 } ).hide(); 322 this.isAnimating = false; 323 } 324 }; 325 326 var logError = function( message ) { 327 if ( window.console ) { 328 window.console.error( message ); 329 } 330 }; 331 332 $.fn.flipshow = function( options ) { 333 if ( typeof options === 'string' ) { 334 var args = Array.prototype.slice.call( arguments, 1 ); 335 this.each(function() { 336 var instance = $.data( this, 'flipshow' ); 337 if ( !instance ) { 338 logError( "cannot call methods on flipshow prior to initialization; " + 339 "attempted to call method '" + options + "'" ); 340 return; 341 } 342 if ( !$.isFunction( instance[options] ) || options.charAt(0) === "_" ) { 343 logError( "no such method '" + options + "' for flipshow instance" ); 344 return; 345 } 346 instance[ options ].apply( instance, args ); 347 }); 348 } 349 else { 350 this.each(function() { 351 var instance = $.data( this, 'flipshow' ); 352 if ( instance ) { 353 instance._init(); 354 } 355 else { 356 instance = $.data( this, 'flipshow', new $.Flipshow( options, this ) ); 357 } 358 }); 359 } 360 return this; 361 }; 362 363} )( jQuery, window );
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.