[ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
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 );
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated : Thu Nov 21 08:20:01 2024 | Cross-referenced by PHPXref |