/*
 * Polaris Articles Slider.
 * Polaris Attachments Slider.
 * Polaris Nivo Slider.
 * Author: Erlend Heiberg, Roar Stette - Adresseavisen(Polarismedia)
 *
 * Based on:  
 * jQuery Nivo Slider v2.4
 * http://nivo.dev7studios.com
 *
 * Copyright 2011, Gilbert Pellegrom
 * Free to use and abuse under the MIT license.
 * http://www.opensource.org/licenses/mit-license.php
 * 
 * May 2010 - Pick random effect from specified set of effects by toronegro
 * May 2010 - controlNavThumbsFromRel option added by nerd-sh
 * May 2010 - Do not start nivoRun timer if there is only 1 slide by msielski
 * April 2010 - controlNavThumbs option added by Jamie Thompson (http://jamiethompson.co.uk)
 * March 2010 - manualAdvance option added by HelloPablo (http://hellopablo.co.uk)
 */

(function($) {
	
	/* POLARIS ARTICLES */
	$.polarisCarouselArticles = function(node, autoplay) {
                
		// Adjust margin on numberlist items
		var numberListWidth = $(node + ' .numberList').width();
		var numberListItems = $(node + ' .numberList li').length;
		var numberListItemWidth = $(node + ' .numberList li').width();
		
		var numberListItemMargin = Math.floor((numberListWidth - (numberListItems * numberListItemWidth)) / (numberListItems - 1));
		if (numberListItemMargin < 1)
		{
			numberListItemMargin = 1; // Minimum margin between items
		}
		if (numberListItemMargin > 30)
		{
			numberListItemMargin = 30; // Maximum margin between items
		}
		var unusedWidth = numberListWidth - ((numberListItems-1) * numberListItemMargin) - (numberListItems * numberListItemWidth);
		if (unusedWidth < 0)
		{
			unusedWidth = 0; // Should never be a negative value
		}

		// Set new left margin on all items
		$(node + ' .numberList li').css(
			{
				marginLeft: numberListItemMargin,
				marginRight: 0
			}
		);
		// Set left margin on first item to half the unused width
		$(node + ' .numberList li:first').css('marginLeft', Math.floor(unusedWidth/2));
		$(node + '.numberList').animate({opacity: 1},1000);

		$(node + ' .carouselWrapper').scrollable({next:'.next', prev:'.prev', circular: true, keyboard: true, items: '.scrollable'}).autoscroll({autopause: autoplay, autoplay: autoplay}); 				
		var api = $(node + ' .carouselWrapper').data('scrollable');
		api.onSeek(function() {
			var position = api.getIndex();
			var size = api.getSize();

			//for index overlay
            $(node + ' .index').html(position+1 + ' / ' + size);

			//for tabs overlay
			$(node + ' ul.numberList').find('a.current').removeClass('current');
			$(node + ' ul.numberList li').each(function(index){
				if (index == position) {
					$(this).find('a').addClass('current');
				}
			});
		}); 
		if (autoplay) {
			$(node + ' .carouselWrapper').hover(
				function(){	api.pause(); },	
				function(){	api.play();	}
			);
		}

		$(node + ' ul.numberList li a').click(function(){
			api.pause();
			var clickedIndex = parseInt($(this).attr('rel'))-1;
			api.seekTo(clickedIndex);
		});
	}
	
	
	/* POLARIS ATTACHMENTS */
	$.polarisCarouselAttachments = function(node ,showThumbnails) {
		var api;
		var thumbs_api;
		var stopRecursion = false;
		var thumbIndex;
	
		$(node + ' .carouselWrapper').scrollable({next:'.next', prev:'.prev', circular: false, keyboard: 'static', items: '.scrollable'}); 
		api = $(node + " .carouselWrapper").data("scrollable");	
		var currentSlideCaption = $(node + ' #slide0').find('.caption').html();
		$(node + " div.caption").html(currentSlideCaption);

		if (showThumbnails) {
			$(node + ' .thumbs').scrollable({next:'.nextThumbNot', prev:'.prevThumbNot',circular: false, keyboard:false, items: '.thumbsScrollable'}); 
			
			thumbs_api = $(node + ' .thumbs').data('scrollable');		
			thumbs_api.onSeek(function() {
				thumbIndex = this.getIndex();
			});
			thumbs_api.seekTo(0);
			
			$(node + ' .thumbs .slide').click(function(){	
				$(this).siblings().removeClass('active');
				$(this).addClass('active');					
				var clickedIndex = ($(this).attr('id')).substr(5);	
				var thumbIndex = thumbs_api.getIndex();
				var viewIndex = clickedIndex - thumbIndex + 1;

				if (!stopRecursion) {
					api.seekTo(clickedIndex,0);				
				}
				//console.log("viewindex:" + viewIndex + ", thumbIndex:" + thumbIndex + "apiindex:"  + thumbs_api.getSize());
				if (viewIndex==1) {
					if (thumbIndex == 1) {	
						thumbs_api.seekTo(0);				
					}
					if (thumbIndex >= 2) {	
						thumbs_api.seekTo(thumbIndex-2);	
					}
				}
				if (viewIndex==2) {
					thumbs_api.seekTo(thumbIndex-1);	
				}
				if (viewIndex==4) {
					if (thumbIndex < thumbs_api.getSize()-5) {
						thumbs_api.seekTo(thumbIndex+1);	
					}
				}				
				if (viewIndex==5) {
					if (thumbIndex < thumbs_api.getSize()-6) {					
						thumbs_api.seekTo(thumbIndex+2);						
					} else if (thumbIndex < thumbs_api.getSize()-5) {			
						thumbs_api.seekTo(thumbIndex+1);													
					}
				}
				stopRecursion = false;
			});			

			$(node + ' .thumbs').find('.nextThumb').click(function() {
				thumbIndex = thumbs_api.getIndex();
				if (thumbIndex <= thumbs_api.getSize()-10) {
					thumbs_api.move(5);					
				} else if (thumbIndex <= thumbs_api.getSize()-5) {
					thumbs_api.seekTo(thumbs_api.getSize()-5);					
				} 
			});
			$(node + ' .thumbs').find('.prevThumb').click(function() {
				if (thumbIndex >= 5) {
					thumbs_api.move(-5);					
				} else {
					thumbs_api.seekTo(0);
				}
			});			
		}

		api.onSeek(function() {
			var position = api.getIndex();
			var size = api.getSize();
			var thumbIndex = thumbs_api.getIndex();
			var currentThumb = $(node + ' #thumb' + position);
			$(currentThumb).siblings().removeClass('active');
			$(currentThumb).addClass('active');					
			stopRecursion = true;

			//update caption
			var currentSlideCaption = $(node + ' #slide' + position).find('.caption').html();
			$(node + ' div.caption').html(currentSlideCaption);

			//for index overlay
			$(node + " .index").html(position+1 + ' / ' + size);
			//for tabs overlay
			$(node + ' ul.numberList').find('a.current').removeClass('current');
			$(node + ' ul.numberList li').each(function(thumbIndex){
				if (thumbIndex == position) {
					$(this).find('a').addClass('current');
				}
			});
			$(currentThumb).trigger('click');
		});
	}
	
	/* POLARIS NIVO SLIDER */
    var NivoSlider = function(element, options){
        
        var debug = false; 
        
        // Output to console if possible, else use alert
        function trace(msg, meta)
        {
            if (debug)
            {
                if (typeof(meta) !== 'undefined')
                {
                    meta = meta + ': '; 
                }
                else
                {
                    meta = '';  
                }
                if (this.console && typeof console.log !== 'undefined')
                {
                    console.log(meta + msg);
                }
                else
                {
                    alert(meta + msg);
                }
            }
        }
        
        //Defaults are below
        var settings = $.extend({}, $.fn.nivoSlider.defaults, options);
        //Useful variables. Play carefully.
        var vars = {
            isInit: true,
            currentSlide: 0,
            currentImage: '',
            totalSlides: 0,
            randAnim: '',
            running: false,
            paused: true,
            stop: false,
            thumbStyle: '',
            currentTotalSlides: 0,
            currentTotalThumbs: 0,
            thumbWidth: '',
            thumbRows: []
        };
        
        /************************************************************
        ***** Set div contexts to be used with jQuery-selectors *****
        ************************************************************/
        //Get this slider
        var slider = $(element).find('.slider');
        slider.data('nivo:vars', vars);
        slider.css('position', 'relative');
        
        //Set caption context
        var captionContext = $(element).find('.caption');
        
        //Set thumbnail context
        var thumbContext = $(element).find('.thumbnails');
          
        /*******************************************************************************************************
        ***** Set calculated CSS for the "container"-elements (.slideshow, .slider, .caption, .thumbnails) *****
        *******************************************************************************************************/
        //Set slideshow container CSS
        var containerWidth = $(element).width();
        $(element).css(
            {
                'background': 'url('+settings.backgroundImage+') no-repeat',
                'backgroundColor': settings.backgroundColor
            }
        );

        //Set .slider CSS
        var sliderMargins = getMargins(slider);
        //Default width/height-ratio
        var widthDim = 3;
        var heightDim = 2;
        //If image format is set to 'wide' (16:9)
        if (settings.format == 'wide')
        {
            var widthDim = 16;
            var heightDim = 9;
        }
        //If image format is set to auto, calculate best fit. Currently only 16:9 and 3:2 supported. 
        else if (settings.format == 'auto')
        {
            var numOfSlides = settings.images.slides.length;
            var counterDefault = 0;
            var counterWide = 0;
            for( var j = 0; j < numOfSlides; j++ )
            {
                var tempRelation = settings.images.slides[j].width/settings.images.slides[j].height;
                if (((tempRelation - (3/2)) / 2) > (((16/9)-(3/2)) / 2))
                {
                    counterWide++;
                }
                else 
                {
                    counterDefault++;
                }
            }
            if (counterWide > (numOfSlides / 2))
            {
                var widthDim = 16;
                var heightDim = 9;
            }
        }
        slider.css(
            {
                'height': Math.floor((slider.width()/widthDim)*heightDim),
                'margin': sliderMargins.top+'px '+sliderMargins.right+'px '+sliderMargins.bottom+'px '+sliderMargins.left+'px',
                'width' : (containerWidth - sliderMargins.left - sliderMargins.right)+'px'
            }
        );
        
        //Set .caption CSS
        var captionMargins = getMargins(captionContext);
        captionContext.css(
            {
                'margin': captionMargins.top+'px '+captionMargins.right+'px '+captionMargins.bottom+'px '+captionMargins.left+'px',
                'width': (containerWidth - captionMargins.left - captionMargins.right)+'px'
            }
        );
        
        //Set .thumbnails CSS
        var thumbnailsMargins = getMargins(thumbContext);
        thumbContext.css(
            {
                'margin': thumbnailsMargins.top+'px '+thumbnailsMargins.right+'px '+thumbnailsMargins.bottom+'px '+thumbnailsMargins.left+'px',
                'width': (containerWidth - thumbnailsMargins.left - thumbnailsMargins.right)+'px'
            }
        );
        
        /******************************************
        ***** Set all initial variable values *****
        *******************************************/
        //Set total number of slides based on JSON-input (settings.images object)
        vars.totalSlides = settings.images.slides.length;
        
        //Set default startslide value
        var startSlide = 0;
        
        //If url contains hash, check if the characters behind the # is an integer. 
        //If it is and this int is smaller than the total number of slides, use int as startSlide.
        if (window.location.hash)
        {
            //Create array with the chars behind #
            var postHash = window.location.hash.replace('#','').split('');
            var newStartSlide = '';
            //For each char, if int -> append to newStartSlide
            for( i in postHash)
            {
                if ( !isNaN(postHash[i]) ) 
                {
                    newStartSlide += postHash[i];
                }
                else break;
            }
            //If newStartSlide !empty and in the interval [0, total number of slides] replace original startSlide
            if (newStartSlide != '')
            {
                if ( newStartSlide > -1 && newStartSlide < vars.totalSlides) 
                {
                    startSlide = newStartSlide;
                }
            }
        }
        
        //Set current slide equal to startSlide
        vars.currentSlide = startSlide;
        
        //Add initial slide(s). If startSlide is not the first or the last slide, add startSlide + next and previous slide.
        //If startSlide is the first slide, add startSlide + next slide
        var startValue = 0;
        var endValue = 2;
        if (startSlide > 0 && startSlide < (vars.totalSlides - 1))
        {
            startValue = startSlide - 1;
            endValue = startValue + 3;
        }
        else if (startSlide == (vars.totalSlides - 1))
        {
            endValue = startValue + 1;
            //addThumbRow(vars.thumbRows.length - 2);***************************************************************************************************************************************************************************
        }
        trace('start: '+startValue+' end: '+endValue);
        for(var i = startValue; i < endValue; i++) 
        {
            trace("Adding initial slide(s) "+i);
            addSlide(i);
        }
        
        //Set initial image object
        vars.currentImage = $('.slideNum'+startSlide, slider);
        
        //Set initial caption
        setCaption(startSlide);
        
        //Add initial slices. The slices are used during image transitions. Number of slices can be set in settings.slices
        for(var i = 0; i < settings.slices; i++)
        {
            var sliceWidth = Math.round(slider.width() / settings.slices);
            if (i == settings.slices - 1)
            {
                slider.append(
                    $('<div class="nivo-slice"></div>').css({ left:(sliceWidth*i)+'px', width:(slider.width()-(sliceWidth*i))+'px' })
                );
            } 
            else
            {
                slider.append(
                    $('<div class="nivo-slice"></div>').css({ left:(sliceWidth*i)+'px', width:sliceWidth+'px' })
                );
            }
        }
        
        //Set initial background image on .slider. If the width of .slider is greater than the image, calculate background position to center the image.
        var bgPosition = 0;
        if (settings.images.slides[vars.currentSlide].width < slider.width())
        {
            bgPosition = Math.floor((slider.width()-settings.images.slides[vars.currentSlide].width)/2);
        }
        slider.css('background', 'url("'+ vars.currentImage.attr('src') +'") no-repeat '+bgPosition+'px center');
        $('.nivo-slice:first', slider).css('backgroundPosition', bgPosition+'px center');
        
        /**********************************
        ***** Add navigation elements *****
        **********************************/
        
        //Add "direction navigation"-markup, consisting of prev-, next- and play/pause buttons.
        if (settings.directionNav)
        {
            //Show pause-button if slideshow is set to autoplay and number of slides is greater than 1. Else show play-button.
            if (!settings.manualAdvance && vars.totalSlides > 1)
            {
                slider.append('<ul class="directionNav"><li><a class="nivo-prevNav">Prev</a></li><li><a class="nivo-playNav play">Play/pause</a></li><li><a class="nivo-nextNav">Next</a></li></ul>');
            }
            else 
            {
                slider.append('<ul class="directionNav"><li><a class="nivo-prevNav">Prev</a></li><li><a class="nivo-playNav pause">Play/pause</a></li><li><a class="nivo-nextNav">Next</a></li></ul>');
            }
            
            //Show navigation only when hovering over .slider
            if (settings.navHide)
            {
                //Set CSS to hide navigation initially
                $('.directionNav', slider).css('height', 0);
                $('.directionNav li', slider).css('opacity', 0);
                //On mouseover: animate height, then fade in the navigation symbols
                //On mouseout: fade out the navigation symbols, then animate height
                var inDirectionAnimation = false;
                slider.hover(
                    function()
                    {
                        inDirectionAnimation = true;
                        $('.directionNav', slider).animate({height: 40}, 200, 
                            function() 
                            {
                                $('li', this).animate({'opacity': 1}, 150,
                                    function()
                                    {
                                        inDirectionAnimation = false;                                       
                                    }
                                );
                            }
                        );
                    }, 
                    function()
                    {
                        if (inDirectionAnimation === true)
                        {
                            $('.directionNav li', slider).stop().css('opacity', 0);
                            $('.directionNav', slider).stop().css('height', 0);
                        }
                        else
                        {
                            $('.directionNav li', slider).animate({opacity: 0}, 150, 
                                function()
                                {
                                    $('.directionNav', slider).animate({height: 0}, 200);
                                }
                            );
                        }
                    }
                );
            }
            
            //Add event handlers on navigation-buttons.
            //On click prev-btn
            $('a.nivo-prevNav', slider).live('click', 
                function()
                {
                    prevSlide();
                }
            );
            //On click next-btn
            $('a.nivo-nextNav', slider).live('click', 
                function()
                {
                    nextSlide();
                }
            );
            //On click play/pause-button
            $('.nivo-playNav', slider).live('click', 
                function() 
                {
                    if (vars.paused)
                    {
                        startSlideshow();
                    }
                    else
                    {
                        pauseSlideshow();
                    }
                }
            );
        }

        //Add "left and right navigation"-markup, consisting of prev and next buttons.
        if (settings.leftAndRightNav)
        {
            //Add markup only if number of slides greater than 1
            if (vars.totalSlides > 1)
            {
                slider.append('<a class="leftAndRightNav prevSlide" ><span class="nivo-prevNav">Prev</span></a><a class="leftAndRightNav nextSlide"><span class="nivo-nextNav">Next</span></a>');
            }
            
            //Show navigation only when hovering over .slider
            //Set CSS to hide navigation initially
            $('.leftAndRightNav', slider).css('width', 0);
            $('.leftAndRightNav span', slider).css('opacity', 0);
            
            //On mouseover: animate width, then fade in the navigation symbols
            //On mouseout: fade out the navigation symbols, then animate width
            var inLeftRightAnimation = false;
            slider.hover(
                function()
                {
                    inLeftRightAnimation = true;
                    $('.leftAndRightNav', slider).animate({width: 30}, 200, 
                        function()
                        {
                            $('span', this).animate({'opacity': 1}, 150,
                                function()
                                {
                                    inLeftRightAnimation = false;
                                }
                            );
                        }
                    );
                }, 
                function()
                {
                    if (inLeftRightAnimation === true)
                    {
                        $('.leftAndRightNav span', slider).stop(true).css('opacity', 0);
                        $('.leftAndRightNav', slider).stop().css('width', 0);
                    }
                    else
                    {
                        $('.leftAndRightNav span', slider).animate({opacity: 0}, 150,
                            function()
                            {
                                $('.leftAndRightNav', slider).animate({width: 0}, 200);
                            }
                        );
                    }
                }
            );
            
            //Add event handlers on navigation-buttons
            //On click prev button
            $('.prevSlide', slider).live('click', 
                function()
                {
                    prevSlide();
                }
            );
            //On click next button
            $('.nextSlide', slider).live('click', 
                function()
                {
                    nextSlide();
                }
            );
        }
        
        //Add thumbs/numbers control navigation
        if (settings.controlNav)
        {
            //Add the thumb wrapper div
            thumbContext.append('<div class="nivo-controlNav"></div>');
            
            //Create array with items equal to thumbnailrows. Set each item to false until row is loaded.
            for(j = 0; j < Math.ceil(vars.totalSlides/settings.thumbnailsInRow); j++)
            {
                vars.thumbRows[j] = false;
            }
            
            //If thumbnails is selected as controlNav
            if (settings.controlNav == 'thumbs')
            {
                //Get width of container containing the thumbnails
                var availableWidth = thumbContext.width();
                //Set the left margin of the container element equal to (-1)*thumbMargin
                $('.nivo-controlNav', thumbContext).css(
                    {
                        'marginLeft': settings.thumbMargin*(-1),
                        'marginTop': settings.thumbMargin*(-1)
                    }
                );
                //Styling that will be applied to all thumbs
                vars.thumbStyle = new Object;
                vars.thumbStyle.borderWidth = 1;
                vars.thumbStyle.width = Math.floor((availableWidth - ((settings.thumbnailsInRow-1) * settings.thumbMargin) - (settings.thumbnailsInRow*vars.thumbStyle.borderWidth*2) ) / settings.thumbnailsInRow);
                vars.thumbStyle.marginTop = settings.thumbMargin;
                vars.thumbStyle.marginRight = 0;
                vars.thumbStyle.marginBottom = 0;
                vars.thumbStyle.marginLeft = settings.thumbMargin;
                //Add the inital thumb row
                addThumbRow(Math.floor(vars.currentSlide/settings.thumbnailsInRow), 'append', vars.currentSlide);
            }
            
            //If using numbers instead of thumbnails, display all slides since no thumbnail-images needs to be loaded
            else 
            {
                var thumbMarkup = '';
                for(var i = 0; i < vars.totalSlides; i++) 
                {
                    thumbMarkup += '<a class="nivo-control numOnly" rel="'+ i +'">'+(i+1)+'</a>';                   
                }
                $('.nivo-controlNav', thumbContext).append(thumbMarkup);
            }
        }
        else 
        {
            thumbContext.hide();
        }
        
        //Add keyboard navigation event handlers
        if (settings.keyboardNav)
        {
            $(window).keypress(
                function(event)
                {
                    //Left
                    if (event.keyCode == '37')
                    {
                        prevSlide();
                    }
                    //Right
                    if (event.keyCode == '39')
                    {
                        nextSlide();
                    }
                }
            );
        }
        
        /***********************************
        ***** Add social media/sharing *****
        ***********************************/
        if (settings.shareable) 
        {
            //addThis markup. Maybe this markup should be placed outside the JS?
            slider.append('<div class="share">'+
                            '<div class="widget polarisPageTools addThis">'+
                                '<div class="shareText">Del dette bildet</div>'+
                                '<div class="addthis_toolbox addthis_default_style">'+
                                    '<a title="E-post" class="addthis_button_email at300b"></a>'+
                                    '<a class="addthis_button_facebook" title="Facebook"></a>'+
                                    '<a class="addthis_button_twitter" title="Tweet"></a>'+
                                '</div>'+
                                '<script type="text/javascript">var addthis_config = {"data_track_clickback":true};</script>'+
                                '<script type="text/javascript" src="http://s7.addthis.com/js/250/addthis_widget.js#username=trosvoll"></script>'+
                            '</div>'+
                        '</div>');
            
            //Show share only when hovering over .slider
            //On mouseover: animate height, then fade in the addThis items
            //On mouseout: fade out the addThis items, then animate height
            var inShareAnimation = false;
            slider.hover( 
                function()
                {
                    inShareAnimation = true;
                    $('.share', slider).animate({height: 30}, 200,
                        function()
                        {
                            $('.addThis', this).animate({opacity: 1}, 150,
                                function()
                                {
                                    inShareAnimation = false;   
                                }
                            );
                        }
                    );
                },
                function()
                {
                    if (inShareAnimation === true)
                    {
                        $('.share', slider).stop(true).css('height', 0);
                        $('.addThis', slider).stop(true).css('opacity', 0);
                    }
                    else
                    {
                        $('.addThis', slider).animate({opacity: 0}, 150,
                            function()
                            {
                                $('.share', slider).animate({height: 0}, 200);
                            }
                        );
                    }
                }
            );
        }

        //Set initial active thumb
        $('.nivo-controlNav a:eq('+ vars.currentSlide +')', thumbContext).addClass('active');
        //Bind event handlers to thumbs
        $('.nivo-controlNav a', thumbContext).live('click', 
            function()
            {
                //If clicked thumb already has class .active, do nothing
                if (vars.running || $(this).hasClass('active'))
                {
                    return false;
                }
                //If slideshow is running, pause the slideshow
                if (!vars.paused)
                {
                    pauseSlideshow();
                }
                //Set the current image as background image on .slider
                slider.css('background','url("'+ vars.currentImage.attr('src') +'") no-repeat');
                //Set the current slide equal to the "rel"-attribute on the clicked thumb
                vars.currentSlide = $(this).attr('rel');
                //Run transition to next slide/image
                nivoRun(slider, settings);
            }
        );  
                
        //Event when Animation finishes
        slider.bind('nivo:animFinished', 
            function()
            { 
                //No animation in progress
                vars.running = false; 
                //Restart the timer
                if (timer == '' && !vars.paused && !settings.manualAdvance)
                {
                    timer = setInterval(
                        function()
                        {
                            nivoRun(slider, settings);
                        },
                        settings.pauseTime
                    );
                }
            }
        );
        
        var timer = 0;
        
        //If autoplay is on, start the slideshow
        if (!settings.manualAdvance && vars.totalSlides > 1)
        {
            startSlideshow();   
        }
        /***** Finished all init operations ******/
        
        /*********************
        ****** Functions *****
        *********************/
        
        //Updates the url addThis use when the twitter-button is clicked. This is necessary to be able to link to a specific image in the slideshow, ex.: [url].html#10 -> slide number 10
        /*function updateAddThisTwitterUrl() 
        {
            if ($('.addthis_button_twitter', slider).attr('href'))
            {
                var url = $('.addthis_button_twitter', slider).attr('href');
                var splitUrl = url.split('.html');
                splitUrl[1] = splitUrl[1].slice(splitUrl[1].indexOf('%'));
                var newUrl = splitUrl[0]+'.html#'+(vars.currentSlide)+splitUrl[1];
                $('.addthis_button_twitter', slider).attr('href', newUrl);
            }
        }*/
        function updateAddThisTwitterUrl()
        {
            if ($('.addthis_button_twitter', slider).attr('href'))
            {
                var url = $('.addthis_button_twitter', slider).attr('href');
                var splitUrl = url.split('.ece');
                if (splitUrl.length > 1)
                {
                    var newUrl = splitUrl[0]+'.ece%23'+(vars.currentSlide);
                    $('.addthis_button_twitter', slider).attr('href', newUrl);
                }
            }
        }

        //Updates the url addThis use when the facebook-button is clicked. This is necessary to be able to link to a specific image in the slideshow, ex.: [url].html#10 -> slide number 10
        /*function updateAddThisFacebookUrl()
        {
            if ($('.addthis_button_facebook', slider).attr('href'))
            {
                var url = $('.addthis_button_facebook', slider).attr('href');
                trace('fb before: ' + url);
                //var splitUrl = url.split('.html');
                var splitUrl = url.split('.ece');
                trace('fb after: ' + splitUrl);
                splitUrl[1] = splitUrl[1].slice(splitUrl[1].indexOf('%'));
                //var newUrl = splitUrl[0]+'.html#'+(vars.currentSlide)+splitUrl[1];
                var newUrl = splitUrl[0]+'.ece#'+(vars.currentSlide)+splitUrl[1];
                $('.addthis_button_facebook', slider).attr('href', newUrl);
            }
        }*/
        
        function updateAddThisFacebookUrl()
        {
            if ($('.addthis_button_facebook', slider).attr('href'))
            {
                var url = $('.addthis_button_facebook', slider).attr('href');
                var splitUrl = url.split('.ece');
                if (splitUrl.length > 1)
                {
                    var newUrl = splitUrl[0]+'.ece%23'+(vars.currentSlide);
                    $('.addthis_button_facebook', slider).attr('href', newUrl);
                }
            }
        }
        
        //Add row of thumbnails if row exists and isn't already loaded. Set optional param active to specify which slide is active.
        //Input: Int row
        //Input: String order
        //Input: Int active
        function addThumbRow(row, order, active)
        {
            //Check if row exist
            if (vars.thumbRows[row] != undefined && !vars.thumbRows[row]) 
            {
                //DOM-element ref.
                var nivoControlNav = $('.nivo-controlNav', thumbContext);
                //Temp var to store markup (reduces number of DOM inserts)
                var thumbMarkup = '';
                //Number of first thumb in selected row
                var startPosition = row * settings.thumbnailsInRow;
                //startposition + the number of thumbs per row. If this number is greater than the total number of slides, use total number of slides instead
                var endPosition = Math.min(startPosition + settings.thumbnailsInRow, vars.totalSlides);
                //Create markup for each thumb. If param active is set, use this to set thumb with equal index to active
                for(var i = startPosition; i < endPosition; i++) 
                {
                    var isActive = (i == active) ? 'active' : '';
                    thumbMarkup += '<a class="nivo-control thumbNum'+i+' '+isActive+'" rel="'+ i +'" style="border-width: '+vars.thumbStyle.borderWidth+'px; width: '+vars.thumbStyle.width+'px; height: '+vars.thumbStyle.width+'px; margin: '+vars.thumbStyle.marginLeft+'px 0 0 '+vars.thumbStyle.marginLeft+'px;">'+
                                        '<img style="max-width: '+vars.thumbStyle.width+'px;" src="'+settings.images.slides[i].thumbUrl+'" alt="" />'+ //max-height: '+vars.thumbStyle.width+'px; 
                                    '</a>';                 
                }
                //Expand thumbnail container height and add new thumbs
                //Default start height 0. If height of container is defined, use as start height
                var startHeight = 0;
                if (nivoControlNav.height() != 'undefined') 
                {
                    startHeight = nivoControlNav.height();
                }
                var endHeight = startHeight + vars.thumbStyle.width + settings.thumbMargin;
                //Animate height of container, then append input
                nivoControlNav.animate({height: endHeight}, 200, 
                    function()
                    {
                        if (order == 'append')
                        {
                            nivoControlNav.append(thumbMarkup);
                        }
                        else
                        {
                            nivoControlNav.prepend(thumbMarkup);
                        }
                    }
                );
                //Set this row of thumbs loaded
                vars.thumbRows[row] = true;
                //Increase the total number of thumbs counter
                vars.currentTotalThumbs += (endPosition - startPosition);
            }
        }
        
        //Returns the margins of input element as an object
        //Input:    String item (DOM-element)
        //Returns:  Object with properties top, right, bottom, left
        function getMargins(item)
        {
            var margins = new Object;
            margins.top = item.css('marginTop').replace('px','');
            margins.right = item.css('marginRight').replace('px','');
            margins.bottom = item.css('marginBottom').replace('px','');
            margins.left = item.css('marginLeft').replace('px','');
            return margins;
        }
        
        //Check if specified slide is already added to .slider
        //Input: int slideId
        function slideIsLoaded(slideId)
        {
            if ( $('.slideNum'+slideId, slider).length != 0 ) {
                return true;
            }
            else
            {
                return false;
            }
        }
        
        //If slideId is less than total number of slides, add slideimage to .slider
        //Input: Int slideId
        function addSlide(slideId)
        {
            //Make sure the slide exists
            if (slideId < vars.totalSlides)
            {
                var slideMarkup = '<img title="" class="nivo-slide slideNum'+slideId+'" style="display: none;" src="'+settings.images.slides[slideId].imageUrl+'">';
                slider.prepend(slideMarkup);
            }
        }
        
        //Set current image
        //Input: Int id
        function setCurrentImage(id)
        {
            vars.currentImage = $('.slideNum'+id, slider);  
        }

        //Inserts and animates caption. Fade out caption - insert new - adjust height - fade in
        //Input: Int slideNum
        function setCaption(slideNum)
        {
            //If photographer is set, create markup
            var photographer = '';
            if (settings.images.slides[slideNum].photographer)
            {
                photographer = ' <div class="slidePhotographer">Foto: '+settings.images.slides[slideNum].photographer+'</div>';
            }
            var current = Number(slideNum) + 1;
            //Index markup
            var index = '<div class="slideIndex">'+current+' / '+vars.totalSlides+'</div>';
            //Caption text markup
            var caption = '<div class="slideText">'+photographer+settings.images.slides[slideNum].caption+'</div>';
            //Insert caption elements into wrapper div
            captionContext.html('<div style="opacity: 0;">'+index+caption+'</div>');
            //Animate height and opacity of the wrapper div
            captionContext.animate({height: captionContext.find('div').outerHeight(true)},250,
                function()
                {
                    captionContext.find('div').animate({opacity: 1},250);
                }
            );
        }
        
        //Goto next slide
        function nextSlide()
        {
            //First check if a transition/animation is already running
            if (vars.running)
            {
                return false;
            }
            //Increment currentSlide if not at last slide
            if (vars.currentSlide < (vars.totalSlides-1))
            {
                vars.currentSlide++;
            }
            else
            {
                //If slideshow is set to loop, start over from first slide
                if (settings.loop) 
                {
                    vars.currentSlide = 0;
                }
                //Else if slideshow !paused, pause slideshow
                else
                {
                    if (!vars.paused)
                    {
                        pauseSlideshow();
                    }
                    return false;
                }
            }
            nivoRun(slider, settings);
        }
        
        //Goto previous slide
        function prevSlide()
        {
            //Prevent navigating to previous slide when current position == first slide
            if (vars.currentSlide != 0) 
            {
                if (!vars.paused)
                {
                    pauseSlideshow();
                }
                //Decrement currentSlide
                vars.currentSlide -= 1;
                nivoRun(slider, settings);
            }
        }
        
        //Pause the slideshow
        function pauseSlideshow()
        {
            togglePlayBtn();
            vars.paused = true;
            clearInterval(timer);
            timer = '';
        }
        
        //Start the slideshow
        function startSlideshow()
        {
            togglePlayBtn();
            vars.paused = false;
            //Restart the timer
            timer = setInterval(nextSlide, settings.pauseTime);
        }
                
        //Toggle play/pause button class
        function togglePlayBtn()
        {
            var playBtn = $('.nivo-playNav', slider);
            if (playBtn.hasClass('pause'))
            {
                playBtn.removeClass('pause').addClass('play');
            }
            else
            {
                playBtn.removeClass('play').addClass('pause');
            }
        }
        
        // Reset slice width before animations run
        var resetSliceWidth = function(slider, settings)
        {
            var slices = $('.nivo-slice', slider);
            var i = 0;
            slices.each(
                function()
                {
                    var slice = $(this);
                    var sliceWidth = Math.round(slider.width() / settings.slices);
                    if (i == settings.slices - 1)
                    {
                        slice.css('width', (slider.width()-(sliceWidth * i)) + 'px');
                    }
                    else
                    {
                        slice.css('width', sliceWidth + 'px');
                    }
                    i++;
                }
            );
        }

        //Run transition/animation to different slide
        var nivoRun = function(slider, settings)
        {
            //Get our vars
            var vars = slider.data('nivo:vars');

            //Stop
            if (!vars || vars.stop)
            {
                return false;
            }
            
            //Load currentSlide if not already loaded
            if (!slideIsLoaded(vars.currentSlide)) 
            {
                addSlide(vars.currentSlide);
            }
            
            //Load next and previous slide if not already loaded
            var prevSlideId = vars.currentSlide - 1;
            if (prevSlideId < vars.totalSlides && prevSlideId > 0)
            {
                if (!slideIsLoaded(prevSlideId))
                {
                    addSlide(prevSlideId);
                }
            }
            var nextSlideId = parseInt(vars.currentSlide) + 1;
            if (nextSlideId < vars.totalSlides && nextSlideId > 0)
            {
                if (!slideIsLoaded(nextSlideId))
                {
                    addSlide(nextSlideId);
                }
            }
            
            //Set current background before change
            var backgroundPosition = $('.nivo-slice:first', slider).css('backgroundPosition');
            slider.css('background', 'url("'+ vars.currentImage.attr('src') +'") no-repeat '+backgroundPosition);
            
            //When reaching the end/start of thumbnailrow, load next row of thumbnails
            if (settings.controlNav == 'thumbs') 
            {
                //Calculate new row trigger positions
                var thisRow = Math.floor(vars.currentSlide/settings.thumbnailsInRow);
                var rowFirst = thisRow * settings.thumbnailsInRow;
                var rowLast = Math.min(rowFirst + settings.thumbnailsInRow - 1, vars.totalSlides);
                //Append new row...
                if (vars.currentSlide == rowLast)
                {
                    addThumbRow(thisRow + 1, 'append');
                }
                //Prepend new row...
                else if (vars.currentSlide == rowFirst)
                {
                    addThumbRow(thisRow - 1, 'prepend');
                }
            }
            
            //When reaching last slide of slideshow, return to beginning
            if (vars.currentSlide == vars.totalSlides)
            { 
                vars.currentSlide = 0;
            }
            
            //Set vars.currentImage
            setCurrentImage(vars.currentSlide);
                        
            //Set active links
            if (settings.controlNav)
            {
                $('.nivo-controlNav a', thumbContext).removeClass('active');
                $('.nivo-controlNav .thumbNum'+vars.currentSlide, thumbContext).addClass('active');
            }
            
            //Set caption
            setCaption(vars.currentSlide);
            
            //Update social media links
            updateAddThisFacebookUrl();
            updateAddThisTwitterUrl();
            
            //Set offset: if image width < .slider width calculate offset to center image
            var offset = 0;
            if (settings.images.slides[vars.currentSlide].width < slider.width())
            {
                offset = Math.floor((slider.width()-settings.images.slides[vars.currentSlide].width)/2);
            }

            //Set new slice backgrounds
            var  i = 0;
            var currentImg = vars.currentImage.attr('src');
            $('.nivo-slice', slider).each(
                function()
                {
                    var sliceWidth = Math.round(slider.width()/settings.slices);
                    var bgLeftPos = sliceWidth + (i*sliceWidth) - sliceWidth - offset;
                    $(this).css(
                        {
                            'background': 'url("'+ currentImg +'") no-repeat '+ (-1)*bgLeftPos +'px center #000000',
                            'height': '0px',
                            'opacity': '0'
                        }
                    );
                    i++;
                }
            );
            
            if (settings.effect == 'random')
            {
                var anims = new Array('sliceDownRight','sliceDownLeft','sliceUpRight','sliceUpLeft','sliceUpDown','sliceUpDownLeft','fold','fade','slideInRight','slideInLeft');
                vars.randAnim = anims[Math.floor(Math.random() * (anims.length + 1))];
                if (vars.randAnim == undefined)
                {
                    vars.randAnim = 'fade';
                }
            }
            
            //Run random effect from specified set (eg: effect:'fold,fade')
            if (settings.effect.indexOf(',') != -1)
            {
                var anims = settings.effect.split(',');
                vars.randAnim = anims[Math.floor(Math.random()*(anims.length))];
                if (vars.randAnim == undefined)
                {
                    vars.randAnim = 'fade';
                }
            }
        
            //Run effects
            vars.running = true;
            if (settings.effect == 'sliceDown' || settings.effect == 'sliceDownRight' || vars.randAnim == 'sliceDownRight' || settings.effect == 'sliceDownLeft' || vars.randAnim == 'sliceDownLeft') sliceDown();
            else if (settings.effect == 'sliceUp' || settings.effect == 'sliceUpRight' || vars.randAnim == 'sliceUpRight' || settings.effect == 'sliceUpLeft' || vars.randAnim == 'sliceUpLeft') sliceUp();
            else if (settings.effect == 'sliceUpDown' || settings.effect == 'sliceUpDownRight' || vars.randAnim == 'sliceUpDown' || settings.effect == 'sliceUpDownLeft' || vars.randAnim == 'sliceUpDownLeft') sliceUpDown();
            else if (settings.effect == 'fold' || vars.randAnim == 'fold') fold();
            else if (settings.effect == 'fade' || vars.randAnim == 'fade') fade();
            else if (settings.effect == 'slideInRight' || vars.randAnim == 'slideInRight') slideInRight();
            else if (settings.effect == 'slideInLeft' || vars.randAnim == 'slideInLeft') slideInLeft();
            
            if (vars.isInit)
            {
                vars.isInit = false;
            }
        }
        
        /******************************
        ****** Transition effects *****
        ******************************/
        function sliceDown()
        {
            var timeBuff = 0;
            var i = 0;
            resetSliceWidth(slider, settings);
            var slices = $('.nivo-slice', slider);
            if (settings.effect == 'sliceDownLeft' || vars.randAnim == 'sliceDownLeft') slices = $('.nivo-slice', slider)._reverse();
            slices.each(function(){
                var slice = $(this);
                slice.css({ 'top': '0px' });
                if (i == settings.slices-1){
                    setTimeout(function(){
                        slice.animate({ height:'100%', opacity:'1.0' }, settings.animSpeed, '', function(){ slider.trigger('nivo:animFinished'); });
                    }, (100 + timeBuff));
                } else {
                    setTimeout(function(){
                        slice.animate({ height:'100%', opacity:'1.0' }, settings.animSpeed);
                    }, (100 + timeBuff));
                }
                timeBuff += 50;
                i++;
            });
        }
        
        function sliceUp()
        {
            var timeBuff = 0;
            var i = 0;
            resetSliceWidth(slider, settings);
            var slices = $('.nivo-slice', slider);
            if (settings.effect == 'sliceUpLeft' || vars.randAnim == 'sliceUpLeft') slices = $('.nivo-slice', slider)._reverse();
            slices.each(function(){
                var slice = $(this);
                slice.css({ 'bottom': '0px' });
                if (i == settings.slices-1){
                    setTimeout(function(){
                        slice.animate({ height:'100%', opacity:'1.0' }, settings.animSpeed, '', function(){ slider.trigger('nivo:animFinished'); });
                    }, (100 + timeBuff));
                } else {
                    setTimeout(function(){
                        slice.animate({ height:'100%', opacity:'1.0' }, settings.animSpeed);
                    }, (100 + timeBuff));
                }
                timeBuff += 50;
                i++;
            });
        }
        
        function sliceUpDown()
        {
            var timeBuff = 0;
            var i = 0;
            var v = 0;
            resetSliceWidth(slider, settings);
            var slices = $('.nivo-slice', slider);
            if (settings.effect == 'sliceUpDownLeft' || vars.randAnim == 'sliceUpDownLeft') slices = $('.nivo-slice', slider)._reverse();
            slices.each(function(){
                var slice = $(this);
                if (i == 0){
                    slice.css('top','0px');
                    i++;
                } else {
                    slice.css('bottom','0px');
                    i = 0;
                }
                
                if (v == settings.slices-1){
                    setTimeout(function(){
                        slice.animate({ height:'100%', opacity:'1.0' }, settings.animSpeed, '', function(){ slider.trigger('nivo:animFinished'); });
                    }, (100 + timeBuff));
                } else {
                    setTimeout(function(){
                        slice.animate({ height:'100%', opacity:'1.0' }, settings.animSpeed);
                    }, (100 + timeBuff));
                }
                timeBuff += 50;
                v++;
            });
        }
        
        function fold()
        {
            var timeBuff = 0;
            var i = 0;
            resetSliceWidth(slider, settings);
            $('.nivo-slice', slider).each(function(){
                var slice = $(this);
                var origWidth = slice.width();
                slice.css({ top:'0px', height:'100%', width:'0px' });
                if (i == settings.slices-1){
                    setTimeout(function(){
                        slice.animate({ width:origWidth, opacity:'1.0' }, settings.animSpeed, '', function(){ slider.trigger('nivo:animFinished'); });
                    }, (100 + timeBuff));
                } else {
                    setTimeout(function(){
                        slice.animate({ width:origWidth, opacity:'1.0' }, settings.animSpeed);
                    }, (100 + timeBuff));
                }
                timeBuff += 50;
                i++;
            });
        }
        
        function fade()
        {
            slider.css('background','black');
            var firstSlice = $('.nivo-slice:first', slider);
            firstSlice.css({
                'height': '100%',
                'width': slider.width() + 'px'
            });

            firstSlice.animate({ opacity:'1.0' }, (settings.animSpeed*2), '', function(){ slider.trigger('nivo:animFinished'); });
        }
        
        function slideInRight()
        {
            var firstSlice = $('.nivo-slice:first', slider);
            firstSlice.css({
                'height': '100%',
                'width': '0px',
                'opacity': '1'
            });

            firstSlice.animate({ width: slider.width() + 'px' }, (settings.animSpeed*2), '', function(){ slider.trigger('nivo:animFinished'); });
        }
        
        function slideInLeft()
        {
            var firstSlice = $('.nivo-slice:first', slider);
            firstSlice.css({
                'height': '100%',
                'width': '0px',
                'opacity': '1',
                'left': '',
                'right': '0px'
            });

            firstSlice.animate({ width: slider.width() + 'px' }, (settings.animSpeed*2), '', function(){ 
                // Reset positioning
                firstSlice.css({
                    'left': '0px',
                    'right': ''
                });
                slider.trigger('nivo:animFinished'); 
            });
        }       
                
        // Start / Stop
        this.stop = function()
        {
            if (!$(element).data('nivo:vars').stop){
                $(element).data('nivo:vars').stop = true;
                trace('Stop Slider');
            }
        }
        this.start = function()
        {
            if ($(element).data('nivo:vars').stop){
                $(element).data('nivo:vars').stop = false;
                trace('Start Slider');
            }
        }
    };
        
    $.fn.nivoSlider = function(options)
    {
        return this.each(function(){
            var element = $(this);
            // Return early if this element already has a plugin instance
            if (element.data('nivoslider')) return;
            // Pass options to plugin constructor
            var nivoslider = new NivoSlider(this, options);
            // Store plugin object in this element's data
            element.data('nivoslider', nivoslider);
        });
    };
    
    //Default settings
    $.fn.nivoSlider.defaults = 
    {
        animSpeed: 250, //ms - default animation speed
        backgroundColor: 'black', //Background color
        backgroundImage: '', //URL to background image
        controlNav: 'thumbs', //false, 'thumbs', 'numbers'
        directionNav: true, //Show play/pause/next/prev-buttons
        effect: 'fade', //'fade', 'fold', 'sliceDownRight', 'sliceDownLeft', 'sliceUpRight', 'sliceUpLeft', 'sliceUpDown', 'sliceUpDownLeft', 'slideInRight', 'slideInLeft'
        format: 'auto', //'normal'(3:2), 'wide'(16:9), 'auto'(selects normal/wide based on image dimensions)
        images: '', //REQUIRED - JSON-object with url to all images and thumbnails, caption and photographer name
        keyboardNav: true, //Enable navgation using left and right arrows
        leftAndRightNav: true, //Enable separate next/prev-buttons
        loop: false, //Loop the slideshow
        manualAdvance: true, //Autoplay off     
        navHide: true, //Hide directionNav when !hover
        pauseTime: 2500, //ms - time/slide
        shareable: true, //Show links to facebook, twitter etc. using addThis
        slices: 8, //Number of slices to divide slides into when animating
        thumbMargin: 10, //px - Margin between thumbnails
        thumbnailsInRow: 8 //Number of thumbnails/row       
    };
    
    $.fn._reverse = [].reverse;
	
})(jQuery);
