wp/wp-content/themes/twentyfourteen/js/slider.js
changeset 5 5e2f62d02dcd
equal deleted inserted replaced
4:346c88efed21 5:5e2f62d02dcd
       
     1 /*
       
     2  * Twenty Fourteen Featured Content Slider
       
     3  *
       
     4  * Adapted from FlexSlider v2.2.0, copyright 2012 WooThemes
       
     5  * @link http://www.woothemes.com/flexslider/
       
     6  */
       
     7 /* global DocumentTouch:true,setImmediate:true,featuredSliderDefaults:true,MSGesture:true */
       
     8 ( function( $ ) {
       
     9 	// FeaturedSlider: object instance.
       
    10 	$.featuredslider = function( el, options ) {
       
    11 		var slider = $( el ),
       
    12 			msGesture = window.navigator && window.navigator.msPointerEnabled && window.MSGesture,
       
    13 			touch = ( ( 'ontouchstart' in window ) || msGesture || window.DocumentTouch && document instanceof DocumentTouch ), // MSFT specific.
       
    14 			eventType = 'click touchend MSPointerUp',
       
    15 			watchedEvent = '',
       
    16 			watchedEventClearTimer,
       
    17 			methods = {},
       
    18 			namespace;
       
    19 
       
    20 		// Make variables public.
       
    21 		slider.vars = $.extend( {}, $.featuredslider.defaults, options );
       
    22 
       
    23 		namespace = slider.vars.namespace,
       
    24 
       
    25 		// Store a reference to the slider object.
       
    26 		$.data( el, 'featuredslider', slider );
       
    27 
       
    28 		// Private slider methods.
       
    29 		methods = {
       
    30 			init: function() {
       
    31 				slider.animating = false;
       
    32 				slider.currentSlide = 0;
       
    33 				slider.animatingTo = slider.currentSlide;
       
    34 				slider.atEnd = ( slider.currentSlide === 0 || slider.currentSlide === slider.last );
       
    35 				slider.containerSelector = slider.vars.selector.substr( 0, slider.vars.selector.search( ' ' ) );
       
    36 				slider.slides = $( slider.vars.selector, slider );
       
    37 				slider.container = $( slider.containerSelector, slider );
       
    38 				slider.count = slider.slides.length;
       
    39 				slider.prop = 'marginLeft';
       
    40 				slider.isRtl = $( 'body' ).hasClass( 'rtl' );
       
    41 				slider.args = {};
       
    42 				// TOUCH
       
    43 				slider.transitions = ( function() {
       
    44 					var obj = document.createElement( 'div' ),
       
    45 						props = ['perspectiveProperty', 'WebkitPerspective', 'MozPerspective', 'OPerspective', 'msPerspective'],
       
    46 						i;
       
    47 
       
    48 					for ( i in props ) {
       
    49 						if ( obj.style[ props[i] ] !== undefined ) {
       
    50 							slider.pfx = props[i].replace( 'Perspective', '' ).toLowerCase();
       
    51 							slider.prop = '-' + slider.pfx + '-transform';
       
    52 							return true;
       
    53 						}
       
    54 					}
       
    55 					return false;
       
    56 				}() );
       
    57 				// CONTROLSCONTAINER
       
    58 				if ( slider.vars.controlsContainer !== '' ) {
       
    59 					slider.controlsContainer = $( slider.vars.controlsContainer ).length > 0 && $( slider.vars.controlsContainer );
       
    60 				}
       
    61 
       
    62 				slider.doMath();
       
    63 
       
    64 				// INIT
       
    65 				slider.setup( 'init' );
       
    66 
       
    67 				// CONTROLNAV
       
    68 				methods.controlNav.setup();
       
    69 
       
    70 				// DIRECTIONNAV
       
    71 				methods.directionNav.setup();
       
    72 
       
    73 				// KEYBOARD
       
    74 				if ( $( slider.containerSelector ).length === 1 ) {
       
    75 					$( document ).bind( 'keyup', function( event ) {
       
    76 						var keycode = event.keyCode,
       
    77 							target = false;
       
    78 						if ( ! slider.animating && ( keycode === 39 || keycode === 37 ) ) {
       
    79 							if ( keycode === 39 ) {
       
    80 								target = slider.getTarget( 'next' );
       
    81 							} else if ( keycode === 37 ) {
       
    82 								target = slider.getTarget( 'prev' );
       
    83 							}
       
    84 
       
    85 							slider.featureAnimate( target );
       
    86 						}
       
    87 					} );
       
    88 				}
       
    89 
       
    90 				// TOUCH
       
    91 				if ( touch ) {
       
    92 					methods.touch();
       
    93 				}
       
    94 
       
    95 				$( window ).bind( 'resize orientationchange focus', methods.resize );
       
    96 
       
    97 				slider.find( 'img' ).attr( 'draggable', 'false' );
       
    98 			},
       
    99 
       
   100 			controlNav: {
       
   101 				setup: function() {
       
   102 					methods.controlNav.setupPaging();
       
   103 				},
       
   104 				setupPaging: function() {
       
   105 					var type = 'control-paging',
       
   106 						j = 1,
       
   107 						item,
       
   108 						slide,
       
   109 						i;
       
   110 
       
   111 					slider.controlNavScaffold = $( '<ol class="' + namespace + 'control-nav ' + namespace + type + '"></ol>' );
       
   112 
       
   113 					if ( slider.pagingCount > 1 ) {
       
   114 						for ( i = 0; i < slider.pagingCount; i++ ) {
       
   115 							slide = slider.slides.eq( i );
       
   116 							item = '<a>' + j + '</a>';
       
   117 							slider.controlNavScaffold.append( '<li>' + item + '</li>' );
       
   118 							j++;
       
   119 						}
       
   120 					}
       
   121 
       
   122 					// CONTROLSCONTAINER
       
   123 					( slider.controlsContainer ) ? $( slider.controlsContainer ).append( slider.controlNavScaffold ) : slider.append( slider.controlNavScaffold );
       
   124 					methods.controlNav.set();
       
   125 
       
   126 					methods.controlNav.active();
       
   127 
       
   128 					slider.controlNavScaffold.delegate( 'a, img', eventType, function( event ) {
       
   129 						event.preventDefault();
       
   130 
       
   131 						if ( watchedEvent === '' || watchedEvent === event.type ) {
       
   132 							var $this = $( this ),
       
   133 								target = slider.controlNav.index( $this );
       
   134 
       
   135 							if ( ! $this.hasClass( namespace + 'active' ) ) {
       
   136 								slider.direction = ( target > slider.currentSlide ) ? 'next' : 'prev';
       
   137 								slider.featureAnimate( target );
       
   138 							}
       
   139 						}
       
   140 
       
   141 						// Set up flags to prevent event duplication.
       
   142 						if ( watchedEvent === '' ) {
       
   143 							watchedEvent = event.type;
       
   144 						}
       
   145 
       
   146 						methods.setToClearWatchedEvent();
       
   147 					} );
       
   148 				},
       
   149 				set: function() {
       
   150 					var selector = 'a';
       
   151 					slider.controlNav = $( '.' + namespace + 'control-nav li ' + selector, ( slider.controlsContainer ) ? slider.controlsContainer : slider );
       
   152 				},
       
   153 				active: function() {
       
   154 					slider.controlNav.removeClass( namespace + 'active' ).eq( slider.animatingTo ).addClass( namespace + 'active' );
       
   155 				},
       
   156 				update: function( action, pos ) {
       
   157 					if ( slider.pagingCount > 1 && action === 'add' ) {
       
   158 						slider.controlNavScaffold.append( $( '<li><a>' + slider.count + '</a></li>' ) );
       
   159 					} else if ( slider.pagingCount === 1 ) {
       
   160 						slider.controlNavScaffold.find( 'li' ).remove();
       
   161 					} else {
       
   162 						slider.controlNav.eq( pos ).closest( 'li' ).remove();
       
   163 					}
       
   164 					methods.controlNav.set();
       
   165 					( slider.pagingCount > 1 && slider.pagingCount !== slider.controlNav.length ) ? slider.update( pos, action ) : methods.controlNav.active();
       
   166 				}
       
   167 			},
       
   168 
       
   169 			directionNav: {
       
   170 				setup: function() {
       
   171 					var directionNavScaffold = $( '<ul class="' + namespace + 'direction-nav"><li><a class="' + namespace + 'prev" href="#">' + slider.vars.prevText + '</a></li><li><a class="' + namespace + 'next" href="#">' + slider.vars.nextText + '</a></li></ul>' );
       
   172 
       
   173 					// CONTROLSCONTAINER
       
   174 					if ( slider.controlsContainer ) {
       
   175 						$( slider.controlsContainer ).append( directionNavScaffold );
       
   176 						slider.directionNav = $( '.' + namespace + 'direction-nav li a', slider.controlsContainer );
       
   177 					} else {
       
   178 						slider.append( directionNavScaffold );
       
   179 						slider.directionNav = $( '.' + namespace + 'direction-nav li a', slider );
       
   180 					}
       
   181 
       
   182 					methods.directionNav.update();
       
   183 
       
   184 					slider.directionNav.bind( eventType, function( event ) {
       
   185 						event.preventDefault();
       
   186 						var target;
       
   187 
       
   188 						if ( watchedEvent === '' || watchedEvent === event.type ) {
       
   189 							target = ( $( this ).hasClass( namespace + 'next' ) ) ? slider.getTarget( 'next' ) : slider.getTarget( 'prev' );
       
   190 							slider.featureAnimate( target );
       
   191 						}
       
   192 
       
   193 						// Set up flags to prevent event duplication.
       
   194 						if ( watchedEvent === '' ) {
       
   195 							watchedEvent = event.type;
       
   196 						}
       
   197 
       
   198 						methods.setToClearWatchedEvent();
       
   199 					} );
       
   200 				},
       
   201 				update: function() {
       
   202 					var disabledClass = namespace + 'disabled';
       
   203 					if ( slider.pagingCount === 1 ) {
       
   204 						slider.directionNav.addClass( disabledClass ).attr( 'tabindex', '-1' );
       
   205 					} else {
       
   206 						slider.directionNav.removeClass( disabledClass ).removeAttr( 'tabindex' );
       
   207 					}
       
   208 				}
       
   209 			},
       
   210 
       
   211 			touch: function() {
       
   212 				var startX,
       
   213 					startY,
       
   214 					offset,
       
   215 					cwidth,
       
   216 					dx,
       
   217 					startT,
       
   218 					scrolling = false,
       
   219 					localX = 0,
       
   220 					localY = 0,
       
   221 					accDx = 0;
       
   222 
       
   223 				if ( ! msGesture ) {
       
   224 					el.addEventListener( 'touchstart', onTouchStart, false );
       
   225 				} else {
       
   226 					el.style.msTouchAction = 'none';
       
   227 					el._gesture = new MSGesture(); // MSFT specific.
       
   228 					el._gesture.target = el;
       
   229 					el.addEventListener( 'MSPointerDown', onMSPointerDown, false );
       
   230 					el._slider = slider;
       
   231 					el.addEventListener( 'MSGestureChange', onMSGestureChange, false );
       
   232 					el.addEventListener( 'MSGestureEnd', onMSGestureEnd, false );
       
   233 				}
       
   234 
       
   235 				function onTouchStart( e ) {
       
   236 					if ( slider.animating ) {
       
   237 						e.preventDefault();
       
   238 					} else if ( ( window.navigator.msPointerEnabled ) || e.touches.length === 1 ) {
       
   239 						cwidth = slider.w;
       
   240 						startT = Number( new Date() );
       
   241 
       
   242 						// Local vars for X and Y points.
       
   243 						localX = e.touches[0].pageX;
       
   244 						localY = e.touches[0].pageY;
       
   245 
       
   246 						offset = ( slider.currentSlide + slider.cloneOffset ) * cwidth;
       
   247 						if ( slider.animatingTo === slider.last && slider.direction !== 'next' ) {
       
   248 							offset = 0;
       
   249 						}
       
   250 
       
   251 						startX = localX;
       
   252 						startY = localY;
       
   253 
       
   254 						el.addEventListener( 'touchmove', onTouchMove, false );
       
   255 						el.addEventListener( 'touchend', onTouchEnd, false );
       
   256 					}
       
   257 				}
       
   258 
       
   259 				function onTouchMove( e ) {
       
   260 					// Local vars for X and Y points.
       
   261 					localX = e.touches[0].pageX;
       
   262 					localY = e.touches[0].pageY;
       
   263 
       
   264 					dx = startX - localX;
       
   265 					scrolling = Math.abs( dx ) < Math.abs( localY - startY );
       
   266 
       
   267 					if ( ! scrolling ) {
       
   268 						e.preventDefault();
       
   269 						if ( slider.transitions ) {
       
   270 							slider.setProps( offset + dx, 'setTouch' );
       
   271 						}
       
   272 					}
       
   273 				}
       
   274 
       
   275 				function onTouchEnd() {
       
   276 					// Finish the touch by undoing the touch session.
       
   277 					el.removeEventListener( 'touchmove', onTouchMove, false );
       
   278 
       
   279 					if ( slider.animatingTo === slider.currentSlide && ! scrolling && dx !== null ) {
       
   280 						var updateDx = dx,
       
   281 							target = ( updateDx > 0 ) ? slider.getTarget( 'next' ) : slider.getTarget( 'prev' );
       
   282 
       
   283 						slider.featureAnimate( target );
       
   284 					}
       
   285 					el.removeEventListener( 'touchend', onTouchEnd, false );
       
   286 
       
   287 					startX = null;
       
   288 					startY = null;
       
   289 					dx = null;
       
   290 					offset = null;
       
   291 				}
       
   292 
       
   293 				function onMSPointerDown( e ) {
       
   294 					e.stopPropagation();
       
   295 					if ( slider.animating ) {
       
   296 						e.preventDefault();
       
   297 					} else {
       
   298 						el._gesture.addPointer( e.pointerId );
       
   299 						accDx = 0;
       
   300 						cwidth = slider.w;
       
   301 						startT = Number( new Date() );
       
   302 						offset = ( slider.currentSlide + slider.cloneOffset ) * cwidth;
       
   303 						if ( slider.animatingTo === slider.last && slider.direction !== 'next' ) {
       
   304 							offset = 0;
       
   305 						}
       
   306 					}
       
   307 				}
       
   308 
       
   309 				function onMSGestureChange( e ) {
       
   310 					e.stopPropagation();
       
   311 					var slider = e.target._slider,
       
   312 						transX,
       
   313 						transY;
       
   314 					if ( ! slider ) {
       
   315 						return;
       
   316 					}
       
   317 
       
   318 					transX = -e.translationX,
       
   319 					transY = -e.translationY;
       
   320 
       
   321 					// Accumulate translations.
       
   322 					accDx = accDx + transX;
       
   323 					dx = accDx;
       
   324 					scrolling = Math.abs( accDx ) < Math.abs( -transY );
       
   325 
       
   326 					if ( e.detail === e.MSGESTURE_FLAG_INERTIA ) {
       
   327 						setImmediate( function () { // MSFT specific.
       
   328 							el._gesture.stop();
       
   329 						} );
       
   330 
       
   331 						return;
       
   332 					}
       
   333 
       
   334 					if ( ! scrolling || Number( new Date() ) - startT > 500 ) {
       
   335 						e.preventDefault();
       
   336 						if ( slider.transitions ) {
       
   337 							slider.setProps( offset + dx, 'setTouch' );
       
   338 						}
       
   339 					}
       
   340 				}
       
   341 
       
   342 				function onMSGestureEnd( e ) {
       
   343 					e.stopPropagation();
       
   344 					var slider = e.target._slider,
       
   345 						updateDx,
       
   346 						target;
       
   347 					if ( ! slider ) {
       
   348 						return;
       
   349 					}
       
   350 
       
   351 					if ( slider.animatingTo === slider.currentSlide && ! scrolling && dx !== null ) {
       
   352 						updateDx = dx,
       
   353 						target = ( updateDx > 0 ) ? slider.getTarget( 'next' ) : slider.getTarget( 'prev' );
       
   354 
       
   355 						slider.featureAnimate( target );
       
   356 					}
       
   357 
       
   358 					startX = null;
       
   359 					startY = null;
       
   360 					dx = null;
       
   361 					offset = null;
       
   362 					accDx = 0;
       
   363 				}
       
   364 			},
       
   365 
       
   366 			resize: function() {
       
   367 				if ( ! slider.animating && slider.is( ':visible' ) ) {
       
   368 					slider.doMath();
       
   369 
       
   370 					// SMOOTH HEIGHT
       
   371 					methods.smoothHeight();
       
   372 					slider.newSlides.width( slider.computedW );
       
   373 					slider.setProps( slider.computedW, 'setTotal' );
       
   374 				}
       
   375 			},
       
   376 
       
   377 			smoothHeight: function( dur ) {
       
   378 				var $obj = slider.viewport;
       
   379 				( dur ) ? $obj.animate( { 'height': slider.slides.eq( slider.animatingTo ).height() }, dur ) : $obj.height( slider.slides.eq( slider.animatingTo ).height() );
       
   380 			},
       
   381 
       
   382 			setToClearWatchedEvent: function() {
       
   383 				clearTimeout( watchedEventClearTimer );
       
   384 				watchedEventClearTimer = setTimeout( function() {
       
   385 					watchedEvent = '';
       
   386 				}, 3000 );
       
   387 			}
       
   388 		};
       
   389 
       
   390 		// Public methods.
       
   391 		slider.featureAnimate = function( target ) {
       
   392 			if ( target !== slider.currentSlide ) {
       
   393 				slider.direction = ( target > slider.currentSlide ) ? 'next' : 'prev';
       
   394 			}
       
   395 
       
   396 			if ( ! slider.animating && slider.is( ':visible' ) ) {
       
   397 				slider.animating = true;
       
   398 				slider.animatingTo = target;
       
   399 
       
   400 				// CONTROLNAV
       
   401 				methods.controlNav.active();
       
   402 
       
   403 				slider.slides.removeClass( namespace + 'active-slide' ).eq( target ).addClass( namespace + 'active-slide' );
       
   404 
       
   405 				slider.atEnd = target === 0 || target === slider.last;
       
   406 
       
   407 				// DIRECTIONNAV
       
   408 				methods.directionNav.update();
       
   409 
       
   410 				var dimension = slider.computedW,
       
   411 					slideString;
       
   412 
       
   413 				if ( slider.currentSlide === 0 && target === slider.count - 1 && slider.direction !== 'next' ) {
       
   414 					slideString = 0;
       
   415 				} else if ( slider.currentSlide === slider.last && target === 0 && slider.direction !== 'prev' ) {
       
   416 					slideString = ( slider.count + 1 ) * dimension;
       
   417 				} else {
       
   418 					slideString = ( target + slider.cloneOffset ) * dimension;
       
   419 				}
       
   420 				slider.setProps( slideString, '', slider.vars.animationSpeed );
       
   421 				if ( slider.transitions ) {
       
   422 					if ( ! slider.atEnd ) {
       
   423 						slider.animating = false;
       
   424 						slider.currentSlide = slider.animatingTo;
       
   425 					}
       
   426 					slider.container.unbind( 'webkitTransitionEnd transitionend' );
       
   427 					slider.container.bind( 'webkitTransitionEnd transitionend', function() {
       
   428 						slider.wrapup( dimension );
       
   429 					} );
       
   430 				} else {
       
   431 					slider.container.animate( slider.args, slider.vars.animationSpeed, 'swing', function() {
       
   432 						slider.wrapup( dimension );
       
   433 					} );
       
   434 				}
       
   435 
       
   436 				// SMOOTH HEIGHT
       
   437 				methods.smoothHeight( slider.vars.animationSpeed );
       
   438 			}
       
   439 		};
       
   440 
       
   441 		slider.wrapup = function( dimension ) {
       
   442 			if ( slider.currentSlide === 0 && slider.animatingTo === slider.last ) {
       
   443 				slider.setProps( dimension, 'jumpEnd' );
       
   444 			} else if ( slider.currentSlide === slider.last && slider.animatingTo === 0 ) {
       
   445 				slider.setProps( dimension, 'jumpStart' );
       
   446 			}
       
   447 			slider.animating = false;
       
   448 			slider.currentSlide = slider.animatingTo;
       
   449 		};
       
   450 
       
   451 		slider.getTarget = function( dir ) {
       
   452 			slider.direction = dir;
       
   453 
       
   454 			// Swap for RTL.
       
   455 			if ( slider.isRtl ) {
       
   456 				dir = 'next' === dir ? 'prev' : 'next';
       
   457 			}
       
   458 
       
   459 			if ( dir === 'next' ) {
       
   460 				return ( slider.currentSlide === slider.last ) ? 0 : slider.currentSlide + 1;
       
   461 			} else {
       
   462 				return ( slider.currentSlide === 0 ) ? slider.last : slider.currentSlide - 1;
       
   463 			}
       
   464 		};
       
   465 
       
   466 		slider.setProps = function( pos, special, dur ) {
       
   467 			var target = ( function() {
       
   468 				var posCalc = ( function() {
       
   469 						switch ( special ) {
       
   470 							case 'setTotal': return ( slider.currentSlide + slider.cloneOffset ) * pos;
       
   471 							case 'setTouch': return pos;
       
   472 							case 'jumpEnd': return slider.count * pos;
       
   473 							case 'jumpStart': return pos;
       
   474 							default: return pos;
       
   475 						}
       
   476 					}() );
       
   477 
       
   478 					return ( posCalc * -1 ) + 'px';
       
   479 				}() );
       
   480 
       
   481 			if ( slider.transitions ) {
       
   482 				target = 'translate3d(' + target + ',0,0 )';
       
   483 				dur = ( dur !== undefined ) ? ( dur / 1000 ) + 's' : '0s';
       
   484 				slider.container.css( '-' + slider.pfx + '-transition-duration', dur );
       
   485 			}
       
   486 
       
   487 			slider.args[slider.prop] = target;
       
   488 			if ( slider.transitions || dur === undefined ) {
       
   489 				slider.container.css( slider.args );
       
   490 			}
       
   491 		};
       
   492 
       
   493 		slider.setup = function( type ) {
       
   494 			var sliderOffset;
       
   495 
       
   496 			if ( type === 'init' ) {
       
   497 				slider.viewport = $( '<div class="' + namespace + 'viewport"></div>' ).css( { 'overflow': 'hidden', 'position': 'relative' } ).appendTo( slider ).append( slider.container );
       
   498 				slider.cloneCount = 0;
       
   499 				slider.cloneOffset = 0;
       
   500 			}
       
   501 			slider.cloneCount = 2;
       
   502 			slider.cloneOffset = 1;
       
   503 			// Clear out old clones.
       
   504 			if ( type !== 'init' ) {
       
   505 				slider.container.find( '.clone' ).remove();
       
   506 			}
       
   507 
       
   508 			slider.container.append( slider.slides.first().clone().addClass( 'clone' ).attr( 'aria-hidden', 'true' ) ).prepend( slider.slides.last().clone().addClass( 'clone' ).attr( 'aria-hidden', 'true' ) );
       
   509 			slider.newSlides = $( slider.vars.selector, slider );
       
   510 
       
   511 			sliderOffset = slider.currentSlide + slider.cloneOffset;
       
   512 			slider.container.width( ( slider.count + slider.cloneCount ) * 200 + '%' );
       
   513 			slider.setProps( sliderOffset * slider.computedW, 'init' );
       
   514 			setTimeout( function() {
       
   515 				slider.doMath();
       
   516 				slider.newSlides.css( { 'width': slider.computedW, 'float': 'left', 'display': 'block' } );
       
   517 				// SMOOTH HEIGHT
       
   518 				methods.smoothHeight();
       
   519 			}, ( type === 'init' ) ? 100 : 0 );
       
   520 
       
   521 			slider.slides.removeClass( namespace + 'active-slide' ).eq( slider.currentSlide ).addClass( namespace + 'active-slide' );
       
   522 		};
       
   523 
       
   524 		slider.doMath = function() {
       
   525 			var slide = slider.slides.first();
       
   526 
       
   527 			slider.w = ( slider.viewport === undefined ) ? slider.width() : slider.viewport.width();
       
   528 			slider.h = slide.height();
       
   529 			slider.boxPadding = slide.outerWidth() - slide.width();
       
   530 
       
   531 			slider.itemW = slider.w;
       
   532 			slider.pagingCount = slider.count;
       
   533 			slider.last = slider.count - 1;
       
   534 			slider.computedW = slider.itemW - slider.boxPadding;
       
   535 		};
       
   536 
       
   537 		slider.update = function( pos, action ) {
       
   538 			slider.doMath();
       
   539 
       
   540 			// Update currentSlide and slider.animatingTo if necessary.
       
   541 			if ( pos < slider.currentSlide ) {
       
   542 				slider.currentSlide += 1;
       
   543 			} else if ( pos <= slider.currentSlide && pos !== 0 ) {
       
   544 				slider.currentSlide -= 1;
       
   545 			}
       
   546 			slider.animatingTo = slider.currentSlide;
       
   547 
       
   548 			// Update controlNav.
       
   549 			if ( action === 'add' || slider.pagingCount > slider.controlNav.length ) {
       
   550 				methods.controlNav.update( 'add' );
       
   551 			} else if ( action === 'remove' || slider.pagingCount < slider.controlNav.length ) {
       
   552 				if ( slider.currentSlide > slider.last ) {
       
   553 					slider.currentSlide -= 1;
       
   554 					slider.animatingTo -= 1;
       
   555 				}
       
   556 				methods.controlNav.update( 'remove', slider.last );
       
   557 			}
       
   558 			// Update directionNav.
       
   559 			methods.directionNav.update();
       
   560 		};
       
   561 
       
   562 		// FeaturedSlider: initialize.
       
   563 		methods.init();
       
   564 	};
       
   565 
       
   566 	// Default settings.
       
   567 	$.featuredslider.defaults = {
       
   568 		namespace: 'slider-',     // String: prefix string attached to the class of every element generated by the plugin.
       
   569 		selector: '.slides > li', // String: selector, must match a simple pattern.
       
   570 		animationSpeed: 600,      // Integer: Set the speed of animations, in milliseconds.
       
   571 		controlsContainer: '',    // jQuery Object/Selector: container navigation to append elements.
       
   572 
       
   573 		// Text labels.
       
   574 		prevText: featuredSliderDefaults.prevText, // String: Set the text for the "previous" directionNav item.
       
   575 		nextText: featuredSliderDefaults.nextText  // String: Set the text for the "next" directionNav item.
       
   576 	};
       
   577 
       
   578 	// FeaturedSlider: plugin function.
       
   579 	$.fn.featuredslider = function( options ) {
       
   580 		if ( options === undefined ) {
       
   581 			options = {};
       
   582 		}
       
   583 
       
   584 		if ( typeof options === 'object' ) {
       
   585 			return this.each( function() {
       
   586 				var $this = $( this ),
       
   587 					selector = ( options.selector ) ? options.selector : '.slides > li',
       
   588 					$slides = $this.find( selector );
       
   589 
       
   590 			if ( $slides.length === 1 || $slides.length === 0 ) {
       
   591 					$slides.fadeIn( 400 );
       
   592 				} else if ( $this.data( 'featuredslider' ) === undefined ) {
       
   593 					new $.featuredslider( this, options );
       
   594 				}
       
   595 			} );
       
   596 		}
       
   597 	};
       
   598 } )( jQuery );