// !jQuery Easing Methods

$.extend(
	$.easing, {
		easeOutExpo: function(x,t,b,c,d) {
			return (t==d) ? b + c : c * ( -Math.pow(Math.E, -10 * t / d) + 1) + b;
		}
	}
);


/*
 * DragScroll 0.9.0 - jQuery Plugin
 * http://plugins.jquery.com/project/dragscroll
 *
 * Copyright (c) 2009 Radek Matìj
 * Dual licensed under the MIT and GPL licenses.
 *
 * DragScroll adds mouse dragging functionality to overflowed elements with
 * scrollbars similar to Adobe Reader or Google Maps dragging. DragScroll also
 * triggers special events on scrolling with overfloed element, so special
 * behavior can be bound to it.
 *
 * example:  $('#scroll').dragscroll();
 * 
 * Options:
 * - draggedClassName - The class name added to the element when dragging is
 *   active. Class name can be then used for aditional CSS styling (showing
 *   different cursor). The default value is "dragged".
 * - draggableSelector - jQuery selector for selecting the draggable part of
 *   the element. If specified, only matched child elements are draggable, else
 *   whole element content is draggable.
 *
 * example: $('#scroll').dragscroll({draggableSelector: 'div#drag-me'});
 *
 * Events:
 * - dragstart - Dragging starts.
 * - dragend - Dragging ends.
 * - scrollx - The element horizontal scroll position changes Vector parameter
 *   is supplied.
 * - scrolly - The element vertical scroll position changes. Vector parameter
 *   is supplied.
 *
 * example: $('#scroll').bind('dragstart', (function() { $(this).addClass('dragged') }));
 * example: $('#scroll').bind('scrollx', (function(e, vector) { console.log(vector) }));
 *
 * Requires jQuery version 1.2 and higher.
 */

(function($) {
// !$.fn.dragscroll
	$.fn.dragscroll = create;
// !$.fn.removedragscroll
	$.fn.removedragscroll = remove;

	$.fn.dragscroll.options = {
		draggedClassName: 'dragged',
		draggableSelector: null
	};


 	// data keys
	var draggedKey = 'ds.dragged';
	var draggableKey = 'ds.draggable';


	/* Initializes DragScroll with given options on selected elements. */
	function create(options) {
		var settings = $.extend({}, $.fn.dragscroll.options, options);
	
		return this.each(function() {
			
			var container = $(this);

			// select draggable part & bind dragging start to it
			var draggable = settings.draggableSelector ?
				container.find(settings.draggableSelector) :
				container.children();
			draggable.bind('mousedown.ds', { container: container }, onMouseDown);

			// bind dragging end and scroll
			container
				.bind('mouseup.ds', onMouseUp)
				.bind('mouseleave.ds', onMouseLeave)
				.bind('scroll.ds', { left: this.scrollLeft, top: this.scrollTop }, onScroll);

			// bind adding / removing class if draggedClassName specified
			if (settings.draggedClassName)
				container
					.bind('dragstart.ds', { className: settings.draggedClassName }, onDragStart)
					.bind('dragend.ds', { className: settings.draggedClassName }, onDragEnd);
				
		});
	}


	/* Removes DragScroll from selected elements. */
	function remove() {
		return this.each(function() {
			var x = $(this).find('*').andSelf().unbind('.ds');
		});
	}


	/* Starts/binds dragging and starts storing previous mouse position. */
	function onMouseDown(e) {

		e.preventDefault();

		e.data.container
			.data(draggedKey, true)
			.trigger('dragstart')
			.bind('mousemove.ds', { prevX: e.screenX, prevY: e.screenY }, onMouseMove);
	}


	/* Provides the dragging functionality on mouse move event. */
	function onMouseMove(e) {

		e.preventDefault();

		var container = $(this);

		var xVector = e.data.prevX - e.screenX;
		var yVector = e.data.prevY - e.screenY;
		var newX = container.scrollLeft() + xVector;
		var newY = container.scrollTop() + yVector;

		container
			.scrollLeft(newX)
			.scrollTop(newY);

		e.data.prevY = e.screenY;
		e.data.prevX = e.screenX;
	}


	/* Ends/unbinds dragging when mouse leaves the container. */
	function onMouseLeave(e) {
		$(this).trigger('mouseup.ds');
	}


	/* Ends/unbinds dragging when mouse up (only if dragging is in progress). */
	function onMouseUp() {
		var container = $(this);
		if (container.data(draggedKey)) {
			container.unbind('mousemove.ds');
			container
				.data(draggedKey, false)
				.trigger('dragend');
		}
	}


	/* Triggers scrollx & scrolly events on scroll (dragging with mouse, moving
	 * with scrollbars, etc.). */
	function onScroll(e) {

		// this.scrollLeft/Top is faster then $(this).scrollLeft/Top()
		var newLeft = this.scrollLeft;
		var newTop = this.scrollTop;

		var xVector = newLeft - e.data.left;
		var yVector = newTop - e.data.top;

		if (xVector)
			$(this).trigger('scrollx', xVector);
		if (yVector)
			$(this).trigger('scrolly', yVector);

		e.data.left = newLeft;
		e.data.top = newTop;
	};


	/* Functions for adding / removing class on dragstart / dragend events. */
	function onDragStart(e) {
		$(this).addClass(e.data.className);
	};
	function onDragEnd(e) {
		$(this).removeClass(e.data.className);
	};


})(jQuery);

(function($) {
	var monitoring = [];
// !$.fn.fullscreen
	$.fn.fullscreen = function() {
		var _fullscreen = function(img) {
			var frame = $(window);
			var image = $(img);

		    var vm  = frame.width() / frame.height();
		    var im  = image.width() / image.height();
		
		    if (vm > im) {
		        image.css('width', '100%');
		        image.css('height', 'auto');
		    }
		    if (vm < im) {
		        image.css('width', 'auto');
		        image.css('height', '100%');
		    }
		}

		$(this).each(function(index, el) {
//			console.log($.inArray(el, monitoring));
//			if (!$.inArray(el, monitoring)) {
				$(window).resize(function() {
					_fullscreen(el);
				});
				var _l = new Image();
					_l.onload = _l.onerror = function() {
//						monitoring.push(el);
						_fullscreen(el);
					}
					_l.src = $(el).attr('src');
//			} else _fullscreen(el);
		});

		return this;
	}
// !$.fn.setupScroll
	$.fn.setupScroll = function(opts) {
		var options = jQuery.extend({
			'handle': '.scroll-handle',	// the related scroll handle
			'containment': false,		// the scroll handle's containment (default is the parent element)
			'autotoggle': true,			// toggles the containment
			'togglespeed': 200,			// the speed of the toggle-fades
			'autoheight': true,			// resizes the handle
			'minheight': 50				// the minimum height of the handle
		}, opts || {});

		var target = $(this);
		var handle = $(options.handle);
		var parent = options.containment ? $(options.containment) : handle.parents(':first');
		var mainHeight = target.innerHeight();
		var insideHeight = target.children(':first').outerHeight();
		var scrollerHeight = options.autoheight ? mainHeight / insideHeight * mainHeight : handle.height();
			scrollerHeight = options.minheight && scrollerHeight < options.minheight ? options.minheight : scrollerHeight;
		if (insideHeight > mainHeight) {
			if (options.autotoggle) parent.fadeIn(options.togglespeed);
			handle.css({
				'height': scrollerHeight,
				'top': target.scrollTop() / (insideHeight - mainHeight) * (mainHeight - scrollerHeight)
			});
			handle.draggable({
				'containment': options.containment ? parent : 'parent',
				'drag': function(ev, ui) {
					target.scrollTop(handle.position().top / (mainHeight - scrollerHeight) * (insideHeight - mainHeight));
				}
			});
		} else if (options.autotoggle) parent.fadeOut(options.togglespeed);

		return this;
	}

/* !$.history */
    var locationWrapper = {
        put: function(hash, win) {
            (win || window).location.hash = this.encoder(hash);
        },
        get: function(win) {
            var hash = ((win || window).location.hash).replace(/^#/, '');
            try {
                return $.browser.mozilla ? hash : decodeURIComponent(hash);
            }
            catch (error) {
                return hash;
            }
        },
        encoder: encodeURIComponent
    };

    var iframeWrapper = {
        id: "__jQuery_history",
        init: function() {
            var html = '<iframe id="'+ this.id +'" style="display:none" src="javascript:false;" />';
            $("body").prepend(html);
            return this;
        },
        _document: function() {
            return $("#"+ this.id)[0].contentWindow.document;
        },
        put: function(hash) {
            var doc = this._document();
            doc.open();
            doc.close();
            locationWrapper.put(hash, doc);
        },
        get: function() {
            return locationWrapper.get(this._document());
        }
    };

    function initObjects(options) {
        options = $.extend({
                unescape: false
            }, options || {});

        locationWrapper.encoder = encoder(options.unescape);

        function encoder(unescape_) {
            if(unescape_ === true) {
                return function(hash){ return hash; };
            }
            if(typeof unescape_ == "string" &&
               (unescape_ = partialDecoder(unescape_.split("")))
               || typeof unescape_ == "function") {
                return function(hash) { return unescape_(encodeURIComponent(hash)); };
            }
            return encodeURIComponent;
        }

        function partialDecoder(chars) {
            var re = new RegExp($.map(chars, encodeURIComponent).join("|"), "ig");
            return function(enc) { return enc.replace(re, decodeURIComponent); };
        }
    }

    var implementations = {};

    implementations.base = {
        callback: undefined,
        type: undefined,

        check: function() {},
        load:  function(hash) {},
        init:  function(callback, options) {
            initObjects(options);
            self.callback = callback;
            self._options = options;
            self._init();
        },

        _init: function() {},
        _options: {}
    };

    implementations.timer = {
        _appState: undefined,
        _init: function() {
            var current_hash = locationWrapper.get();
            self._appState = current_hash;
            self.callback(current_hash);
            setInterval(self.check, 100);
        },
        check: function() {
            var current_hash = locationWrapper.get();
            if(current_hash != self._appState) {
                self._appState = current_hash;
                self.callback(current_hash);
            }
        },
        load: function(hash) {
            if(hash != self._appState) {
                locationWrapper.put(hash);
                self._appState = hash;
                self.callback(hash);
            }
        }
    };

    implementations.iframeTimer = {
        _appState: undefined,
        _init: function() {
            var current_hash = locationWrapper.get();
            self._appState = current_hash;
            iframeWrapper.init().put(current_hash);
            self.callback(current_hash);
            setInterval(self.check, 100);
        },
        check: function() {
            var iframe_hash = iframeWrapper.get(),
                location_hash = locationWrapper.get();

            if (location_hash != iframe_hash) {
                if (location_hash == self._appState) {    // user used Back or Forward button
                    self._appState = iframe_hash;
                    locationWrapper.put(iframe_hash);
                    self.callback(iframe_hash); 
                } else {                              // user loaded new bookmark
                    self._appState = location_hash;  
                    iframeWrapper.put(location_hash);
                    self.callback(location_hash);
                }
            }
        },
        load: function(hash) {
            if(hash != self._appState) {
                locationWrapper.put(hash);
                iframeWrapper.put(hash);
                self._appState = hash;
                self.callback(hash);
            }
        }
    };

    implementations.hashchangeEvent = {
        _init: function() {
            self.callback(locationWrapper.get());
            $(window).bind('hashchange', self.check);
        },
        check: function() {
            self.callback(locationWrapper.get());
        },
        load: function(hash) {
            locationWrapper.put(hash);
        }
    };

    var self = $.extend({}, implementations.base);

    if($.browser.msie && ($.browser.version < 8 || document.documentMode < 8)) {
        self.type = 'iframeTimer';
    } else if("onhashchange" in window) {
        self.type = 'hashchangeEvent';
    } else {
        self.type = 'timer';
    }

    $.extend(self, implementations[self.type]);
    $.history = self;
})(jQuery);
