/**
* DROPDOWN - "dropdown.js"
* Wraps content into a dropdown div and when triggered by the supplied trigger element displays the content in a floating layer  
*
* Example usage:
*   new Dropdown($('#my-trigger'), $('#my-content'));
* 
* Converted Mootools => jQuery | Andreas Søvik 2011
*/

(function ($) {
	var Dropdown = Class.extend({  
	    triggerElement: null,
	    contentElement: null,
	    container: null,
	    outsideClickEvent: null,
	    
	    /**
	     * @param trigger Element that is to trigger the dropdown
	     * @param content Element that holds the content for the dropdown
	     */
	    init: function(trigger, content, options) {
	        if(!trigger || !content) { return false; }
	        
	        this.options = $.extend({}, this.options, options);
	        
	        //Set variables
	        this.triggerElement = trigger;
	        this.contentElement = content;
	        
	        this.triggerPosition = $(this.triggerElement).offset();
	        
	        this.buildGui();
	        
	        this.outsideClickEvent = $.proxy(this.outsideClick, this);
	        
	        $(this.triggerElement).bind('click', $.proxy(this.show, this));
	        $(this.container).bind('click', function(e) {
	        	e.stopPropagation();
	        });
	        
	        $(this.container).find('.' + this.options.closeClass).bind('click', $.proxy(this.hide, this));
	        $('#more-galleries').css('display', 'block');
	    },
	    
	    /**
	     * Prepare the extra interface needed for the dropdown
	     * - creates two nested divs and puts the content inside the innermost
	     */
	    buildGui: function() {
	        var container = $('<div class="' + this.options.containerClass + '" style="position:absolute;"></div>');
	        var inner = $('<div class="' + this.options.innerClass + ' clearfix"></div>');
	        
	        $(inner).append(this.contentElement);
	        $(container).append(inner);

	        this.container = container;
	        this.hide();
	        
	        $('body').append(this.container);
	    },
	    
	    /**
	     * Place the dropdown according to the alignHorizontally and alignVertically options
	     */
	    place: function() {
	
	        var x = 0, y = 0;
	        this.triggerPosition = $(this.triggerElement).offset();
	
	        //Horizontal placement
	        switch(this.options.alignHorizontally) {
	            case 'trigger-left':
	                x = this.triggerPosition.left;
	                this.container.setStyle('left',  x)
	                break;
	            case 'trigger-center':
	            	x = (this.triggerPosition.left + ($(this.triggerElement).width() / 2)) - ($(this.container).width() / 2);
	                this.container.setStyle('left',  x)
	                break;
	            case 'trigger-right':
	            	x = $(window).width() - (this.triggerPosition.left + $(this.triggerElement).width());
	                this.container.css('right',  x)
	                break;
	        }
	
	        //Prevent that container exceed window size
	        if(x + $(this.container).width() > $(window).width()) {
	            x = Math.max(0, $(window).width() - $(this.container).width());
	        }
	        
	        //Vertical placement
	        switch(this.options.alignVertically) {
	            case 'trigger-top':
	                y = this.triggerPosition.top;
	                break;
	            case 'trigger-center':
	                y = this.triggerPosition.top + ($(this.triggerElement).height() / 2) - ($(this.container).height() / 2);
	                break;
	            case 'trigger-bottom':
	                y = this.triggerPosition.top + $(this.triggerElement).height();
	                break;
	        }
	
	        this.container.css('top', y);
	
	    },
	    
	    /**
	     * Show the dropdown
	     */
	    show: function(e) {
	        this.container.css('display', 'block');
	        this.place();
	        
	        if(typeof(e) == 'object') {
	            e.stopImmediatePropagation();
	        }
	        
	        $('body').bind('click', this.outsideClickEvent);
	    },
	    
	    /**
	     * Hide the dropdown
	     */
	    hide: function(e) {
	        $(this.container).css('display', 'none');
	        $('body').unbind('click', this.outsideClickEvent);

	        if(typeof(e) == 'object') {
	            e.stopImmediatePropagation();
	        }
	    },
	
	    /**
	    * Event for clicks outside of the dropdown
	    */
	    outsideClick: function(e) {
	        this.hide();
	        if(typeof(e) == 'object') {
	            e.stopImmediatePropagation();
	        }        
	    }
	});
	
	
	/**
	 * DERIVATIVE SCALING - "derivative-scaling.js"
	 * replaces image url with the url for the derivate closest in size to the displayed size.
	 */
	var DerivativeScaling = Class.extend({
	    image: false,
	    maxSize: 0, //Will not scale image above this. Set to last derivative in initialize()
	    
	    init: function(image, options) {
	        if(!image) { return false; }

	        this.options = $.extend({}, this.options, options);
	        
	        //Set variables
	        this.image = image;
	        for(size in this.options.derivatives) {
	            if(size > this.maxSize) {
	                this.maxSize = size;    
	            }
	        }

	        if(!this.isLoaded()) {
	        	this.image.load($.proxy(this.refresh, this));         
	        } 
	        
	        this.refresh(); 
	        $(window).resize($.proxy(this.refresh, this));
	    },
	
	    /**
	     * Check if image is allready loaded
	     */
	    isLoaded: function() {
	        // Check that works with Trident. Not so much with gecko browsers
	        if (!this.image.complete) {
	            return false;
	        }
	    
	        // If it failed to load, either of these should be zero. Works with gecko.
	        if (typeof this.image.naturalWidth != "undefined" && this.image.naturalWidth == 0) {
	            return false;
	        }
	    
	        // No other way of checking: assume it's ok.
	        return true;
	        
	    },
	
	
	    /**
	     * Checks if there's a derivative closer in size than the one currrently being used. If so, returns the corresponding key in this.options.derivatives
	     */
	    checkSize: function() {
	        var currentWidth = this.image.width();
	        var closestDiff = 99999;
	        var closest = null;
	        
	        for(d in this.options.derivatives) {
	            var candidateDiff = currentWidth - d;
	            if(candidateDiff < 0) { candidateDiff = candidateDiff * -1; }
	            if(candidateDiff < closestDiff) {
	                closestDiff = candidateDiff;
	                closest = d;
	            }
	        }
	        return closest;
	    },
	    
	    /**
	     * Change the image url to load a different derivative
	     */
	    changeImage: function(newDerivative) {
	        var url = this.image.attr('src');
	        
	        if (url) {
		        var oldDerivative = this.options.derivatives[this.options.currentDerivative];
		        var r = new RegExp(oldDerivative);
		        url = url.replace(r, this.options.derivatives[newDerivative]);
		        
		        this.image.attr('src', url);
		        this.options.currentDerivative = newDerivative;
	        }
	    },
	    
	    /**
	     * Check if a different derivative is needed. Used with window.resize. 
	     */
	    refresh: function() {
	        if(this.options.limitHeight) {
	            var footer = $('#footer');
	            var heightDiff = 65 + ((footer) ? footer.height() : 0);
	            var content = $('#content');
	            var wrapper = $('#image-wrapper');
	            var maxWidth = content.width();
	            var maxHeight = $(window).height() - heightDiff; //subrtact .navigation and footer height + margins instead
	            var ratio = this.image.width() / this.image.height();
	            var newWidth = 0;
	            var newHeight = 0;
	
	            //Test setting width
	            newWidth = Math.min(this.maxSize, maxWidth);
	            newHeight = newWidth / ratio;
	            
	            ////Test setting height
	            if(newHeight > maxHeight) {
	                newHeight = maxHeight;
	                newWidth = newHeight * ratio;
	            }
	                        
	            this.image.css({
	                'width': newWidth,
	                'height': newHeight
	            });
	            
	            wrapper.css({
	                'width': newWidth
	                //'height': newHeight
	            });
	
	        }
	        
	        var oldDerivative = this.options.currentDerivative;
	        var newDerivative = this.checkSize();
	        
	        if(oldDerivative !== newDerivative) {
	            this.changeImage(newDerivative);
	        }
	        
	        $('#image-wrapper').css('visibility', 'visible');
	
	    }
	       
	});
	
	
	/**
	 * INITIALIZING - "gallery.js"
	 */
	$(document).ready(function() {
		$('html').removeClass('non-js').addClass('js');

	    //If currently displaying an ad, don't display the overlay arrows usually displayed on image mouseover
	    var ad = $('#image-wrapper .ad');

	    if(ad.size() > 0) {
	        $('.image-next').css('display', 'none');
	        $('.image-previous').css('display', 'none');
	    }
	    
	    $('#image-wrapper').css('visibility', 'visible');
	    
	    //Footer
	    var bottomAd = $('#bottom-ad');
	    var footer = $('#footer');
	    
	    if (footer) {
	        var footerHeight = ((footer) ? footer.height() : 0) + ((bottomAd) ? bottomAd.height() : 0);
	        footer.css('height', footerHeight);
	    }
	
	    //Init image scaling
	    new DerivativeScaling($('#image-wrapper > img'), {	limitHeight: true,
													        currentDerivative: 980,
														        derivatives: { 
														            480: "derivative_480",
														            580: "derivative_580",
														            647: "derivative_647",
														            980: "derivative_980"
														        }
	    													}// key is width in pixels, value is substring in image url to replace
	    												);
	    
	    var dropdownClose = $('<a href="" class="dropdown-close">Lukk</a>');
	    $('#more-galleries').append($(dropdownClose));

	    new Dropdown($('a.dropdown'), $('#more-galleries'), {	containerClass: 'dropdown-wrapper', //the dropdown content gets wrapped in a div with this class
														        closeClass: 'dropdown-close', //content in the dropdown with this class will get a click event that hides the dropdown
														        innerClass: 'inner',
														        alignHorizontally: 'trigger-right', //trigger-left, trigger-center, trigger-right
														        alignVertically: 'trigger-top' //trigger-top, trigger-center, trigger-bottom
														    });
	    
	    //keyboard navigation
	    var prevLink = $('a.image-previous');
	    var nextLink = $('a.image-next');
	    
	    $(window).bind('keyup', function(e) {
	        if(e.keyCode == 37) {
	            if(prevLink) { window.location = prevLink.attr('href'); }
	        } else if (e.keyCode == 39) {
	            if(nextLink) { window.location = nextLink.attr('href'); }
	        }
	    });
	    
	});
})(jQuery);

