PageSourceSearch

https://www.bmo-wine.com/js/jquery.sudoSlider.min.js

js bmo-wine.com collected 2026-10-06 18:37:24 UTC 92,503 bytes, 2,406 lines download raw bytes

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.