1/**@preserve 2 * Sudo Slider version 3.4.9 - jQuery plugin 3 * Written by Erik Krogh Kristensen [email protected]. 4 * http://webbies.dk/SudoSlider/ 5 * 6 * Dual licensed under the MIT and GPL licenses. 7 * 8 * Based on EasySlider http://cssglobe.com/easy-slider-17-numeric-navigation-jquery-slider/ 9 * But bear little resemblance at this point. 10 * 11 * Built for jQuery library 12 * http://jquery.com 13 * 14 */ 15(function(factory) { 16 // window/root object. 17 var root = (typeof self == 'object' && self.self == self && self) || 18 (typeof global == 'object' && global.global == global && global); 19 20 // AMD 21 if (typeof define === 'function' && define.amd) { 22 define(['jquery'], function($) { 23 factory($, root); 24 }); 25 26 // CommonJS 27 } else if (typeof exports !== 'undefined') { 28 var $ = require('jquery'); 29 factory($, root); 30 31 // Finally, as a browser global. 32 } else { 33 factory(root.jQuery || root.$, root); 34 } 35 36})(function ($, win) { 37 // Saves space in the minified version. 38 var undefined; // Makes sure that undefined really is undefined within this scope. 39 var FALSE = false; 40 var TRUE = true; 41 42 // Constants 43 var PAGES_MARKER_STRING = "pages"; 44 var NEXT_STRING = "next"; 45 var PREV_STRING = "prev"; 46 var LAST_STRING = "last"; 47 var FIRST_STRING = "first"; 48 var ABSOLUTE_STRING = "absolute"; 49 var RELATIVE_STRING = "relative"; 50 var HIDDEN_STRING = "hidden"; 51 var SWING = "swing"; 52 var EMPTY_FUNCTION = function () { }; 53 var ANIMATION_CLONE_MARKER_CLASS = "sudo-box"; 54 var DIV_TAG = "<div>"; 55 var CSSVendorPrefix = getCSSVendorPrefix(); 56 var jWin = jQuery(win); 57 var doc = jQuery(document); 58 59 var TOUCHSTART = "touchstart"; 60 var TOUCHMOVE = "touchmove"; 61 var TOUCHCANCEL = "touchcancel"; 62 var TOUCHEND = "touchend"; 63 var MOUSEDOWN = "mousedown"; 64 var MOUSEMOVE = "mousemove"; 65 var MOUSEUP = "mouseup"; 66 var SLIDES_CONTAINER = "slidesContainer"; 67 var SUDO_DRAGGING_CLASS = "sudoSlider-dragging"; 68 69 jQuery.fn.sudoSlider = function (optionsOrg) { 70 // Defining the base element. 71 var baseSlider = this; 72 73 optionsOrg = $.extend(objectToLowercase(getDefaultOptions()), objectToLowercase(optionsOrg)); 74 if (CSSVendorPrefix === FALSE || !minJQueryVersion([1, 8, 0])) { 75 optionsOrg.usecss = FALSE; 76 } 77 78 return this.each(function () { 79 var init, 80 fullyInitialized = FALSE, 81 isSlideContainerUl, 82 slidesContainer, 83 slides, 84 imagesInSlidesLoaded, 85 totalSlides, 86 currentSlide, 87 previousSlide, 88 clickable, 89 currentlyAnimatingTowards, 90 numericControls, 91 numericContainer, 92 destroyed, 93 slideNumberBeforeDestroy = FALSE, 94 controls, 95 nextbutton, 96 prevbutton, 97 autoTimeout, 98 autoOn, 99 numberOfVisibleSlides, 100 asyncDelayedSlideLoadTimeout, 101 obj = $(this), 102 finishedAdjustingTo = FALSE, // This variable tells if the slider is currently adjusted (height and width) to any specific slide. This is usefull when ajax-loading stuff. 103 adjustingTo, // This one tells what slide we are adjusting to, to make sure that we do not adjust to something we shouldn't. 104 adjustTargetTime = 0, // This one holds the time that the autoadjust animation should complete. 105 currentlyAnimating = FALSE, 106 currentAnimation, 107 currentAnimationCallback, 108 currentAnimationObject, 109 runAfterAnimationCallbacks, 110 awaitingAjaxCallbacks, 111 startedAjaxLoads, 112 finishedAjaxLoads, 113 animateToAfterCompletion = FALSE, 114 animateToAfterCompletionClicked, 115 animateToAfterCompletionSpeed, 116 slideContainerCreated = FALSE, 117 option = [], 118 options = $.extend(TRUE, {}, optionsOrg), 119 currentSliderPositionTop, 120 currentSliderPositionLeft, 121 unBindCallbacks = [], 122 autoStartedWithPause = FALSE, 123 animationWasInterrupted = FALSE; 124 125 // The call to the init function is after the definition of all the functions. 126 function initSudoSlider() { 127 // Storing the public options in an array.
128 var optionIndex = 0; 129 for (var key in options) { 130 option[optionIndex] = options[key]; 131 optionIndex++; 132 } 133 134 init = TRUE; 135 fullyInitialized = FALSE; 136 137 imagesInSlidesLoaded = []; 138 runAfterAnimationCallbacks = []; 139 awaitingAjaxCallbacks = []; 140 startedAjaxLoads = []; 141 finishedAjaxLoads = []; 142 143 // Fix for nested list items 144 slidesContainer = childrenNotAnimationClones(obj); 145 146 // Is the ul element there? 147 var ulLength = slidesContainer.length; 148 var newUl = $(DIV_TAG); 149 if (!ulLength) { 150 obj.append(slidesContainer = newUl); 151 isSlideContainerUl = FALSE; 152 } else if (!((isSlideContainerUl = slidesContainer.is("ul")) || slidesContainer.hasClass(SLIDES_CONTAINER)) && !slideContainerCreated) { 153 newUl.append(slidesContainer); 154 obj.append(slidesContainer = newUl); 155 } 156 slideContainerCreated = TRUE; 157 158 var slidesJquery = childrenNotAnimationClones(slidesContainer); 159 160 slides = []; 161 162 totalSlides = slidesJquery.length; 163 164 slidesJquery.each(function (index, elem) { 165 var that = $(elem); 166 slides[index] = that; 167 that.css({position: RELATIVE_STRING}); 168 if (that.css("display") == "none") { 169 that.css("display", "inline"); 170 } 171 }); 172 173 // Adding CSS classes 174 slidesContainer.addClass(SLIDES_CONTAINER); 175 176 slidesJquery.addClass("slide"); 177 178 slidesJquery.each(function (index, elem) { 179 $(elem).attr("data-slide", index + 1); 180 }); 181 182 // Now we are going to fix the document, if it's 'broken'. (No <li>). 183 // I assume that it's can only be broken, if ajax is enabled. If it's broken without Ajax being enabled, the script doesn't have anything to fill the holes. 184 if (option[30]/*ajax*/) { 185 // Do we have enough list elements to fill out all the ajax documents. 186 var numerOfAjaxUrls = option[30]/*ajax*/.length; 187 if (numerOfAjaxUrls > totalSlides) { 188 for (var a = 1; a <= numerOfAjaxUrls - totalSlides; a++) { 189 var tag; 190 if (isSlideContainerUl) { 191 tag = "li"; 192 } else { 193 tag = "div"; 194 } 195 var slide = $("<" + tag + ">" + option[32]/*loadingtext*/ + "</" + tag + ">"); 196 slidesContainer.append(slide); 197 slides[totalSlides + (a - 1)] = slide; 198 } 199 slidesJquery = childrenNotAnimationClones(slidesContainer); 200 totalSlides = numerOfAjaxUrls; 201 } 202 } 203 204 slidesJquery.each(function (index, elem) { 205 imagesInSlidesLoaded[index] = FALSE; 206 runOnImagesLoaded($(elem), TRUE, function () { 207 imagesInSlidesLoaded[index] = TRUE; 208 }); 209 }); 210 211 if (slideNumberBeforeDestroy === FALSE) { 212 currentSlide = 0; 213 } else { 214 currentSlide = slideNumberBeforeDestroy; 215 } 216 currentSlide = currentSlide || 0; 217 218 previousSlide = currentSlide; 219 220 clickable = TRUE; 221 numericControls = []; 222 destroyed = FALSE; 223 224 225 // Set obj overflow to hidden (and position to relative <strike>, if fade is enabled. </strike>) 226 obj.css({overflow: HIDDEN_STRING}); 227 if (obj.css("position") == "static") obj.css({position: RELATIVE_STRING}); // Fixed a lot of IE6 + IE7 bugs. 228 229 // Float items to the left, and make sure that all elements are shown. 230 slidesJquery.css({"float": "left", listStyle: "none"}); 231 // The last CSS to make it work. 232 slidesContainer.add(slidesJquery).css({display: "block", position: RELATIVE_STRING, margin: "0"}); 233 234 adjustPositionToPosition(0, 0, TRUE); 235 236 option[7]/*slidecount*/ = parseInt10(option[7]/*slidecount*/); 237 238 // Lets just redefine slidecount 239 numberOfVisibleSlides = option[7]/*slidecount*/; 240 241 option[7]/*slidecount*/ += option[8]/*movecount*/ - 1; 242 243 // startslide can only be a number (and not 0). Converting from 1 index to 0 index. 244 // unless it is the string "random". 245 if (typeof option[9]/*startslide*/ == "string" && option[9]/*startslide*/.toLowerCase() == "random") { 246 option[9]/*startslide*/ = (Math.random() * totalSlides) | 0; 247 } 248 option[9]/*startslide*/ = parseInt10(option[9]/*startslide*/) - 1 || 0; 249 250 option[0]/*effect*/ = getEffectMethod(option[0]/*effect*/); 251 252 // Cloning numericText, so the array same array can be modifed outside SudoSlider without doing weird things. 253 option[18]/*numerictext*/ = option[18]/*numerictext*/.slice(0); 254 255 for (var a = 0; a < totalSlides; a++) { 256 if (!option[18]/*numerictext*/[a] && option[18]/*numerictext*/[a] != "") { 257 option[18]/*numerictext*/[a] = (a + 1); 258 } 259 if (option[30]/*ajax*/) { 260 option[30]/*ajax*/[a] = option[30]/*ajax*/[a] || FALSE; 261 } 262 } 263
264 option[4]/*controlsfade*/ = option[4]/*controlsfade*/ && !option[15]/*continuous*/; 265 266 if (option[10]/*responsive*/) { 267 adjustResponsiveLayout(TRUE); 268 } 269 270 // Making sure that i have enough room in the <ul> (Through testing, i found out that the max supported size (height or width) in Firefox is 17895697px, Chrome supports up to 134217726px, and i didn't find any limits in IE (6/7/8/9)). 271 // 9000000px gives room for about 12500 slides of 700px each (and works in every browser i tested). Down to 9000000 from 10000000 because the later might not work perfectly in FireFox on OSX. 272 slidesContainer[option[6]/*vertical*/ ? "height" : "width"](9000000)[option[6]/*vertical*/ ? "width" : "height"]("100%"); 273 274 // If responsive is turned on, autowidth doesn't work. 275 option[28]/*autowidth*/ = option[28]/*autowidth*/ && !option[10]/*responsive*/; 276 277 if (option[10]/*responsive*/) { 278 bindAndRegisterOff(jWin, "resize focus", adjustResponsiveLayout, ""); 279 } 280 281 if (option[17]/*numeric*/ || option[16]/*prevnext*/) { 282 controls = $("<span " + option[35]/*controlsattr*/ + "></span>"); 283 obj[option[5]/*insertafter*/ ? "after" : "before"](controls); 284 285 if (option[17]/*numeric*/) { 286 numericContainer = $("<ol " + option[36]/*numericattr*/ + "></ol>"); 287 controls.prepend(numericContainer); 288 var usePages = option[17]/*numeric*/ == PAGES_MARKER_STRING; 289 var distanceBetweenPages = usePages ? numberOfVisibleSlides : 1; 290 for (var a = 0; a < totalSlides - ((option[15]/*continuous*/ || usePages) ? 1 : numberOfVisibleSlides) + 1; a += distanceBetweenPages) { 291 numericControls[a] = $("<li data-target=\"" + (a + 1) + "\"><a href=\"#\"><span>" + option[18]/*numerictext*/[a] + "</span></a></li>") 292 .appendTo(numericContainer) 293 .click(function () { 294 enqueueAnimation(getTargetAttribute(this) - 1, TRUE); 295 return FALSE; 296 }); 297 } 298 } 299 if (option[16]/*prevnext*/) { 300 nextbutton = makecontrol(option[34]/*nexthtml*/, NEXT_STRING); 301 prevbutton = makecontrol(option[33]/*prevhtml*/, PREV_STRING); 302 } 303 if (option[4]/*controlsfade*/) { 304 fadeControls(currentSlide, 0); 305 } 306 } 307 308 309 // Lets make those fast/normal/fast into some numbers we can make calculations with. 310 var optionsToConvert = [4/*controlsfadespeed*/, 1/*speed*/, 14/*pause*/]; 311 for (var i = 0; i < optionsToConvert.length; i++) { 312 option[optionsToConvert[i]] = textSpeedToNumber(option[optionsToConvert[i]]); 313 } 314 315 if (option[2]/*customlink*/) { 316 var filter = stringTrim(option[2]/*customlink*/); 317 if (filter.charAt(0) == ">") { 318 bindAndRegisterOff(obj, "click", customLinkClickHandler, filter.substr(1, filter.length)); 319 } else { 320 bindAndRegisterOff(doc, "click", customLinkClickHandler, filter); 321 } 322 } 323 324 runOnImagesLoaded(getSlides(option[9]/*startslide*/, option[7]/*slidecount*/), TRUE, function () { 325 if (slideNumberBeforeDestroy !== FALSE) { 326 goToSlide(slideNumberBeforeDestroy, FALSE); 327 } else if (option[26]/*history*/) { 328 // I support the jquery.address plugin, Ben Alman's hashchange plugin and Ben Alman's jQuery.BBQ. 329 var hashPlugin; 330 if (hashPlugin = jWin.hashchange) { 331 hashPlugin(URLChange); 332 } else if (hashPlugin = $.address) { 333 hashPlugin.change(URLChange); 334 } else { 335 // This assumes that jQuery BBQ is included. If not, stuff won't work in old browsers. 336 bindAndRegisterOff(jWin, "hashchange", URLChange); 337 } 338 URLChange(); 339 340 } else { 341 goToSlide(option[9]/*startslide*/, FALSE); 342 } 343 344 setCurrent(currentSlide); 345 }); 346 if (option[30]/*ajax*/[option[9]/*startslide*/]) { 347 ajaxLoad(option[9]/*startslide*/); 348 } 349 if (option[31]/*preloadajax*/ === TRUE) { 350 for (var i = 0; i < totalSlides; i++) { 351 if (option[30]/*ajax*/[i] && option[9]/*startslide*/ != i) { 352 ajaxLoad(i); 353 } 354 } 355 } else { 356 startAsyncDelayedLoad(); 357 } 358 } 359 360 /* 361 * The functions do the magic. 362 */ 363 364 function customLinkClickHandler() { 365 var target; 366 if (target = getTargetAttribute(this)) { 367 if (target == 'stop') { 368 option[12]/*auto*/ = FALSE; 369 stopAuto(); 370 } else if (target == "start") { 371 startAuto(); 372 option[12]/*auto*/ = TRUE; 373 } else if (target == 'block') { 374 clickable = FALSE; 375 } else if (target == 'unblock') { 376 clickable = TRUE; 377 } else { 378 enqueueAnimation((target == parseInt10(target)) ? target - 1 : target, TRUE); 379 } 380 } 381 return FALSE; 382 } 383 384 // Adjusts the slider when a change in layout has happened.
385 var previousAdjustedResponsiveWidth = -1; 386 387 function adjustResponsiveLayout(forced) { 388 function doTheAdjustment() { 389 if ((cantDoAdjustments() && !(forced === TRUE)) || totalSlides == 0) { 390 return; 391 } 392 393 var subPixelNewWidth = getResponsiveWidth(); 394 var newWidth = parseInt10(subPixelNewWidth); 395 var addAPixelEvery = 1 / (subPixelNewWidth - newWidth); 396 397 if (previousAdjustedResponsiveWidth != newWidth || (forced === TRUE)) { 398 previousAdjustedResponsiveWidth = newWidth; 399 400 var slideCounter = 1; 401 for (var i = 0; i < totalSlides; i++) { 402 slideCounter++; 403 if (slideCounter >= addAPixelEvery) { 404 slideCounter = 0; 405 slides[i].width(newWidth + 1); 406 } else { 407 slides[i].width(newWidth); 408 } 409 } 410 if (autoStartedWithPause !== FALSE) { 411 startAuto(autoStartedWithPause); 412 } 413 414 stopAnimation(); 415 ensureSliderContainerCSSDurationReset(); 416 adjustPositionTo(currentSlide); 417 autoadjust(currentSlide, 0); 418 } 419 } 420 421 doTheAdjustment(); 422 callAsync(doTheAdjustment); // Fixing invisible scrollbar. 423 schedule(doTheAdjustment, 20); 424 } 425 426 // Returns the width of a single <li> if the page layout is responsive. 427 function getResponsiveWidth() { 428 var width = obj.width(); 429 if (option[6]/*vertical*/) { 430 return width; 431 } else { 432 return width / numberOfVisibleSlides; 433 } 434 } 435 436 // For backwards compability, the rel attribute is used as a fallback. 437 function getTargetAttribute(that) { 438 that = $(that); 439 return that.attr("data-target") || that.attr("rel"); 440 } 441 442 // Triggered when the URL changes. 443 function URLChange() { 444 var target = getUrlHashTarget(); 445 if (init) { 446 goToSlide(target, FALSE); 447 } else { 448 enqueueAnimation(target, FALSE); 449 } 450 } 451 452 function startAsyncDelayedLoad() { 453 if (option[31]/*preloadajax*/ !== FALSE) { 454 var preloadAjaxTime = parseInt10(option[31]/*preloadajax*/); 455 if (option[30]/*ajax*/) { 456 for (var i = 0; i < option[30]/*ajax*/.length; i++) { 457 if (option[30]/*ajax*/[i]) { 458 clearTimeout(asyncDelayedSlideLoadTimeout); 459 asyncDelayedSlideLoadTimeout = schedule(function () { 460 if (option[30]/*ajax*/[i]) { 461 ajaxLoad(i); 462 } else { 463 startAsyncDelayedLoad(); 464 } 465 }, preloadAjaxTime); 466 467 break; 468 } 469 } 470 } 471 } 472 } 473 474 function startAuto(pause) { 475 if (pause === undefined) { 476 var dataPause = slides[currentSlide].attr("data-pause"); 477 if (dataPause !== undefined) { 478 pause = parseInt10(dataPause); 479 } else { 480 pause = option[13]/*pause*/; 481 } 482 } 483 if (animationWasInterrupted) { 484 pause = mathMax(pause, 100); 485 } 486 stopAuto(); 487 autoOn = TRUE; 488 autoStartedWithPause = pause; 489 autoTimeout = schedule(function () { 490 if (autoOn && !currentlyAnimating) { 491 enqueueAnimation(NEXT_STRING, FALSE); 492 autoStartedWithPause = FALSE; 493 } 494 }, pause); 495 } 496 497 function stopAuto(autoPossibleStillOn) { 498 if (autoTimeout) { 499 clearTimeout(autoTimeout); 500 } 501 if (!autoPossibleStillOn) autoOn = FALSE; 502 } 503 504 function textSpeedToNumber(speed) { 505 if (parseInt10(speed) || speed == 0) { 506 return parseInt10(speed); 507 } 508 if (speed == "fast") { 509 return 200; 510 } 511 if (speed == "normal" || speed == "medium") { 512 return 400; 513 } 514 if (speed == "slow") { 515 return 600; 516 } 517 return 600; 518 } 519 520 function makecontrol(html, action) { 521 return $(html).prependTo(controls).click(function () { 522 enqueueAnimation(action, TRUE); 523 return FALSE; 524 }); 525 } 526 527 function enqueueAnimation(direction, clicked, speed) { 528 if (clickable && !init) { 529 // Stopping, because if its needed then its restarted after the end of the animation. 530 stopAuto(TRUE); 531 532 if (!destroyed) { 533 loadSlidesAndAnimate(direction, clicked, speed); 534 } 535 } else { 536 if (option[37]/*interruptible*/ && currentlyAnimating) { 537 if (getRealPos(filterDir(direction)) !== currentlyAnimatingTowards) { 538 stopAnimation(); 539 enqueueAnimation(direction, clicked, speed); 540 } 541 } else { 542 animateToAfterCompletion = direction; 543 animateToAfterCompletionClicked = clicked; 544 animateToAfterCompletionSpeed = speed; 545 546 // I can just as well start the ajax loads 547 if (option[30]/*ajax*/) { 548 var targetSlide = filterDir(direction); 549 for (var loadSlide = targetSlide; loadSlide < targetSlide + numberOfVisibleSlides; loadSlide++) { 550 if (option[30]/*ajax*/[loadSlide]) { 551 ajaxLoad(getRealPos(loadSlide)); 552 } 553 } 554 } 555 } 556 } 557 } 558 559 // It may not sound like it, but the variable fadeOpacity is only for TRUE/FALSE.
560 function fadeControl(fadeOpacity, fadetime, nextcontrol) { 561 fadeOpacity = fadeOpacity ? 1 : 0; 562 var fadeElement = $(); 563 564 if (option[16]/*prevnext*/) { 565 fadeElement = nextcontrol ? nextbutton : prevbutton; 566 } 567 568 if (option[2]/*customlink*/) { 569 var customLink = $(option[2]/*customlink*/); 570 var filterString = "=\"" + (nextcontrol ? NEXT_STRING : PREV_STRING) + "\"]"; 571 var filtered = customLink.filter("[rel" + filterString + ", [data-target" + filterString + ""); 572 fadeElement = fadeElement.add(filtered); 573 } 574 575 var adjustObject = {opacity: fadeOpacity}; 576 577 function callback() { 578 if (!fadeOpacity && fadeElement.css("opacity") == 0) { 579 fadeElement.css({visibility: HIDDEN_STRING}); 580 } 581 } 582 583 if (fadeOpacity) { 584 fadeElement.css({visibility: "visible"}); 585 } 586 587 if (option[38]/*useCSS*/) { 588 animate(fadeElement, adjustObject, fadetime, option[46]/*CSSease*/, callback); 589 } else { 590 fadeElement.animate( 591 adjustObject, 592 { 593 queue: FALSE, 594 duration: fadetime, 595 easing: option[11]/*ease*/, 596 callback: callback 597 } 598 ); 599 } 600 } 601 602 // Fade the controls, if we are at the end of the slide. 603 // It's all the different kind of controls. 604 function fadeControls(slide, fadetime) { 605 fadeControl(slide, fadetime, FALSE); // abusing that the number 0 == FALSE. 606 // The new way of doing it. 607 fadeControl(slide < totalSlides - numberOfVisibleSlides, fadetime, TRUE); 608 } 609 610 // Updating the 'current' class 611 function setCurrent(i) { 612 i = getRealPos(i) + 1; 613 614 // Fixing that the last numeric control isn't marked when we are at the last possible position. 615 if (option[17]/*numeric*/ == PAGES_MARKER_STRING && i == totalSlides - numberOfVisibleSlides + 1 && !option[15]/*continuous*/) { 616 i = totalSlides; 617 } 618 619 if (option[17]/*numeric*/) { 620 for (var control = 0; control < numericControls.length; ++control) { 621 var element = numericControls[control]; 622 setCurrentElement(element, i) 623 } 624 } 625 if (option[2]/*customlink*/) setCurrentElement($(option[2]/*customlink*/), i); 626 } 627 628 function setCurrentElement(element, i) { 629 if (element && element.filter) { 630 element 631 .filter(".current") 632 .removeClass("current"); 633 634 element 635 .filter(function () { 636 var elementTarget = getTargetAttribute(this); 637 if (option[17]/*numeric*/ == PAGES_MARKER_STRING) { 638 for (var a = numberOfVisibleSlides - 1; a >= 0; a--) { 639 if (elementTarget == i - a) { 640 return TRUE; 641 } 642 } 643 } else { 644 return elementTarget == i; 645 } 646 return FALSE; 647 }) 648 .addClass("current"); 649 } 650 } 651 652 function getUrlHashTarget() { 653 var hashString = location.hash.substr(1) 654 for (var i = 0; i < option[18]/*numerictext*/.length; i++) { 655 if (option[18]/*numerictext*/[i] == hashString) { 656 return i; 657 } 658 } 659 if (hashString && !init) { 660 return currentSlide; 661 } else { 662 return option[9]/*startslide*/; 663 } 664 } 665 666 function autoadjust(i, speed) { 667 i = getRealPos(i); // I assume that the continuous clones, and the original element is the same height. So i always adjust according to the original element. 668 669 adjustingTo = i; 670 adjustTargetTime = getTimeInMillis() + speed; 671 672 if (speed == 0) { 673 finishedAdjustingTo = i; 674 } else { 675 finishedAdjustingTo = FALSE; 676 } 677 678 if (option[27]/*autoheight*/ || option[28]/*autowidth*/) { 679 autoHeightWidth(i); 680 } 681 } 682 683 684 function autoHeightWidth(i) { 685 obj.ready(function () { 686 adjustHeightWidth(i); 687 runOnImagesLoaded(slides[i], FALSE, makeCallback(adjustHeightWidth, [i])); 688 }); 689 } 690
691 // Axis: TRUE == height, FALSE == width. 692 function getSliderDimensions(fromSlide, vertical) { 693 var pixels = 0; 694 for (var slide = fromSlide; slide < fromSlide + numberOfVisibleSlides; slide++) { 695 var targetSlide = slides[getRealPos(slide)]; 696 if (targetSlide) { 697 var targetPixels = targetSlide['outer' + (vertical ? "Height" : "Width")](TRUE); 698 if (vertical == option[6]/*vertical*/) { 699 pixels += targetPixels; 700 } else { 701 pixels = mathMax(targetPixels, pixels); 702 } 703 } 704 } 705 return pixels; 706 } 707 708 var prevHeightWidthAdjustObject = {}; 709 710 function adjustHeightWidth(i) { 711 if (i != adjustingTo || cantDoAdjustments()) { 712 return; 713 } 714 715 var speed = adjustTargetTime - getTimeInMillis(); 716 speed = mathMax(speed, 0); 717 var adjustObject = {}; 718 if (option[27]/*autoheight*/) { 719 adjustObject.height = getSliderDimensions(i, TRUE) || 1; // Making it completely invisible gives trouble. 720 } 721 if (option[28]/*autowidth*/) { 722 adjustObject.width = getSliderDimensions(i, FALSE) || 1; 723 } 724 725 726 if (simpleObjectEquals(prevHeightWidthAdjustObject, adjustObject)) { 727 return; 728 } else { 729 prevHeightWidthAdjustObject = adjustObject; 730 } 731 732 if (option[38]/*useCSS*/) { 733 animate(obj, adjustObject, speed, option[46]/*CSSease*/) 734 } else { 735 if (speed == 0) { 736 // Doing CSS if speed == 0, 1: its faster. 2: it fixes bugs. 737 obj.stop().css(adjustObject); 738 } else { 739 obj.animate( 740 adjustObject, 741 { 742 queue: FALSE, 743 duration: speed, 744 easing: option[11]/*ease*/ 745 } 746 ); 747 } 748 } 749 } 750 751 function adjustPositionTo(slide) { 752 var left = getSlidePosition(slide, FALSE); 753 var top = getSlidePosition(slide, TRUE); 754 755 adjustPositionToPosition(left, top); 756 } 757 758 function adjustPositionToPosition(left, top, both) { 759 currentSliderPositionLeft = left; 760 currentSliderPositionTop = top; 761 762 if (option[38]/*useCSS*/ || both) { 763 slidesContainer.css({transform: "translate(" + left + "px, " + top + "px)"}); 764 } 765 if (!option[38]/*useCSS*/ || both) { 766 function setMargins(left, top) { 767 slidesContainer.css({ 768 marginLeft: left, 769 marginTop: top 770 }); 771 } 772 773 setMargins(0, 0); 774 setMargins(left, top); 775 } 776 } 777 778 function getSlidePosition(slide, vertical) { 779 if (vertical == undefined) { 780 vertical = option[6]/*vertical*/; 781 } 782 var targetSlide = slides[getRealPos(slide)]; 783 return (targetSlide && targetSlide.length) ? -targetSlide.position()[vertical ? "top" : "left"] : 0; 784 } 785 786 function callQueuedAnimation() { 787 if (animateToAfterCompletion !== FALSE) { 788 var animateTo = animateToAfterCompletion; 789 animateToAfterCompletion = FALSE; 790 callAsync(makeCallback(enqueueAnimation, [animateTo, animateToAfterCompletionClicked, animateToAfterCompletionSpeed])); 791 } 792 } 793 794 function adjust(clicked) { 795 ensureSliderContainerCSSDurationReset(); 796 797 autoadjust(currentSlide, 0); 798 currentSlide = getRealPos(currentSlide); // Going to the real slide, away from the clone. 799 if (!option[29]/*updateBefore*/) setCurrent(currentSlide); 800 adjustPositionTo(currentSlide); 801 clickable = TRUE; 802 currentlyAnimatingTowards = FALSE; 803
804 if (option[12]/*auto*/) { 805 // Stopping auto if clicked. And also continuing after X seconds of inactivity. 806 if (clicked) { 807 stopAuto(); 808 if (option[14]/*resumepause*/) startAuto(option[14]/*resumepause*/); 809 } else if (!init) { 810 startAuto(); 811 } 812 } 813 814 callQueuedAnimation(); 815 } 816 817 // This function is called when i need a callback on the current element and it's continuous clones (if they are there). 818 // after: TRUE == afteranimation : FALSE == beforeanimation; 819 function aniCall(i, after, synchronous, speed) { 820 i = getRealPos(i); 821 // Wierd fix to let IE accept the existance of the sudoSlider object. 822 var func = makeCallback(after ? afterAniCall : beforeAniCall, [slides[i], i + 1, speed]); 823 if (synchronous) { 824 func(); 825 } else { 826 callAsync(func); 827 } 828 } 829 830 function afterAniCall(el, a) { 831 option[25]/*afteranimation*/.call(el, a, baseSlider); 832 } 833 834 function beforeAniCall(el, a, speed) { 835 option[24]/*beforeanimation*/.call(el, a, baseSlider, speed); 836 } 837 838 // Convert the direction into a usefull number. 839 function filterDir(dir) { 840 if (dir == NEXT_STRING) { 841 return limitDir(currentSlide + option[8]/*movecount*/, dir); 842 } else if (dir == PREV_STRING) { 843 return limitDir(currentSlide - option[8]/*movecount*/, dir); 844 } else if (dir == FIRST_STRING) { 845 return 0; 846 } else if (dir == LAST_STRING) { 847 return totalSlides - 1; 848 } else { 849 return limitDir(parseInt10(dir), dir); 850 } 851 } 852 853 // If continuous is off, we sometimes do not want to move to far. 854 // This method was added in 2.1.8, se the changelog as to why. 855 function limitDir(i, dir) { 856 if (option[15]/*continuous*/) { 857 if (dir == NEXT_STRING || dir == PREV_STRING) { 858 return i; 859 } else { 860 return getRealPos(i); 861 } 862 } else { 863 var maxSlide = totalSlides - numberOfVisibleSlides; 864 if (i > maxSlide) { 865 if (currentSlide == maxSlide && dir == NEXT_STRING) { 866 return 0; 867 } else { 868 return maxSlide; 869 } 870 } else if (i < 0) { 871 if (currentSlide == 0 && dir == PREV_STRING) { 872 return maxSlide; 873 } else { 874 return 0; 875 } 876 } else { 877 return i; 878 } 879 } 880 } 881 882 // Load a ajax document (or image) into a slide. 883 // If testing this locally (loading everything from a harddisk instead of the internet), it may not work. 884 // But then try to upload it to a server, and see it shine. 885 function ajaxLoad(slide, ajaxCallBack) { 886 if (ajaxCallBack) { 887 var callbackList = awaitingAjaxCallbacks[slide]; 888 if (!callbackList) { 889 callbackList = awaitingAjaxCallbacks[slide] = []; 890 } 891 callbackList.push(ajaxCallBack); 892 } 893 894 if (finishedAjaxLoads[slide]) { 895 if (ajaxCallBack) { 896 runOnImagesLoaded(slides[slide], TRUE, makeCallback(callAsync, [ajaxCallBack])); 897 } 898 return; 899 } 900 901 if (startedAjaxLoads[slide]) { 902 return; 903 } 904 startedAjaxLoads[slide] = TRUE; 905 906 var target = option[30]/*ajax*/[slide]; 907 if (!target) { 908 callAsync(ajaxCallBack); 909 return; 910 } 911 912 if (asyncDelayedSlideLoadTimeout) clearTimeout(asyncDelayedSlideLoadTimeout);// I dont want it to run to often. 913 914 var targetslide = slides[slide]; 915 916 // Loads the url as an image, either if it is an image, or if everything else failed. 917 function loadImage() { 918 var image = new Image(); 919 image.src = target; 920 var thatImage = $(image); 921 runOnImagesLoaded(thatImage, TRUE, function () { 922 targetslide.empty().append(image); 923 924 ajaxAdjust(slide, TRUE); 925 }); 926 } 927 928 // It is loaded, we dont need to do that again. 929 option[30]/*ajax*/[slide] = FALSE; 930 // It is the only option that i need to change for good. 931 options.ajax[slide] = FALSE; 932 933 if (option[47]/*AjaxHasHTML*/) { 934 var succesRan = FALSE; 935 $.ajax({ 936 url: target, 937 success: function (data, textStatus, jqXHR) { 938 succesRan = TRUE; 939 runWhenNotAnimating(function () { 940 var type = jqXHR.getResponseHeader('Content-Type'); 941 if (type && type.substr(0, 1) != "i") { 942 targetslide.html(data); 943 ajaxAdjust(slide, FALSE); 944 } else { 945 loadImage(); 946 } 947 }); 948 }, 949 complete: function () { 950 // Some browsers wont load images this way, so i treat an error as an image. 951 // There is no stable way of determining if it's a real error or if i tried to load an image in a old browser, so i do it this way. 952 if (!succesRan) { 953 loadImage(); 954 } 955 } 956 }); 957 } else { 958 loadImage(); 959 } 960 } 961 962 // Performs the callback immediately if no animation is running. 963 // Otherwise waits for the animation to complete in a FIFO queue. 964 function runWhenNotAnimating(completeFunction) { 965 if (currentlyAnimating) { 966 runAfterAnimationCallbacks.push(completeFunction); 967 } else { 968 callAsync(completeFunction); 969 } 970 } 971 972 function ajaxAdjust(i, img) { 973 var target = slides[i]; 974 975 if (!currentlyAnimating) { 976 adjustPositionTo(currentSlide); 977 autoadjust(currentSlide, 0); 978 } 979 980 runOnImagesLoaded(target, TRUE, makeCallback(runWhenNotAnimating, [ 981 function () { 982 adjustPositionTo(currentSlide); 983 autoadjust(currentSlide, 0); 984 985 finishedAjaxLoads[i] = TRUE; 986 987 performCallbacks(awaitingAjaxCallbacks[i]); 988 989 startAsyncDelayedLoad(); 990 991 callAsync(function () {
992 option[23]/*ajaxload*/.call(slides[i], i + 1, img, baseSlider); 993 }); 994 995 if (init) { 996 init = FALSE; 997 callAsync(performInitCallback); 998 } 999 } 1000 ])); 1001 } 1002 1003 function performInitCallback() { 1004 fullyInitialized = TRUE; 1005 if (option[15]/*continuous*/) { 1006 centerTargetSlideAfter(currentSlide); 1007 } 1008 1009 autoadjust(currentSlide, 0); 1010 adjustPositionTo(currentSlide); 1011 callQueuedAnimation(); 1012 if (option[10]/*responsive*/) { 1013 adjustResponsiveLayout(); 1014 } 1015 if (option[12]/*auto*/) { 1016 startAuto(); 1017 } 1018 option[22]/*initCallback*/.call(baseSlider); 1019 1020 if (option[41]/*touch*/) { 1021 setUpTouch(); 1022 } 1023 1024 // Fixing once and for all that the wrong slide is shown on init. 1025 runOnImagesLoaded(getSlides(currentSlide, totalSlides), FALSE, makeCallback(runWhenNotAnimating, [ 1026 function () { 1027 autoadjust(currentSlide, 0); 1028 adjustPositionTo(currentSlide); 1029 } 1030 ])); 1031 } 1032 1033 function setUpTouch() { 1034 var body = $("body"); 1035 var easingToUse; 1036 var runningTouchEffect = FALSE; 1037 1038 var prevEffect = option[0]/*effect*/; 1039 1040 option[0]/*effect*/ = function (obj) { 1041 if (runningTouchEffect) { 1042 runningTouchEffect = FALSE; 1043 var options = obj.options; 1044 options.ease = easingToUse; 1045 options.cssease = easingToUse; 1046 return slide(obj); 1047 } else { 1048 return prevEffect(obj); 1049 } 1050 }; 1051 var initialOffsetLeft; 1052 var initialOffsetTop; 1053 1054 var startTime; 1055 var lastTime; 1056 var lastDistance; 1057 1058 var bufferSize = 3; 1059 var positionsBuffer = []; 1060 var timeBuffer = []; 1061 var bufferIndex = 0; 1062 1063 var currentTouchSlide; 1064 var baseDistance; 1065 1066 function touchStart(x, y) { 1067 body.addClass(SUDO_DRAGGING_CLASS); 1068 currentTouchSlide = currentSlide; 1069 baseDistance = 0; 1070 1071 currentlyAnimating = TRUE; 1072 ensureSliderContainerCSSDurationReset(); 1073 initialOffsetTop = currentSliderPositionTop; 1074 initialOffsetLeft = currentSliderPositionLeft; 1075 1076 var distance; 1077 if (option[6]/*vertical*/) { 1078 distance = mathAbs(y); 1079 } else { 1080 distance = mathAbs(x); 1081 } 1082 1083 lastDistance = distance; 1084 startTime = getTimeInMillis(); 1085 lastTime = startTime; 1086 1087 var currentSlidePosition = getSlidePosition(currentTouchSlide); 1088 distanceToRightSlide = getSlidePosition(currentTouchSlide + 1) - currentSlidePosition; 1089 1090 correctionWhenCalculatingWhereToMoveTouchDistance = FALSE; 1091 } 1092 1093 var distanceToRightSlide; 1094 var correctionWhenCalculatingWhereToMoveTouchDistance; 1095 1096 function touchMove(x, y) { 1097 var distance; 1098 if (option[6]/*vertical*/) { 1099 distance = y; 1100 } else { 1101 distance = x; 1102 } 1103 var distanceAbs = mathAbs(distance); 1104 positionsBuffer[bufferIndex] = distanceAbs - lastDistance; 1105 var newTime = getTimeInMillis(); 1106 timeBuffer[bufferIndex] = newTime - lastTime; 1107 bufferIndex = (bufferIndex + 1) % bufferSize; 1108 1109 lastTime = newTime; 1110 lastDistance = distanceAbs; 1111 1112 if (option[15]/*continuous*/ && totalSlides >= numberOfVisibleSlides + 1) { 1113 // Moving everything to the right 1114 var direction = 0; 1115 if ((distance - baseDistance) < distanceToRightSlide) { 1116 correctionWhenCalculatingWhereToMoveTouchDistance = FALSE; 1117 1118 baseDistance += distanceToRightSlide; 1119 direction = 1; 1120 1121 var rightSlidePositionBefore = getSlidePosition(currentTouchSlide + direction); 1122
1123 centerTargetSlideAfter(currentTouchSlide + direction); 1124 var rightSlidePositionAfter = getSlidePosition(currentTouchSlide + direction); 1125 1126 } 1127 1128 // Moving everything to the left. 1129 if ((distance - baseDistance) > 0) { 1130 direction = -1; 1131 1132 var rightSlidePositionBefore = getSlidePosition(currentTouchSlide); 1133 1134 centerTargetSlideAfter(currentTouchSlide + direction); 1135 rightSlidePositionAfter = getSlidePosition(currentTouchSlide); 1136 1137 var moveBaseDistance = getSlidePosition(currentTouchSlide - 1) - rightSlidePositionAfter; 1138 baseDistance += moveBaseDistance; 1139 1140 correctionWhenCalculatingWhereToMoveTouchDistance = -moveBaseDistance; 1141 } 1142 1143 if (direction != 0) { 1144 currentTouchSlide += direction; 1145 1146 if (option[6]/*vertical*/) { 1147 initialOffsetTop -= rightSlidePositionBefore - rightSlidePositionAfter; 1148 } else { 1149 initialOffsetLeft -= rightSlidePositionBefore - rightSlidePositionAfter; 1150 } 1151 1152 distanceToRightSlide = getSlidePosition(currentTouchSlide + 1) - getSlidePosition(currentTouchSlide); 1153 } 1154 } 1155 1156 if (option[6]/*vertical*/) { 1157 x = 0; 1158 } else { 1159 y = 0; 1160 } 1161 adjustPositionToPosition(initialOffsetLeft + x, initialOffsetTop + y); 1162 } 1163 1164 function touchEnd(x, y) { 1165 body.removeClass(SUDO_DRAGGING_CLASS); 1166 var distance; 1167 if (option[6]/*vertical*/) { 1168 distance = y; 1169 } else { 1170 distance = x; 1171 } 1172 distance -= baseDistance; 1173 1174 if (correctionWhenCalculatingWhereToMoveTouchDistance) { 1175 distance -= correctionWhenCalculatingWhereToMoveTouchDistance; 1176 currentTouchSlide++; 1177 } 1178 1179 var distanceAbs = mathAbs(distance); 1180 var currentTime = getTimeInMillis(); 1181 var time = 0; 1182 var bufferDistance = 0; 1183 for (var i = 0; i < bufferSize; i++) { 1184 var thisTime = timeBuffer[i]; 1185 if (thisTime + 100 < currentTime) { 1186 time += thisTime; 1187 bufferDistance += positionsBuffer[i]; 1188 } 1189 } 1190 var slideDimensions; 1191 if (option[6]/*vertical*/) { 1192 slideDimensions = obj.height(); 1193 } else { 1194 slideDimensions = obj.width(); 1195 } 1196 // This is in pixels pr. ms. 1197 var speed = mathAbs(bufferDistance) / time; 1198 1199 var goToAnotherSlide = speed >= 0.2 || distanceAbs >= slideDimensions / 2; 1200 1201 if ((bufferDistance > 0 && distanceAbs < 0) || (bufferDistance < 0 && distanceAbs > 0) || distanceAbs <= 10) { 1202 goToAnotherSlide = FALSE; 1203 } 1204 1205 1206 var direction = distance < 0 ? NEXT_STRING : PREV_STRING; 1207 1208 if (!option[15]/*continuous*/) { 1209 if (currentSlide + 1 == totalSlides) { 1210 if (direction == NEXT_STRING) { 1211 goToAnotherSlide = FALSE; 1212 } 1213 } else if (currentSlide == 0) { 1214 if (direction == PREV_STRING) { 1215 goToAnotherSlide = FALSE; 1216 } 1217 } 1218 } 1219 1220 1221 direction = direction == NEXT_STRING ? currentTouchSlide + 1 : currentTouchSlide - 1; 1222 direction = mod(direction, totalSlides); 1223 1224 var distanceLeft; 1225 if (goToAnotherSlide) { 1226 distanceLeft = slideDimensions - distanceAbs; 1227 } else { 1228 distanceLeft = distanceAbs; 1229 } 1230 1231 var timeFromSpeed = (distanceLeft / speed) * 1.3; 1232 var timeFromDistance = mathMax((option[1]/*speed*/) * (slideDimensions / distanceLeft), (option[1]/*speed*/) / 4); 1233 1234 var timeLeft; 1235 if (timeFromSpeed < timeFromDistance) { 1236 timeLeft = mathMin(timeFromSpeed, (option[1]/*speed*/)); 1237 } else { 1238 timeLeft = mathMin(timeFromDistance, (option[1]/*speed*/)); 1239 } 1240 1241 var cubicBezierY = (speed * timeLeft) / (distanceLeft + speed * timeLeft); 1242 var cubicBezierX = 1 - cubicBezierY;//distanceLeft/(distanceLeft + speed*timeLeft); 1243
1244 if (option[38]/*useCSS*/) { 1245 easingToUse = "cubic-bezier(" + cubicBezierX + "," + cubicBezierY + ",0.3,1)"; 1246 } else { 1247 easingToUse = makeBezier([cubicBezierX || 0, cubicBezierY || 0, 0.3, 1]); 1248 } 1249 1250 clickable = FALSE; 1251 runningTouchEffect = TRUE; 1252 if (goToAnotherSlide) { 1253 performAnimation(direction, timeLeft, TRUE, TRUE, TRUE); 1254 } else { 1255 performAnimation(currentTouchSlide, timeLeft, TRUE, TRUE, TRUE); 1256 } 1257 } 1258 1259 { 1260 var startedTouch = FALSE; 1261 var startX = 0; 1262 var startY = 0; 1263 var prevX = 0; 1264 var prevY = 0; 1265 1266 var dragFunction = function (event) { 1267 if (!clickable) { 1268 return; 1269 } 1270 var type = event.type; 1271 var startEvent; 1272 var endEvent1; 1273 var endEvent2; 1274 var isMouseEvent = type.substr(0, 1) == "m"; 1275 if (isMouseEvent) { 1276 startEvent = MOUSEDOWN; 1277 endEvent1 = MOUSEUP; 1278 endEvent2 = ""; 1279 } else { 1280 startEvent = TOUCHSTART; 1281 endEvent1 = TOUCHEND; 1282 endEvent2 = TOUCHCANCEL; 1283 event = event.originalEvent; 1284 } 1285 1286 1287 if (!startedTouch) { 1288 if (type != startEvent) { 1289 return; 1290 } 1291 1292 var eventTarget = event.target; 1293 var target = $(eventTarget); 1294 if (!option[42]/*touchHandle*/) { 1295 target = target.parents().add(eventTarget); 1296 } 1297 var filter = option[42]/*touchHandle*/ || obj; 1298 if (typeof filter === "string") { 1299 filter = stringTrim(filter); 1300 if (filter.charAt(0) == ">") { 1301 filter = $(filter.substr(1, filter.length), obj); 1302 } 1303 } 1304 1305 var isTarget = target.filter(filter).length; 1306 1307 if (!isTarget) { 1308 return; 1309 } else { 1310 startedTouch = TRUE; 1311 } 1312 } 1313 1314 if (type != endEvent1 && type != endEvent2) { 1315 var x; 1316 var y; 1317 if (isMouseEvent) { 1318 x = event.pageX; 1319 y = event.pageY; 1320 } else { 1321 var touch = event.touches[0]; 1322 x = touch.pageX; 1323 y = touch.pageY; 1324 } 1325 1326 1327 if (type == startEvent) { 1328 startX = x; 1329 startY = y; 1330 touchStart(x - startX, y - startY); 1331 event.preventDefault(); 1332 } else { 1333 touchMove(x - startX, y - startY); 1334 1335 if (!allowScroll(isMouseEvent, x - startX, y - startY)) { 1336 event.preventDefault(); 1337 } 1338 } 1339 1340 prevX = x - startX; 1341 prevY = y - startY; 1342 } else { 1343 touchEnd(prevX, prevY); 1344 startedTouch = FALSE; 1345 } 1346 }; 1347 bindAndRegisterOff(doc, [TOUCHSTART, TOUCHMOVE, TOUCHEND, TOUCHCANCEL].join(" "), dragFunction); 1348 if (option[44]/*mouseTouch*/) { 1349 bindAndRegisterOff(doc, [MOUSEDOWN, MOUSEMOVE, MOUSEUP].join(" "), dragFunction); 1350 } 1351 1352 } 1353 1354 function allowScroll(isMouseEvent, x, y) { 1355 var isGeneralDirectionVertical = mathAbs(y) > mathAbs(x); 1356 if (isMouseEvent) { 1357 // If the user drags vertically, prevent the (horizontal) scroll event 1358 return FALSE; 1359 } 1360 if (!option[45]/*allowScroll*/) { 1361 return FALSE; 1362 } 1363 if (option[6]/*vertical*/) { 1364 return !isGeneralDirectionVertical; 1365 } else { 1366 return isGeneralDirectionVertical; 1367 } 1368 } 1369 } 1370 1371 function performCallbacks(callbacks) { 1372 while (callbacks && callbacks.length) { 1373 // Removing and running the first, so we maintain FIFO. 1374 callbacks.splice(0, 1)[0](); 1375 } 1376 } 1377 1378 function isContentInSlideReady(slide) { 1379 if (!imagesInSlidesLoaded[slide]) { 1380 return FALSE; 1381 } 1382 if (!option[30]/*ajax*/) { 1383 return TRUE; 1384 } else { 1385 if (option[30]/*ajax*/[slide]) { 1386 return FALSE; 1387 } 1388 return !(startedAjaxLoads[slide] && !finishedAjaxLoads[slide]); 1389 } 1390 } 1391 1392 function loadSlidesAndAnimate(i, clicked, speed) { 1393 var dir = filterDir(i); 1394 var prevNext = i == NEXT_STRING || i == PREV_STRING; 1395 1396 var targetSlide = getRealPos(dir);
1397 if (targetSlide == currentSlide) { 1398 return; 1399 } 1400 clickable = FALSE; 1401 currentlyAnimatingTowards = targetSlide; 1402 1403 if (option[30]/*ajax*/) { 1404 var waitCounter = 0; 1405 for (var loadSlide = targetSlide; loadSlide < targetSlide + numberOfVisibleSlides; loadSlide++) { 1406 var realLoadSlide = getRealPos(loadSlide); 1407 if (!isContentInSlideReady(realLoadSlide)) { 1408 waitCounter++; 1409 ajaxLoad(realLoadSlide, function () { 1410 // This runs aync, so every callback is placed before the first is run. Therefore this works. 1411 waitCounter--; 1412 if (waitCounter == 0) { 1413 option[40]/*loadFinish*/.call(baseSlider, dir + 1); 1414 performAnimation(dir, speed, clicked, prevNext); 1415 } 1416 }); 1417 } 1418 } 1419 if (waitCounter == 0) { 1420 performAnimation(dir, speed, clicked, prevNext); 1421 } else { 1422 option[39]/*loadStart*/.call(baseSlider, dir + 1); 1423 } 1424 } else { 1425 performAnimation(dir, speed, clicked, prevNext); 1426 } 1427 } 1428 1429 function ensureSliderContainerCSSDurationReset() { 1430 if (option[38]/*useCSS*/) { 1431 slidesContainer.css(CSSVendorPrefix + "transition-duration", ""); 1432 } 1433 } 1434 1435 var reorderedSlidesToStartFromSlide = 0; 1436 1437 function reorderSlides(slide) { 1438 slide = getRealPos(slide); 1439 if (slide == reorderedSlidesToStartFromSlide) { 1440 return; 1441 } 1442 reorderedSlidesToStartFromSlide = slide; 1443 ensureSliderContainerCSSDurationReset(); 1444 for (var i = 0; i < totalSlides; i++) { 1445 var slideToInsert = slides[getRealPos((slide + i))]; 1446 slidesContainer.append(slideToInsert); 1447 } 1448 adjustPositionTo(currentSlide); 1449 } 1450 1451 function centerTargetSlideAdjusted(targetSlide, extraSpace) { 1452 var offset = mathMax(parseInt10((totalSlides - extraSpace - numberOfVisibleSlides) / 2), 0); 1453 targetSlide = mod(targetSlide - offset, totalSlides); 1454 reorderSlides(targetSlide); 1455 } 1456 1457 function centerTargetSlideAfter(targetSlide) { 1458 centerTargetSlideAdjusted(targetSlide, 0); 1459 } 1460 1461 function centerTargetSlideBefore(targetSlide) { 1462 var startSlide = mathMin(targetSlide, currentSlide); 1463 var adjustment = mathAbs(targetSlide - currentSlide); 1464 1465 centerTargetSlideAdjusted(startSlide, adjustment); 1466 } 1467 1468 1469 function performAnimation(dir, speed, clicked, prevNext, skipPreCenterTargetSlide) { 1470 if (option[29]/*updateBefore*/) setCurrent(dir); 1471 1472 if (option[26]/*history*/ && clicked) win.location.hash = option[18]/*numerictext*/[dir]; 1473 1474 if (option[4]/*controlsfade*/) fadeControls(dir, option[3]/*controlsfadespeed*/); 1475 1476 var fromSlides = $(); 1477 var toSlides = $(); 1478 for (var a = 0; a < numberOfVisibleSlides; a++) { 1479 fromSlides = fromSlides.add(slides[getRealPos(currentSlide + a)]); 1480 toSlides = toSlides.add(slides[getRealPos(dir + a)]); 1481 } 1482 1483 1484 // Finding a "shortcut", used for calculating the offsets. 1485 var diff = dir - currentSlide; 1486 var targetSlide; 1487 if (option[15]/*continuous*/ && !prevNext) { 1488 var diffAbs = mathAbs(diff); 1489 targetSlide = dir; 1490 1491 var newDiff = -currentSlide + dir + totalSlides; 1492 if (mathAbs(newDiff) < diffAbs) { 1493 targetSlide = dir + totalSlides; 1494 diff = newDiff; 1495 diffAbs = mathAbs(diff); 1496 } 1497 1498 newDiff = -currentSlide + dir - totalSlides; 1499 if (mathAbs(newDiff) < diffAbs) { 1500 targetSlide = dir - totalSlides; 1501 diff = newDiff; 1502 } 1503 } else { 1504 targetSlide = dir; 1505 } 1506 1507 if (option[15]/*continuous*/ && !skipPreCenterTarget
1507Slide) { 1508 centerTargetSlideBefore(targetSlide); 1509 } 1510 1511 var leftTarget = getSlidePosition(targetSlide, FALSE); 1512 var topTarget = getSlidePosition(targetSlide, TRUE); 1513 1514 var targetLi = slides[getRealPos(dir)]; 1515 var callOptions = $.extend(TRUE, {}, options); // Making a copy, to enforce read-only. 1516 var overwritingSpeed = option[1]/*speed*/; 1517 var attributeSpeed = targetLi.attr("data-speed"); 1518 if (attributeSpeed != undefined) { 1519 overwritingSpeed = parseInt10(attributeSpeed); 1520 } 1521 if (speed != undefined) { 1522 overwritingSpeed = parseInt10(speed); 1523 } 1524 callOptions.speed = overwritingSpeed; 1525 1526 var effect = option[0]/*effect*/; 1527 1528 var specificEffectAttrName = "data-effect"; 1529 var slideSpecificEffect = targetLi.attr(specificEffectAttrName); 1530 if (slideSpecificEffect) { 1531 effect = getEffectMethod(slideSpecificEffect); 1532 } 1533 1534 var slideOutSlide = slides[currentSlide]; 1535 if (slideOutSlide) { 1536 var slideOutSpecificEffect = slides[currentSlide].attr(specificEffectAttrName + "out") 1537 if (slideOutSpecificEffect) { 1538 effect = getEffectMethod(slideOutSpecificEffect); 1539 } 1540 } 1541 1542 currentlyAnimating = TRUE; 1543 currentAnimation = effect; 1544 1545 var callbackHasYetToRun = TRUE; 1546 currentAnimationCallback = function () { 1547 currentlyAnimating = FALSE; 1548 callbackHasYetToRun = FALSE; 1549 1550 goToSlide(dir, clicked); 1551 fixClearType(toSlides); 1552 1553 if (option[15]/*continuous*/) { 1554 centerTargetSlideAfter(targetSlide); 1555 } 1556 1557 // afteranimation 1558 aniCall(dir, TRUE); 1559 if (option[10]/*responsive*/) { 1560 adjustResponsiveLayout(); 1561 } 1562 1563 performCallbacks(runAfterAnimationCallbacks); 1564 }; 1565 currentAnimationObject = { 1566 fromSlides: fromSlides, 1567 toSlides: toSlides, 1568 slider: obj, 1569 container: slidesContainer, 1570 options: callOptions, 1571 to: dir + 1, 1572 from: currentSlide + 1, 1573 diff: diff, 1574 target: { 1575 left: leftTarget, 1576 top: topTarget 1577 }, 1578 stopCallbacks: [], 1579 callback: function () { 1580 if (callbackHasYetToRun) { 1581 callbackHasYetToRun = FALSE; 1582 stopAnimation(); 1583 } 1584 }, 1585 goToNext: function () { 1586 if (callbackHasYetToRun) { 1587 // Only moving after there is content ready to replace the previous. 1588 runOnImagesLoaded($("." + ANIMATION_CLONE_MARKER_CLASS, obj), TRUE, makeCallback(adjustPositionTo, [dir])); 1589 } 1590 } 1591 }; 1592 1593 autoadjust(dir, overwritingSpeed); 1594 callAsync(function () { 1595 // beforeanimation 1596 aniCall(dir, FALSE, TRUE, overwritingSpeed); 1597 1598 effect.call(baseSlider, currentAnimationObject); 1599 }); 1600 } 1601 1602 function stopAnimation() { 1603 if (currentlyAnimating) { 1604 //noinspection JSUnusedAssignment 1605 animationWasInterrupted = TRUE; 1606 // Doing it in this order isn't a problem in relation to the user-callbacks, since they are run in a setTimeout(callback, 0) anyway. 1607 if (currentAnimationCallback) { 1608 currentAnimationCallback(); 1609 } 1610
1611 performCallbacks(currentAnimationObject.stopCallbacks); 1612 1613 1614 var stopFunction = currentAnimation.stop; 1615 if (stopFunction) { 1616 stopFunction(); 1617 } else { 1618 defaultStopFunction(); 1619 } 1620 autoadjust(currentSlide, 0); 1621 adjustPositionTo(currentSlide); 1622 animationWasInterrupted = FALSE; 1623 } 1624 } 1625 1626 function bindAndRegisterOff(element, events, handler, selector) { 1627 element.on(events, selector, handler); 1628 unBindCallbacks.push(function () { 1629 element.off(events, selector, handler); 1630 }); 1631 } 1632 1633 function cantDoAdjustments() { 1634 return !obj.is(":visible") || init || destroyed; 1635 } 1636 1637 function defaultStopFunction() { 1638 $("." + ANIMATION_CLONE_MARKER_CLASS, obj).remove(); 1639 slidesContainer.stop(); 1640 } 1641 1642 function goToSlide(slide, clicked) { 1643 clickable = !clicked && !option[12]/*auto*/; 1644 previousSlide = currentSlide; 1645 currentSlide = slide; 1646 1647 adjust(clicked); 1648 1649 if (option[4]/*controlsfade*/ && init) { 1650 fadeControls(currentSlide, 0); 1651 } 1652 // This is handles in AjaxAdjust, if something is loading. 1653 if (init && !option[30]/*ajax*/[currentSlide] && !startedAjaxLoads[currentSlide]) { 1654 init = FALSE; 1655 callAsync(performInitCallback); 1656 } 1657 } 1658 1659 function getSlides(from, count) { 1660 var visibleSlides = $(); 1661 for (var i = 0; i < count; i++) { 1662 visibleSlides = visibleSlides.add(slides[getRealPos(from + i)]); 1663 } 1664 return visibleSlides; 1665 } 1666 1667 function getRealPos(a) { 1668 return mod(a, totalSlides); 1669 } 1670 1671 function fixClearType(element) { 1672 if (screen.fontSmoothingEnabled && element.style) { 1673 try { 1674 element.style.removeAttribute("filter"); // Fix cleartype 1675 } catch (ignored) { } 1676 } 1677 } 1678 1679 /* 1680 * Public methods. 1681 */ 1682 1683 // First i just define those i use more than one. Then i just add the others as anonymous functions. 1684 function publicDestroy() { 1685 stopAuto(); 1686 stopAnimation(); 1687 autoadjust(currentSlide, 0); 1688 destroyed = TRUE; 1689 1690 slideNumberBeforeDestroy = currentSlide; 1691 1692 performCallbacks(unBindCallbacks); 1693 1694 ensureSliderContainerCSSDurationReset(); 1695 if (controls) { 1696 controls.remove(); 1697 } 1698 1699 1700 reorderSlides(0); 1701 adjustPositionTo(currentSlide); 1702 1703 option[43]/*destroyCallback*/.call(baseSlider); 1704 } 1705 1706 baseSlider.destroy = publicDestroy; 1707 1708 function publicInit() { 1709 if (destroyed) { 1710 initSudoSlider(); 1711 } 1712 } 1713 1714 function runOnDestroyedSlider(func) { 1715 return function foo() { 1716 var reinit = !destroyed; 1717 if (!init && !fullyInitialized) { 1718 var args = arguments; 1719 callAsync(function () { 1720 foo.apply(undefined, args); 1721 }); // Fixing a very special, special case 1722 return; 1723 } 1724 publicDestroy(); 1725 1726 func.apply(this, arguments); 1727 1728 if (reinit) { 1729 publicInit(); 1730 } 1731 } 1732 } 1733 1734 baseSlider.init = publicInit; 1735 1736 baseSlider.getOption = function (a) { 1737 return options[a.toLowerCase()]; 1738 }; 1739 1740 baseSlider.setOption = runOnDestroyedSlider(function (key, val) { 1741 options[key.toLowerCase()] = val; 1742 }); 1743 1744 baseSlider.setOptions = runOnDestroyedSlider(function (newOptions) { 1745 for (var key in newOptions) { 1746 options[key.toLowerCase()] = newOptions[key]; 1747 } 1748 }); 1749 1750 baseSlider.runWhenNotAnimating = runWhenNotAnimating; 1751 1752 baseSlider.insertSlide = runOnDestroyedSlider(function (html, pos, numtext, goToSlide) { 1753 // pos = 0 means before everything else. 1754 // pos = 1 means after the first slide. 1755 // if pos is negative, then we count from the right instead. 1756 if (pos < 0) { 1757 pos = totalSlides - mod(-pos - 1, totalSlides + 1); 1758 } else { 1759 pos = mod(pos, totalSlides + 1); 1760 } 1761 1762 html = $(html || DIV_TAG); 1763 if (isSlideContainerUl) { 1764 html = $("<li>").prepend(html); 1765 } else { 1766 if (html.length != 1) { 1767 html = $(DIV_TAG).prepend(html); 1768 } else { 1769 // Inserting as is. 1770 } 1771 } 1772 1773 if (!pos || pos == 0) { 1774 slidesContainer.prepend(html); 1775 } else { 1776 slides[pos - 1].after(html); 1777 } 1778 1779 // Finally, we make it work again. 1780 if (goToSlide) { 1781 slideNumberBeforeDestroy = goToSlide - 1; 1782 } else if (pos <= slideNumberBeforeDestroy || (!pos || pos == 0)) { 1783 slideNumberBeforeDestroy++; 1784 } 1785 1786 if (option[18]/*numerictext*/.length < pos) { 1787 option[18]/*numerictext*/.length = pos; 1788 } 1789 1790 option[18]/*numerictext*/.splice(pos, 0, numtext || parseInt10(pos) + 1); 1791 }); 1792 1793 baseSlider.removeSlide = runOnDestroyedSlider(function (pos) { 1794 pos = mathMax(0, parseInt10(pos) - 1); // 1 == the first. 1795 1796 slides[mathMin(pos, totalSlides - 1)].remove(); 1797 option[18]/*numerictext*/.splice(pos, 1); 1798 if (pos < slideNumberBeforeDestroy) { 1799 slideNumberBeforeDestroy--; 1800 } 1801 }); 1802 1803 baseSlider.goToSlide = function (a, speed) { 1804 var parsedDirection = (a == parseInt10(a)) ? a - 1 : a; 1805 callAsync(makeCallback(enqueueAnimation, [parsedDirection, TRUE, speed])); 1806 }; 1807 1808 baseSlider.block = function () { 1809 clickable = FALSE; 1810 }; 1811 1812 baseSlider.unblock = function () { 1813 clickable = TRUE; 1814 }; 1815 1816 baseSlider.startAuto = function () { 1817 option[12]/*auto*/ = TRUE; 1818 startAuto(); 1819 }; 1820 1821 baseSlider.stopAuto = function () { 1822 option[12]/*auto*/ = FALSE; 1823 stopAuto(); 1824 }; 1825 1826 baseSlider.adjust = function adjustMethod(repeat) { 1827 var autoAdjustSpeed = mathMax(adjustTargetTime - getTimeInMillis(), 0); 1828 autoadjust(currentSlide, autoAdjustSpeed); 1829 if (!currentlyAnimating) { 1830 adjustPositionTo(currentSlide); 1831 } 1832 if (!repeat) { 1833 callAsync(makeCallback(adjustMethod, [true])); 1834 } 1835 }; 1836 1837 baseSlider.getValue = function (a) { 1838 return { 1839 currentslide: currentSlide + 1, 1840 totalslides: totalSlides, 1841 clickable: clickable, 1842 destroyed: destroyed, 1843 autoanimation: autoOn 1844 }[a.toLowerCase()]; 1845 }; 1846 1847 baseSlider.getSlide = function (number) { 1848 return slides[getRealPos(parseInt10(number) - 1)]; 1849 }; 1850 1851 baseSlider.stopAnimation = stopAnimation; 1852 1853 // Done, now initialize. 1854 initSudoSlider(); 1855 }); 1856 }; 1857 1858 /* 1859 * End generic slider. 1860 * Factory method for default options (no accidental writes!). 1861 */ 1862 function getDefaultOptions() { 1863 return { 1864 effect: "slide", /*option[0]/*effect*/ 1865 speed: 1500, /* option[1]/*speed*/
1866 customLink: FALSE, /* option[2]/*customlink*/ 1867 controlsFadeSpeed: 400, /* option[3]/*controlsfadespeed*/ 1868 controlsFade: TRUE, /* option[4]/*controlsfade*/ 1869 insertAfter: TRUE, /* option[5]/*insertafter*/ 1870 vertical: FALSE, /* option[6]/*vertical*/ 1871 slideCount: 1, /* option[7]/*slidecount*/ 1872 moveCount: 1, /* option[8]/*movecount*/ 1873 startSlide: 1, /* option[9]/*startslide*/ 1874 responsive: TRUE, /* option[10]/*responsive*/ 1875 ease: SWING, /* option[11]/*ease*/ 1876 auto: FALSE, /* option[12]/*auto*/ 1877 pause: 2000, /* option[13]/*pause*/ 1878 resumePause: FALSE, /* option[14]/*resumepause*/ 1879 continuous: FALSE, /* option[15]/*continuous*/ 1880 prevNext: TRUE, /* option[16]/*prevnext*/ 1881 numeric: FALSE, /* option[17]/*numeric*/ 1882 numericText: [], /* option[18]/*numerictext*/ 1883 slices: 15, /* option[19]/*slices*/ 1884 boxCols: 8, /* option[20]/*boxCols*/ 1885 boxRows: 4, /* option[21]/*boxRows*/ 1886 initCallback: EMPTY_FUNCTION, /* option[22]/*initCallback*/ 1887 ajaxLoad: EMPTY_FUNCTION, /* option[23]/*ajaxload*/ 1888 beforeAnimation: EMPTY_FUNCTION, /* option[24]/*beforeanimation*/ 1889 afterAnimation: EMPTY_FUNCTION, /* option[25]/*afteranimation*/ 1890 history: FALSE, /* option[26]/*history*/ 1891 autoHeight: TRUE, /* option[27]/*autoheight*/ 1892 autoWidth: TRUE, /* option[28]/*autowidth*/ 1893 updateBefore: FALSE, /* option[29]/*updateBefore*/ 1894 ajax: FALSE, /* option[30]/*ajax*/ 1895 preloadAjax: 100, /* option[31]/*preloadajax*/ 1896 loadingText: "", /* option[32]/*loadingtext*/ 1897 prevHtml: '<a href="#" class="prevBtn"> previous </a>', /* option[33]/*prevhtml*/ 1898 nextHtml: '<a href="#" class="nextBtn"> next </a>', /* option[34]/*nexthtml*/ 1899 controlsAttr: 'class="controls"', /* option[35]/*controlsattr*/ 1900 numericAttr: 'class="numericControls"', /* option[36]/*numericattr*/ 1901 interruptible: FALSE, /* option[37]/*interruptible*/ 1902 useCSS: TRUE, /* option[38]/*useCSS*/ 1903 loadStart: EMPTY_FUNCTION, /* option[39]/*loadStart*/ 1904 loadFinish: EMPTY_FUNCTION, /* option[40]/*loadFinish*/ 1905 touch: FALSE, /* option[41]/*touch*/ 1906 touchHandle: FALSE, /* option[42]/*touchHandle*/ 1907 destroyCallback: EMPTY_FUNCTION, /* option[43]/*destroyCallback*/ 1908 mouseTouch: TRUE, /* option[44]/*mouseTouch*/ 1909 allowScroll: TRUE, /* option[45]/*allowScroll*/ 1910 CSSease: SWING, /* option[46]/*CSSease*/ 1911 ajaxHasHTML: FALSE /* option[47]/*AjaxHasHTML*/ 1912 1913 }; 1914 } 1915 jQuery.fn.sudoSlider.getDefaultOptions = getDefaultOptions; 1916 1917 /* Start animations. 1918 * A lot of the code here is an if-else-elseif nightmare. This is because it is smaller in JavaScript, and this thing needs to be small (when minimized). 1919 */ 1920 1921 var GROW_IN = "GrowIn"; 1922 var GROW_OUT = "GrowOut"; 1923 var ROUNDED = "Rounded"; 1924 var FLY_IN = "FlyIn"; 1925 var FLY_OUT = "FlyOut"; 1926 1927 // Start by defining everything, the implementations are below 1928 var normalEffectsPrefixObject = { 1929 box: { 1930 Random: [ 1931 "", 1932 GROW_IN, 1933 GROW_IN + ROUNDED, 1934 GROW_OUT, 1935 GROW_OUT + ROUNDED, 1936 FLY_IN, 1937 FLY_OUT, 1938 boxRandomTemplate 1939 ], 1940 Rain: [ 1941 "", 1942 GROW_IN, 1943 GROW_IN + ROUNDED, 1944 GROW_OUT, 1945 GROW_OUT + ROUNDED, 1946 FLY_IN, 1947 FLY_OUT, 1948 [ 1949 "UpLeft", 1950 "DownLeft", 1951 "DownRight", 1952 "UpRight", 1953 boxRainTemplate 1954 ] 1955 ], 1956 Spiral: [ 1957 "InWards", 1958 "OutWards", 1959 { 1960 "": boxSpiralTemplate, 1961 Grow: [ 1962 "In", 1963 "Out", 1964 [ 1965 "", 1966 "Rounded", 1967 boxSpiralGrowTemplate 1968 ] 1969 ] 1970 } 1971 ] 1972 }, 1973 fade: { 1974 "": fade, 1975 OutIn: fadeOutIn 1976 }, 1977 foldRandom: [ 1978 "Horizontal", 1979 "Vertical", 1980 foldRandom 1981 ], 1982 slide: slide, 1983 stack: [ 1984 "Up", 1985 "Right", 1986 "Down", 1987 "Left", 1988 [ 1989 "", 1990 "Reverse", 1991 stackTemplate 1992 ] 1993 ] 1994 // TODO: Name! 1995 /*unnamed: [ 1996 "", 1997 "Reveal", 1998 [ 1999 "", 2000 "Vertical", 2001 [ 2002 "", 2003 "Reverse", 2004 "Random", 2005 testAnimation 2006 ] 2007 ] 2008 ]*/ 2009 }; 2010 2011 // Generic effects needs to have a "dir" attribute as their last argument. 2012 var genericEffectsPrefixObject = { 2013 blinds: [ 2014 "1", 2015 "2", 2016 blinds 2017 ], 2018 fold: fold, 2019 push: [ 2020 "Out", 2021 "In", 2022 pushTemplate 2023 ], 2024 reveal: revealTemplate, 2025 slice: { 2026 "": [ 2027 "", 2028 "Reveal", 2029 [ 2030 "", 2031 "Reverse", 2032 "Random", 2033 slice 2034 ] 2035 ], 2036 Fade: slicesFade 2037 }, 2038 zip: zip, 2039 unzip: unzip 2040 }; 2041 2042 2043 function parsePrefixedEffects(resultObject, effectsObject, prefix, generic, argumentsStack) { 2044 if (isFunction(effectsObject)) { 2045 if (generic) { 2046 // Parsing the value 0, as a hack to make generic effects work, see the below else case. 2047 parsePrefixedEffects(resultObject, ["", "Up", "Right", "Down", "Left", effectsObject], prefix, 0, argumentsStack); 2048 } else { 2049 resultObject[prefix] = function (obj) { 2050 var argumentArray = [obj].concat(argumentsStack); 2051 2052 // Ugly hack, to make "generic" functions to work. 2053 var genericArgumentIndex = argumentArray.length - 1; 2054 if (generic === 0 && argumentArray[genericArgumentIndex] == 0) { 2055 argumentArray[genericArgumentIndex] = getDirFromAnimationObject(obj); 2056 } 2057 2058 effectsObject.apply(this, argumentArray); 2059 } 2060 } 2061 } else if (isArray(effectsObject)) { 2062 var effectIndex = effectsObject.length - 1; 2063 var effect = effectsObject[effectIndex]; 2064 for (var i = 0; i < effectIndex; i++) { 2065 var newArgumentStack = cloneArray(argumentsStack); 2066 newArgumentStack.push(i); 2067 var name = effectsObject[i]; 2068 parsePrefixedEffects(resultObject, effect, prefix + name, generic, newArgumentStack); 2069 } 2070 } else { 2071 jQuery.each(effectsObject, function (name, effect) { 2072 parsePrefixedEffects(resultObject, effect, prefix + name, generic, argumentsStack); 2073 }); 2074 } 2075 } 2076 2077 2078 var allEffects = {}; 2079 parsePrefixedEffects(allEffects, genericEffectsPrefixObject, "", TRUE, []); 2080 parsePrefixedEffects(allEffects, normalEffectsPrefixObject, "", FALSE, []); 2081 2082 allEffects.random = makeRandomEffect(allEffects); 2083 2084 // Saving it. 2085 jQuery.fn.sudoSlider.effects = allEffects; 2086 2087 2088 // The implementations 2089 // dir: 0: UpRight, 1: DownRight: 2: DownLeft, 3: UpLeft 2090 // effect: 0: none, 1: growIn, 2: growRoundedIn, 3: growOut, 4: growRoundedOut, 5: flyIn, 6: flyOut 2091 function boxRainTemplate(obj, effect, dir) { 2092 var reverseRows = dir == 1 || dir == 3; 2093 var reverse = dir == 0 || dir == 3; 2094 var grow = effect >= 1 && effect <= 4; 2095 var flyIn = effect == 5 || effect == 6; 2096 var reveal = effect == 6 || effect == 3 || effect == 4; 2097 var roundedGrow = effect == 2 || effect == 4; 2098 boxTemplate(obj, reverse, reverseRows, grow, FALSE, 1, flyIn, reveal, roundedGrow); 2099 } 2100 2101 function boxSpiralTemplate(obj, direction) { 2102 boxTemplate(obj, direction, FALSE, FALSE, FALSE, 2, FALSE, FALSE, FALSE); 2103 } 2104 2105 function boxSpiralGrowTemplate(obj, direction, reveal, rounded) { 2106 boxTemplate(obj, direction, FALSE, TRUE, FALSE, 2, FALSE, reveal, rounded); 2107 } 2108 2109 // effect: 0: no grow, 1: growIn: 2: growInRounded, 3: growOut, 4: growOutRounded, 5: flyIn, 6: flyOut 2110 function boxRandomTemplate(obj, effect) { 2111 var reveal = effect == 3 || effect == 4 || effect == 6; 2112 var roundedGrow = effect == 2 || effect == 4; 2113 var flyIn = effect == 5 || effect == 6; 2114 boxTemplate(obj, FALSE, FALSE, effect > 0 && effect < 5, TRUE, 0, flyIn, reveal, roundedGrow); 2115 } 2116 2117 // SelectionAlgorithm: 0: Standard selection, 1: rain, 2: spiral 2118 function boxTemplate(obj, reverse, reverseRows, grow, randomize, selectionAlgorithm, flyIn, reveal, roundedGrow) { 2119 var options = obj.options; 2120 var boxRows = options.boxrows; 2121 var boxCols = options.boxcols; 2122 var totalBoxes = boxRows * boxCols; 2123 var speed = options.speed / (totalBoxes == 1 ? 1 : 2.5); // To make the actual time spent equal to options.speed. 2124 var boxes = createLazyBoxes(obj, boxCols, boxRows, !reveal); 2125 var timeBuff = 0; 2126 var rowIndex = 0; 2127 var colIndex = 0; 2128 var box2DArr = []; 2129 box2DArr[rowIndex] = []; 2130 if (reverse) { 2131 reverseArray(boxes); 2132 } 2133 if (randomize) { 2134 shuffle(boxes); 2135 } 2136 2137 for (var i = 0; i < boxes.length; i++) { 2138 var element = boxes[i]; 2139 box2DArr[rowIndex][colIndex] = element; 2140 colIndex++; 2141 if (colIndex == boxCols) { 2142 if (reverseRows) { 2143 reverseArray(box2DArr[rowIndex]); 2144 } 2145 rowIndex++; 2146 colIndex = 0; 2147 box2DArr[rowIndex] = []; 2148 } 2149 } 2150 2151 var boxesResult = []; 2152 if (selectionAlgorithm == 1) { 2153 // Rain 2154 for (var cols = 0; cols < (boxCols * 2) + 1; cols++) { 2155 var prevCol = cols; 2156 var boxesResultLine = []; 2157 for (var rows = 0; rows < boxRows; rows++) { 2158 if (prevCol >= 0 && prevCol < boxCols) { 2159 var rawBox = box2DArr[rows][prevCol]; 2160 if (!rawBox) { 2161 return; 2162 } 2163 boxesResultLine.push(rawBox); 2164 } 2165 prevCol--; 2166 } 2167 if (boxesResultLine.length != 0) { 2168 boxesResult.push(boxesResultLine); 2169 } 2170 } 2171 } else if (selectionAlgorithm == 2) { 2172 // Spiral 2173 // Algorithm borrowed from the Camera plugin by Pixedelic.com 2174 var rows2 = boxRows / 2, x, y, z, n = reverse ? totalBoxes : -1; 2175 var negative = reverse ? -1 : 1; 2176 for (z = 0; z < rows2; z++) { 2177 y = z; 2178 for (x = z; x < boxCols - z - 1; x++) { 2179 boxesResult[n += negative] = boxes[y * boxCols + x]; 2180 } 2181 x = boxCols - z - 1; 2182 for (y = z; y < boxRows - z - 1; y++) { 2183 boxesResult[n += negative] = boxes[y * boxCols + x]; 2184 } 2185 y = boxRows - z - 1; 2186 for (x = boxCols - z - 1; x > z; x--) { 2187 boxesResult[n += negative] = boxes[y * boxCols + x]; 2188 } 2189 x = z; 2190 for (y = boxRows - z - 1; y > z; y--) { 2191 boxesResult[n += negative] = boxes[y * boxCols + x]; 2192 } 2193 } 2194 } else { 2195 for (var row = 0; row < boxRows; row++) { 2196 for (var col = 0; col < boxCols; col++) { 2197 boxesResult.push([box2DArr[row][col]]); 2198 } 2199 } 2200 } 2201 2202 if (reveal) { 2203 obj.goToNext(); 2204 } 2205 2206 var count = 0; 2207 for (var i = 0; i < boxesResult.length; i++) { 2208 var boxLine = boxesResult[i]; 2209 2210 if (!isArray(boxLine)) { 2211 boxLine = [boxLine]; 2212 } 2213 2214 for (var j = 0; j < boxLine.length; j++) { 2215 var lazyBox = boxLine[j]; 2216 (function (lazyBox, delay) { 2217 function boxAnimationFunction(delay) { 2218 var box = lazyBox(); 2219 var boxChildren = box.children(); 2220 var orgWidth = box.width(); 2221 var orgHeight = box.height(); 2222 var goToWidth = orgWidth; 2223 var goToHeight = orgHeight; 2224 var orgLeft = parseNumber(box.css("left")); 2225 var orgTop = parseNumber(box.css("top")); 2226 var goToLeft = orgLeft; 2227 var goToTop = orgTop; 2228 2229 var childOrgLeft = parseNumber(boxChildren.css("left")); 2230 var childOrgTop = parseNumber(boxChildren.css("top")); 2231 var childGoToLeft = childOrgLeft; 2232 var childGoToTop = childOrgTop; 2233 2234 if (flyIn) { 2235 var adjustTop; 2236 var adjustLeft; 2237 2238 if (randomize) { 2239 adjustLeft = pickRandomValue([-goToWidth, goToWidth]); 2240 adjustTop = pickRandomValue([-goToHeight, goToHeight]); 2241 } else { 2242 adjustLeft = reverse != reverseRows ? -goToWidth : goToWidth; 2243 adjustTop = reverse ? -goToHeight : goToHeight; 2244 } 2245 2246 2247 var flyDistanceFactor = 1.5; 2248 2249 if (reveal) { 2250 goToLeft -= adjustLeft * flyDistanceFactor; 2251 goToTop -= adjustTop * flyDistanceFactor; 2252 } else { 2253 box.css({ 2254 left: orgLeft + adjustLeft * flyDistanceFactor, 2255 top: orgTop + adjustTop * flyDistanceFactor 2256 }); 2257 } 2258 } 2259 2260 if (grow) { 2261 if (reveal) { 2262 childGoToLeft -= goToWidth / 2; 2263 goToLeft += goToWidth / 2; 2264 childGoToTop -= goToHeight / 2; 2265 goToTop += goToHeight / 2; 2266 2267 goToHeight = goToWidth = 0; 2268 } else { 2269 box.css({left: orgLeft + (goToWidth / 2), top: orgTop + (goToHeight / 2)}); 2270 boxChildren.css({ 2271 left: childOrgLeft - goToWidth / 2, 2272 top: childOrgTop - goToHeight / 2 2273 }); 2274 2275 box.width(0).height(0); 2276 if (roundedGrow) { 2277 box.css({borderRadius: mathMax(orgHeight, orgWidth)}); 2278 } 2279 } 2280 } 2281 2282 2283 if (reveal) { 2284 box.css({opacity: 1}); 2285 } 2286 count++; 2287 schedule(function () { 2288 doc.ready(function () { 2289 animate(boxChildren,
2289 {left: childGoToLeft, top: childGoToTop}, speed, FALSE, FALSE, obj); 2290 animate(box, { 2291 opacity: reveal ? 0 : 1, 2292 width: goToWidth, 2293 height: goToHeight, 2294 left: goToLeft, 2295 top: goToTop, 2296 borderRadius: grow && reveal && roundedGrow ? mathMax(orgHeight, orgWidth) : 0 2297 }, speed, FALSE, function () { 2298 count--; 2299 if (count == 0) { 2300 obj.callback(); 2301 } 2302 }, obj); 2303 }) 2304 }, delay); 2305 } 2306 2307 var minWaitTime = 150; 2308 if (reveal || delay < minWaitTime) { 2309 boxAnimationFunction(delay); 2310 } else { 2311 schedule(makeCallback(boxAnimationFunction, [minWaitTime]), delay - minWaitTime); 2312 } 2313 })(lazyBox, timeBuff); 2314 } 2315 timeBuff += (speed / boxesResult.length) * 1.5; 2316 } 2317 } 2318 2319 function slicesFade(obj, dir) { 2320 var vertical = dir == 2 || dir == 4; 2321 var negative = dir == 1 || dir == 4; 2322 foldTemplate(obj, vertical, negative, FALSE, TRUE); 2323 } 2324 2325 function fold(obj, dir) { 2326 var vertical = dir == 2 || dir == 4; 2327 var negative = dir == 1 || dir == 4; 2328 foldTemplate(obj, vertical, negative); 2329 } 2330 2331 function foldRandom(obj, vertical) { 2332 foldTemplate(obj, vertical, FALSE, TRUE); 2333 } 2334 2335 function blinds(obj, blindsEffect, dir) { 2336 blindsEffect++; 2337 var vertical = dir == 2 || dir == 4; 2338 var negative = dir == 1 || dir == 4; 2339 foldTemplate(obj, vertical, negative, FALSE, FALSE, blindsEffect); 2340 } 2341 2342 function slice(obj, reveal, reverse, dir) { 2343 var random = reverse == 2; 2344 var vertical = dir == 1 || dir == 3; 2345 var negative = dir == 1 || dir == 4; 2346 foldTemplate(obj, vertical, reverse, random, FALSE, 0, negative ? 1 : 2, reveal); 2347 } 2348 2349 function testAnimation(obj, reveal, vertical, reverseArg) { 2350 var reverse = reverseArg == 1; 2351 var random = reverseArg == 2; 2352 2353 foldTemplate(obj, vertical, reverse, random, FALSE, 0, 1, reveal); 2354 foldTemplate(obj, vertical, reverse, random, FALSE, 0, 2, reveal); 2355 } 2356 2357 function zip(obj, dir) { 2358 var vertical = dir == 2 || dir == 4; 2359 var negative = dir == 1 || dir == 4; 2360 foldTemplate(obj, vertical, negative, FALSE, FALSE, 0, 3); 2361 } 2362 2363 function unzip(obj, dir) { 2364 var vertical = dir == 2 || dir == 4; 2365 var negative = dir == 1 || dir == 4; 2366 foldTemplate(obj, vertical, negative, FALSE, FALSE, 0, 3, TRUE); 2367 } 2368 2369 function foldTemplate(obj, vertical, reverse, randomize, onlyFade, curtainEffect, upDownEffect, reveal) { 2370 var options = obj.options; 2371 var slides = options.slices; 2372 var speed = options.speed / 2; // To make the actual time spent be equal to options.speed 2373 var objSlider = obj.slider; 2374 var lazySlides = createLazyBoxes(obj, vertical ? slides : 1, vertical ? 1 : slides, !reveal); 2375 var slicesElement = $(); 2376 for (var i = 0; i < lazySlides.length; i++) { 2377 slicesElement = slicesElement.add(lazySlides[i]()); 2378 } 2379 var count = 0; 2380 var upDownAlternator = FALSE; 2381 if (reverse) { 2382 reverseArray(slicesElement); 2383 } else { 2384 $(reverseArray(slicesElement.get())).appendTo(objSlider); 2385 } 2386 if (randomize) { 2387 shuffle(slicesElement); 2388 } 2389 slicesElement.each(function (i) { 2390 var timeout = ((speed / slides) * i); 2391 var slice = $(this); 2392 var orgWidth = slice.width(); 2393 var orgHeight = slice.height(); 2394 var goToLeft = slice.css("left"); 2395 var goToTop = slice.css("top"); 2396 var startPosition = vertical ? goToLeft : goToTop; 2397 2398 var innerBox = slice.children(); 2399 var startAdjustment = innerBox[vertical ? "width" : "height"](); 2400 if (curtainEffect == 1) { 2401 startPosition = 0 2402 } else if (curtainEffect == 2) { 2403 startPosition = startAdjustment / 2; 2404 } 2405 if (reverse) { 2406 startPosition = startAdjustment - startPosition; 2407 } 2408 if (vertical) { 2409 slice.css({ 2410 width: (onlyFade || upDownEffect ? orgWidth : 0), 2411 left: startPosition 2412 }); 2413 } else { 2414 slice.css({
2415 height: (onlyFade || upDownEffect ? orgHeight : 0), 2416 top: startPosition 2417 }); 2418 } 2419 2420 if (reveal) { 2421 var negative = upDownEffect == 1 ? -1 : 1; 2422 slice.css({ 2423 top: goToTop, 2424 left: goToLeft, 2425 width: orgWidth, 2426 height: orgHeight, 2427 opacity: 1 2428 }); 2429 if (vertical) { 2430 goToTop = negative * orgHeight; 2431 } else { 2432 goToLeft = negative * orgWidth; 2433 } 2434 } 2435 2436 if (upDownEffect) { 2437 var bottom = TRUE; 2438 if (upDownEffect == 3) { 2439 if (upDownAlternator) { 2440 bottom = FALSE; 2441 upDownAlternator = FALSE; 2442 } else { 2443 upDownAlternator = TRUE; 2444 } 2445 } else if (upDownEffect == 2) { 2446 bottom = FALSE; 2447 } 2448 if (vertical) { 2449 if (reveal) { 2450 goToTop = (bottom ? -1 : 1) * orgHeight; 2451 } else { 2452 slice.css({ 2453 bottom: bottom ? 0 : orgHeight, 2454 top: bottom ? orgHeight : 0,
2455 height: reveal ? orgHeight : 0 2456 }); 2457 } 2458 } else { 2459 if (reveal) { 2460 goToLeft = (bottom ? -1 : 1) * orgWidth; 2461 } else { 2462 slice.css({ 2463 right: bottom ? 0 : orgWidth, 2464 left: bottom ? orgWidth : 0, 2465 width: reveal ? orgWidth : 0 2466 }); 2467 } 2468 } 2469 } 2470 2471 2472 count++; 2473 schedule(makeCallback(animate, [ 2474 slice, { 2475 width: orgWidth, 2476 height: orgHeight, 2477 opacity: reveal ? 0 : 1, 2478 left: goToLeft, 2479 top: goToTop 2480 }, speed, FALSE, function () { 2481 count--; 2482 if (count == 0) { 2483 obj.callback(); 2484 } 2485 }, obj]) 2486 , timeout); 2487 }); 2488 if (reveal) { 2489 obj.goToNext(); 2490 } 2491 } 2492 2493 function stackTemplate(obj, dir, reverse) { 2494 var pushIn = obj.diff > 0; 2495 if (reverse) { 2496 pushIn = !pushIn; 2497 } 2498 2499 pushTemplate(obj, pushIn, ++dir); 2500 } 2501 2502 // 1: up, 2: right, 3: down, 4, left: 2503 function pushTemplate(obj, pushIn, dir) { 2504 var vertical = dir == 2 || dir == 4; 2505 var negative = (dir == 2 || dir == 3) ? 1 : -1; 2506 var options = obj.options; 2507 var speed = options.speed; 2508 var callback = obj.callback; 2509 if (pushIn) { 2510 var fromSlides = obj.fromSlides; 2511 var toSlides = makeClone(obj, TRUE).hide(); 2512 obj.slider.append(toSlides); 2513 var height = mathMax(toSlides.height(), fromSlides.height()); 2514 var width = mathMax(toSlides.width(), fromSlides.width()); 2515 toSlides.css(vertical ? {left: negative * width} : {top: negative * height}).show(); 2516 animate(toSlides, {left: 0, top: 0}, speed, FALSE, callback, obj); 2517 } else { 2518 var fromSlides = makeClone(obj, FALSE); 2519 obj.slider.append(fromSlides); 2520 obj.goToNext(); 2521 var toSlides = obj.toSlides; 2522 2523 var measurementSlides = negative == -1 ? fromSlides : toSlides; 2524 var height = measurementSlides.height(); 2525 var width = measurementSlides.width(); 2526 2527 animate(fromSlides, vertical ? {left: negative * width} : {top: negative * height}, speed, FALSE, callback, obj); 2528 } 2529 } 2530 2531 function revealTemplate(obj, dir) { 2532 var vertical = dir == 1 || dir == 3; 2533 var options = obj.options; 2534 var speed = options.speed; 2535 var innerBox = makeClone(obj, TRUE); 2536 var width = innerBox.width(); 2537 var height = innerBox.height(); 2538 var box = createBox(innerBox, 0, 0, 0, 0) 2539 .css({opacity: 1}) 2540 .appendTo(obj.slider); 2541 var both = box.add(innerBox); 2542 both.hide(); // FF css animation fix 2543 if (vertical) { 2544 box.css({width: width}); 2545 if (dir == 1) { 2546 innerBox.css({top: -height}); 2547 box.css({bottom: 0, top: "auto"}); 2548 } 2549 } else { 2550 box.css({height: height}); 2551 if (dir == 4) { 2552 innerBox.css({left: -width}); 2553 box.css({right: 0, left: "auto"}); 2554 } 2555 } 2556 // <FF css animation fix> 2557 both.show(); 2558 if (vertical) { 2559 both.width(width); 2560 } else { 2561 both.height(height); 2562 } 2563 // </FF css animation fix> 2564 animate(innerBox, {left: 0, top: 0}, speed, FALSE, EMPTY_FUNCTION, obj); 2565 animate(box, {width: width, height: height}, speed, FALSE, obj.callback, obj); 2566 } 2567 2568 function slide(obj) { 2569 var ul = childrenNotAnimationClones(obj.slider); 2570 var options = obj.options; 2571 var speed = options.speed; 2572 var target = obj.target; 2573 2574 var left = target.left; 2575 var top = target.top; 2576 2577 if (obj.options.usecss) { 2578 animate(ul, {transform: "translate(" + left + "px, " + top + "px)"}, speed, FALSE, obj.callback, obj, TRUE); 2579 } else { 2580 animate(ul, {marginTop: top, marginLeft: left}, speed, FALSE, obj.callback, obj); 2581 } 2582 } 2583 2584 function animate(elem, properties, speed, ease, callback, obj, doNotResetCss) { 2585 var usecss = !obj || obj.options.usecss; 2586 if (CSSVendorPrefix === FALSE || !usecss) { 2587 if (!ease) { 2588 ease = obj.options.ease; 2589 } 2590 elem.animate(properties, speed, ease, callback); 2591 return; 2592 } 2593 if (!ease) { 2594 ease = obj.options.cssease; 2595 } 2596 2597 var CSSObject = {}; 2598 var transitionProperty = CSSVendorPrefix + "transition"; 2599 var keys = getKeys(properties); 2600 // Adding vendor prefix, because sometimes it's needed. 2601 CSSObject[transitionProperty] = keys.join(" ") + (CSSVendorPrefix == "" ? "" : " " + CSSVendorPrefix + keys.join(" " + CSSVendorPrefix)); 2602 2603 var transitionTiming = transitionProperty + "-duration"; 2604 CSSObject[transitionTiming] = speed + "ms"; 2605 2606 var transitionEase = transitionProperty + "-timing-function"; 2607 if (ease == SWING) { 2608 ease = "ease-in-out"; 2609 } 2610 CSSObject[transitionEase] = ease; 2611 2612 function resetCSS() { 2613 if (!doNotResetCss) { 2614 var cssObject = {}; 2615 cssObject[transitionTiming] = "0s"; 2616 cssObject[transitionEase] = ""; 2617 cssObject[transitionProperty] = ""; 2618 elem.css(cssObject); 2619 } 2620 } 2621 2622 if (obj) { 2623 obj.stopCallbacks.push(resetCSS); 2624 } 2625 2626 var eventsVendorPrefix = CSSVendorPrefix.replace(/\-/g, ""); // replaces all "-" with ""; 2627 var eventsSuffix = (eventsVendorPrefix ? "T" : "t") + "ransitionend"; 2628 var events = eventsVendorPrefix + eventsSuffix + " t" + "ransitionend"; 2629 2630 var called = FALSE; 2631 var callbackFunction = function () { 2632 if (!called) { 2633 called = TRUE; 2634 elem.unbind(events); 2635 resetCSS(); 2636 if (callback) { 2637 callback(); 2638 } 2639 } 2640 }; 2641 2642 if (speed < 20) { // If instant animation 2643 elem.css(properties); 2644 callbackFunction(); 2645 return; 2646 } 2647 2648 callAsync(function () { 2649 elem.css(CSSObject); 2650 callAsync(function () { 2651 elem.css(properties); 2652 var startTime = getTimeInMillis(); 2653 2654 elem.on(events, function eventHandler(event) { 2655 if (elem.is(event.target) && (getTimeInMillis() - startTime) - speed > -100) { 2656 elem.off(events, eventHandler); 2657 callbackFunction(); 2658 } 2659 }); 2660 // If the animation doesn't do anything, the bind will never be triggered, so this is a fallback. 2661 schedule(callbackFunction, speed + 100); 2662 }); 2663 }); 2664 return callbackFunction 2665 } 2666 2667 function fadeOutIn(obj) { 2668 var options = obj.options; 2669 var fadeSpeed = options.speed; 2670 2671 var fadeinspeed = parseInt10(fadeSpeed * (3 / 5)); 2672 var fadeoutspeed = fadeSpeed - fadeinspeed; 2673 2674 obj.stopCallbacks.push(function () { 2675 obj.fromSlides.stop().css({opacity: 1}); 2676 }); 2677 2678 animate(obj.fromSlides, {opacity: 0.0001}, fadeoutspeed, FALSE, makeCallback(finishFadeAnimation, [obj, fadeSpeed]), obj); 2679 } 2680 2681 2682 function fade(obj) { 2683 finishFadeAnimation(obj, obj.options.speed); 2684 } 2685 2686 function finishFadeAnimation(obj, speed) { 2687 var options = obj.options; 2688 options.boxcols = 1; 2689 options.boxrows = 1; 2690 options.speed = speed; 2691 boxTemplate(obj, FALSE); 2692 } 2693 2694 // 1: up, 2: right, 3: down, 4, left: 2695 function getDirFromAnimationObject(obj) { 2696 var vertical = obj.options.vertical; 2697 var diff = obj.diff; 2698 var dir; 2699 if (vertical) { 2700 if (diff < 0) { 2701 dir = 1; 2702 } else { 2703 dir = 3; 2704 } 2705 } else { 2706 if (diff < 0) { 2707 dir = 2; 2708 } else { 2709 dir = 4; 2710 } 2711 } 2712 return dir; 2713 } 2714 2715 2716 function createLazyBoxes(obj, numberOfCols, numberOfRows, useToSlides) { 2717 var slider = obj.slider; 2718 var vertical = obj.options.vertical; 2719 var result = []; 2720 var width; 2721 if (!vertical) { 2722 width = 0; 2723 } else { 2724 if (useToSlides) { 2725 width = obj.toSlides.width(); 2726 } else { 2727 width = obj.slider.width(); 2728 } 2729 } 2730 2731 var height; 2732 if (vertical) { 2733 height = 0; 2734 } else { 2735 if (useToSlides) { 2736 height = obj.toSlides.height(); 2737 } else { 2738 height = obj.slider.height(); 2739 } 2740 } 2741 2742 obj.toSlides.each(function () { 2743 var that = $(this); 2744 if (vertical) { 2745 height += that.height(); 2746 } else { 2747 width += that.width(); 2748 } 2749 }); 2750 2751 var boxWidth = Math.ceil(width / numberOfCols);
2752 var boxHeight = Math.ceil(height / numberOfRows); 2753 for (var row = 0; row < numberOfRows; row++) { 2754 for (var col = 0; col < numberOfCols; col++) { 2755 doStuff(row, col); 2756 } 2757 } 2758 function doStuff(row, col) { 2759 result.push(function () { 2760 var innerBox = makeClone(obj, useToSlides); 2761 2762 var box = createBox(innerBox, boxHeight * row, boxWidth * col, boxHeight, boxWidth); 2763 slider.append(box); 2764 return box; 2765 }); 2766 } 2767 2768 return result; 2769 } 2770 2771 function createBox(innerBox, top, left, height, width) { 2772 innerBox.css({ 2773 width: innerBox.width(), 2774 height: innerBox.height(), 2775 display: "block", 2776 top: -top, 2777 left: -left 2778 }); 2779 return $(DIV_TAG).css({ 2780 left: left, 2781 top: top, 2782 width: width, 2783 height: height, 2784 opacity: 0, 2785 overflow: HIDDEN_STRING, 2786 position: ABSOLUTE_STRING 2787 }).append(innerBox).addClass(ANIMATION_CLONE_MARKER_CLASS); 2788 } 2789 2790 // Makes a single box that contains clones of the toSlides/fromSlides. Positioned correctly relative to each other. And the returned box has the correct height and width. 2791 function makeClone(obj, useToSlides) { 2792 var slides = useToSlides ? obj.toSlides : obj.fromSlides; 2793 var firstSlidePosition = slides.eq(0).position(); 2794 var orgLeft = firstSlidePosition.left; 2795 var orgTop = firstSlidePosition.top; 2796 var height = 0; 2797 var width = 0; 2798 var result = $(DIV_TAG).css({ 2799 position: ABSOLUTE_STRING, 2800 top: 0, 2801 left: 0 2802 }).addClass(ANIMATION_CLONE_MARKER_CLASS); 2803 slides.each(function (index, elem) { 2804 var that = $(elem); 2805 var cloneWidth = that.outerWidth(TRUE); 2806 var cloneHeight = that.outerHeight(TRUE); 2807 var clone = that.clone(); 2808 var position = that.position(); 2809 var left = position.left - orgLeft; 2810 var top = position.top - orgTop; 2811 clone.css({position: ABSOLUTE_STRING, left: left, top: top, opacity: 1}); 2812 height = mathMax(height, top + cloneHeight); 2813 width = mathMax(width, left + cloneWidth); 2814 result.append(clone); 2815 }); 2816 result.width(width).height(height); 2817 return result; 2818 } 2819 2820 /* 2821 * Util scripts. 2822 */ 2823 2824 // This is not deep equals, and only using == 2825 function simpleObjectEquals(a, b) { 2826 if (getKeys(a).length != getKeys(b).length) { 2827 return FALSE; 2828 } 2829 for (var key in a) { 2830 if (a[key] != b[key]) { 2831 return FALSE; 2832 } 2833 } 2834 return TRUE; 2835 } 2836 2837 function makeCallback(func, args) { 2838 return function () { 2839 func.apply(undefined, args); 2840 } 2841 } 2842 2843 function runOnImagesLoaded(target, waitForAllImages, callback) { 2844 if (!target) { 2845 callback(); 2846 return; 2847 } 2848 var elems = target.add(target.find("img")).filter("img"); 2849 var numberOfRemainingImages = elems.length; 2850 if (!numberOfRemainingImages) { 2851 callback(); 2852 return; 2853 } 2854 2855 elems.each(function () { 2856 var that = this; 2857 var jQueryThat = $(that); 2858 var events = "load error"; 2859 var loadFunction = function () { 2860 jQueryThat.off(events, loadFunction); 2861 numberOfRemainingImages--; 2862 if (waitForAllImages) { 2863 if (numberOfRemainingImages == 0) { 2864 callback(); 2865 } 2866 } else { 2867 callback(); 2868 } 2869 }; 2870 jQueryThat.on(events, loadFunction); 2871 /* 2872 * Start ugly working IE fix. 2873 */ 2874 if (that.readyState == "complete") { 2875 jQueryThat.trigger("load"); 2876 } else if (that.readyState) { 2877 // Sometimes IE doesn't fire the readystatechange, even though the readystate has been changed to complete. AARRGHH!! I HATE IE, I HATE IT, I HATE IE! 2878 that.src = that.src;
2878 // Do not ask me why this works, ask the IE team! 2879 } 2880 /* 2881 * End ugly working IE fix. 2882 */ 2883 else if (that.complete) { 2884 jQueryThat.trigger("load"); 2885 } 2886 else if (that.complete === undefined) { 2887 var src = that.src; 2888 // webkit hack from http://groups.google.com/group/jquery-dev/browse_thread/thread/eee6ab7b2da50e1f 2889 // data uri bypasses webkit log warning (thx doug jones) 2890 that.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw=="; 2891 that.src = src; 2892 } 2893 }); 2894 } 2895 2896 // The minVersion is specified in an array, like [1, 8, 0] for 1.8.0 2897 // Partially copy-pasted from: https://gist.github.com/dshaw/652870 2898 function minJQueryVersion(minVersion) { 2899 var version = $.fn.jquery.split("."); 2900 var length = version.length 2901 for (var a = 0; a < length; a++) { 2902 if (minVersion[a] && +version[a] < +minVersion[a]) { 2903 return FALSE; 2904 } 2905 } 2906 return TRUE; 2907 } 2908 2909 function getVendorPrefixedProperty(property, searchElement) { 2910 for (var name in searchElement) { 2911 if (endsWith(name.toLowerCase(), property.toLowerCase())) { 2912 return name; 2913 } 2914 } 2915 return FALSE; 2916 } 2917 2918 function getCSSVendorPrefix() { 2919 var property = "transition"; 2920 var styleName = getVendorPrefixedProperty(property, jQuery(DIV_TAG)[0].style); 2921 if (styleName === FALSE) { 2922 return FALSE; 2923 } 2924 var prefix = styleName.slice(0, styleName.length - property.length); 2925 if (prefix.length != 0) { 2926 return "-" + prefix + "-"; 2927 } 2928 return ""; 2929 } 2930 2931 function stringTrim(str) { 2932 return str.replace(/^\s+|\s+$/g, ''); 2933 } 2934 2935 function endsWith(string, suffix) { 2936 return string.indexOf(suffix, string.length - suffix.length) !== -1; 2937 } 2938 2939 function getKeys(obj) { 2940 var keys = []; 2941 for (var key in obj) { 2942 keys.push(key); 2943 } 2944 return keys; 2945 } 2946 2947 // Puts the specified function in a setTimeout([function], 0); 2948 function callAsync(func) { 2949 schedule(func, 0); 2950 } 2951 2952 function schedule(func, time) { 2953 return setTimeout(func, time); 2954 } 2955 2956 function matches(string, patternWithWildCards) { 2957 return !!string.match(new RegExp("^" + patternWithWildCards.split("*").join(".*") + "$", "g")); 2958 } 2959 2960 function startsWith(string, prefix) { 2961 return string.indexOf(prefix) == 0; 2962 } 2963 2964 function cloneArray(arrayToClone) { 2965 return arrayToClone.slice(); 2966 } 2967 2968 // This mutates the given array, so that it is reversed. 2969 // It also returns it. 2970 function reverseArray(array) { 2971 return [].reverse.call(array); 2972 } 2973 2974 function childrenNotAnimationClones(obj) { 2975 return obj.children().not("." + ANIMATION_CLONE_MARKER_CLASS); 2976 } 2977 2978 function objectToLowercase(obj) { 2979 var ret = {}; 2980 for (var key in obj) 2981 ret[key.toLowerCase()] = obj[key]; 2982 return ret; 2983 } 2984 2985 // Mutates and returns the array. 2986 function shuffle(array) { 2987 for (var j, x, i = array.length; i; j = (Math.random() * i) | 0, x = array[--i], array[i] = array[j], array[j] = x) { 2988 } 2989 return array; 2990 } 2991 2992 function isFunction(func) { 2993 return jQuery.isFunction(func); 2994 } 2995 2996 function isArray(object) { 2997 return jQuery.isArray(object); 2998 } 2999 3000 function parseInt10(num) { 3001 return parseInt(num, 10); 3002 } 3003 3004 function parseNumber(num) { 3005 return parseFloat(num); 3006 } 3007 3008 function getTimeInMillis() { 3009 return +new Date(); 3010 } 3011 3012 // Actual modulo, not remainder. From here: http://stackoverflow.com/questions/4467539/javascript-modulo-not-behaving 3013 // Added a or zero, to ensure it returns a number. 3014 function mod(a, n) { 3015 return (((a % n) + n) % n) || 0; 3016 } 3017 3018 function mathAbs(number) { 3019 return number < 0 ? -number : number; 3020 } 3021 3022 function mathMax(a, b) { 3023 return a > b ? a : b; 3024 } 3025 3026 function mathMin(a, b) { 3027 return a < b ? a : b; 3028 } 3029 3030 function getEffectMethod(inputEffect) { 3031 if (isArray(inputEffect)) { 3032 return makeRandomEffect(inputEffect); 3033 } else if (isFunction(inputEffect)) { 3034 return inputEffect 3035 } else /* if (typeof inputEffect === "string") */{ 3036 inputEffect = stringTrim(inputEffect); 3037 if (inputEffect.indexOf(",") != -1) { 3038 var array = inputEffect.split(","); 3039 return makeRandomEffect(array); 3040 } else { 3041 var effects = objectToLowercase(allEffects); 3042 var effectName = stringTrim(inputEffect.toLowerCase()); 3043 var result = effects[effectName]; 3044 if (result) { 3045 return result; 3046 } else { 3047 var array = []; 3048 for (var name in effects) { 3049 if (matches(name, effectName)) { 3050 array.push(effects[name]); 3051 } 3052 } 3053 if (!array.length) { 3054 return slide; 3055 } 3056 return makeRandomEffect(array); 3057 } 3058 } 3059 } 3060 } 3061 3062 function makeRandomEffect(array) { 3063 return function (obj) { 3064 var effect = pickRandomValue(array); 3065 return getEffectMethod(effect)(obj); 3066 } 3067 } 3068 3069 function pickRandomValue(obj) { 3070 return obj[shuffle(getKeys(obj))[0]]; 3071 } 3072 3073 var requestAnimationFrame = function(callback, frameCount){ 3074 var equestAnimationFrame = "equestAnimationFrame"; 3075 var requestWindow = win["r" + equestAnimationFrame] || 3076 win["webkitR" + equestAnimationFrame] || 3077 win["mozR" + equestAnimationFrame] || 3078 win["oR" + equestAnimationFrame] || 3079 win["msR" + equestAnimationFrame] || 3080 function (callback) { 3081 schedule(callback, 1000 / 60); 3082 }; 3083 if (frameCount) { 3084 requestWindow(makeCallback(recursive, [callback, frameCount - 1])); 3085 } else { 3086 requestWindow(callback); 3087 } 3088 }; 3089 3090 // From this guy: https://github.com/rdallasgray/bez 3091 // Inlined into my own script to make it shorter. 3092 function makeBezier(coOrdArray) { 3093 var encodedFuncName = "bez_" + coOrdArray.join("_").replace(/\./g, "p"); 3094 var jqueryEasing = $.easing; 3095 if (!isFunction(jqueryEasing[encodedFuncName])) { 3096 var polyBez = function (p1, p2) { 3097 var A = [0, 0]; 3098 var B = [0, 0]; 3099 var C = [0, 0]; 3100 3101 function bezCoOrd(t, ax) { 3102 C[ax] = 3 * p1[ax], B[ax] = 3 * (p2[ax] - p1[ax]) - C[ax], A[ax] = 1 - C[ax] - B[ax]; 3103 return t * (C[ax] + t * (B[ax] + t * A[ax])); 3104 } 3105 3106 function xDeriv(t) { 3107 return C[0] + t * (2 * B[0] + 3 * A[0] * t); 3108 } 3109 3110 function xForT(t) { 3111 var x = t, i = 0, z; 3112 while (++i < 14) { 3113 z = bezCoOrd(x, 0) - t; 3114 if (mathAbs(z) < 1e-3) break; 3115 x -= z / xDeriv(x); 3116 } 3117 return x; 3118 } 3119 3120 return function (t) { 3121 return bezCoOrd(xForT(t), 1); 3122 } 3123 }; 3124 jqueryEasing[encodedFuncName] = function (x, t, b, c, d) { 3125 return c * polyBez([coOrdArray[0], coOrdArray[1]], [coOrdArray[2], coOrdArray[3]])(t / d) + b; 3126 } 3127 } 3128 return encodedFuncName; 3129 } 3130 3131}); 3132// If you did just read the entire code, congrats. 3133// Did you find a bug? I didn't, so plz tell me if you did. (https://github.com/webbiesdk/SudoSlider/issues)
3134// You can use this fiddle: http://jsfiddle.net/32m7bhtn/ as a starting point if you want to create a snall test-case for me.
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.