1/** 2 * BxSlider v4.0 - Fully loaded, responsive content slider 3 * http://bxslider.com 4 * 5 * Copyright 2012, Steven Wanderski - http://stevenwanderski.com - http://bxcreative.com 6 * Written while drinking Belgian ales and listening to jazz 7 * 8 * Released under the WTFPL license - http://sam.zoy.org/wtfpl/ 9 */ 10 11;(function($){ 12 13 var defaults = { 14 15 // GENERAL 16 mode: 'horizontal', 17 slideSelector: '', 18 infiniteLoop: true, 19 hideControlOnEnd: false, 20 speed: 500, 21 easing: 'swing', 22 slideMargin: 0, 23 startSlide: 0, 24 captions: false, 25 ticker: false, 26 tickerHover: false, 27 adaptiveHeight: false, 28 adaptiveHeightSpeed: 500, 29 touchEnabled: true, 30 swipeThreshold: 50, 31 video: false, 32 33 // PAGER 34 pager: true, 35 pagerType: 'full', 36 pagerShortSeparator: ' / ', 37 pagerSelector: null, 38 buildPager: null, 39 pagerCustom: null, 40 41 // CONTROLS 42 controls: true, 43 nextText: 'Next', 44 prevText: 'Prev', 45 nextSelector: null, 46 prevSelector: null, 47 autoControls: false, 48 startText: 'Start', 49 stopText: 'Stop', 50 autoControlsCombine: false, 51 autoControlsSelector: null, 52 53 // AUTO 54 auto: false, 55 pause: 4000, 56 autoStart: true, 57 autoDirection: 'next', 58 autoHover: false, 59 autoDelay: 0, 60 61 // CAROUSEL 62 minSlides: 1, 63 maxSlides: 1, 64 moveSlides: 0, 65 slideWidth: 0, 66 67 // CALLBACKS 68 onSliderLoad: function() {}, 69 onSlideBefore: function() {}, 70 onSlideAfter: function() {}, 71 onSlideNext: function() {}, 72 onSlidePrev: function() {} 73 } 74 75 $.fn.bxSlider = function(options){ 76 77 // support mutltiple elements 78 if(this.length > 1){ 79 this.each(function(){$(this).bxSlider(options)}); 80 return this; 81 } 82 83 // create a namespace to be used throughout the plugin 84 var slider = {}; 85 // set a reference to our slider element 86 var el = this; 87 88 /** 89 * =================================================================================== 90 * = PRIVATE FUNCTIONS 91 * =================================================================================== 92 */ 93 94 /** 95 * Initializes namespace settings to be used throughout plugin 96 */ 97 var init = function(){ 98 // merge user-supplied options with the defaults 99 slider.settings = $.extend({}, defaults, options); 100 // store the original children 101 slider.children = el.children(slider.settings.slideSelector); 102 // store active slide information 103 slider.active = { index: slider.settings.startSlide } 104 // store if the slider is in carousel mode (displaying / moving multiple slides) 105 slider.carousel = slider.settings.minSlides > 1 || slider.settings.maxSlides > 1; 106 // calculate the min / max width thresholds based on min / max number of slides 107 // used to setup and update carousel slides dimensions 108 slider.minThreshold = (slider.settings.minSlides * slider.settings.slideWidth) + ((slider.settings.minSlides - 1) * slider.settings.slideMargin); 109 slider.maxThreshold = (slider.settings.maxSlides * slider.settings.slideWidth) + ((slider.settings.maxSlides - 1) * slider.settings.slideMargin); 110 // store the current state of the slider (if currently animating, working is true) 111 slider.working = false; 112 // initialize the controls object 113 slider.controls = {} 114 // perform all DOM / CSS modifications 115 setup(); 116 // if ticker is true, start the ticker 117 if (slider.settings.ticker) initTicker(); 118 // if pager is requested, make the appropriate pager link active 119 if (slider.settings.pager) updatePagerActive(slider.settings.startSlide); 120 // check for any updates to the controls (like hideControlOnEnd updates) 121 if (slider.settings.controls) updateDirectionControls(); 122 // if touchEnabled is true, setup the touch events 123 if (slider.settings.touchEnabled) initTouch(); 124 } 125 126 /** 127 * Performs all DOM and CSS modifications 128 */ 129 var setup = function(){ 130 // wrap el in a wrapper 131 el.wrap('<div class="bx-wrapper"><div class="bx-viewport"></div></div>'); 132 // store a namspace reference to .bx-viewport 133 slider.viewport = el.parent(); 134 // add a loading div to display while images are loading 135 slider.loader = $('<div class="bx-loading" />');
136 slider.viewport.prepend(slider.loader); 137 // set el to a massive width, to hold any needed slides 138 // also strip any margin and padding from el 139 el.css({ 140 width: slider.settings.mode == 'horizontal' ? '999999px' : 'auto', 141 height: 0, 142 overflow: 'hidden', 143 position: 'relative', 144 margin: 0, 145 padding: 0 146 }); 147 // make modifications to the viewport (.bx-viewport) 148 slider.viewport.css({ 149 width: '100%', 150 height: '50', 151 overflow: 'hidden', 152 position: 'relative' 153 }); 154 // apply css to all slider children 155 slider.children.css({ 156 float: slider.settings.mode == 'horizontal' ? 'left' : 'none', 157 position: 'relative', 158 width: getSlideWidth(), 159 listStyle: 'none', 160 marginRight: slider.settings.mode == 'horizontal' ? slider.settings.slideMargin : 0, 161 marginBottom: slider.settings.mode == 'vertical' ? slider.settings.slideMargin: 0 162 }); 163 // if "fade" mode, add positioning and z-index CSS 164 if(slider.settings.mode == 'fade'){ 165 slider.children.css({ 166 position: 'absolute', 167 zIndex: 0, 168 display: 'none' 169 }); 170 // prepare the z-index on the showing element 171 slider.children.eq(slider.settings.startSlide).css({zIndex: 50, display: 'block'}); 172 } 173 // create an element to contain all slider controls (pager, start / stop, etc) 174 slider.controls.el = $('<div class="bx-controls" />'); 175 // if captions are requested, add them 176 if(slider.settings.captions) appendCaptions(); 177 // if infinite loop, prepare additional slides 178 if(slider.settings.infiniteLoop && !slider.carousel && slider.settings.mode != 'fade' && !slider.settings.ticker){ 179 var cloneAppend = slider.children.first().clone().addClass('bx-clone'); 180 var clonePrepend = slider.children.last().clone().addClass('bx-clone'); 181 el.append(cloneAppend).prepend(clonePrepend); 182 } 183 // check if startSlide is last slide 184 slider.active.last = slider.settings.startSlide == getPagerQty() - 1; 185 // if video is true, set up the fitVids plugin 186 if(slider.settings.video) el.fitVids();
187 // only check for control addition if not in "ticker" mode 188 if(!slider.settings.ticker){ 189 // if pager is requested, add it 190 if(slider.settings.pager) appendPager(); 191 // if controls are requested, add them 192 if(slider.settings.controls) appendControls(); 193 // if auto is true, and auto controls are requested, add them 194 if(slider.settings.auto && slider.settings.autoControls) appendControlsAuto(); 195 // if any control option is requested, add the controls wrapper 196 if(slider.settings.controls || slider.settings.autoControls || slider.settings.pager) slider.viewport.after(slider.controls.el); 197 } 198 // preload all images, then perform final DOM / CSS modifications that depend on images being loaded 199 preloadImages(function(){ 200 el.css('overflow', 'visible'); 201 // set the left / top position of "el" 202 setSlidePosition(); 203 // if "vertical" mode, always use adaptiveHeight to prevent odd behavior 204 if (slider.settings.mode == 'vertical') slider.settings.adaptiveHeight = true; 205 // set the viewport height 206 slider.viewport.animate({height: getViewportHeight()}, 200, function(){ 207 // onSliderLoad callback 208 slider.settings.onSliderLoad(); 209 }); 210 // if auto is true, start the show 211 if (slider.settings.auto && slider.settings.autoStart) initAuto(); 212 }); 213 } 214 215 /** 216 * Preload all images and iframes 217 * 218 * @param callback (function) 219 * - Function to be called after images are loaded 220 */ 221 var preloadImages = function(callback){ 222 // get all the images 223 var images = slider.children.find('img[src!=""], iframe'); 224 // counter that stores loaded images 225 var loaded = 0; 226 // if images exist 227 if(images.length > 0){ 228 // cycle through each image 229 images.each(function(index){ 230 var img = $(this); 231 // on image load 232 img.load(function(){ 233 // increase the counter 234 ++loaded; 235 // if all images have been loaded 236 if(images.length == loaded){ 237 // remove the loading DOM element 238 slider.loader.remove(); 239 // fire the callback function 240 callback(); 241 } 242 }); 243 // silly IE needs this hack to fire "load" events on images 244 }).each(function() { 245 if(this.complete) $(this).load(); 246 }); 247 // if images do not exist, fire the callback function immediately 248 }else{ 249 // remove the loading DOM element 250 slider.loader.remove(); 251 callback(); 252 } 253 } 254 255 /** 256 * Returns the calculated height of the viewport, used to determine either adaptiveHeight or the maxHeight value 257 */ 258 var getViewportHeight = function(){ 259 var height = 0; 260 // first determine which children (slides) should be used in our height calculation 261 var children = ''; 262 // if mode is not "vertical", adaptiveHeight is always false, so return all children 263 if(slider.settings.mode != 'vertical' && !slider.settings.adaptiveHeight){ 264 children = slider.children; 265 }else{ 266 // if not carousel, return the single active child 267 if(!slider.carousel){ 268 children = slider.children.eq(slider.active.index); 269 // if carousel, return a slice of children 270 }else{ 271 // if last slide 272 if(slider.active.last){ 273 children = slider.children.slice(slider.children.length - slider.settings.minSlides, slider.children.length); 274 // if not last slide 275 }else{ 276 children = slider.children.slice(slider.active.index * getMoveBy(), slider.settings.minSlides + (slider.active.index * getMoveBy())); 277 } 278 } 279 } 280 281 // if "vertical" mode, calculate the sum of the heights of the children 282 if(slider.settings.mode == 'vertical'){ 283 children.each(function(index) { 284 height += $(this).outerHeight(); 285 }); 286 // add user-supplied margins 287 if(slider.settings.slideMargin > 0){ 288 height += slider.settings.slideMargin * (slider.settings.minSlides - 1); 289 } 290 // if not "vertical" mode, calculate the max height of the children 291 }else{ 292 height = Math.max.apply(Math, children.map(function(){ 293 return $(this).outerHeight(); 294 }).get()); 295 } 296 297 return height; 298 } 299 300 /** 301 * Returns the calculated width to be applied to each slide 302 */ 303 var getSlideWidth = function(){ 304 // start with any user-supplied slide width 305 var newElWidth = slider.settings.slideWidth; 306 // get the current viewport width 307 var wrapWidth = slider.viewport.width(); 308 // if slide width was not supplied, use the viewport width (means not carousel) 309 if(slider.settings.slideWidth == 0){ 310 newElWidth = wrapWidth; 311 // if carousel, use the thresholds to determine the width 312 }else{ 313 if(wrapWidth > slider.maxThreshold){ 314 newElWidth = (wrapWidth - (slider.settings.slideMargin * (slider.settings.maxSlides - 1))) / slider.settings.maxSlides; 315 }else if(wrapWidth < slider.minThreshold){ 316 newElWidth = (wrapWidth - (slider.settings.slideMargin * (slider.settings.minSlides - 1))) / slider.settings.minSlides; 317 } 318 } 319 return newElWidth; 320 } 321 322 /** 323 * Returns the number of slides currently visible in the viewport (includes partially visible slides) 324 */ 325 var getNumberSlidesShowing = function(){ 326 var slidesShowing = 1; 327 if(slider.settings.mode == 'horizontal'){ 328 // if viewport is smaller than minThreshold, return minSlides 329 if(slider.viewport.width() < slider.minThreshold){ 330 slidesShowing = slider.settings.minSlides; 331 // if viewport is larger than minThreshold, return maxSlides 332 }else if(slider.viewport.width() > slider.maxThreshold){ 333 slidesShowing = slider.settings.maxSlides; 334 // if viewport is between min / max thresholds, divide viewport width by first child width 335 }else{ 336 var childWidth = slider.children.first().width(); 337 slidesShowing = Math.floor(slider.viewport.width() / childWidth); 338 } 339 // if "vertical" mode, slides showing will always be minSlides 340 }else if(slider.settings.mode == 'vertical'){ 341 slidesShowing = slider.settings.minSlides; 342 } 343 return slidesShowing; 344 } 345 346 /** 347 * Returns the number of pages (one full viewport of slides is one "page") 348 */ 349 var getPagerQty = function(){ 350 var pagerQty = 0; 351 // if moveSlides is specified by the user 352 if(slider.settings.moveSlides > 0){ 353 // use a while loop to determine pages 354 var breakPoint = 0; 355 var counter = 0 356 // when breakpoint goes above children length, counter is the number of pages 357 while (breakPoint < slider.children.length){ 358 ++pagerQty; 359 breakPoint = counter + getNumberSlidesShowing(); 360 counter += slider.settings.moveSlides <= getNumberSlidesShowing() ? slider.settings.moveSlides : getNumberSlidesShowing(); 361 }
362 // if moveSlides is 0 (auto) divide children length by sides showing, then round up 363 }else{ 364 pagerQty = Math.ceil(slider.children.length / getNumberSlidesShowing()); 365 } 366 return pagerQty; 367 } 368 369 /** 370 * Returns the number of indivual slides by which to shift the slider 371 */ 372 var getMoveBy = function(){ 373 // if moveSlides was set by the user and moveSlides is less than number of slides showing 374 if(slider.settings.moveSlides > 0 && slider.settings.moveSlides <= getNumberSlidesShowing()){ 375 return slider.settings.moveSlides; 376 } 377 // if moveSlides is 0 (auto) 378 return getNumberSlidesShowing(); 379 } 380 381 /** 382 * Sets the slider's (el) left or top position 383 */ 384 var setSlidePosition = function(){ 385 // if last slide 386 if(slider.active.last){ 387 if (slider.settings.mode == 'horizontal'){ 388 // get the last child's position 389 var lastChild = slider.children.last(); 390 var position = lastChild.position(); 391 // set the left position 392 el.css('left', -(position.left - (slider.viewport.width() - lastChild.width()))); 393 }else if(slider.settings.mode == 'vertical'){ 394 // get the last showing index's position 395 var lastShowingIndex = slider.children.length - slider.settings.minSlides; 396 var position = slider.children.eq(lastShowingIndex).position(); 397 // set the top position 398 el.css('top', -position.top); 399 } 400 // if not last slide 401 }else{ 402 // get the position of the first showing slide 403 var position = slider.children.eq(slider.active.index * getMoveBy()).position(); 404 // check for last slide 405 if (slider.active.index == getPagerQty() - 1) slider.active.last = true; 406 // set the repective position 407 if (position != undefined){ 408 if (slider.settings.mode == 'horizontal') el.css('left', -position.left); 409 else if (slider.settings.mode == 'vertical') el.css('top', -position.top); 410 } 411 } 412 } 413 414 /** 415 * Populates the pager with proper amount of pages 416 */ 417 var populatePager = function(){ 418 var pagerHtml = ''; 419 pagerQty = getPagerQty(); 420 // loop through each pager item 421 for(var i=0; i < pagerQty; i++){ 422 var linkContent = ''; 423 // if a buildPager function is supplied, use it to get pager link value, else use index + 1 424 if(slider.settings.buildPager && $.isFunction(slider.settings.buildPager)){ 425 linkContent = slider.settings.buildPager(i); 426 slider.pagerEl.addClass('bx-custom-pager'); 427 }else{ 428 linkContent = i + 1; 429 slider.pagerEl.addClass('bx-default-pager'); 430 } 431 // var linkContent = slider.settings.buildPager && $.isFunction(slider.settings.buildPager) ? slider.settings.buildPager(i) : i + 1; 432 // add the markup to the string 433 pagerHtml += '<div class="bx-pager-item"><a href="" data-slide-index="' + i + '" class="bx-pager-link">' + linkContent + '</a></div>'; 434 }; 435 // populate the pager element with pager links 436 slider.pagerEl.html(pagerHtml); 437 } 438 439 /** 440 * Appends the pager to the controls element 441 */ 442 var appendPager = function(){ 443 if(!slider.settings.pagerCustom){ 444 // create the pager DOM element 445 slider.pagerEl = $('<div class="bx-pager" />'); 446 // if a pager selector was supplied, populate it with the pager 447 if(slider.settings.pagerSelector){ 448 $(slider.settings.pagerSelector).html(slider.pagerEl); 449 // if no pager selector was supplied, add it after the wrapper 450 }else{ 451 slider.controls.el.addClass('bx-has-pager').append(slider.pagerEl); 452 } 453 // populate the pager 454 populatePager(); 455 }else{ 456 slider.pagerEl = $(slider.settings.pagerCustom); 457 } 458 // assign the pager click binding 459 slider.pagerEl.delegate('a', 'click', clickPagerBind); 460 } 461 462 /** 463 * Appends prev / next controls to the controls element 464 */ 465 var appendControls = function(){ 466 slider.controls.next = $('<a class="bx-next" href="">' + slider.settings.nextText + '</a>'); 467 slider.controls.prev = $('<a class="bx-prev" href="">' + slider.settings.prevText + '</a>'); 468 // bind click actions to the controls 469 slider.controls.next.bind('click', clickNextBind); 470 slider.controls.prev.bind('click', clickPrevBind); 471 // if nextSlector was supplied, populate it 472 if(slider.settings.nextSelector){ 473 $(slider.settings.nextSelector).append(slider.controls.next); 474 } 475 // if prevSlector was supplied, populate it 476 if(slider.settings.prevSelector){ 477 $(slider.settings.prevSelector).append(slider.controls.prev); 478 } 479 // if no custom selectors were supplied
vendor: 1,906 bytes, lines 480-515
480 if(!slider.settings.nextSelector && !slider.settings.prevSelector){ 481 // add the controls to the DOM 482 slider.controls.directionEl = $('<div class="bx-controls-direction" />'); 483 // add the control elements to the directionEl 484 slider.controls.directionEl.append(slider.controls.prev).append(slider.controls.next); 485 // slider.viewport.append(slider.controls.directionEl); 486 slider.controls.el.addClass('bx-has-controls-direction').append(slider.controls.directionEl); 487 } 488 } 489 490 /** 491 * Appends start / stop auto controls to the controls element 492 */ 493 var appendControlsAuto = function(){ 494 slider.controls.start = $('<div class="bx-controls-auto-item"><a class="bx-start" href="">' + slider.settings.startText + '</a></div>'); 495 slider.controls.stop = $('<div class="bx-controls-auto-item"><a class="bx-stop" href="">' + slider.settings.stopText + '</a></div>'); 496 // add the controls to the DOM 497 slider.controls.autoEl = $('<div class="bx-controls-auto" />'); 498 // bind click actions to the controls 499 slider.controls.autoEl.delegate('.bx-start', 'click', clickStartBind); 500 slider.controls.autoEl.delegate('.bx-stop', 'click', clickStopBind); 501 // if autoControlsCombine, insert only the "start" control 502 if(slider.settings.autoControlsCombine){ 503 slider.controls.autoEl.append(slider.controls.start); 504 // if autoControlsCombine is false, insert both controls 505 }else{ 506 slider.controls.autoEl.append(slider.controls.start).append(slider.controls.stop); 507 } 508 // if auto controls selector was supplied, populate it with the controls 509 if(slider.settings.autoControlsSelector){ 510 $(slider.settings.autoControlsSelector).html(slider.controls.autoEl); 511 // if auto controls selector was not supplied, add it after the wrapper 512 }else{ 513 slider.controls.el.addClass('bx-has-controls-auto').append(slider.controls.autoEl); 514 } 515 // update the auto controls
516 updateAutoControls(slider.settings.autoStart ? 'stop' : 'start'); 517 } 518 519 /** 520 * Appends image captions to the DOM 521 */ 522 var appendCaptions = function(){ 523 // cycle through each child 524 slider.children.each(function(index){ 525 // get the image title attribute 526 var title = $(this).find('img:first').attr('title'); 527 // append the caption 528 if (title != undefined) $(this).append('<div class="bx-caption"><span>' + title + '</span></div>'); 529 }); 530 } 531 532 /** 533 * Click next binding 534 * 535 * @param e (event) 536 * - DOM event object 537 */ 538 var clickNextBind = function(e){ 539 // if auto show is running, stop it 540 if (slider.settings.auto) el.stopAuto(); 541 el.goToNextSlide(); 542 e.preventDefault(); 543 } 544 545 /** 546 * Click prev binding 547 * 548 * @param e (event) 549 * - DOM event object 550 */ 551 var clickPrevBind = function(e){ 552 // if auto show is running, stop it 553 if (slider.settings.auto) el.stopAuto(); 554 el.goToPrevSlide(); 555 e.preventDefault(); 556 } 557 558 /** 559 * Click start binding 560 * 561 * @param e (event) 562 * - DOM event object 563 */ 564 var clickStartBind = function(e){ 565 el.startAuto(); 566 e.preventDefault(); 567 } 568 569 /** 570 * Click stop binding 571 * 572 * @param e (event) 573 * - DOM event object 574 */ 575 var clickStopBind = function(e){ 576 el.stopAuto(); 577 e.preventDefault(); 578 } 579 580 /** 581 * Click pager binding 582 * 583 * @param e (event) 584 * - DOM event object 585 */ 586 var clickPagerBind = function(e){ 587 // if auto show is running, stop it 588 if (slider.settings.auto) el.stopAuto(); 589 var pagerLink = $(e.currentTarget); 590 var pagerIndex = parseInt(pagerLink.attr('data-slide-index')); 591 // if clicked pager link is not active, continue with the goToSlide call 592 if(pagerIndex != slider.active.index) el.goToSlide(pagerIndex); 593 e.preventDefault(); 594 } 595 596 /** 597 * Updates the pager links with an active class 598 * 599 * @param slideIndex (int) 600 * - index of slide to make active 601 */ 602 var updatePagerActive = function(slideIndex){ 603 // if "short" pager type 604 if(slider.settings.pagerType == 'short'){ 605 slider.pagerEl.html((slideIndex + 1) + slider.settings.pagerShortSeparator + slider.children.length); 606 return; 607 } 608 // remove all pager active classes 609 slider.pagerEl.find('a').removeClass('active'); 610 // apply the active class 611 slider.pagerEl.find('a').eq(slideIndex).addClass('active'); 612 } 613 614 /** 615 * Performs needed actions after a slide transition 616 */ 617 var updateAfterSlideTransition = function(){ 618 // if not carousel and infinte loop is true 619 if(!slider.carousel && slider.settings.infiniteLoop){ 620 // last slide 621 if(slider.active.index == 0){ 622 // set the new position 623 var position = slider.children.eq(0).position(); 624 if (slider.settings.mode == 'horizontal') { el.css('left', -position.left); } 625 else if (slider.settings.mode == 'vertical') { el.css('top', -position.top); } 626 }else if(slider.active.index == slider.children.length - 1){ 627 // set the new position 628 var position = slider.children.eq(slider.children.length - 1).position(); 629 if (slider.settings.mode == 'horizontal') { el.css('left', -position.left); } 630 else if (slider.settings.mode == 'vertical') { el.css('top', -position.top); } 631 } 632 } 633 // declare that the transition is complete 634 slider.working = false; 635 // onSlideAfter callback 636 slider.settings.onSlideAfter(slider.children.eq(slider.active.index)); 637 } 638 639 /** 640 * Updates the auto controls state (either active, or combined switch) 641 * 642 * @param state (string) "start", "stop" 643 * - the new state of the auto show 644 */ 645 var updateAutoControls = function(state){ 646 // if autoControlsCombine is true, replace the current control with the new state 647 if(slider.settings.autoControlsCombine){ 648 slider.controls.autoEl.html(slider.controls[state]); 649 // if autoControlsCombine is false, apply the "active" class to the appropriate control 650 }else{ 651 slider.controls.autoEl.find('a').removeClass('active'); 652 slider.controls.autoEl.find('a:not(.bx-' + state + ')').addClass('active'); 653 } 654 } 655 656 /** 657 * Updates the direction controls (checks if either should be hidden) 658 */ 659 var updateDirectionControls = function(){ 660 // if infiniteLoop is false and hideControlOnEnd is true
661 if(!slider.settings.infiniteLoop && slider.settings.hideControlOnEnd){ 662 // if first slide 663 if (slider.active.index == 0){ 664 slider.controls.prev.addClass('disabled'); 665 slider.controls.next.removeClass('disabled'); 666 // if last slide 667 }else if(slider.active.index == getPagerQty() - 1){ 668 slider.controls.next.addClass('disabled'); 669 slider.controls.prev.removeClass('disabled'); 670 // if any slide in the middle 671 }else{ 672 slider.controls.prev.removeClass('disabled'); 673 slider.controls.next.removeClass('disabled'); 674 } 675 } 676 } 677 678 /** 679 * Initialzes the auto process 680 */ 681 var initAuto = function(){ 682 // if autoDelay was supplied, launch the auto show using a setTimeout() call 683 if(slider.settings.autoDelay > 0){ 684 var timeout = setTimeout(el.startAuto, slider.settings.autoDelay); 685 // if autoDelay was not supplied, start the auto show normally 686 }else{ 687 el.startAuto(); 688 } 689 // if autoHover is requested 690 if(slider.settings.autoHover){ 691 // on el hover 692 el.hover(function(){ 693 // if the auto show is currently playing (has an active interval) 694 if(slider.interval){ 695 // stop the auto show and pass true agument which will prevent control update 696 el.stopAuto(true); 697 // create a new autoPaused value which will be used by the relative "mouseout" event 698 slider.autoPaused = true; 699 } 700 }, function(){ 701 // if the autoPaused value was created be the prior "mouseover" event 702 if(slider.autoPaused){ 703 // start the auto show and pass true agument which will prevent control update 704 el.startAuto(true); 705 // reset the autoPaused value 706 slider.autoPaused = null; 707 } 708 }); 709 } 710 } 711 712 /** 713 * Initialzes the ticker process 714 */ 715 var initTicker = function(){ 716 // if autoDirection is "next", append a clone of the entire slider 717 if(slider.settings.autoDirection == 'next'){ 718 el.append(slider.children.clone().addClass('bx-clone')); 719 // if autoDirection is "prev", prepend a clone of the entire slider, and set the left position 720 }else{ 721 el.prepend(slider.children.clone().addClass('bx-clone')); 722 var position = slider.children.first().position(); 723 var startPosition = slider.settings.mode == 'horizontal' ? {left: -position.left} : {top: -position.top}; 724 el.css(startPosition); 725 } 726 // do not allow controls in ticker mode 727 slider.settings.pager = false; 728 slider.settings.controls = false; 729 slider.settings.autoControls = false; 730 // if autoHover is requested 731 if(slider.settings.tickerHover){ 732 // on el hover 733 slider.viewport.hover(function(){ 734 el.stop(); 735 }, function(){ 736 // calculate the total width of children (used to calculate the speed ratio) 737 var totalDimens = 0; 738 slider.children.each(function(index){ 739 totalDimens += slider.settings.mode == 'horizontal' ? $(this).outerWidth(true) : $(this).outerHeight(true); 740 }); 741 // calculate the speed ratio (used to determine the new speed to finish the paused animation) 742 var ratio = slider.settings.speed / totalDimens; 743 // determine which property to use 744 var property = slider.settings.mode == 'horizontal' ? 'left' : 'top'; 745 // calculate the new speed 746 var newSpeed = ratio * (totalDimens - (Math.abs(parseInt(el.css(property))))); 747 tickerLoop(newSpeed); 748 }); 749 } 750 // start the ticker loop 751 tickerLoop(); 752 } 753 754 /** 755 * Runs a continuous loop, news ticker-style 756 */ 757 var tickerLoop = function(resumeSpeed){ 758 speed = resumeSpeed ? resumeSpeed : slider.settings.speed; 759 var position = {left: 0, top: 0}; 760 var reset = {left: 0, top: 0}; 761 // if "next" animate left position to last child, then reset left to 0 762 if(slider.settings.autoDirection == 'next'){ 763 position = el.find('.bx-clone').first().position(); 764 // if "prev" animate left position to 0, then reset left to first non-clone child 765 }else{ 766 reset = slider.children.first().position(); 767 } 768 var animateProperty = slider.settings.mode == 'horizontal' ? {left: -position.left} : {top: -position.top}; 769 var resetProperty = slider.settings.mode == 'horizontal' ? {left: -reset.left} : {top: -reset.top}; 770 el.animate(animateProperty, speed, 'linear', function(){ 771 el.css(resetProperty); 772 // run the recursive loop after animation 773 tickerLoop(); 774 }); 775 } 776 777 /** 778 * Initializes touch events 779 */ 780 var initTouch = function(){ 781 // initialize object to contain all touch values 782 slider.touch = { 783 start: {x: 0, y: 0}, 784 end: {x: 0, y: 0} 785 } 786 slider.viewport.bind('touchstart', onTouchStart); 787 } 788 789 /** 790 * Event handler for "touchstart" 791 * 792 * @param e (event) 793 * - DOM event object 794 */ 795 var onTouchStart = function(e){ 796 if(slider.working){ 797 e.preventDefault(); 798 }else{ 799 // record the original position when touch starts 800 slider.touch.originalPos = el.position(); 801 var orig = e.originalEvent; 802 // record the starting touch x, y coordinates 803 // slider.touch.start = slider.settings.mode == 'horizontal' ? orig.changedTouches[0].pageX : orig.changedTouches[0].pageY;
804 slider.touch.start.x = orig.changedTouches[0].pageX; 805 slider.touch.start.y = orig.changedTouches[0].pageY; 806 // bind a "touchmove" event to the viewport 807 slider.viewport.bind('touchmove', onTouchMove); 808 // bind a "touchend" event to the viewport 809 slider.viewport.bind('touchend', onTouchEnd); 810 } 811 } 812 813 /** 814 * Event handler for "touchmove" 815 * 816 * @param e (event) 817 * - DOM event object 818 */ 819 var onTouchMove = function(e){ 820 e.preventDefault(); 821 if(slider.settings.mode != 'fade'){ 822 var orig = e.originalEvent; 823 // if horizontal, drag along x axis 824 if(slider.settings.mode == 'horizontal'){ 825 var change = orig.changedTouches[0].pageX - slider.touch.start.x; 826 property = {left: slider.touch.originalPos.left + change}; 827 // if vertical, drag along y axis 828 }else{ 829 var change = orig.changedTouches[0].pageY - slider.touch.start.y; 830 property = {top: slider.touch.originalPos.top + change}; 831 } 832 el.css(property); 833 } 834 } 835 836 /** 837 * Event handler for "touchend" 838 * 839 * @param e (event) 840 * - DOM event object 841 */ 842 var onTouchEnd = function(e){ 843 slider.viewport.unbind('touchmove', onTouchMove); 844 var orig = e.originalEvent; 845 var property; 846 // record end x, y positions 847 slider.touch.end.x = orig.changedTouches[0].pageX; 848 slider.touch.end.y = orig.changedTouches[0].pageY; 849 // if fade mode, check if absolute x distance clears the threshold 850 if(slider.settings.mode == 'fade'){ 851 var distance = Math.abs(slider.touch.start.x - slider.touch.end.x); 852 if(distance >= slider.settings.swipeThreshold){ 853 slider.touch.start.x > slider.touch.end.x ? el.goToNextSlide() : el.goToPrevSlide(); 854 el.stopAuto(); 855 } 856 // not fade mode 857 }else{ 858 var distance = 0; 859 // calculate distance and el's animate property 860 if(slider.settings.mode == 'horizontal'){ 861 distance = slider.touch.end.x - slider.touch.start.x; 862 property = {left: slider.touch.originalPos.left}; 863 }else{ 864 distance = slider.touch.end.x - slider.touch.start.x; 865 property = {top: slider.touch.originalPos.top}; 866 } 867 // if not infinite loop and first / last slide, do not attempt a slide transition 868 if(!slider.settings.infiniteLoop && ((slider.active.index == 0 && distance > 0) || (slider.active.last && distance < 0))){ 869 el.animate(property, 200); 870 }else{ 871 // check if distance clears threshold 872 if(Math.abs(distance) >= slider.settings.swipeThreshold){ 873 distance < 0 ? el.goToNextSlide() : el.goToPrevSlide(); 874 el.stopAuto(); 875 }else{ 876 el.animate(property, 200); 877 } 878 } 879 } 880 slider.viewport.unbind('touchend', onTouchEnd); 881 } 882 883 /** 884 * =================================================================================== 885 * = PUBLIC FUNCTIONS 886 * =================================================================================== 887 */ 888 889 /** 890 * Performs slide transition to the specified slide 891 * 892 * @param slideIndex (int) 893 * - the destination slide's index (zero-based) 894 * 895 * @param direction (string) 896 * - INTERNAL USE ONLY - the direction of travel ("prev" / "next") 897 */ 898 el.goToSlide = function(slideIndex, direction){ 899 // if plugin is currently in motion, ignore request 900 if(slider.working || slider.active.index == slideIndex) return; 901 // declare that plugin is in motion 902 slider.working = true; 903 // if slideIndex is less than zero, set active index to last child (this happens during infinite loop) 904 if(slideIndex < 0){ 905 slider.active.index = slider.children.length - 1; 906 // if slideIndex is greater than children length, set active index to 0 (this happens during infinite loop) 907 }else if(slideIndex >= slider.children.length){ 908 slider.active.index = 0; 909 // set active index to requested slide 910 }else{ 911 slider.active.index = slideIndex; 912 } 913 // onSlideBefore, onSlideNext, onSlidePrev callbacks 914 slider.settings.onSlideBefore(slider.children.eq(slider.active.index)); 915 if(direction == 'next'){ 916 slider.settings.onSlideNext(slider.children.eq(slider.active.index)); 917 }else if(direction == 'prev'){ 918 slider.settings.onSlidePrev(slider.children.eq(slider.active.index)); 919 } 920 // check if last slide 921 slider.active.last = slider.active.index >= getPagerQty() - 1; 922 // update the pager with active class 923 if(slider.settings.pager) updatePagerActive(slider.active.index); 924 // // check for direction control update 925 if(slider.settings.controls) updateDirectionControls(); 926 // if slider is set to mode: "fade" 927 if(slider.settings.mode == 'fade'){ 928 // if adaptiveHeight is true and next height is different from current height, animate to the new height 929 if(slider.settings.adaptiveHeight && slider.viewport.height() != getViewportHe
929ight()){ 930 slider.viewport.animate({height: getViewportHeight()}, slider.settings.adaptiveHeightSpeed); 931 } 932 // fade out the visible child and reset its z-index value 933 slider.children.filter(':visible').fadeOut(slider.settings.speed).css({zIndex: 0}); 934 // fade in the newly requested slide 935 slider.children.eq(slider.active.index).css('zIndex', 51).fadeIn(slider.settings.speed, function(){ 936 $(this).css('zIndex', 50); 937 updateAfterSlideTransition(); 938 }); 939 // slider mode is not "fade" 940 }else{ 941 // if adaptiveHeight is true and next height is different from current height, animate to the new height 942 if(slider.settings.adaptiveHeight && slider.viewport.height() != getViewportHeight()){ 943 slider.viewport.animate({height: getViewportHeight()}, slider.settings.adaptiveHeightSpeed); 944 } 945 var moveBy = 0; 946 var position = {left: 0, top: 0}; 947 // if carousel mode and last slide 948 if(slider.carousel && slider.active.last){ 949 if(slider.settings.mode == 'horizontal'){ 950 // get the last child position 951 var lastChild = slider.children.eq(slider.children.length - 1); 952 position = lastChild.position(); 953 // calculate the position of the last slide 954 moveBy = slider.viewport.width() - lastChild.width(); 955 }else{ 956 // get last showing index position 957 var lastShowingIndex = slider.children.length - slider.settings.minSlides; 958 position = slider.children.eq(lastShowingIndex).position(); 959 } 960 // if not carousel and infinite loop, and "Next" is clicked on the last slide 961 }else if(!slider.carousel && direction == 'next' && slider.active.index == 0){ 962 // get the last clone position 963 position = el.find('.bx-clone:last').position(); 964 slider.active.last = false; 965 // all other requests 966 }else if(slideIndex >= 0){ 967 var requestEl = slideIndex * getMoveBy(); 968 position = slider.children.eq(requestEl).position(); 969 } 970 // plugin values to be animated 971 var animateProperty = slider.settings.mode == 'horizontal' ? {left: -(position.left - moveBy)} : {top: -position.top} 972 el.animate(animateProperty, slider.settings.speed, slider.settings.easing, function(){ 973 updateAfterSlideTransition(); 974 }); 975 } 976 } 977 978 /** 979 * Transitions to the next slide in the show 980 */ 981 el.goToNextSlide = function(){ 982 // if infiniteLoop is false and last page is showing, disregard call 983 if (!slider.settings.infiniteLoop && slider.active.last) return; 984 var pagerIndex = slider.active.index + 1; 985 // if carousel mode, infinite loop is true and "next" was clicked while on the last slide, go to slide 0 986 if (slider.carousel && slider.settings.infiniteLoop && pagerIndex >= getPagerQty()) pagerIndex = 0; 987 el.goToSlide(pagerIndex, 'next'); 988 } 989 990 /** 991 * Transitions to the prev slide in the show 992 */ 993 el.goToPrevSlide = function(){ 994 // if infiniteLoop is false and last page is showing, disregard call 995 if (!slider.settings.infiniteLoop && slider.active.index == 0) return; 996 var pagerIndex = slider.active.index - 1; 997 // if carousel mode, infinite loop is true and "prev" was clicked while on the first slide, go to last slide 998 if (slider.carousel && slider.settings.infiniteLoop && pagerIndex < 0) pagerIndex = getPagerQty() - 1; 999 el.goToSlide(pagerIndex, 'prev'); 1000 } 1001 1002 /** 1003 * Starts the auto show 1004 * 1005 * @param preventControlUpdate (boolean) 1006 * - if true, auto controls state will not be updated 1007 */ 1008 el.startAuto = function(preventControlUpdate){ 1009 // if an interval already exists, disregard call 1010 if(slider.interval) return; 1011 // create an interval 1012 slider.interval = setInterval(function(){ 1013 slider.settings.autoDirection == 'next' ? el.goToNextSlide() : el.goToPrevSlide(); 1014 }, slider.settings.pause); 1015 // if auto controls are displayed and preventControlUpdate is not true 1016 if (slider.settings.autoControls && preventControlUpdate != true) updateAutoControls('stop'); 1017 } 1018 1019 /** 1020 * Stops the auto show 1021 * 1022 * @param preventControlUpdate (boolean) 1023 * - if true, auto controls state will not be updated 1024 */ 1025 el.stopAuto = function(preventControlUpdate){ 1026 // if no interval exists, disregard call
1027 if(!slider.interval) return; 1028 // clear the interval 1029 clearInterval(slider.interval); 1030 slider.interval = null; 1031 // if auto controls are displayed and preventControlUpdate is not true 1032 if (slider.settings.autoControls && preventControlUpdate != true) updateAutoControls('start'); 1033 } 1034 1035 /** 1036 * Returns current slide index (zero-based) 1037 */ 1038 el.getCurrentSlide = function(){ 1039 return slider.active.index; 1040 } 1041 1042 /** 1043 * Returns number of slides in show 1044 */ 1045 el.getSlideCount = function(){ 1046 return slider.children.length; 1047 } 1048 1049 /** 1050 * Makes slideshow responsive 1051 */ 1052 // first get the original window dimens (thanks alot IE) 1053 var windowWidth = $(window).width(); 1054 var windowHeight = $(window).height(); 1055 $(window).resize(function(){ 1056 // get the new window dimens (again, thank you IE) 1057 var windowWidthNew = $(window).width(); 1058 var windowHeightNew = $(window).height(); 1059 // make sure that it is a true window resize 1060 // *we must check this because our dinosaur friend IE fires a window resize event when certain DOM elements 1061 // are resized. Can you just die already?* 1062 if(windowWidth != windowWidthNew || windowHeight != windowHeightNew){ 1063 // set the new window dimens 1064 windowWidth = windowWidthNew; 1065 windowHeight = windowHeightNew; 1066 // resize all children in ratio to new screen size 1067 slider.children.add(el.find('.bx-clone')).width(getSlideWidth()); 1068 // adjust the height 1069 slider.viewport.css('height', getViewportHeight()); 1070 // if active.last was true before the screen resize, we want 1071 // to keep it last no matter what screen size we end on 1072 if (slider.active.last) slider.active.index = getPagerQty() - 1; 1073 // if the active index (page) no longer exists due to the resize, simply set the index as last 1074 if (slider.active.index >= getPagerQty()) slider.active.last = true; 1075 // if a pager is being displayed and a custom pager is not being used, update it 1076 if(slider.settings.pager && !slider.settings.pagerCustom){ 1077 populatePager(); 1078 updatePagerActive(slider.active.index); 1079 } 1080 // update the slide position 1081 setSlidePosition(); 1082 } 1083 }); 1084 1085 init(); 1086 1087 // returns the current jQuery object 1088 return this; 1089 } 1090 1091})(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.