1/* 2 * Sudo Slider verion 3.2.2 - jQuery plugin 3 * Written by Erik Krogh Kristensen [email protected]. 4 * 5 * Dual licensed under the MIT 6 * and GPL licenses. 7 * 8 * Built for jQuery library 9 * http://jquery.com 10 * 11 */ 12(function ($, win) { 13 // Saves space in the minified version. 14 var undefined; // Makes sure that undefined really is undefined within this scope. 15 var FALSE = false; 16 var TRUE = true; 17 18 // Constants 19 var PAGES_MARKER_STRING = "pages"; 20 var NEXT_STRING = "next"; 21 var PREV_STRING = "prev"; 22 var LAST_STRING = "last"; 23 var FIRST_STRING = "first"; 24 var ABSOLUTE_STRING = "absolute"; 25 var EMPTY_FUNCTION = function () { }; 26 var ANIMATION_CLONE_MARKER_CLASS = "sudo-box"; 27 var CSSVendorPrefix = getCSSVendorPrefix(); 28 29 var bg_controls = ["#0C2251","#023401","#3B2623","#711D1D"]; 30 31 32 $.fn.sudoSlider = function (optionsOrg) { 33 // default configuration properties 34 var defaults = { 35 effect: "slide", /*option[0]/*effect*/ 36 speed: 1500, /* option[1]/*speed*/ 37 customLink: FALSE, /* option[2]/*customlink*/ 38 controlsShow: TRUE, /* option[3]/*controlsShow*/ 39 controlsFadeSpeed: 400, /* option[4]/*controlsfadespeed*/ 40 controlsFade: TRUE, /* option[5]/*controlsfade*/ 41 insertAfter: TRUE, /* option[6]/*insertafter*/ 42 vertical: FALSE, /* option[7]/*vertical*/ 43 slideCount: 1, /* option[8]/*slidecount*/ 44 moveCount: 1, /* option[9]/*movecount*/ 45 startSlide: 1, /* option[10]/*startslide*/ 46 responsive: FALSE, /* option[11]/*responsive*/ 47 ease: "swing", /* option[12]/*ease*/ 48 auto: FALSE, /* option[13]/*auto*/ 49 pause: 2000, /* option[14]/*pause*/ 50 resumePause: FALSE, /* option[15]/*resumepause*/ 51 continuous: FALSE, /* option[16]/*continuous*/ 52 prevNext: TRUE, /* option[17]/*prevnext*/ 53 numeric: FALSE, /* option[18]/*numeric*/ 54 numericText: [], /* option[19]/*numerictext*/ 55 slices: 15, /* option[20]/*slices*/ 56 boxCols: 8, /* option[21]/*boxCols*/ 57 boxRows: 4, /* option[22]/*boxRows*/ 58 initCallback: EMPTY_FUNCTION, /* option[23]/*initCallback*/ 59 ajaxLoad: EMPTY_FUNCTION, /* option[24]/*ajaxload*/ 60 beforeAnimation: EMPTY_FUNCTION, /* option[25]/*beforeanimation*/ 61 afterAnimation: EMPTY_FUNCTION, /* option[26]/*afteranimation*/ 62 history: FALSE, /* option[27]/*history*/ 63 autoHeight: TRUE, /* option[28]/*autoheight*/ 64 autoWidth: TRUE, /* option[29]/*autowidth*/ 65 updateBefore: FALSE, /* option[30]/*updateBefore*/ 66 ajax: FALSE, /* option[31]/*ajax*/ 67 preloadAjax: 100, /* option[32]/*preloadajax*/ 68 loadingText: "", /* option[33]/*loadingtext*/ 69 prevHtml: '<a href="#" class="prevBtn"> previous </a>', /* option[34]/*prevhtml*/ 70 nextHtml: '<a href="#" class="nextBtn"> next </a>', /* option[35]/*nexthtml*/ 71 controlsAttr: 'id="controls"', /* option[36]/*controlsattr*/ 72 numericAttr: 'class="controls"', /* option[37]/*numericattr*/ 73 animationZIndex: 10000, /* option[38]/*animationZIndex*/ 74 interruptible: FALSE, /* option[39]/*interruptible*/ 75 useCSS: TRUE, /* option[40]/*useCSS*/ 76 loadStart: EMPTY_FUNCTION, /* option[41]/*loadStart*/ 77 loadFinish: EMPTY_FUNCTION /* option[42]/*loadFinish*/ 78 }; 79 // Defining the base element. 80 var baseSlider = this; 81 82 optionsOrg = $.extend(objectToLowercase(defaults), objectToLowercase(optionsOrg)); 83 if (CSSVendorPrefix === FALSE || !minJQueryVersion([1, 8, 0])) { 84 optionsOrg.usecss = FALSE; 85 } 86 87 return this.each(function () { 88 var init, 89 isSlideContainerUl, 90 slidesContainer, 91 slides, 92 imagesInSlidesLoaded, 93 totalSlides, 94 currentSlide, 95 previousSlide, 96 clickable, 97 numericControls, 98 numericContainer, 99 destroyed, 100 slideNumberBeforeDestroy = FALSE, 101 controls, 102 nextbutton, 103 prevbutton, 104 autoTimeout, 105 autoOn, 106 numberOfVisibleSlides, 107 asyncDelayedSlideLoadTimeout, 108 obj = $(this), 109 finishedAdjustingTo = FALSE, // This variable teels if the slider is currently adjusted (height and width) to any specific slide. This is usefull when ajax-loading stuff. 110 adjustingTo, // This one tells what slide we are adjusting to, to make sure that we do not adjust to something we shouldn't. 111 adjustTargetTime = 0, // This one holds the time that the autoadjust animation should complete. 112 currentlyAnimating = FALSE, 113 currentAnimation, 114 currentAnimationCallback, 115 currentAnimationObject, 116 runAfterAnimationCallbacks, 117 awaitingAjaxCallbacks, 118 startedAjaxLoads, 119 finishedAjaxLoads, 120 animateToAfterCompletion = FALSE, 121 animateToAfterCompletionClicked, 122 animateToAfterCompletionSpeed, 123 slideContainerCreated = FALSE, 124 option = [], 125 options = {}; 126 $.extend(TRUE, options, optionsOrg); 127 128 // The call to the init function is after the definition of all the functions. 129 function initSudoSlider() { 130 // Storing the public options in an array.
131 var optionIndex = 0; 132 for (var key in options) { 133 option[optionIndex] = options[key]; 134 optionIndex++; 135 } 136 137 init = TRUE; 138 139 imagesInSlidesLoaded = []; 140 runAfterAnimationCallbacks = []; 141 awaitingAjaxCallbacks = []; 142 startedAjaxLoads = []; 143 finishedAjaxLoads = []; 144 145 // Fix for nested list items 146 slidesContainer = childrenNotAnimationClones(obj); 147 148 // Is the ul element there? 149 var ulLength = slidesContainer.length; 150 var newUl = $("<div></div>"); 151 if (!ulLength) { 152 obj.append(slidesContainer = newUl); 153 isSlideContainerUl = FALSE; 154 } else if (!(isSlideContainerUl = slidesContainer.is("ul")) && !slideContainerCreated) { 155 newUl.append(slidesContainer); 156 obj.append(slidesContainer = newUl); 157 } 158 slideContainerCreated = TRUE; 159 160 var slidesJquery = childrenNotAnimationClones(slidesContainer); 161 slides = []; 162 163 totalSlides = slidesJquery.length; 164 165 slidesJquery.each(function (index, elem) { 166 slides[index] = $(elem); 167 }); 168 169 // Now we are going to fix the document, if it's 'broken'. (No <li>). 170 // 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. 171 if (option[31]/*ajax*/) { 172 // Do we have enough list elements to fill out all the ajax documents. 173 var numerOfAjaxUrls = option[31]/*ajax*/.length; 174 if (numerOfAjaxUrls > totalSlides) { 175 for (var a = 1; a <= numerOfAjaxUrls - totalSlides; a++) { 176 var tag; 177 if (isSlideContainerUl) { 178 tag = "li"; 179 } else { 180 tag = "div"; 181 } 182 var slide = $("<" + tag + ">" + option[33]/*loadingtext*/ + "</" + tag + ">"); 183 slidesContainer.append(slide); 184 slides[totalSlides + (a - 1)] = slide; 185 } 186 slidesJquery = childrenNotAnimationClones(slidesContainer); 187 totalSlides = numerOfAjaxUrls; 188 } 189 } 190 191 slidesJquery.each(function (index, elem) { 192 imagesInSlidesLoaded[index] = FALSE; 193 runOnImagesLoaded($(elem), TRUE, function () { 194 imagesInSlidesLoaded[index] = TRUE; 195 }); 196 }); 197 198 if (slideNumberBeforeDestroy === FALSE) { 199 currentSlide = 0; 200 } else { 201 currentSlide = slideNumberBeforeDestroy; 202 } 203 previousSlide = currentSlide; 204 205 clickable = TRUE; 206 numericControls = []; 207 destroyed = FALSE; 208 209 210 // Set obj overflow to hidden (and position to relative <strike>, if fade is enabled. </strike>) 211 obj.css({overflow: "hidden"}); 212 if (obj.css("position") == "static") obj.css({position: "relative"}); // Fixed a lot of IE6 + IE7 bugs. 213 214 // Float items to the left, and make sure that all elements are shown. 215 slidesJquery.css({"float": "left", listStyle: "none"}); 216 // The last CSS to make it work. 217 slidesContainer.add(slidesJquery).css({display: "block", position: "relative", margin: "0"}); 218 219 option[8]/*slidecount*/ = parseInt10(option[8]/*slidecount*/); 220 221 // Lets just redefine slidecount 222 numberOfVisibleSlides = option[8]/*slidecount*/; 223 224 option[8]/*slidecount*/ += option[9]/*movecount*/ - 1; 225 226 // startslide can only be a number (and not 0). Converting from 1 index to 0 index. 227 option[10]/*startslide*/ = parseInt10(option[10]/*startslide*/) - 1 || 0; 228 229 option[0]/*effect*/ = getEffectMethod(option[0]/*effect*/); 230 231 for (var a = 0; a < totalSlides; a++) { 232 if (!option[19]/*numerictext*/[a] && option[19]/*numerictext*/[a] != "") { 233 option[19]/*numerictext*/[a] = (a + 1); 234 } 235 option[31]/*ajax*/[a] = option[31]/*ajax*/[a] || FALSE; 236 } 237
238 option[5]/*controlsfade*/ = option[5]/*controlsfade*/ && !option[16]/*continuous*/; 239 240 if (option[11]/*responsive*/) { 241 adjustResponsiveLayout(TRUE); 242 } 243 244 // 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)). 245 slidesContainer[option[7]/*vertical*/ ? 'height' : 'width'](9000000); // That 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. 246 247 // If responsive is turned on, autowidth doesn't work. 248 option[29]/*autowidth*/ = option[29]/*autowidth*/ && !option[11]/*responsive*/; 249 250 if (option[11]/*responsive*/) { 251 $(win).on("resize focus", adjustResponsiveLayout); 252 } 253 254 if (option[3]/*controlsShow*/) { 255 controls = $('<span ' + option[36]/*controlsattr*/ + '></span>'); 256 obj[option[6]/*insertafter*/ ? 'after' : 'before'](controls); 257 258 if (option[18]/*numeric*/) { 259 numericContainer = $('<ol ' + option[37]/*numericattr*/ + '></ol>'); 260 controls.prepend(numericContainer); 261 var usePages = option[18]/*numeric*/ == PAGES_MARKER_STRING; 262 var distanceBetweenPages = usePages ? numberOfVisibleSlides : 1; 263 for (var a = 0; a < totalSlides - ((option[16]/*continuous*/ || usePages) ? 1 : numberOfVisibleSlides) + 1; a += distanceBetweenPages) { 264 numericControls[a] = $("<li name='"+bg_controls[a]+"' data-target='" + (a + 1) + "'><a href='#'><span>" + option[19]/*numerictext*/[a] + "</span></a></li>") 265 .appendTo(numericContainer) 266 .click(function () { 267 enqueueAnimation(getTargetAttribute(this) - 1, TRUE); 268 return FALSE; 269 }); 270 } 271 } 272 if (option[17]/*prevnext*/) { 273 nextbutton = makecontrol(option[35]/*nexthtml*/, NEXT_STRING); 274 prevbutton = makecontrol(option[34]/*prevhtml*/, PREV_STRING); 275 } 276 } 277 278 279 // Lets make those fast/normal/fast into some numbers we can make calculations with. 280 var optionsToConvert = [4/*controlsfadespeed*/, 1/*speed*/, 14/*pause*/]; 281 for (var i = 0; i < optionsToConvert.length; i++) { 282 option[optionsToConvert[i]] = textSpeedToNumber(option[optionsToConvert[i]]); 283 } 284 285 if (option[2]/*customlink*/) { 286 $(document).on("click", option[2]/*customlink*/, customLinkClickHandler); 287 } 288 289 runOnImagesLoaded(getSlides(option[10]/*startslide*/, option[8]/*slidecount*/), TRUE, function () { 290 if (slideNumberBeforeDestroy !== FALSE) { 291 goToSlide(slideNumberBeforeDestroy, FALSE); 292 } else if (option[27]/*history*/) { 293 // I support the jquery.address plugin, Ben Alman's hashchange plugin and Ben Alman's jQuery.BBQ. 294 var window = $(win); // BYTES! 295 var hashPlugin; 296 if (hashPlugin = window.hashchange) { 297 hashPlugin(URLChange); 298 } else if (hashPlugin = $.address) { 299 hashPlugin.change(URLChange); 300 } else { 301 // This assumes that jQuery BBQ is included. If not, stuff won't work in old browsers. 302 window.on("hashchange", URLChange); 303 } 304 URLChange(); 305 } else { 306 goToSlide(option[10]/*startslide*/, FALSE); 307 } 308 309 setCurrent(currentSlide); 310 }); 311 if (option[31]/*ajax*/[option[10]/*startslide*/]) { 312 ajaxLoad(option[10]/*startslide*/); 313 } 314 if (option[32]/*preloadajax*/ === TRUE) { 315 for (var i = 0; i < totalSlides; i++) { 316 if (option[31]/*ajax*/[i] && option[10]/*startslide*/ != i) { 317 ajaxLoad(i); 318 } 319 } 320 } else { 321 startAsyncDelayedLoad(); 322 } 323 } 324 325 /* 326 * The functions do the magic. 327 */ 328 329 function customLinkClickHandler() { 330 var target; 331 if (target = getTargetAttribute(this)) { 332 if (target == 'stop') { 333 option[13]/*auto*/ = FALSE; 334 stopAuto(); 335 } else if (target == "start") { 336 startAuto(); 337 option[13]/*auto*/ = TRUE; 338 } else if (target == 'block') { 339 clickable = FALSE; 340 } else if (target == 'unblock') { 341 clickable = TRUE; 342 } else { 343 enqueueAnimation((target == parseInt10(target)) ? target - 1 : target, TRUE); 344 } 345 } 346 return FALSE; 347 }; 348 349 // Adjusts the slider when a change in layout has happened.
350 function adjustResponsiveLayout(forced) { 351 function doTheAdjustment() { 352 if (cantDoAdjustments() && !forced) { 353 return; 354 } 355 var slide = slides[currentSlide]; 356 var oldWidth = slide.width(); 357 var newWidth = getResponsiveWidth(); 358 for (var i = 0; i < totalSlides; i++) { 359 slides[i].width(newWidth); 360 } 361 362 if (oldWidth != newWidth) { 363 stopAnimation(); 364 ensureSliderContainerCSSDurationReset(); 365 adjustPositionTo(currentSlide); 366 autoadjust(currentSlide, 0); 367 } 368 } 369 doTheAdjustment(); 370 callAsync(doTheAdjustment); // Fixing invisible scrollbar. 371 } 372 373 // Returns the width of a single <li> if the page layout is responsive. 374 function getResponsiveWidth() { 375 return obj.width() / numberOfVisibleSlides; 376 } 377 378 // For backwards compability, the rel attribute is used as a fallback. 379 function getTargetAttribute(that) { 380 that = $(that); 381 return that.attr("data-target") || that.attr("rel"); 382 } 383 384 // Triggered when the URL changes. 385 function URLChange() { 386 var target = getUrlHashTarget(); 387 if (init) { 388 goToSlide(target, FALSE); 389 } else { 390 enqueueAnimation(target, FALSE); 391 } 392 } 393 394 function startAsyncDelayedLoad() { 395 if (option[32]/*preloadajax*/ !== FALSE) { 396 var preloadAjaxTime = parseInt10(option[32]/*preloadajax*/); 397 if (option[31]/*ajax*/) { 398 for (var i = 0; i < option[31]/*ajax*/.length; i++) { 399 if (option[31]/*ajax*/[i]) { 400 clearTimeout(asyncDelayedSlideLoadTimeout); 401 asyncDelayedSlideLoadTimeout = setTimeout(function () { 402 if (option[31]/*ajax*/[i]) { 403 ajaxLoad(parseInt10(i)); 404 } else { 405 startAsyncDelayedLoad(); 406 } 407 }, preloadAjaxTime); 408 409 break; 410 } 411 } 412 } 413 } 414 } 415 416 function startAuto(pause) { 417 if (pause === undefined) { 418 var dataPause = slides[currentSlide].attr("data-pause"); 419 if (dataPause !== undefined) { 420 pause = parseInt10(dataPause); 421 } else { 422 pause = option[14]/*pause*/; 423 } 424 } 425 stopAuto(); 426 autoOn = TRUE; 427 autoTimeout = setTimeout(function () { 428 if (autoOn) { 429 enqueueAnimation(NEXT_STRING, FALSE); 430 } 431 }, pause); 432 } 433 434 function stopAuto(autoPossibleStillOn) { 435 clearTimeout(autoTimeout); 436 if (!autoPossibleStillOn) autoOn = FALSE; 437 } 438 439 function textSpeedToNumber(speed) { 440 return (parseInt10(speed) || speed == 0) ? 441 parseInt10(speed) : 442 speed == 'fast' ? 443 200 : 444 (speed == 'normal' || speed == 'medium') ? 445 400 : 446 speed == 'slow' ? 447 600 : 448 400; 449 } 450 451 function makecontrol(html, action) { 452 return $(html).prependTo(controls).click(function () { 453 enqueueAnimation(action, TRUE); 454 return FALSE; 455 }); 456 } 457 458 function enqueueAnimation(direction, clicked, speed) { 459 if (clickable && !init) { 460 // Stopping, because if its needed then its restarted after the end of the animation. 461 stopAuto(TRUE); 462 463 if (!destroyed) { 464 loadSlidesAndAnimate(direction, clicked, speed); 465 } 466 } else { 467 if (option[39]/*interruptible*/ && currentlyAnimating) { 468 stopAnimation(); 469 enqueueAnimation(direction, clicked, speed); 470 } else { 471 animateToAfterCompletion = direction; 472 animateToAfterCompletionClicked = clicked; 473 animateToAfterCompletionSpeed = speed; 474 475 // I can just as well start the ajax loads 476 if (option[31]/*ajax*/) { 477 var targetSlide = filterDir(direction); 478 for (var loadSlide = targetSlide; loadSlide < targetSlide + numberOfVisibleSlides; loadSlide++) { 479 if (option[31]/*ajax*/[loadSlide]) { 480 ajaxLoad(getRealPos(loadSlide)); 481 } 482 } 483 } 484 } 485 } 486 } 487 488 // It may not sound like it, but the variable fadeOpacity is only for TRUE/FALSE.
489 function fadeControl(fadeOpacity, fadetime, nextcontrol) { 490 fadeOpacity = fadeOpacity ? 1 : 0; 491 var fadeElement = $(); 492 493 if (option[3]/*controlsShow*/ && option[17]/*prevnext*/) { 494 fadeElement = nextcontrol ? nextbutton : prevbutton; 495 } 496 497 if (option[2]/*customlink*/) { 498 var customLink = $(option[2]/*customlink*/); 499 var filterString = "=\"" + (nextcontrol ? NEXT_STRING : PREV_STRING) + "\"]"; 500 var filtered = customLink.filter("[rel" + filterString + ", [data-target" + filterString + ""); 501 fadeElement = fadeElement.add(filtered); 502 } 503 504 var adjustObject = {opacity: fadeOpacity}; 505 506 function callback() { 507 if (!fadeOpacity && fadeElement.css("opacity") == 0) { 508 fadeElement.css({visibility: "hidden"}); 509 } 510 } 511 512 if (fadeOpacity) { 513 fadeElement.css({visibility: "visible"}); 514 } 515 516 if (option[40]/*useCSS*/) { 517 animate(fadeElement, adjustObject, fadetime, option[12]/*ease*/, callback); 518 } else { 519 fadeElement.animate( 520 adjustObject, 521 { 522 queue: FALSE, 523 duration: fadetime, 524 easing: option[12]/*ease*/, 525 callback: callback 526 } 527 ); 528 } 529 } 530 531 // Fade the controls, if we are at the end of the slide. 532 // It's all the different kind of controls. 533 function fadeControls(a, fadetime) { 534 fadeControl(a, fadetime, FALSE); // abusing that the number 0 == FALSE. 535 // The new way of doing it. 536 fadeControl(a < totalSlides - numberOfVisibleSlides, fadetime, TRUE); 537 } 538 539 // Updating the 'current' class 540 function setCurrent(i) { 541 i = getRealPos(i) + 1; 542 543 // Fixing that the last numeric control isn't marked when we are at the last possible position. 544 if (option[18]/*numeric*/ == PAGES_MARKER_STRING && i == totalSlides - numberOfVisibleSlides + 1 && !option[16]/*continuous*/) { 545 i = totalSlides; 546 } 547 548 if (option[18]/*numeric*/){ 549 for (var control = 0; control < numericControls.length; ++control) { 550 var element = numericControls[control]; 551 setCurrentElement(element, i) 552 } 553 } 554 if (option[2]/*customlink*/) setCurrentElement($(option[2]/*customlink*/), i); 555 } 556 557 function setCurrentElement(element, i) { 558 if (element && element.filter) { 559 element 560 .filter(".current") 561 .removeClass("current"); 562 563 element 564 .filter(function () { 565 var elementTarget = getTargetAttribute(this); 566 if (option[18]/*numeric*/ == PAGES_MARKER_STRING) { 567 for (var a = numberOfVisibleSlides - 1; a >= 0; a--) { 568 if (elementTarget == i - a) { 569 return TRUE; 570 } 571 } 572 } else { 573 return elementTarget == i; 574 } 575 return FALSE; 576 }) 577 .addClass("current"); 578 var bg_c = $(".current").attr("name"); 579 $("#slider_wrap").css({"background-color":bg_c}); 580 } 581 } 582 583 function getUrlHashTarget() { 584 var hashString = location.hash.substr(1) 585 for (var i = 0; i < option[19]/*numerictext*/.length; i++) { 586 if (option[19]/*numerictext*/[i] == hashString) { 587 return i; 588 } 589 } 590 return hashString ? currentSlide : 0; 591 } 592 593 function runOnImagesLoaded(target, waitForAllImages, callback) { 594 var elems = target.add(target.find("img")).filter("img"); 595 var len = elems.length; 596 if (!len) { 597 callback(); 598 // No need to do anything else. 599 return; 600 } 601 function loadFunction(that) { 602 $(that).off('load error'); 603 604 // Webkit/Chrome (not sure) fix. 605 if (that.naturalHeight && !that.clientHeight) { 606 $(that).height(that.naturalHeight).width(that.naturalWi
606dth); 607 } 608 if (waitForAllImages) { 609 len--; 610 if (len == 0) { 611 callback(); 612 } 613 } else { 614 callback(); 615 } 616 } 617 618 elems.each(function () { 619 var that = this; 620 $(that).on('load error', function () { 621 loadFunction(that); 622 }); 623 /* 624 * Start ugly working IE fix. 625 */ 626 if (that.readyState == "complete") { 627 $(that).trigger("load"); 628 } else if (that.readyState) { 629 // 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! 630 that.src = that.src; // Do not ask me why this works, ask the IE team! 631 } 632 /* 633 * End ugly working IE fix. 634 */ 635 else if (that.complete) { 636 $(that).trigger("load"); 637 } 638 else if (that.complete === undefined) { 639 var src = that.src; 640 // webkit hack from http://groups.google.com/group/jquery-dev/browse_thread/thread/eee6ab7b2da50e1f 641 // data uri bypasses webkit log warning (thx doug jones) 642 that.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw=="; 643 that.src = src; 644 } 645 }); 646 } 647 648 function autoadjust(i, speed) { 649 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. 650 651 adjustingTo = i; 652 adjustTargetTime = getTimeInMillis() + speed; 653 654 if (speed == 0) { 655 finishedAdjustingTo = i; 656 } else { 657 finishedAdjustingTo = FALSE; 658 } 659 660 if (option[28]/*autoheight*/ || option[29]/*autowidth*/) { 661 autoHeightWidth(i); 662 } 663 } 664 665 666 function autoHeightWidth(i) { 667 obj.ready(function () { 668 adjustHeightWidth(i); 669 runOnImagesLoaded(slides[i], FALSE, function () { 670 adjustHeightWidth(i); 671 }); 672 }); 673 } 674 675 // Axis: TRUE == height, FALSE == width. 676 function getSliderDimensions(fromSlide, axis) { 677 var pixels = 0; 678 for (var slide = fromSlide; slide < fromSlide + numberOfVisibleSlides; slide++) { 679 var targetSlide = slides[getRealPos(slide)]; 680 var targetPixels = targetSlide['outer' + (axis ? "Height" : "Width")](TRUE); 681 if (axis == option[7]/*vertical*/) { 682 pixels += targetPixels; 683 } else { 684 pixels = mathMax(targetPixels, pixels); 685 } 686 } 687 return pixels; 688 } 689 690 function adjustHeightWidth(i) { 691 if (i != adjustingTo || cantDoAdjustments()) { 692 return; 693 } 694 695 var speed = adjustTargetTime - getTimeInMillis(); 696 speed = mathMax(speed, 0); 697 var adjustObject = {}; 698 if (option[28]/*autoheight*/) { 699 adjustObject.height = getSliderDimensions(i, TRUE) || 1; // Making it completely invisible gives trouble. 700 } 701 if (option[29]/*autowidth*/) { 702 adjustObject.width = getSliderDimensions(i, FALSE) || 1; 703 } 704 705 if (option[40]/*useCSS*/) { 706 animate(obj, adjustObject, speed, option[12]/*ease*/) 707 } else { 708 if (speed == 0) { 709 // Doing CSS if speed == 0, 1: its faster. 2: it fixes bugs. 710 obj.stop().css(adjustObject); 711 } else { 712 obj.animate( 713 adjustObject, 714 { 715 queue: FALSE, 716 duration: speed, 717 easing: option[12]/*ease*/ 718 } 719 ); 720 } 721 } 722 } 723 724 function adjustPositionTo(slide) { 725 var left = getSlidePosition(slide, FALSE); 726 var top = getSlidePosition(slide, TRUE); 727
728 if (option[40]/*useCSS*/) { 729 slidesContainer.css({transform: "translate(" + left + "px, " + top + "px)"}); 730 } else { 731 function setMargins(left, top) { 732 slidesContainer.css({ 733 marginLeft: left, 734 marginTop: top 735 }); 736 } 737 setMargins(0, 0); 738 setMargins(left, top); 739 } 740 } 741 742 function getSlidePosition(slide, vertical) { 743 var targetSlide = slides[getRealPos(slide)]; 744 return targetSlide.length ? -targetSlide.position()[vertical ? "top" : "left"] : 0; 745 } 746 747 function callQueuedAnimation() { 748 if (animateToAfterCompletion !== FALSE) { 749 var animateTo = animateToAfterCompletion; 750 animateToAfterCompletion = FALSE; 751 callAsync(function () { 752 enqueueAnimation(animateTo, animateToAfterCompletionClicked, animateToAfterCompletionSpeed); 753 }); 754 } 755 } 756 757 function adjust(clicked) { 758 autoadjust(currentSlide, 0); 759 currentSlide = getRealPos(currentSlide); // Going to the real slide, away from the clone. 760 if (!option[30]/*updateBefore*/) setCurrent(currentSlide); 761 adjustPositionTo(currentSlide); 762 clickable = TRUE; 763 764 if (option[13]/*auto*/) { 765 // Stopping auto if clicked. And also continuing after X seconds of inactivity. 766 if (clicked) { 767 stopAuto(); 768 if (option[15]/*resumepause*/) startAuto(option[15]/*resumepause*/); 769 } else if (!init) { 770 startAuto(); 771 } 772 } 773 774 callQueuedAnimation(); 775 } 776 777 // This function is called when i need a callback on the current element and it's continuous clones (if they are there). 778 // after: TRUE == afteranimation : FALSE == beforeanimation; 779 function aniCall(i, after, synchronous) { 780 i = getRealPos(i);
781 // Wierd fix to let IE accept the existance of the sudoSlider object. 782 var func = function () { 783 (after ? afterAniCall : beforeAniCall)(slides[i], i + 1); 784 }; 785 if (synchronous) { 786 func(); 787 } else { 788 callAsync(func); 789 } 790 } 791 792 function afterAniCall(el, a) { 793 option[26]/*afteranimation*/.call(el, a); 794 } 795 796 function beforeAniCall(el, a) { 797 option[25]/*beforeanimation*/.call(el, a); 798 } 799 800 // Convert the direction into a usefull number. 801 function filterDir(dir) { 802 if (dir == NEXT_STRING) { 803 return limitDir(currentSlide + option[9]/*movecount*/, dir); 804 } else if (dir == PREV_STRING) { 805 return limitDir(currentSlide - option[9]/*movecount*/, dir); 806 } else if (dir == FIRST_STRING) { 807 return 0; 808 } else if (dir == LAST_STRING) { 809 return totalSlides - 1; 810 } else { 811 return limitDir(parseInt10(dir), dir); 812 } 813 } 814 815 // If continuous is off, we sometimes do not want to move to far. 816 // This method was added in 2.1.8, se the changelog as to why. 817 function limitDir(i, dir) { 818 if (option[16]/*continuous*/) { 819 if (dir == NEXT_STRING || dir == PREV_STRING) { 820 return i; 821 } else { 822 return getRealPos(i); 823 } 824 } else { 825 var maxSlide = totalSlides - numberOfVisibleSlides; 826 if (i > maxSlide) { 827 if (currentSlide == maxSlide && dir == NEXT_STRING) { 828 return 0; 829 } else { 830 return maxSlide; 831 } 832 } else if (i < 0) { 833 if (currentSlide == 0 && dir == PREV_STRING) { 834 return maxSlide; 835 } else { 836 return 0; 837 } 838 } else { 839 return i; 840 } 841 } 842 } 843 844 // Load a ajax document (or image) into a slide. 845 // If testing this locally (loading everything from a harddisk instead of the internet), it may not work. 846 // But then try to upload it to a server, and see it shine. 847 function ajaxLoad(slide, ajaxCallBack) { 848 if (ajaxCallBack) { 849 var callbackList = awaitingAjaxCallbacks[slide]; 850 if (!callbackList) { 851 callbackList = awaitingAjaxCallbacks[slide] = []; 852 } 853 callbackList.push(ajaxCallBack); 854 } 855 856 if (finishedAjaxLoads[slide]) { 857 if (ajaxCallBack) { 858 runOnImagesLoaded(slide, TRUE, function () { 859 callAsync(ajaxCallBack); 860 }); 861 } 862 return; 863 } 864 865 if (startedAjaxLoads[slide]) { 866 return; 867 } 868 startedAjaxLoads[slide] = TRUE; 869 870 871 if (asyncDelayedSlideLoadTimeout) clearTimeout(asyncDelayedSlideLoadTimeout);// I dont want it to run to often. 872 873 var target = option[31]/*ajax*/[slide]; 874 var targetslide = slides[slide]; 875 876 // Loads the url as an image, either if it is an image, or if everything else failed. 877 function loadImage() { 878 var image = new Image(); 879 image.src = target; 880 var thatImage = $(image); 881 runOnImagesLoaded(thatImage, TRUE, function () { 882 runWhenNotAnimating(function () { 883 // Some browsers (FireFox) forces the loaded image to its original dimensions. Thereby overwriting any CSS rule. This fixes it. 884 // Other browsers (IE) tends to completely hide images that are errors. Therefore we set the height/width of those to 20. 885 var setHeightWidth = ""; 886 if (!thatImage.height()) { 887 setHeightWidth = 20; 888 } 889 thatImage.height(setHeightWidth).width(setHeightWidth); 890 891 targetslide.empty().append(image); 892 893 ajaxAdjust(slide, TRUE); 894 }); 895 }); 896 } 897 898 var succesRan = FALSE; 899 900 $.ajax({ 901 url: target, 902 success: function (data, textStatus, jqXHR) { 903 succesRan = TRUE; 904 runWhenNotAnimating(function () { 905 var type = jqXHR.getResponseHeader('Content-Type'); 906 if (type && type.substr(0, 1) != "i") { 907 targetslide.html(data); 908 ajaxAdjust(slide, FALSE); 909 } else { 910 loadImage(); 911 } 912 }); 913 }, 914 complete: function () { 915 // Some browsers wont load images this way, so i treat an error as an image. 916 // 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. 917 if (!succesRan) { 918 loadImage(); 919 } 920 } 921 }); 922 // It is loaded, we dont need to do that again. 923 option[31]/*ajax*/[slide] = FALSE; 924 // It is the only option that i need to change for good. 925 options.ajax[slide] = FALSE; 926 } 927 928 // Performs the callback immediately if no animation is running. 929 // Otherwise waits for the animation to complete in a FIFO queue. 930 function runWhenNotAnimating(completeFunction) { 931 if (currentlyAnimating) { 932 runAfterAnimationCallbacks.push(completeFunction); 933 } else { 934 callAsync(completeFunction); 935 } 936 } 937 938 function ajaxAdjust(i, img) { 939 var target = slides[i]; 940 941 adjustPositionTo(currentSlide); 942 autoadjust(currentSlide, 0); 943 944 runOnImagesLoaded(target, TRUE, function () { 945 runWhenNotAnimating(function () { 946 adjustPositionTo(currentSlide); 947 autoadjust(currentSlide, 0); 948 949 finishedAjaxLoads[i] = TRUE; 950 951 var callbacks = awaitingAjaxCallbacks[i]; 952 if (callbacks) { 953 performCallbacks(callbacks); 954 } 955 956 startAsyncDelayedLoad(); 957 958 callAsync(function () {
959 option[24]/*ajaxload*/.call(slides[i], parseInt10(i) + 1, img); 960 }); 961 962 if (init) { 963 init = FALSE; 964 callAsync(performInitCallback); 965 } 966 }); 967 }); 968 } 969 970 function performInitCallback() { 971 if (option[16]/*continuous*/) { 972 centerTargetSlideAfter(currentSlide); 973 } 974 975 autoadjust(currentSlide, 0); 976 adjustPositionTo(currentSlide); 977 callQueuedAnimation(); 978 if (option[11]/*responsive*/) { 979 adjustResponsiveLayout(); 980 } 981 if (option[13]/*auto*/) { 982 startAuto(); 983 } 984 option[23]/*initCallback*/.call(baseSlider); 985 986 // Fixing once and for all that the wrong slide is shown on init. 987 runOnImagesLoaded(getSlides(currentSlide, totalSlides), FALSE, function () { 988 runWhenNotAnimating(function () { 989 autoadjust(currentSlide, 0); 990 adjustPositionTo(currentSlide); 991 }) 992 }); 993 } 994 995 function performCallbacks(callbacks) { 996 while (callbacks.length) { 997 // Removing and running the first, so we maintain FIFO. 998 callbacks.splice(0, 1)[0](); 999 } 1000 } 1001 1002 function isContentInSlideReady(slide) { 1003 if (!imagesInSlidesLoaded[slide]) { 1004 return FALSE; 1005 } 1006 if (!option[31]/*ajax*/) { 1007 return TRUE; 1008 } else { 1009 return option[31]/*ajax*/[slide] || (startedAjaxLoads[slide] && !finishedAjaxLoads[slide]); 1010 } 1011 } 1012 1013 function loadSlidesAndAnimate(i, clicked, speed) { 1014 var dir = filterDir(i); 1015 var prevNext = i == NEXT_STRING || i == PREV_STRING; 1016 1017 var targetSlide = getRealPos(dir); 1018 if (targetSlide == currentSlide) { 1019 return; 1020 } 1021 clickable = FALSE; 1022 if (option[31]/*ajax*/) { 1023 var waitCounter = 0; 1024 for (var loadSlide = targetSlide; loadSlide < targetSlide + numberOfVisibleSlides; loadSlide++) { 1025 if (isContentInSlideReady(loadSlide)) { 1026 waitCounter++; 1027 ajaxLoad(getRealPos(loadSlide), function () { 1028 // This runs aync, so every callback is placed before the first is run. Therefore this works. 1029 waitCounter--; 1030 if (waitCounter == 0) { 1031 option[42]/*loadFinish*/.call(baseSlider, dir + 1); 1032 performAnimation(dir, speed, clicked, prevNext); 1033 } 1034 }); 1035 } 1036 } 1037 if (waitCounter == 0) { 1038 performAnimation(dir, speed, clicked, prevNext); 1039 } else { 1040 option[41]/*loadStart*/.call(baseSlider, dir + 1); 1041 } 1042 } else { 1043 performAnimation(dir, speed, clicked, prevNext); 1044 } 1045 } 1046 1047 var reorderedSlidesToStartFromSlide = 0; 1048 1049 function ensureSliderContainerCSSDurationReset() { 1050 if (option[40]/*useCSS*/) { 1051 slidesContainer.css(CSSVendorPrefix + "transition-duration", ""); 1052 } 1053 } 1054 1055 function reorderSlides(slide) { 1056 if (getRealPos(slide) == reorderedSlidesToStartFromSlide) { 1057 return; 1058 } 1059 for (var i = 0; i < totalSlides; i++) { 1060 if (!isContentInSlideReady(i)) { 1061 return; // Nope. 1062 } 1063 } 1064 reorderedSlidesToStartFromSlide = slide; 1065 ensureSliderContainerCSSDurationReset(); 1066 for (var i = 0; i < totalSlides; i++) { 1067 var slideToInsert = slides[getRealPos((slide + i))]; 1068 slidesContainer.append(slideToInsert); 1069 } 1070 adjustPositionTo(currentSlide); 1071 } 1072
1073 function centerTargetSlideAdjusted(targetSlide, extraSpace) { 1074 var offset = mathMax(parseInt10((totalSlides - extraSpace - numberOfVisibleSlides) / 2), 0); 1075 targetSlide = mod(targetSlide - offset, totalSlides); 1076 reorderSlides(targetSlide); 1077 } 1078 1079 function centerTargetSlideAfter(targetSlide) { 1080 centerTargetSlideAdjusted(targetSlide, 0); 1081 } 1082 1083 function centerTargetSlideBefore(targetSlide) { 1084 var startSlide = mathMin(targetSlide, currentSlide); 1085 var adjustment = mathAbs(targetSlide - currentSlide); 1086 1087 centerTargetSlideAdjusted(startSlide, adjustment); 1088 } 1089 1090 1091 function performAnimation(dir, speed, clicked, prevNext) { 1092 if (option[30]/*updateBefore*/) setCurrent(dir); 1093 1094 if (option[27]/*history*/ && clicked) win.location.hash = option[19]/*numerictext*/[dir]; 1095 1096 if (option[5]/*controlsfade*/) fadeControls(dir, option[4]/*controlsfadespeed*/); 1097 1098 var fromSlides = $(); 1099 var toSlides = $(); 1100 for (var a = 0; a < numberOfVisibleSlides; a++) { 1101 fromSlides = fromSlides.add(slides[getRealPos(currentSlide + a)]); 1102 toSlides = toSlides.add(slides[getRealPos(dir + a)]); 1103 } 1104 1105 1106 // Finding a "shortcut", used for calculating the offsets. 1107 var diff = -currentSlide + dir; 1108 var targetSlide; 1109 if (option[16]/*continuous*/ && !prevNext) { 1110 var diffAbs = mathAbs(diff); 1111 targetSlide = dir; 1112 1113 var newDiff = -currentSlide + dir + totalSlides; 1114 if (mathAbs(newDiff) < diffAbs) { 1115 targetSlide = dir + totalSlides; 1116 diff = newDiff; 1117 diffAbs = mathAbs(diff); 1118 } 1119 1120 newDiff = -currentSlide + dir - totalSlides; 1121 if (mathAbs(newDiff) < diffAbs) { 1122 targetSlide = dir - totalSlides; 1123 diff = newDiff; 1124 } 1125 } else { 1126 targetSlide = dir; 1127 } 1128 1129 if (option[16]/*continuous*/) { 1130 centerTargetSlideBefore(targetSlide); 1131 } 1132 1133 var leftTarget = getSlidePosition(targetSlide, FALSE); 1134 var topTarget = getSlidePosition(targetSlide, TRUE); 1135 1136 var targetLi = slides[getRealPos(dir)]; 1137 var callOptions = $.extend(TRUE, {}, options); // Making a copy, to enforce read-only. 1138 var overwritingSpeed = option[1]/*speed*/; 1139 var attributeSpeed = targetLi.attr("data-speed"); 1140 if (attributeSpeed != undefined) { 1141 overwritingSpeed = parseInt10(attributeSpeed); 1142 } 1143 if (speed != undefined) { 1144 overwritingSpeed = parseInt10(speed); 1145 } 1146 callOptions.speed = overwritingSpeed; 1147 1148 var effect = option[0]/*effect*/; 1149 1150 var specificEffectAttrName = "data-effect"; 1151 var slideSpecificEffect = targetLi.attr(specificEffectAttrName); 1152 if (slideSpecificEffect) { 1153 effect = getEffectMethod(slideSpecificEffect); 1154 } 1155 var slideOutSpecificEffect = slides[currentSlide].attr(specificEffectAttrName + "out"); 1156 if (slideOutSpecificEffect) { 1157 effect = getEffectMethod(slideOutSpecificEffect); 1158 } 1159 1160 currentlyAnimating = TRUE; 1161 currentAnimation = effect; 1162 1163 var callbackHasYetToRun = TRUE; 1164 currentAnimationCallback = function () { 1165 currentlyAnimating = FALSE; 1166 callbackHasYetToRun = FALSE; 1167 1168 goToSlide(dir, clicked); 1169 fixClearType(toSlides); 1170 1171 if (option[16]/*continuous*/) {
1172 centerTargetSlideAfter(targetSlide); 1173 } 1174 1175 // afteranimation 1176 aniCall(dir, TRUE); 1177 1178 performCallbacks(runAfterAnimationCallbacks); 1179 }; 1180 currentAnimationObject = { 1181 fromSlides: fromSlides, 1182 toSlides: toSlides, 1183 slider: obj, 1184 options: callOptions, 1185 to: dir + 1, 1186 from: currentSlide + 1, 1187 diff: diff, 1188 target: { 1189 left: leftTarget, 1190 top: topTarget 1191 }, 1192 stopCallbacks: [], 1193 callback: function () { 1194 if (callbackHasYetToRun) { 1195 callbackHasYetToRun = FALSE; 1196 stopAnimation(); 1197 } 1198 }, 1199 goToNext: function () { 1200 if (callbackHasYetToRun) { 1201 // Only moving after there is content ready to replace the previous. 1202 runOnImagesLoaded($("." + ANIMATION_CLONE_MARKER_CLASS, obj), TRUE, function () { 1203 adjustPositionTo(dir); 1204 }); 1205 } 1206 } 1207 }; 1208 1209 autoadjust(dir, overwritingSpeed); 1210 callAsync(function () { 1211 // beforeanimation 1212 aniCall(dir, FALSE, TRUE); 1213 1214 effect.call(baseSlider, currentAnimationObject); 1215 }); 1216 } 1217 1218 function stopAnimation() { 1219 if (currentlyAnimating) { 1220 // 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. 1221 currentAnimationCallback(); 1222
1223 performCallbacks(currentAnimationObject.stopCallbacks); 1224 1225 1226 var stopFunction = currentAnimation.stop; 1227 if (stopFunction) { 1228 stopFunction(); 1229 } else { 1230 defaultStopFunction(); 1231 } 1232 autoadjust(currentSlide, 0); 1233 adjustPositionTo(currentSlide); 1234 } 1235 } 1236 1237 function cantDoAdjustments() { 1238 return !obj.is(":visible") || init; 1239 } 1240 1241 function defaultStopFunction() { 1242 $("." + ANIMATION_CLONE_MARKER_CLASS, obj).remove(); 1243 slidesContainer.stop(); 1244 } 1245 1246 function goToSlide(slide, clicked) { 1247 clickable = !clicked && !option[13]/*auto*/; 1248 previousSlide = currentSlide; 1249 currentSlide = slide; 1250 1251 adjust(clicked); 1252 1253 if (option[5]/*controlsfade*/ && init) { 1254 fadeControls(currentSlide, 0); 1255 } 1256 // This is handles in AjaxAdjust, if something is loading. 1257 if (init && !option[31]/*ajax*/[currentSlide] && !startedAjaxLoads[currentSlide]) { 1258 init = FALSE; 1259 callAsync(performInitCallback); 1260 } 1261 } 1262 1263 function getSlides(from, count) { 1264 var visibleSlides = $(); 1265 for (var i = 0; i < count; i++) { 1266 visibleSlides = visibleSlides.add(slides[getRealPos(from + i)]); 1267 } 1268 return visibleSlides; 1269 } 1270 1271 function getRealPos(a) { 1272 return mod(a, totalSlides); 1273 } 1274 1275 // Actual modulo, not remainder. From here: http://stackoverflow.com/questions/4467539/javascript-modulo-not-behaving 1276 function mod(a, n) { 1277 return ((a % n) + n) % n; 1278 } 1279 1280 function fixClearType(element) { 1281 if (screen.fontSmoothingEnabled && element.style) element.style.removeAttribute("filter"); // Fix cleartype 1282 } 1283 1284 /* 1285 * Public methods. 1286 */ 1287 1288 // First i just define those i use more than one. Then i just add the others as anonymous functions. 1289 function publicDestroy() { 1290 stopAnimation(); 1291 destroyed = TRUE; 1292 slideNumberBeforeDestroy = currentSlide; 1293 1294 if (option[11]/*responsive*/) { 1295 $(win).off("resize focus", adjustResponsiveLayout); 1296 } 1297 1298 ensureSliderContainerCSSDurationReset(); 1299 1300 if (controls) { 1301 controls.remove(); 1302 } 1303 1304 $(document).off("click", option[2]/*customlink*/, customLinkClickHandler); 1305 1306 reorderSlides(0); 1307 1308 adjustPositionTo(currentSlide); 1309 autoadjust(currentSlide, 0); 1310 } 1311 1312 baseSlider.destroy = publicDestroy; 1313 1314 function publicInit() { 1315 if (destroyed) { 1316 initSudoSlider(); 1317 } 1318 } 1319 1320 baseSlider.init = publicInit; 1321 1322 baseSlider.getOption = function (a) { 1323 return options[a.toLowerCase()]; 1324 }; 1325 1326 baseSlider.setOption = function (a, val) { 1327 publicDestroy(); 1328 options[a.toLowerCase()] = val; 1329 publicInit(); 1330 }; 1331 1332 baseSlider.runWhenNotAnimating = runWhenNotAnimating; 1333 1334 baseSlider.insertSlide = function (html, pos, numtext, goToSlide) { 1335 publicDestroy(); 1336 // pos = 0 means before everything else. 1337 // pos = 1 means after the first slide. 1338 if (pos > totalSlides) { 1339 pos = totalSlides; 1340 } 1341 1342 html = $(html || "<div>"); 1343 if (isSlideContainerUl) { 1344 html = $("<li>").prepend(html); 1345 } else { 1346 if (html.length != 1) { 1347 html = $("<div>").prepend(html); 1348 } else { 1349 // Inserting as is. 1350 } 1351 } 1352 1353 if (!pos || pos == 0) { 1354 slidesContainer.prepend(html); 1355 } else { 1356 slides[pos - 1].after(html); 1357 } 1358 1359 // Finally, we make it work again. 1360 if (goToSlide) { 1361 slideNumberBeforeDestroy = goToSlide - 1; 1362 } else if (pos <= slideNumberBeforeDestroy || (!pos || pos == 0)) { 1363 slideNumberBeforeDestroy++; 1364 } 1365 1366 if (option[19]/*numerictext*/.length < pos) { 1367 option[19]/*numerictext*/.length = pos; 1368 } 1369 1370 option[19]/*numerictext*/.splice(pos, 0, numtext || parseInt10(pos) + 1); 1371 publicInit(); 1372 }; 1373 1374 baseSlider.removeSlide = function (pos) { 1375 pos--; // 1 == the first. 1376 publicDestroy(); 1377 1378 slides[pos].remove(); 1379 option[19]/*numerictext*/.splice(pos, 1); 1380 if (pos < slideNumberBeforeDestroy) { 1381 slideNumberBeforeDestroy--; 1382 } 1383 1384 publicInit(); 1385 }; 1386 1387 baseSlider.goToSlide = function (a, speed) { 1388 var parsedDirection = (a == parseInt10(a)) ? a - 1 : a; 1389 callAsync(function () { 1390 enqueueAnimation(parsedDirection, TRUE, speed); 1391 }); 1392 }; 1393 1394 baseSlider.block = function () { 1395 clickable = FALSE; 1396 }; 1397 1398 baseSlider.unblock = function () { 1399 clickable = TRUE; 1400 }; 1401 1402 baseSlider.startAuto = function () { 1403 option[13]/*auto*/ = TRUE; 1404 startAuto(); 1405 }; 1406 1407 baseSlider.stopAuto = function () { 1408 option[13]/*auto*/ = FALSE; 1409 stopAuto(); 1410 }; 1411 1412 baseSlider.adjust = function () { 1413 var autoAdjustSpeed = mathMax(adjustTargetTime - getTimeInMillis(), 0); 1414 autoadjust(currentSlide, autoAdjustSpeed); 1415 if (!currentlyAnimating) { 1416 adjustPositionTo(currentSlide); 1417 } 1418 }; 1419 1420 baseSlider.getValue = function (a) { 1421 return { 1422 currentslide: currentSlide + 1, 1423 totalslides: totalSlides, 1424 clickable: clickable, 1425 destroyed: destroyed, 1426 autoanimation: autoOn 1427 }[a.toLowerCase()]; 1428 }; 1429 1430 baseSlider.getSlide = function (number) { 1431 return slides[getRealPos(parseInt10(number) - 1)]; 1432 }; 1433 1434 baseSlider.stopAnimation = stopAnimation; 1435 1436 // Done, now initialize. 1437 initSudoSlider(); 1438 }); 1439 }; 1440 /* 1441 * End generic slider. Start animations. 1442 * 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). 1443 */ 1444 1445 // Start by defining everything, the implementations are below.
1446 var normalEffectsPrefixObject = { 1447 box: { 1448 Random: [ 1449 "", 1450 "GrowIn", 1451 "GrowOut", 1452 boxRandomTemplate 1453 ], 1454 Rain: [ 1455 "", 1456 "GrowIn", 1457 "GrowOut", 1458 "FlyIn", 1459 "FlyOut", 1460 [ 1461 "UpLeft", 1462 "DownLeft", 1463 "DownRight", 1464 "UpRight", 1465 boxRainTemplate 1466 ] 1467 ], 1468 Spiral: [ 1469 "InWards", 1470 "OutWards", 1471 { 1472 "": boxSpiralTemplate, 1473 Grow: [ 1474 "In", 1475 "Out", 1476 boxSpiralGrowTemplate 1477 ] 1478 } 1479 ] 1480 }, 1481 fade: { 1482 "": fade, 1483 OutIn: fadeOutIn 1484 }, 1485 foldRandom: [ 1486 "Horizontal", 1487 "Vertical", 1488 foldRandom 1489 ], 1490 slide: slide, 1491 stack: [ 1492 "Up", 1493 "Right", 1494 "Down", 1495 "Left", 1496 [ 1497 "", 1498 "Reverse", 1499 stackTemplate 1500 ] 1501 ] 1502 } 1503 1504 // Generic effects needs to have a "dir" attribute as their last argument. 1505 var genericEffectsPrefixObject = { 1506 blinds: [ 1507 "1", 1508 "2", 1509 blinds 1510 ], 1511 fold: fold, 1512 push: 1513 [ 1514 "Out", 1515 "In", 1516 pushTemplate 1517 ], 1518 reveal: revealTemplate, 1519 slice: { 1520 "": [ 1521 "", 1522 "Reveal", 1523 [ 1524 "", 1525 "Reverse", 1526 "Random", 1527 slice 1528 ] 1529 ], 1530 Fade: slicesFade 1531 }, 1532 zip: zip, 1533 unzip: unzip 1534 } 1535 1536 1537 function parsePrefixedEffects(resultObject, effectsObject, prefix, generic, argumentsStack) { 1538 if (isFunction(effectsObject)) { 1539 if (generic) { 1540 // Parsing the value 0, as a hack to make generic effects work, see the below else case. 1541 parsePrefixedEffects(resultObject, ["", "Up", "Right", "Down", "Left", effectsObject], prefix, 0, argumentsStack); 1542 } else { 1543 resultObject[prefix] = function (obj) { 1544 var argumentArray = [obj].concat(argumentsStack); 1545 1546 // Ugly hack, to make "generic" functions to work. 1547 var genericArgumentIndex = (argumentArray.length - 1); 1548 if (generic === 0 && argumentArray[genericArgumentIndex] == 0) { 1549 argumentArray[genericArgumentIndex] = getDirFromAnimationObject(obj); 1550 } 1551 1552 effectsObject.apply(this, argumentArray); 1553 } 1554 } 1555 } else if (isArray(effectsObject)) { 1556 var effectIndex = effectsObject.length - 1; 1557 var effect = effectsObject[effectIndex]; 1558 for (var i = 0; i < effectIndex; i++) { 1559 var newArgumentStack = cloneArray(argumentsStack); 1560 newArgumentStack.push(i); 1561 var name = effectsObject[i]; 1562 parsePrefixedEffects(resultObject, effect, prefix + name, generic, newArgumentStack); 1563 } 1564 } else { 1565 $.each(effectsObject, function (name, effect) { 1566 parsePrefixedEffects(resultObject, effect, prefix + name, generic, argumentsStack); 1567 }); 1568 } 1569 } 1570 1571 1572 var allEffects = {}; 1573 parsePrefixedEffects(allEffects, genericEffectsPrefixObject, "", TRUE, []); 1574 parsePrefixedEffects(allEffects, normalEffectsPrefixObject, "", FALSE, []); 1575 1576 allEffects.random = makeRandomEffect(allEffects); 1577 1578 // Saving it. 1579 $.fn.sudoSlider.effects = allEffects; 1580 1581 1582 // The implementations 1583 // dir: 0: UpRight, 1: DownRight: 2: DownLeft, 3: UpLeft 1584 // effect: 0: none, 1: growIn, 2: growOut, 3: flyIn, 4: flyOut. 1585 function boxRainTemplate(obj, effect, dir) { 1586 var reverseRows = dir == 1 || dir == 3; 1587 var reverse = dir == 0 || dir == 3; 1588 var grow = effect == 1 || effect == 2; 1589 var flyIn = effect == 3 || effect == 4; 1590 var reveal = effect == 4 || effect == 2; 1591 boxTemplate(obj, reverse, reverseRows, grow, FALSE, 1, flyIn, reveal); 1592 } 1593 1594 function boxSpiralTemplate(obj, direction) { 1595 boxTemplate(obj, direction, FALSE, FALSE, FALSE, 2, FALSE, FALSE); 1596 } 1597 1598 function boxSpiralGrowTemplate(obj, direction, reveal) { 1599 boxTemplate(obj, direction, FALSE, TRUE, FALSE, 2, FALSE, reveal); 1600 } 1601 1602 // grow: 0: no grow, 1: growIn, 2: growOut 1603 function boxRandomTemplate(obj, grow) { 1604 var reveal = grow == 2; 1605 boxTemplate(obj, FALSE, FALSE, grow, TRUE, 0, FALSE, reveal); 1606 } 1607 1608 // SelectionAlgorithm: 0: Standard selection, 1: rain, 2: spiral 1609 function boxTemplate(obj, reverse, reverseRows, grow, randomize, selectionAlgorithm, flyIn, reveal) { 1610 var options = obj.options; 1611 var ease = options.ease; 1612 var boxRows = options.boxrows; 1613 var boxCols = options.boxcols; 1614 var totalBoxes = boxRows * boxCols; 1615 var speed = options.speed / (totalBoxes == 1 ? 1 : 2.5); // To make the actual time spent equal to options.speed. 1616 var boxes = createBoxes(obj, boxCols, boxRows, !reveal); 1617 var timeBuff = 0; 1618 var rowIndex = 0; 1619 var colIndex = 0; 1620 var box2DArr = []; 1621 box2DArr[rowIndex] = []; 1622 if (reverse) { 1623 reverseArray(boxes); 1624 } 1625 if (randomize) { 1626 shuffle(boxes); 1627 } 1628 1629 1630 boxes.each(function () { 1631 box2DArr[rowIndex][colIndex] = this; 1632 colIndex++; 1633 if (colIndex == boxCols) { 1634 if (reverseRows) { 1635 reverseArray(box2DArr[rowIndex]); 1636 } 1637 rowIndex++; 1638 colIndex = 0; 1639 box2DArr[rowIndex] = []; 1640 } 1641 }); 1642 1643 var boxesResult = []; 1644 if (selectionAlgorithm == 1) { 1645 // Rain 1646 for (var cols = 0; cols < (boxCols * 2) + 1; cols++) { 1647 var prevCol = cols; 1648 var boxesResultLine = []; 1649 for (var rows = 0; rows < boxRows; rows++) { 1650 if (prevCol >= 0 && prevCol < boxCols) { 1651 var rawBox = box2DArr[rows][prevCol]; 1652 if (!rawBox) { 1653 return; 1654 } 1655 boxesResultLine.push(rawBox); 1656 } 1657 prevCol--; 1658 } 1659 if (boxesResultLine.length != 0) { 1660 boxesResult.push(boxesResultLine); 1661 } 1662 } 1663 } else if (selectionAlgorithm == 2) { 1664 // Spiral 1665 // Algorithm borrowed from the Camera plugin by Pixedelic.com 1666 var rows2 = boxRows / 2, x, y, z, n = reverse ? totalBoxes : -1; 1667 var negative = reverse ? -1 : 1; 1668 for (z = 0; z < rows2; z++) { 1669 y = z; 1670 for (x = z; x < boxCols - z - 1; x++) { 1671 boxesResult[n += negative] = boxes.eq(y * boxCols + x); 1672 } 1673 x = boxCols - z - 1; 1674 for (y = z; y < boxRows - z - 1; y++) { 1675 boxesResult[n += negative] = boxes.eq(y * boxCols + x); 1676 } 1677 y = boxRows - z - 1; 1678 for (x = boxCols - z - 1; x > z; x--) { 1679 boxesResult[n += negative] = boxes.eq(y * boxCols + x); 1680 } 1681 x = z; 1682 for (y = boxRows - z - 1; y > z; y--) { 1683 boxesResult[n += negative] = boxes.eq(y * boxCols + x); 1684 } 1685 } 1686 } else { 1687 for (var row = 0; row < boxRows; row++) { 1688 for (var col = 0; col < boxCols; col++) { 1689 boxesResult.push([box2DArr[row][col]]); 1690 } 1691 } 1692 } 1693 1694 if (reveal) { 1695 obj.goToNext(); 1696 } 1697 1698 var count = 0; 1699 for (var i = 0; i < boxesResult.length; i++) { 1700 var boxLine = boxesResult[i]; 1701 for (var j = 0; j < boxLine.length; j++) { 1702 var box = $(boxLine[j]); 1703 (function (box, timeBuff) { 1704 var boxChildren = box.children(); 1705 var goToWidth = box.width(); 1706 var goToHeight = box.height(); 1707 var orgLeft = parseNumber(box.css("left")); 1708 var orgTop = parseNumber(box.css("top")); 1709 var goToLeft = orgLeft; 1710 var goToTop = orgTop; 1711 1712 var childOrgLeft = parseNumber(boxChildren.css("left")); 1713 var childOrgTop = parseNumber(boxChildren.css("top")); 1714 var childGoToLeft = childOrgLeft; 1715 var childGoToTop = childOrgTop; 1716 1717 if (flyIn) { 1718 var adjustLeft = reverse != reverseRows ? -goToWidth : goToWidth; 1719 var adjustTop = reverse ? -goToHeight : goToHeight; 1720 1721 var flyDistanceFactor = 1.5; 1722 1723 if (reveal) { 1724 goToLeft -= adjustLeft * flyDistanceFactor; 1725 goToTop -= adjustTop * flyDistanceFactor; 1726 } else { 1727 box.css({left: orgLeft + adjustLeft * flyDistanceFactor, top: orgTop + adjustTop * flyDistanceFactor}); 1728 } 1729 } 1730 1731 if (grow) { 1732 if (reveal) { 1733 childGoToLeft -= goToWidth / 2; 1734 goToLeft += goToWidth / 2; 1735 childGoToTop -= goToHeight / 2; 1736 goToTop += goToHeight / 2; 1737 1738 goToHeight = goToWidth = 0; 1739 } else { 1740 box.css({left: orgLeft + (goToWidth / 2), top: orgTop + (goToHeight / 2)}); 1741 boxChildren.css({left: childOrgLeft - goToWidth / 2, top: childOrgTop - goToHeight / 2}); 1742 1743 box.width(0).height(0); 1744 } 1745 } 1746 1747 1748 if (reveal) { 1749 box.css({opacity: 1}); 1750 } 1751 count++; 1752 setTimeout(function () { 1753 animate(boxChildren, {left: childGoToLeft, top: childGoToTop}, speed, ease, FALSE, obj); 1754 animate(box, { 1755 opacity: reveal ? 0 : 1, 1756 width: goToWidth, 1757 height: goToHeight, 1758 left: goToLeft, 1759 top: goToTop 1760 }, speed, ease, function () { 1761 count--; 1762 if (count == 0) { 1763 obj.callback(); 1764 } 1765 }, obj); 1766 }, timeBuff); 1767 })(box, timeBuff); 1768 } 1769 timeBuff += (speed / boxesResult.length) * 1.5; 1770 } 1771 } 1772 1773 function slicesFade(obj, dir) { 1774 var vertical = dir == 2 || dir == 4; 1775 var negative = dir == 1 || dir == 4; 1776 foldTemplate(obj, vertical, negative, FALSE, TRUE); 1777 } 1778 1779 function fold(obj, dir) { 1780 var vertical = dir == 2 || dir == 4; 1781 var negative = dir == 1 || dir == 4; 1782 foldTemplate(obj, vertical, negative); 1783 } 1784 1785 function foldRandom(obj, vertical) { 1786 foldTemplate(obj, vertical, FALSE, TRUE); 1787 } 1788 1789 function blinds(obj, blindsEffect, dir) { 1790 blindsEffect++; 1791 var vertical = dir == 2 || dir == 4; 1792 var negative = dir == 1 || dir == 4; 1793 foldTemplate(obj, vertical, negative, FALSE, FALSE, blindsEffect); 1794 } 1795 1796 function slice(obj, reveal, reverse, dir) { 1797 var random = reverse == 2; 1798 var vertical = dir == 1 || dir == 3; 1799 var negative = dir == 1 || dir == 4; 1800 foldTemplate(obj, vertical, reverse, random, FALSE, 0, negative ? 1 : 2, reveal); 1801 } 1802 1803 function zip(obj, dir) { 1804 var vertical = dir == 2 || dir == 4; 1805 var negative = dir == 1 || dir == 4; 1806 foldTemplate(obj, vertical, negative, FALSE, FALSE, 0, 3); 1807 } 1808 1809 function unzip(obj, dir) { 1810 var vertical = dir == 2 || dir == 4; 1811 var negative = dir == 1 || dir == 4; 1812 foldTemplate(obj, vertical, negative, FALSE, FALSE, 0, 3, TRUE); 1813 } 1814 1815 function foldTemplate(obj, vertical, reverse, randomize, onlyFade, curtainEffect, upDownEffect, reveal) { 1816 var options = obj.options;
1817 var slides = options.slices; 1818 var speed = options.speed / 2; // To make the actual time spent be equal to options.speed 1819 var ease = options.ease; 1820 var objSlider = obj.slider; 1821 var slicesElement = createBoxes(obj, vertical ? slides : 1, vertical ? 1 : slides, !reveal); 1822 var count = 0; 1823 var upDownAlternator = FALSE; 1824 if (reverse) { 1825 reverseArray(slicesElement); 1826 } else { 1827 $(reverseArray(slicesElement.get())).appendTo(objSlider); 1828 } 1829 if (randomize) { 1830 shuffle(slicesElement); 1831 } 1832 slicesElement.each(function (i) { 1833 var timeout = ((speed / slides) * i); 1834 var slice = $(this); 1835 var orgWidth = slice.width(); 1836 var orgHeight = slice.height(); 1837 var goToLeft = slice.css("left"); 1838 var goToTop = slice.css("top"); 1839 var startPosition = vertical ? goToLeft : goToTop; 1840 1841 var innerBox = slice.children(); 1842 var startAdjustment = innerBox[vertical ? "width" : "height"](); 1843 if (curtainEffect == 1) { 1844 startPosition = 0 1845 } else if (curtainEffect == 2) { 1846 startPosition = startAdjustment / 2; 1847 } 1848 if (reverse) { 1849 startPosition = startAdjustment - startPosition; 1850 } 1851 if (vertical) { 1852 slice.css({ 1853 width: (onlyFade || upDownEffect ? orgWidth : 0), 1854 left: startPosition 1855 }); 1856 } else { 1857 slice.css({ 1858 height: (onlyFade || upDownEffect ? orgHeight : 0), 1859 top: startPosition 1860 }); 1861 } 1862 1863 if (reveal) { 1864 var negative = upDownEffect == 1 ? -1 : 1; 1865 slice.css({ 1866 top: goToTop, 1867 left: goToLeft, 1868 width: orgWidth, 1869 height: orgHeight, 1870 opacity: 1 1871 }); 1872 if (vertical) { 1873 goToTop = negative * orgHeight; 1874 } else { 1875 goToLeft = negative * orgWidth; 1876 } 1877 } 1878 1879 if (upDownEffect) { 1880 var bottom = TRUE; 1881 if (upDownEffect == 3) { 1882 if (upDownAlternator) { 1883 bottom = FALSE; 1884 upDownAlternator = FALSE; 1885 } else { 1886 upDownAlternator = TRUE; 1887 } 1888 } else if (upDownEffect == 2) { 1889 bottom = FALSE; 1890 } 1891 if (vertical) { 1892 if (reveal) { 1893 goToTop = (bottom ? -1 : 1) * orgHeight; 1894 } else { 1895 slice.css({ 1896 bottom: bottom ? 0 : orgHeight, 1897 top: bottom ? orgHeight : 0,
1898 height: reveal ? orgHeight : 0 1899 }); 1900 } 1901 } else { 1902 if (reveal) { 1903 goToLeft = (bottom ? -1 : 1) * orgWidth; 1904 } else { 1905 slice.css({ 1906 right: bottom ? 0 : orgWidth, 1907 left: bottom ? orgWidth : 0, 1908 width: reveal ? orgWidth : 0 1909 }); 1910 } 1911 } 1912 } 1913 1914 1915 count++; 1916 setTimeout(function () { 1917 animate(slice, { 1918 width: orgWidth, 1919 height: orgHeight, 1920 opacity: reveal ? 0 : 1, 1921 left: goToLeft, 1922 top: goToTop 1923 }, speed, ease, function () { 1924 count--; 1925 if (count == 0) { 1926 obj.callback(); 1927 } 1928 }, obj); 1929 }, timeout); 1930 }); 1931 if (reveal) { 1932 obj.goToNext(); 1933 } 1934 } 1935 1936 function stackTemplate(obj, dir, reverse) { 1937 var pushIn = obj.diff > 0; 1938 if (reverse) { 1939 pushIn = !pushIn; 1940 } 1941 1942 pushTemplate(obj, pushIn, ++dir); 1943 } 1944 1945 // 1: up, 2: right, 3: down, 4, left: 1946 function pushTemplate(obj, pushIn, dir) { 1947 var vertical = dir == 2 || dir == 4; 1948 var negative = (dir == 2 || dir == 3) ? 1 : -1; 1949 var options = obj.options; 1950 var ease = options.ease; 1951 var speed = options.speed; 1952 if (pushIn) { 1953 var fromSlides = obj.fromSlides; 1954 var toSlides = makeClone(obj, TRUE).hide(); 1955 toSlides.prependTo(obj.slider); 1956 var height = mathMax(toSlides.height(), fromSlides.height()); 1957 var width = mathMax(toSlides.width(), fromSlides.width()); 1958 toSlides.css(vertical ? {left: negative * width} : {top: negative * height}).show(); 1959 animate(toSlides, {left: 0, top: 0}, speed, ease, obj.callback, obj); 1960 } else { 1961 var fromSlides = makeClone(obj, FALSE); 1962 fromSlides.prependTo(obj.slider); 1963 obj.goToNext(); 1964 var toSlides = obj.toSlides; 1965 1966 var measurementSlides = negative == -1 ? fromSlides : toSlides; 1967 var height = measurementSlides.height(); 1968 var width = measurementSlides.width(); 1969 1970 animate(fromSlides, vertical ? {left: negative * width} : {top: negative * height}, speed, ease, obj.callback, obj); 1971 } 1972 } 1973 1974 function revealTemplate(obj, dir) { 1975 var vertical = dir == 1 || dir == 3; 1976 var options = obj.options; 1977 var ease = options.ease; 1978 var speed = options.speed; 1979 var innerBox = makeClone(obj, TRUE); 1980 var width = innerBox.width(); 1981 var height = innerBox.height(); 1982 var box = makeBox(innerBox, 0, 0, 0, 0, obj) 1983 .css({opacity: 1}) 1984 .appendTo(obj.slider); 1985 var both = box.add(innerBox); 1986 both.hide(); // FF css animation fix 1987 if (vertical) { 1988 box.css({width: width}); 1989 if (dir == 1) { 1990 innerBox.css({top: -height}); 1991 box.css({bottom: 0, top: "auto"}); 1992 } 1993 } else { 1994 box.css({height: height}); 1995 if (dir == 4) { 1996 innerBox.css({left: -width}); 1997 box.css({right: 0, left: "auto"}); 1998 } 1999 } 2000 // <FF css animation fix> 2001 both.show(); 2002 if (vertical) { 2003 both.width(width); 2004 } else { 2005 both.height(height); 2006 } 2007 // </FF css animation fix> 2008 animate(innerBox, {left: 0, top: 0}, speed, ease, FALSE, obj); 2009 animate(box, {width: width, height: height}, speed, ease, obj.callback, obj); 2010 } 2011 2012 function slide(obj) { 2013 var ul = childrenNotAnimationClones(obj.slider); 2014 var options = obj.options; 2015 var ease = options.ease; 2016 var speed = options.speed; 2017 var target = obj.target; 2018 2019 var left = target.left; 2020 var top = target.top; 2021 2022 if (obj.options.usecss) { 2023 animate(ul, {transform: "translate(" + left + "px, " + top + "px)"}, speed, ease, obj.callback, obj, TRUE); 2024 } else { 2025 animate(ul, {marginTop: top, marginLeft: left}, speed, ease, obj.callback, obj); 2026 } 2027 } 2028 2029 function animate(elem, properties, speed, ease, callback, obj, doNotResetCss) { 2030 var usecss = !obj || obj.options.usecss; 2031 if (CSSVendorPrefix === FALSE || !usecss) { 2032 elem.animate(properties, speed, ease, callback); 2033 return; 2034 } 2035 2036 var CSSObject = {}; 2037 var transitionProperty = CSSVendorPrefix + "transition"; 2038 var keys = getKeys(properties); 2039 // Adding vendor prefix, because sometimes it's needed. 2040 CSSObject[transitionProperty] = keys.join(" ") + (CSSVendorPrefix == "" ? "" : " " + CSSVendorPrefix + keys.join(" " + CSSVendorPrefix)); 2041 2042 var transitionTiming = transitionProperty + "-duration"; 2043 CSSObject[transitionTiming] = speed + "ms"; 2044 2045 var transitionEase = transitionProperty + "-timing-function"; 2046 if (ease == "swing") { 2047 ease = "ease-in-out"; 2048 } 2049 CSSObject[transitionEase] = ease; 2050 2051 function resetCSS() { 2052 if (!doNotResetCss) { 2053 var cssObject = {}; 2054 cssObject[transitionTiming] = "0s"; 2055 cssObject[transitionEase] = ""; 2056 cssObject[transitionProperty] = ""; 2057 elem.css(cssObject); 2058 } 2059 } 2060 2061 if (obj) { 2062 obj.stopCallbacks.push(resetCSS); 2063 } 2064 2065 var eventsVendorPrefix = CSSVendorPrefix.replace(/\-/g, ""); // replaces all "-" with ""; 2066 var eventsSuffix = (eventsVendorPrefix ? "T" : "t") + "ransitionend"; 2067 var events = eventsVendorPrefix + eventsSuffix + " t" + "ransitionend"; 2068 2069 var called = FALSE; 2070 var callbackFunction = function () { 2071 if (!called) { 2072 called = TRUE; 2073 elem.unbind(events); 2074 resetCSS(); 2075 if (callback) { 2076 callback(); 2077 } 2078 } 2079 }; 2080 2081 callAsync(function () { 2082 if (speed < 20) { // If instant animation 2083 elem.css(properties); 2084 callbackFunction(); 2085 return; 2086 } 2087 elem.css(CSSObject); 2088 2089 callAsync(function () { 2090 elem.css(properties); 2091 2092 elem.on(events, function (event) { 2093 if (elem.is(event.target)) { 2094 callbackFunction(); 2095 } 2096 }); 2097 // If the animation doesn't do anything, the bind will never be triggered, so this is a fallback. 2098 setTimeout(callbackFunction, speed + 100); 2099 }); 2100 }); 2101 return callbackFunction 2102 } 2103 2104 function fadeOutIn(obj) { 2105 var options = obj.options; 2106 var fadeSpeed = options.speed; 2107 var ease = options.ease; 2108 2109 var fadeinspeed = parseInt10(fadeSpeed * (3 / 5)); 2110 var fadeoutspeed = fadeSpeed - fadeinspeed; 2111 2112 obj.stopCallbacks.push(function () { 2113 obj.fromSlides.stop().css({opacity: 1}); 2114 }); 2115 2116 animate(obj.fromSlides, { opacity: 0.0001 }, fadeoutspeed, ease, function () { 2117 finishFadeAnimation(obj, fadeSpeed); 2118 }, obj); 2119 } 2120 2121 2122 function fade(obj) { 2123 finishFadeAnimation(obj, obj.options.speed); 2124 } 2125 2126 function finishFadeAnimation(obj, speed) { 2127 var options = obj.options; 2128 options.boxcols = 1; 2129 options.boxrows = 1; 2130 options.speed = speed; 2131 boxTemplate(obj); 2132 } 2133 2134 // 1: up, 2: right, 3: down, 4, left: 2135 function getDirFromAnimationObject(obj) { 2136 var vertical = obj.options.vertical; 2137 var diff = obj.diff; 2138 var dir; 2139 if (vertical) { 2140 if (diff < 0) { 2141 dir = 1; 2142 } else { 2143 dir = 3; 2144 } 2145 } else { 2146 if (diff < 0) { 2147 dir = 2; 2148 } else { 2149 dir = 4; 2150 } 2151 } 2152 return dir; 2153 } 2154 2155 2156 function createBoxes(obj, numberOfCols, numberOfRows, useToSlides) { 2157 var slider = obj.slider; 2158 var result = $(); 2159 var boxWidth, boxHeight; 2160 var first = TRUE; 2161 for (var rows = 0; rows < numberOfRows; rows++) { 2162 for (var cols = 0; cols < numberOfCols; cols++) { 2163 var innerBox = makeClone(obj, useToSlides); 2164 2165 if (first) { 2166 first = FALSE; 2167 boxWidth = Math.ceil(innerBox.width() / numberOfCols);
2168 boxHeight = Math.ceil(innerBox.height() / numberOfRows); 2169 } 2170 2171 var box = makeBox( 2172 innerBox, // innerBox 2173 boxHeight * rows, // top 2174 boxWidth * cols, // left 2175 boxHeight, // height 2176 boxWidth, // width 2177 obj // for options. 2178 ); 2179 slider.append(box); 2180 result = result.add(box); 2181 } 2182 } 2183 return result; 2184 } 2185 2186 function makeBox(innerBox, top, left, height, width, obj) { 2187 innerBox.css({ 2188 width: innerBox.width(), 2189 height: innerBox.height(), 2190 display: "block", 2191 top: -top, 2192 left: -left 2193 }); 2194 var box = $("<div>").css({ 2195 left: left, 2196 top: top, 2197 width: width, 2198 height: height, 2199 opacity: 0, 2200 overflow: "hidden", 2201 position: ABSOLUTE_STRING, 2202 zIndex: obj.options.animationzindex 2203 }); 2204 box.append(innerBox).addClass(ANIMATION_CLONE_MARKER_CLASS); 2205 return box; 2206 } 2207 2208 // 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. 2209 function makeClone(obj, useToSlides) { 2210 var slides = useToSlides ? obj.toSlides : obj.fromSlides; 2211 var firstSlidePosition = slides.eq(0).position(); 2212 var orgLeft = firstSlidePosition.left; 2213 var orgTop = firstSlidePosition.top; 2214 var height = 0; 2215 var width = 0; 2216 var result = $("<div>").css({zIndex: obj.options.animationzindex, position: ABSOLUTE_STRING, top: 0, left: 0}).addClass(ANIMATION_CLONE_MARKER_CLASS); 2217 slides.each(function (index, elem) { 2218 var that = $(elem); 2219 var cloneWidth = that.outerWidth(TRUE); 2220 var cloneHeight = that.outerHeight(TRUE); 2221 var clone = that.clone(); 2222 var position = that.position(); 2223 var left = position.left - orgLeft; 2224 var top = position.top - orgTop; 2225 clone.css({position: ABSOLUTE_STRING, left: left, top: top, opacity: 1}); 2226 height = mathMax(height, top + cloneHeight); 2227 width = mathMax(width, left + cloneWidth); 2228 result.append(clone); 2229 }); 2230 result.width(width).height(height); 2231 return result; 2232 } 2233 2234 2235 /* 2236 * Util scripts. 2237 */ 2238 2239 // The minVersion is specified in an array, like [1, 8, 0] for 1.8.0 2240 // Partially copy-pasted from: https://gist.github.com/dshaw/652870 2241 function minJQueryVersion(minVersion) { 2242 var version = $.fn.jquery.split("."); 2243 var length = version.length 2244 for (var a = 0; a < length; a++) { 2245 if (minVersion[a] && +version[a] < +minVersion[a]) { 2246 return FALSE; 2247 } 2248 } 2249 return TRUE; 2250 } 2251 2252 function getVendorPrefixedProperty(property, searchElement) { 2253 for (var name in searchElement) { 2254 if (endsWith(name.toLowerCase(), property.toLowerCase())) { 2255 return name; 2256 } 2257 } 2258 return FALSE; 2259 } 2260 2261 function stringTrim(str) { 2262 return str.replace(/^\s+|\s+$/g, ''); 2263 } 2264 2265 function getCSSVendorPrefix() { 2266 var property = "transition"; 2267 var styleName = getVendorPrefixedProperty(property, $("<div>")[0].style); 2268 if (styleName === FALSE) { 2269 return FALSE; 2270 } 2271 var prefix = styleName.slice(0, styleName.length - property.length); 2272 if (prefix.length != 0) { 2273 return "-" + prefix + "-"; 2274 } 2275 return ""; 2276 } 2277 2278 function endsWith(string, suffix) { 2279 return string.indexOf(suffix, string.length - suffix.length) !== -1; 2280 } 2281 2282 function getKeys(obj) { 2283 var keys = []; 2284 for (var key in obj) { 2285 keys.push(key); 2286 } 2287 return keys; 2288 } 2289 2290 // Puts the specified function in a setTimeout([function], 0); 2291 function callAsync(func) { 2292 setTimeout(func, 0); 2293 } 2294 2295 function startsWith(string, prefix) { 2296 return string.indexOf(prefix) == 0; 2297 } 2298 2299 function cloneArray(arrayToClone) { 2300 return arrayToClone.slice(); 2301 } 2302 2303 // This mutates the given array, so that it is reversed. 2304 // It also returns it. 2305 function reverseArray(array) { 2306 return [].reverse.call(array); 2307 } 2308 2309 function childrenNotAnimationClones(obj) { 2310 return obj.children().not("." + ANIMATION_CLONE_MARKER_CLASS); 2311 } 2312 2313 function objectToLowercase(obj) { 2314 var ret = {}; 2315 for (var key in obj) 2316 ret[key.toLowerCase()] = obj[key]; 2317 return ret; 2318 } 2319 2320 // Mutates and returns the array. 2321 function shuffle(array) { 2322 for (var j, x, i = array.length; i; j = parseInt(Math.random() * i), x = array[--i], array[i] = array[j], array[j] = x) { 2323 } 2324 return array; 2325 } 2326 2327 function isFunction(func) { 2328 return $.isFunction(func); 2329 } 2330 2331 function isArray(object) { 2332 return $.isArray(object); 2333 } 2334 2335 function parseInt10(num) { 2336 return parseInt(num, 10); 2337 } 2338 2339 function parseNumber(num) { 2340 return parseFloat(num); 2341 } 2342 2343 function getTimeInMillis() { 2344 return +new Date(); 2345 } 2346 2347 function mathAbs(number) { 2348 return number < 0 ? -number : number; 2349 } 2350 2351 function mathMax(a, b) { 2352 return a > b ? a : b; 2353 } 2354 2355 function mathMin(a, b) { 2356 return a < b ? a : b; 2357 } 2358 2359 var fallbackEffect = getEffectMethod("slide"); 2360 2361 function getEffectMethod(inputEffect) { 2362 if (isArray(inputEffect)) { 2363 return makeRandomEffect(inputEffect); 2364 } else if (isFunction(inputEffect)) { 2365 return inputEffect 2366 } else /* if (typeof inputEffect === "string") */{ 2367 inputEffect = stringTrim(inputEffect); 2368 if (inputEffect.indexOf(",") != -1) { 2369 var array = inputEffect.split(","); 2370 return makeRandomEffect(array); 2371 } else { 2372 var effects = objectToLowercase($.fn.sudoSlider.effects); 2373 var effectName = inputEffect.toLowerCase(); 2374 var result = effects[effectName]; 2375 if (result) { 2376 return result; 2377 } else { 2378 var array = []; 2379 for (var name in effects) { 2380 if (startsWith(name, effectName)) { 2381 array.push(effects[name]); 2382 } 2383 } 2384 if (!array.length) { 2385 return fallbackEffect; 2386 } 2387 return makeRandomEffect(array); 2388 } 2389 } 2390 } 2391 } 2392 2393 function makeRandomEffect(array) { 2394 return function (obj) { 2395 var effect = pickRandomValue(array); 2396 return getEffectMethod(effect)(obj); 2397 } 2398 } 2399 2400 function pickRandomValue(obj) { 2401 return obj[shuffle(getKeys(obj))[0]]; 2402 } 2403 2404})(jQuery, window); 2405// If you did just read the entire code, congrats. 2406// Did you find a bug? I didn't, so plz tell me if you did. (https://github.com/webbiesdk/SudoSlider/issues)
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.