﻿/*
*  Sudo Slider ver 1.0.11 - jQuery plugin 
*  Written by Erik Kristensen info@webbies.dk. 
*  Based on Easy Slider 1.7 by Alen Grakalic http://cssglobe.com/post/5780/easy-slider-17-numeric-navigation-jquery-slider
*/
(function ($) {
    $.fn.sudoSlider = function (options) {
        if (typeof (options) != 'object' && options != '' && options) {
            // Here, i just trigger it to do something, it's way down the actual action happens. 
            this.each(function () {
                $(this).trigger("sudoSliderEvent", [options]);
            });
        }
        else {
            // default configuration properties
            var defaults = {
                prevNext: true,
                prevHtml: '',
                nextHtml: '<a href="#" class="nextBtn"><div id="nextBtn"><img src="/_layouts/images/TKI.NewsScroll/clear.png" width="300" height="300" /></div></a>',
                controlsShow: true,
                controlsAttr: 'id="controls"',
                controlsFadeSpeed: '200',
                controlsFade: true,
                insertAfter: true,
                firstShow: false,
                firstHtml: '<a href="#" class="firstBtn"></a>',
                lastShow: false,
                lastHtml: '<a href="#" class="lastBtn"></a>',
                numericAttr: 'class="controls"',
                numericText: ['1'],
                vertical: false,
                speed: '600',
                ease: 'swing',
                auto: false,
                pause: '2000',
                continuous: true,
                clickableAni: false,
                numeric: false,
                updateBefore: false,
                history: false,
                speedhistory: '400',
                autoheight: true,
                customLink: false,
                fade: false,
                crossFade: true,
                fadespeed: '1000',
                ajax: false,
                loadingText: false,
                preloadAjax: false,
                startSlide: false,
                imgAjaxFunction: false,
                docAjaxFunction: false,
                beforeAniFunc: false,
                afterAniFunc: false,
                uncurrentFunc: false,
                currentFunc: false
            };
            var options = $.extend(defaults, options);

            // To make it smaller when minimized.
            // Not including the variables only used once in the code. 
            // I just found out that this (as in now, not the same as final release) makes the script 572 bytes smaller. (That's about 6%)
            //var optionscontrolsShow = options.controlsShow; // Only used once.
            var optionscontrolsFadeSpeed = options.controlsFadeSpeed;
            //var optionscontrolsBefore = options.controlsBefore; // Only used once.
            //var optionscontrolsAfter = options.controlsAfter; // Only used once.
            var optionscontrolsFade = options.controlsFade;
            //var optionsinsertAfter = options.insertAfter;// Only used once.
            var optionsfirstShow = options.firstShow;
            var optionslastShow = options.lastShow;
            var optionsvertical = options.vertical;
            var optionsspeed = options.speed;
            var optionsease = options.ease;
            var optionsauto = options.auto;
            var optionspause = options.pause;
            var optionscontinuous = options.continuous;
            var optionsprevNext = options.prevNext;
            var optionsnumeric = options.numeric;
            var optionsnumericAttr = options.numericAttr;
            var optionsnumericText = options.numericText;
            //var optionsclickableAni = options.clickableAni; // Only used once.
            var optionshistory = options.history;
            var optionsspeedhistory = options.speedhistory;
            var optionsautoheight = options.autoheight;
            var optionscustomLink = options.customLink;
            var optionsfade = options.fade;
            var optionscrossFade = options.crossFade;
            var optionsfadespeed = options.fadespeed;
            var optionsupdateBefore = options.updateBefore;
            var optionsajax = options.ajax;
            //var optionspreloadAjax= options.preloadAjax; // Only used once.
            var optionsstartSlide = options.startSlide;
            var optionsimgAjaxFunction = options.imgAjaxFunction;
            var optionsdocAjaxFunction = options.docAjaxFunction;
            var optionsbeforeAniFunc = options.beforeAniFunc;
            var optionsafterAniFunc = options.afterAniFunc;
            var optionsuncurrentFunc = options.uncurrentFunc;
            var optionscurrentFunc = options.currentFunc;

            return this.each(function () {
                // There are some things we don't do at init. 
                var init = true; // I know it's an ugly workaround, but it works. 
                // If auto is on, so is continuous. (People tend to forget things they don't think about :p)
                if (optionsauto) optionscontinuous = true;

                // Setting up some variables. 
                var obj = $(this);

                // Fix for nested list items
                var ul = obj.children("ul");
                var li = ul.children("li");

                // Some variables i'm gonna use alot. 
                var s = li.length;
                var w = li.eq(0).width(); // All slides must be same width, so this shouldn't be a problem. 
                var h = obj.height();

                // Now we are going to fix the document, if it's 'broken'. (No <ul> or no <li>). 
                // 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. 
                if (optionsajax) {
                    // Is the ul element there?
                    if (ul.length == 0) {
                        // No it's not, lets create it. 
                        obj.append('<ul></ul>');
                        ul = obj.children("ul");
                    }

                    // Do we have enough list elements to fill out all the ajax documents. 
                    if (optionsajax.length > s) {
                        // No we dont. 
                        for (var i = 1; i <= optionsajax.length - s; i++) ul.append('<li><p>' + returnFunnyLoadingText() + '</p></li>');
                        li = ul.children("li");
                        s = li.length;
                        w = li.eq(0).width();
                    }
                }
                // i just love stackoverflow (http://stackoverflow.com/questions/182112/what-are-some-funny-loading-statements-to-keep-users-amused-closed)
                // i know this is just an easter egg, because you really should never see it. 
                // But what the heck, i want it. 
                function returnFunnyLoadingText() {
                    var funnyLoadingTexts = [
                    //"Locating the required gigapixels to render",
						"Spinning up the hamster",
                    //"&pi; &times; 1337% == 42",
                    //"&pi; &times; 1337% != 42!",
                    //"Shovelling coal into the server",
						"Programming the flux capacitor",
                    //"The last time I tried this the monkey didn't survive",
						"Testing data on Timmy... ... ... We need another Timmy",
                    //"I should have had a V8 this morning",
                    //"My other load screen is much faster. You should try that one instead",
                    //"The version I have of this in testing has much funnier load screens",
						"Warming up Large Hadron Collider",
						"It looks like you're waiting for something to load"
					];
                    return options.loadingText ? options.loadingText : (funnyLoadingTexts[Math.round(Math.random() * (funnyLoadingTexts.length - 1))] + '...');
                };


                // Continuing with the variables. 
                var t = 0;
                var ot = t;
                var nt = t;
                var ts = s - 1;

                var clickable = true;
                var buttonclicked = false;
                var fading = false;
                var ajaxloading = false;
                var autoheightdocument = 0;
                var numericControls = new Array();
                var numericContainer = false;
                var destroyed = false;

                // Set obj overflow to hidden (and position to relative <strike>, if fade is enabled. </strike>)
                obj.css("overflow", "hidden");
                if (obj.css("position") == "static") obj.css("position", "relative"); // Fixed a lot of IE6 + IE7 bugs. 

                // Float items to the left
                li.css('float', 'left');

                // They doens't always put a text in the numericText. 
                // With this, if the user dont, the code will. 
                for (var i = 0; i < s; i++) {
                    if (optionsnumericText[i] == undefined) optionsnumericText[i] = (i + 1);
                    // Same thing for ajax thingy. 
                    if (optionsajax && optionsajax[i] == undefined) optionsajax[i] = false;
                }

                // Clone elements for continuous scrolling
                if (optionscontinuous) {
                    if (optionsvertical) {
                        // First we create the elements, pretending AJAX is a city in Russia. 
                        ul.prepend(li.filter(":last-child").clone().css("margin-top", "-" + h + "px"));
                        ul.append(li.filter(":nth-child(2)").clone());
                        ul.height((s + 1) * h);
                    } else {
                        // First we create the elements, pretending AJAX is a city in Russia. 
                        ul.prepend(li.filter(":last-child").clone().css("margin-left", "-" + w + "px"));
                        ul.append(li.filter(":nth-child(2)").clone());
                        ul.width((s + 1) * w);
                    }
                    // Now, lets check if AJAX really is a city in Russia.
                    if (optionsajax) {
                        // Now we move from Russia back to reallity (nothing bad about the Russians, it's just a saying in Denmark.)
                        // Starting with putting the first document after the last. 
                        if (optionsajax[0]) {
                            ajaxLoad('last', 0, false, 0);
                            // ajaxLoad(0, 0, false, 0); //And this would just be a waste of brandwith. 
                        }
                        // And putting the last document before the first. 
                        if (optionsajax[s - 1]) {
                            ajaxLoad('first', (s - 1), false, 0);
                            // And then preloading the last document (the same document, but into it's entended position). No need to preload the first slide, it gets loaded elsewhere. 
                            ajaxLoad(ts, ts, false, 0);
                            optionsajax[s - 1] = false;
                        }
                    }
                }
                else // <strike>Bug fix</strike> feature.
                {
                    if (optionsvertical) ul.height(s * h);
                    else ul.width(s * w);
                };

                // Display the controls.
                if (options.controlsShow) {
                    var controls = $('<span ' + options.controlsAttr + '></span>');
                    if (options.insertAfter) $(obj).after(controls);
                    else $(obj).before(controls);

                    var html = options.controlsBefore;
                    if (optionsnumeric) {
                        numericContainer = controls.prepend('<ol ' + optionsnumericAttr + '></ol>').children();
                        for (var i = 0; i < s; i++) {
                            numericControls[i] = $(document.createElement("li"))
							.attr({ 'rel': (i + 1) })
							.html('<a href="#"><span>' + optionsnumericText[i] + '</span></a>')
							.appendTo(numericContainer)
							.click(function () {
							    goToSlide($(this).attr('rel') - 1, true);
							    return false;
							});
                        };
                    }
                    if (optionsfirstShow) {
                        var firstbutton = makecontrol(options.firstHtml, "first");
                    }
                    if (optionslastShow) {
                        var lastbutton = makecontrol(options.lastHtml, "last");
                    }
                    if (optionsprevNext) {
                        var nextbutton = makecontrol(options.nextHtml, "next");
                        var prevbutton = makecontrol(options.prevHtml, "prev");
                    }
                };

                // Preload elements. 
                if (options.preloadAjax) {
                    for (var i = 0; i <= ts; i++) // Preload everything.
                    {

                        if (optionsajax[i]) {
                            // If somethings is to be loaded, lets load it. 
                            ajaxLoad(i, i, false, 0);
                            // Making sure it aint loaded again. 
                            optionsajax[i] = false;
                        }
                    }
                }

                function goToSlide(i, clicked) {
                    if (!destroyed) {
                        if (optionsfade) {
                            fadeto(i, clicked);
                        } else {
                            animate(i, clicked, true);
                        }
                    }
                };
                // I go a long way to save lines of code. 
                function makecontrol(html, action) {
                    var button = $(html);
                    controls.prepend(button);
                    button.click(function () {
                        goToSlide(action, true);
                        return false;
                    });
                    return button;
                }

                // Lets make those fast/normal/fast into some numbers we can make calculations with.
                optionscontrolsFadeSpeed = textSpeedToNumber(optionscontrolsFadeSpeed);
                optionsspeed = textSpeedToNumber(optionsspeed);
                optionspause = textSpeedToNumber(optionspause);
                optionsspeedhistory = textSpeedToNumber(optionsspeedhistory);
                optionsfadespeed = textSpeedToNumber(optionsfadespeed);
                // The functions do the magic.
                function textSpeedToNumber(speed) {
                    if (parseInt(speed)) var returnspeed = parseInt(speed);
                    else {
                        switch (speed) {
                            case 'fast':
                                var returnspeed = 200;
                                break;
                            case 'normal':
                                var returnspeed = 400;
                                break;
                            case 'medium':
                                var returnspeed = 400;
                                break;
                            case 'slow':
                                var returnspeed = 600;
                                break;
                            default:
                                var returnspeed = 400;
                        }
                    }
                    return returnspeed;
                };
                function runOnImagesLoaded(e, _cb) {
                    // This function is based on the onImagesLoaded plugin by soundphed, that was in a comment on this page "http://engineeredweb.com/blog/09/12/preloading-images-jquery-and-javascript#comment-92". 
                    e.each(function () {
                        var $imgs = (this.tagName.toLowerCase() === 'img') ? $(this) : $('img', this),
						_cont = this,
						i = 0,
						_done = function () {
						    if (typeof _cb === 'function') _cb(_cont);
						};

                        if ($imgs.length) {
                            $imgs.each(function () {
                                var _img = this,
								_checki = function (e) {
								    if ((_img.complete) || (_img.readyState == 'complete' && e.type == 'readystatechange')) {
								        if (++i === $imgs.length) _done();
								    }
								    else if (_img.readyState === undefined) // dont for IE
								    {
								        $(_img).attr('src', $(_img).attr('src')); // re-fire load event
								    }
								}; // _checki \\
                                $(_img).bind('load readystatechange', function (e) { _checki(e); });
                                _checki({ type: 'readystatechange' }); // bind to 'load' event...
                            });
                        } else _done();
                    });
                };

                // Is the file a image? (This function is not only used in the Ajaxload function)
                function imageCheck(file) {
                    var image = false;

                    var len = file.length;
                    var ext = file.substr(len - 4, 4);

                    if (ext == '.jpg' || ext == '.png' || ext == '.bmp' || ext == '.gif') {
                        image = true;
                    }
                    var ext = file.substr(len - 5, 5);
                    if (ext == '.jpeg') {
                        image = true;
                    }

                    return image;
                }
                function fadeControl(fadeOpacity, fadetime, nextcontrol) {
                    if (nextcontrol) {
                        var eA = nextbutton;
                        var eB = lastbutton;
                        var directionA = 'next';
                        var directionB = 'last';
                        var firstlastshow = optionslastShow;
                    }
                    else {
                        var eA = prevbutton;
                        var eB = firstbutton;
                        var directionA = 'prev';
                        var directionB = 'first';
                        var firstlastshow = optionsfirstShow;
                    }
                    if (!optionscontinuous) {
                        if (optionsprevNext) eA.fadeTo(fadetime, fadeOpacity, function () { if (fadeOpacity == 0) $(this).hide(); });
                        if (firstlastshow) eB.fadeTo(fadetime, fadeOpacity, function () { if (fadeOpacity == 0) $(this).hide(); });
                        if (optionscustomLink) {
                            $(optionscustomLink)
							.filter(function (index) {
							    return ($(this).attr("rel") == directionA || $(this).attr("rel") == directionB);
							})
							.fadeTo(fadetime, fadeOpacity, function () { if (fadeOpacity == 0) $(this).hide(); });
                        }
                    }
                };
                // Fade the controls, if we are at the end of the slide. 
                // It's all the different kind of controls. 
                function fadeControls(a, fadetime) {
                    if (a == 0) fadeControl(0, fadetime, false);
                    else fadeControl(1, fadetime, false);

                    if (a == ts) fadeControl(0, fadetime, true);
                    else fadeControl(1, fadetime, true);
                };



                // Updating the 'current' class
                function setCurrent(i) {
                    i = parseInt((i > ts) ? i = 0 : ((i < 0) ? i = ts : i)) + 1;
                    for (var a = 0; a < numericControls.length; a++) setCurrentElement(numericControls[a], i);
                    if (optionscustomLink) setCurrentElement(optionscustomLink, i);
                };
                function setCurrentElement(element, i) {
                    $(element)
						.filter(".current")
						.removeClass("current")
						.each(function () {
						    if ($.isFunction(optionsuncurrentFunc)) { optionsuncurrentFunc.call(this, $(this).attr("rel")); }
						});
                    $(element)
						.filter(function () {
						    return $(this).attr("rel") == i;
						})
						.addClass("current")
						.each(function (index) {
						    if ($.isFunction(optionscurrentFunc)) { optionscurrentFunc.call(this, i); }
						});
                };
                // Find out wich numericText fits the current url. 
                function filterUrlHash(t) {
                    var te = 0;
                    for (var i = 0; i <= s; i = i + 1) if (optionsnumericText[i] == t) te = i;
                    return te;
                };
                // Automaticly adjust the height, i love this function. 
                function autoheight(i, speed) {
                    if (i == s) i = 0;
                    // First i run it. In case there are no images. 
                    var target = li.eq(i);
                    var nheight = target.height();
                    if (nheight != 0) setHeight(nheight, speed);
                    // Then i run it again after the images has been loaded. (If any)
                    runOnImagesLoaded(target, function (imgtarget) {
                        nheight = $(imgtarget).height();
                        if (nheight != 0) setHeight(nheight, speed);
                    });
                };
                function setHeight(nheight, speed) {
                    obj.animate(
						{ height: nheight },
						{
						    queue: false,
						    duration: speed,
						    easing: optionsease
						}
					);
                };
                // When the animation finishes (fade or sliding), we need to adjust the slider. 
                function adjust() {
                    if (t > ts) t = 0;
                    if (t < 0) t = ts;
                    if (!optionsupdateBefore) setCurrent(t);
                    if (optionsvertical) ul.css("margin-top", (t * h * -1));
                    else ul.css("margin-left", (t * w * -1));
                    clickable = true;
                    if (optionshistory && buttonclicked) window.location.hash = optionsnumericText[t];
                    if (!fading) {
                        // Lets run the after animation function.
                        if ($.isFunction(optionsafterAniFunc)) { optionsafterAniFunc.call(li.eq(t), t + 1); }
                    }
                };
                // Convert the direction into a usefull number.
                function filterDir(dir, ot) {
                    var nt = t; // i dont want to mess with the 't' variable.
                    switch (dir) {
                        case "next":
                            nt = (ot >= ts) ? (optionscontinuous ? nt + 1 : ts) : nt + 1;
                            break;
                        case "prev":
                            nt = (t <= 0) ? (optionscontinuous ? nt - 1 : 0) : nt - 1;
                            break;
                        case "first":
                            nt = 0;
                            break;
                        case "last":
                            nt = ts;
                            break;
                        default:
                            nt = parseInt(dir);
                            break;
                    };
                    return nt;
                };
                // Load a ajax document (or i image) into a list element. 
                // If testing this locally (loading everything from a harddisk instead of the internet), it may not work. 
                // But then try to upload it to a server, and see it shine. 
                function ajaxLoad(i, l, adjust, speed) {
                    var targetslide = false;
                    if (parseInt(i) || i == 0) targetslide = li.eq(i);
                    else {
                        if (i == 'last') targetslide = $('li:last', obj);
                        else targetslide = $('li:first', obj);
                    }
                    // What speed should the autoheight function animate with?
                    var ajaxspeed = (fading) ? (!optionscrossFade ? parseInt(optionsfadespeed * (2 / 5)) : optionsfadespeed) : speed;
                    // The script itself is not using the 'tt' variable. But a custom function can use it. 
                    var tt = l + 1;
                    if (imageCheck(optionsajax[l])) {
                        // Load the image.
                        targetslide.html(' ').append($(new Image()).attr('src', optionsajax[l]));
                        // When the document is ready again, we launch a autoheight event. 
                        runOnImagesLoaded(targetslide, function (img) {
                            var target = $(img).children();
                            // If the image is to wide, shrink it. 
                            var width = target.width();
                            var height = target.height();
                            target.attr({ 'oldheight': height, 'oldwidth': width });
                            if (width > w) target.animate({ width: w, height: (height / width) * w }, 0);
                            // If we want, we can launch a function here. 
                            if ($.isFunction(optionsimgAjaxFunction)) { optionsimgAjaxFunction.call($(img), tt); }
                            // Then do the autoheight.
                            if (optionsautoheight && adjust) autoheight(t, ajaxspeed);
                        });
                    }
                    else {

                        // Load the document into the list element. 
                        targetslide.load(optionsajax[l], function (response, status, xhr) {
                            if (status == "error" || !$(this).html()) $(this).html("Sorry but there was an error: " + (xhr.status ? xhr.status : 'no content') + " " + xhr.statusText);
                            // If we want, we can launch a function here. 
                            if (status != "error" && $.isFunction(optionsdocAjaxFunction)) { optionsdocAjaxFunction.call($(this), tt); }
                            // Lets adjust the height, i don't care if there's an error or not. 
                            var nheight = $(this).height();
                            if (optionsautoheight && adjust) autoheight(l, ajaxspeed);
                        });
                    }
                };
                // It's not only a slider, it can also fade from slide to slide. 
                function fadeto(i, clicked) {
                    if (i != t && !destroyed) // We doesn't want something to happen all the time. The URL can change a lot, and cause som "flickering". 
                    {
                        if (clickable) {
                            ajaxloading = false;
                            // Stop auto if cliked.
                            if (clicked) clearTimeout(timeout);
                            // Update the current class of the buttons. 
                            if (optionsupdateBefore) setCurrent(filterDir(i, ot));
                            // Only clickable if not clicked.
                            clickable = !clicked;
                            // Setting the speed. 
                            var speed = (!clicked && !optionsauto && optionshistory) ? optionsfadespeed * (optionsspeedhistory / optionsspeed) : optionsfadespeed;
                            var ll = filterDir(i, ot);
                            // Lets make sure that the target actually exists. 
                            if (ll > ts) ll = 0;
                            if (ll < 0) ll = ts;
                            // Lets make sure the prev/next buttons also fade. 
                            if (optionscontrolsFade) fadeControls(ll, optionscontrolsFadeSpeed);
                            // Lets adjust the height, but not if the ajax document isn't loaded. 
                            if (optionsautoheight) {
                                if (optionsajax) {
                                    // If Ajax is enabled
                                    if (!optionsajax[ll]) autoheight(ll, optionsfadespeed); // we only want to change the height, if the document we are fading to, is allready loaded.
                                }
                                else autoheight(ll, optionsfadespeed); // The height animation takes the full lenght of the fade animation (fadein + fadeout if it's not crossfading).  
                            }
                            // Define the target. 
                            var target = li.eq(ll);
                            // So lets run the function.
                            if ($.isFunction(optionsbeforeAniFunc)) { optionsbeforeAniFunc.call(target, ll + 1); }
                            // Crossfading?
                            if (optionscrossFade) {
                                // I clone the target, and fade it in, then hide the cloned element while adjusting the slider to show the real target.
                                // I dont hide it right away, because that breaks the autoheight function, and the function that auto-resizes ajax-loaded images.
                                var fadeIntarget = target.clone().prependTo(obj).css({ 'z-index': '100000', 'position': 'absolute', 'list-style': 'none', 'top': '0', 'left': '0' });
                                // Maybe we need to load some content into it first?
                                if (optionsajax[ll]) {
                                    // I have to load the Ajax-content into the target clone, and the target itself. 
                                    // First the target clone.
                                    ajaxLoad(0, ll, false, speed);
                                    // Then the target.
                                    if (imageCheck(optionsajax[ll])) // Weird bugs, weird fixes. But this works. 
                                    {
                                        ajaxLoad(ll + 1, ll, false, speed);
                                        runOnImagesLoaded(li.eq(ll + 1), function () {
                                            if (optionsautoheight) autoheight(ll, optionsfadespeed);
                                        });
                                    }
                                    else {
                                        ajaxLoad(ll + 1, ll, true, speed);
                                    }
                                    optionsajax[ll] = false;
                                }
                                // Lets fade it in. 
                                fadeIntarget.hide().fadeIn(optionsfadespeed, function () {
                                    // So the animate function knows what to do. 
                                    clickable = true;
                                    fading = true;
                                    animate(i, false, false); // Moving to the correct place.
                                    // Removing it again, if i dont, it will just be a pain in the ....
                                    $(this).remove();
                                    if (optionshistory && clicked) window.location.hash = optionsnumericText[t]; // It's just one line of code, no need to make a function of it. 
                                    // Lets put that variable back to the default (and not during animation) value. 
                                    fading = false;
                                    // Now run that after animation function.
                                    // We already got the target and the slider number from earlier.
                                    // So lets run the function.
                                    if ($.isFunction(optionsafterAniFunc)) { optionsafterAniFunc.call(target, ll + 1); }
                                });
                            }
                            else {
                                // fadeOut and fadeIn.
                                var fadeinspeed = parseInt((speed) * (3 / 5));
                                var fadeoutspeed = speed - fadeinspeed;
                                // I set the opacity to something higher than 0, because if it's 0, the content that i try to read (to make the autoheight work etc.) aint there.
                                obj.children().fadeTo(fadeoutspeed, 0.00001, function () {
                                    // So the animation function knows what to do. 
                                    clickable = true;
                                    fading = true;
                                    animate(i, false, false); // Moving to the correct place.
                                    // Only clickable if not clicked.
                                    clickable = !clicked;
                                    // Now, lets fade the slider back in. 
                                    obj.children().fadeTo(fadeinspeed, 1, function () {
                                        if (optionshistory && clicked) window.location.hash = optionsnumericText[t]; // It's just one line of code, no need to make a function of it. 
                                        clickable = true;
                                        fading = false;
                                        // Now run that after animation function.
                                        // We already got the target and the slider number from earlier.
                                        // So lets run the function.
                                        if ($.isFunction(optionsafterAniFunc)) { optionsafterAniFunc.call(target, ll + 1); }
                                    });
                                });
                            }
                        }
                    }
                };
                function animate(dir, clicked, time) // (Direction, did the user click something, is this to be done in >1ms?) 
                {
                    if (clickable && !destroyed) {
                        ajaxloading = false;
                        clickable = (!clicked && !optionsauto) ? true : options.clickableAni;
                        // to the adjust function. 
                        buttonclicked = clicked;
                        ot = t;
                        t = filterDir(dir, ot);
                        if (optionsupdateBefore) setCurrent(t);
                        // Calculating the speed to do the animation with. 
                        var diff = Math.sqrt(Math.abs(ot - t));
                        var speed = parseInt(diff * optionsspeed);
                        if (!clicked && !optionsauto) speed = parseInt(diff * optionsspeedhistory); // Auto:true and history:true doens't work well together, and they ain't supposed to. 
                        if (!time) speed = 0;

                        // Ajax begins here 
                        // I also these variables in the below code (running custom function).
                        var i = t;
                        if (t > ts) i = 0;
                        if (t < 0) i = ts;
                        if (optionsajax) {
                            // Loading the target slide, if not already loaded. 
                            if (optionsajax[i]) {
                                ajaxLoad(i, i, true, speed);
                                optionsajax[i] = false;
                                ajaxloading = true;
                            }
                            // It can look stupid the script scroll over some not-loaded slides. Therefore, they are loaded. 
                            // It can produce some heavy load, so the script wont do it, it it's more than 10 slides.
                            if (!fading) {
                                // I dont like copypasting the same code, but this is the most efficient way i can think of atm. 
                                var countajax = 0;
                                if (ot > t) {
                                    for (a = t; a <= ot; a++) {
                                        if (a <= ts && a >= 0) {
                                            if (optionsajax[a]) {
                                                ajaxLoad(a, a, false, speed);
                                                optionsajax[a] = false;
                                                countajax++;
                                            }
                                        }
                                        if (countajax == 10) a = ot;
                                    }
                                }
                                else {
                                    for (a = ot; a <= t; a++) {
                                        if (a <= ts && a >= 0) {
                                            if (optionsajax[a]) {
                                                ajaxLoad(a, a, false, speed);
                                                optionsajax[a] = false;
                                                countajax++;
                                            }
                                        }
                                        if (countajax == 10) a = t;
                                    }
                                }
                            }
                            // Then we have to preload the next one. 
                            if ((i + 1 <= ts) && !init) {
                                if (optionsajax[i + 1]) {
                                    ajaxLoad(i + 1, i + 1, false, 0);
                                    optionsajax[i + 1] = false;
                                }
                            }
                            // And the previous one. 
                            if (i - 1 >= 0 && !init) {
                                if (optionsajax[i - 1]) {
                                    ajaxLoad(i - 1, i - 1, false, 0);
                                    optionsajax[i - 1] = false;
                                }
                            }
                        }
                        // Ajax ends here
                        if (!fading) {
                            // Lets run the before animation function.
                            if ($.isFunction(optionsbeforeAniFunc)) {
                                optionsbeforeAniFunc.call(li.eq(i), i + 1);
                                if (t == -1 || t == s) optionsbeforeAniFunc.call(ul.children("li").eq((t == -1) ? 0 : -1), i + 1);
                            }

                        }
                        // Start animation. 
                        if (!optionsvertical) {
                            if (optionsautoheight && !fading && !ajaxloading) autoheight(t, speed);
                            p = (t * w * -1);
                            ul.animate(
								{ marginLeft: p },
								{
								    queue: false,
								    duration: speed,
								    easing: optionsease,
								    complete: adjust
								}
							);
                        } else {
                            p = (t * h * -1);
                            ul.animate(
								{ marginTop: p },
								{
								    queue: false,
								    duration: speed,
								    easing: optionsease,
								    complete: adjust
								}
							);
                        };
                        // End animation. 

                        // Fading the next/prev/last/first controls in/out if needed. 
                        if (optionscontrolsFade) {
                            var fadetime = optionscontrolsFadeSpeed;
                            if (!clicked && !optionsauto) fadetime = (optionsspeedhistory / optionsspeed) * optionscontrolsFadeSpeed;
                            if (!time) fadetime = 0;
                            if (fading) fadetime = parseInt((optionsfadespeed) * (3 / 5));
                            fadeControls(t, fadetime);
                        }

                        // Stopping auto if clicked. 
                        if (clicked) clearTimeout(timeout);
                        // Continuing if not clicked.
                        if (optionsauto && dir == "next" && !clicked) {
                            timeout = startAuto(optionspause + optionsspeed);
                        };
                    };
                };
                // init
                var timeout;

                // Starting auto. 
                if (optionsauto) {
                    timeout = startAuto(optionspause);
                };
                function startAuto(pause) {
                    return setTimeout(function () {
                        goToSlide("next", false);
                    }, pause);
                }
                if (optionscustomLink) // customLinks. Easy to make, great to use. 
                {
                    // Using live, that way javascript ajax-loaded buttons and javascript generated content will work.
                    $(optionscustomLink).live('click', function () { //høns
                        var a = $(this).attr('rel');
                        if (a) doExternalInput(a);
                        return false;
                    });
                }
                obj.bind('sudoSliderEvent', function (e, a) {
                    doExternalInput(a);
                });
                function doExternalInput(a) {
                    // Check for special events
                    if (a == 'stop') clearTimeout(timeout)
                    else if (a == 'start') {
                        timeout = startAuto(optionspause);
                        optionsauto = true;
                    }
                    else if (a == 'block') clickable = false;
                    else if (a == 'unblock') clickable = true;
                    else if (a == 'action') alert('The slider just performed an action');
                    else if (a == 'destroy') {
                        // First, i remove the controls. 
                        controls.remove(); // that's it.
                        // Now to set a variable, so nothing is run. 
                        destroyed = true; // No animation, no fading, no clicking from now. 
                        // Then remove the customLink bindings:
                        $(optionscustomLink).die("click");
                        // Now remove the "continuous clones". 
                        if (optionscontinuous) {
                            ul.children("li").eq(0).remove();
                            ul.children("li").eq(-1).remove();
                        }
                    }
                    // The general case. 
                    // That means, typeof(a) == numbers and first,last,next,prev
                    // I dont make any kind of input validation, meaning that it's quite easy to break the script with non-valid input. 
                    else if (clickable) goToSlide((a == parseInt(a)) ? a - 1 : a, true);
                };
                // Done.
                init = false; //nasty workaround, but it works. 


                // Lets make those bookmarks and back/forward buttons work. 
                if (optionshistory) {
                    // Going to the correct slide at load. 
                    $.address.init(function (e) {
                        var i = filterUrlHash(e.value);
                        animate(i, false, false);
                    })
                    // Sliding/fading to the correct slide, on url change. 
					.change(function (e) {
					    var i = filterUrlHash(e.value);
					    if (i != t) goToSlide(i, false);
					});
                }
                // The startSlide setting only require one line of code. And here it is:
                else if (optionsstartSlide) animate(optionsstartSlide - 1, false, false);
                // doing it anyway. good way to fix bugs. 
                // And i only preload the next and previous slide after init (which this is). So i'm doing it. 
                // + if i didn't do this, a lot of things wouldn't happen on page load. By always animating, i ensure that everthing that's supposed to happen, do happen. 
                else animate(0, false, false);
            });
        }
    };
})(jQuery);
