/**
 * tools.overlay 1.1.2 - Overlay HTML with eye candy.
 *
 * Copyright (c) 2009 Tero Piirainen
 * http://flowplayer.org/tools/overlay.html
 *
 * Dual licensed under MIT and GPL 2+ licenses
 * http://www.opensource.org/licenses
 *
 * Launch  : March 2008
 * Date: ${date}
 * Revision: ${revision}
 */
(function($) {

	// static constructs
	$.tools = $.tools || {};

	$.tools.overlay = {

		version: '1.1.2',

		addEffect: function(name, loadFn, closeFn) {
			effects[name] = [loadFn, closeFn];
		},

		conf: {
			top: '10%',
			left: 'center',
			absolute: false,

			speed: 'normal',
			closeSpeed: 'fast',
			effect: 'default',

			close: null,
			oneInstance: true,
			closeOnClick: true,
			closeOnEsc: true,
			api: false,
			expose: null,

			// target element to be overlayed. by default taken from [rel]
			target: null
		}
	};


	var effects = {};

	// the default effect. nice and easy!
	$.tools.overlay.addEffect('default',

		/*
			onLoad/onClose functions must be called otherwise none of the
			user supplied callback methods won't be called
		*/
		function(onLoad) {
			this.getOverlay().fadeIn(this.getConf().speed, onLoad);

		}, function(onClose) {
			this.getOverlay().fadeOut(this.getConf().closeSpeed, onClose);
		}
	);


	var instances = [];


	function Overlay(trigger, conf) {

		// private variables
		var self = this,
			 $self = $(this),
			 w = $(window),
			 closers,
			 overlay,
			 opened,
			 expose = conf.expose && $.tools.expose.version;

		// get overlay and triggerr
		var jq = conf.target || trigger.attr("rel");
		overlay = jq ? $(jq) : null || trigger;

		// overlay not found. cannot continue
		if (!overlay.length) { throw "Could not find Overlay: " + jq; }

		// if trigger is given - assign it's click event
		if (trigger && trigger.index(overlay) == -1) {
			trigger.click(function(e) {
				self.load(e);
				return e.preventDefault();
			});
		}

		// bind all callbacks from configuration
		$.each(conf, function(name, fn) {
			if ($.isFunction(fn)) { $self.bind(name, fn); }
		});


		// API methods
		$.extend(self, {

			load: function(e) {

				// can be opened only once
				if (self.isOpened()) { return self; }


				// find the effect
		 		var eff = effects[conf.effect];
		 		if (!eff) { throw "Overlay: cannot find effect : \"" + conf.effect + "\""; }

				// close other instances?
				if (conf.oneInstance) {
					$.each(instances, function() {
						this.close(e);
					});
				}

				// onBeforeLoad
				e = e || $.Event();
				e.type = "onBeforeLoad";
				$self.trigger(e);
				if (e.isDefaultPrevented()) { return self; }

				// opened
				opened = true;

				// possible expose effect
				if (expose) { overlay.expose().load(e); }

				// calculate end position
				var top = conf.top;
				var left = conf.left;

				// get overlay dimensions
				var oWidth = overlay.outerWidth({margin:true});
				var oHeight = overlay.outerHeight({margin:true});

				if (typeof top == 'string')  {
					top = top == 'center' ? Math.max((w.height() - oHeight) / 2, 0) :
						parseInt(top, 10) / 100 * w.height();
				}

				if (left == 'center') { left = Math.max((w.width() - oWidth) / 2, 0); }

				if (!conf.absolute)  {
					top += w.scrollTop();
					left += w.scrollLeft();
				}

				// position overlay
				overlay.css({top: top, left: left, position: 'absolute'});

				// onStart
				e.type = "onStart";
				$self.trigger(e);

		 		// load effect
				eff[0].call(self, function() {
					if (opened) {
						e.type = "onLoad";
						$self.trigger(e);
					}
				});

				// when window is clicked outside overlay, we close
				if (conf.closeOnClick) {
					$(document).bind("click.overlay", function(e) {
						if (!self.isOpened()) { return; }
						var et = $(e.target);
						if (et.parents(overlay).length > 1) { return; }
						$.each(instances, function() {
							this.close(e);
						});
					});
				}

				// keyboard::escape
				if (conf.closeOnEsc) {

					// one callback is enough if multiple instances are loaded simultaneously
					$(document).unbind("keydown.overlay").bind("keydown.overlay", function(e) {
						if (e.keyCode == 27) {
							$.each(instances, function() {
								this.close(e);
							});
						}
					});
				}

				return self;
			},

			close: function(e) {

				if (!self.isOpened()) { return self; }

				e = e || $.Event();
				e.type = "onBeforeClose";
				$self.trigger(e);
				if (e.isDefaultPrevented()) { return; }

				opened = false;

				// close effect
				effects[conf.effect][1].call(self, function() {
					e.type = "onClose";
					$self.trigger(e);
				});

				// if all instances are closed then we unbind the keyboard / clicking actions
				var allClosed = true;
				$.each(instances, function() {
					if (this.isOpened()) { allClosed = false; }
				});

				if (allClosed) {
					$(document).unbind("click.overlay").unbind("keydown.overlay");
				}


				return self;
			},

			// @deprecated
			getContent: function() {
				return overlay;
			},

			getOverlay: function() {
				return overlay;
			},

			getTrigger: function() {
				return trigger;
			},

			getClosers: function() {
				return closers;
			},

			isOpened: function()  {
				return opened;
			},

			// manipulate start, finish and speeds
			getConf: function() {
				return conf;
			},

			// bind
			bind: function(name, fn) {
				$self.bind(name, fn);
				return self;
			},

			// unbind
			unbind: function(name) {
				$self.unbind(name);
				return self;
			}

		});

		// callbacks
		$.each("onBeforeLoad,onStart,onLoad,onBeforeClose,onClose".split(","), function(i, ev) {
			self[ev] = function(fn) {
				return self.bind(ev, fn);
			};
		});


		// exposing effect
		if (expose) {

			// expose configuration
			if (typeof conf.expose == 'string') { conf.expose = {color: conf.expose}; }

			$.extend(conf.expose, {
				api: true,
				closeOnClick: conf.closeOnClick,

				// only overlay control's the esc button
				closeOnEsc: false
			});

			// initialize expose api
			var ex = overlay.expose(conf.expose);

			ex.onBeforeClose(function(e) {
				self.close(e);
			});

			self.onClose(function(e) {
				ex.close(e);
			});
		}

		// close button
		closers = overlay.find(conf.close || ".close");

		if (!closers.length && !conf.close) {
			closers = $('<div class="close"></div>');
			overlay.prepend(closers);
		}

		closers.click(function(e) {
			self.close(e);
		});
	}

	// jQuery plugin initialization
	$.fn.overlay = function(conf) {

		// already constructed --> return API
		var el = this.eq(typeof conf == 'number' ? conf : 0).data("overlay");
        
		if (el) { return el; }

		if ($.isFunction(conf)) {
			conf = {onBeforeLoad: conf};
		}

		var globals = $.extend({}, $.tools.overlay.conf);
		conf = $.extend(true, globals, conf);

		this.each(function() {
			el = new Overlay($(this), conf);
			instances.push(el);
			$(this).data("overlay", el);
		});
        

		return conf.api ? el: this;
	};

})(jQuery);



/**
 * Overlay Gallery plugin, version: 1.0.0
 *
 * Copyright (c) 2009 Tero Piirainen
 * http://flowplayer.org/tools/overlay.html#gallery
 *
 * Dual licensed under MIT and GPL 2+ licenses
 * http://www.opensource.org/licenses
 *
 * Since  : July 2009
 * Date: ${date}
 * Revision: ${revision}
 */
(function($) {

	// TODO: next(), prev(), getIndex(), onChange event

	// version number
	var t = $.tools.overlay;
	t.plugins = t.plugins || {};

	t.plugins.gallery = {
		version: '1.0.0',
		conf: {
			imgId: 'img',
			next: '.next',
			prev: '.prev',
			info: '.info',
			progress: '.progress',
			disabledClass: 'disabled',
			activeClass: 'active',
			opacity: 0.8,
			speed: 'slow',
			template: '<strong>${title}</strong> <span>Zdjęcie ${index} z ${total}</span>',
			autohide: true,
			preload: true,
			api: false
		}
	};

	$.fn.gallery = function(opts) {
               if (!this) return false;
               
		var conf = $.extend({}, t.plugins.gallery.conf), api;
		$.extend(conf, opts);

		// common variables for all gallery images
		api = this.overlay();

		var links = this,
			 overlay = api.getOverlay(),
			 next = overlay.find(conf.next),
			 prev = overlay.find(conf.prev),
			 info = overlay.find(conf.info),
			 progress = overlay.find(conf.progress),
			 els = prev.add(next).add(info).css({opacity: conf.opacity}),
			 close = api.getClosers(),
			 index;


//{{{ load

		function load(el) {

			progress.fadeIn();
			els.hide(); close.hide();

			var url = el.attr("href");

			// download the image
			var image = new Image();

			image.onload = function() {

				progress.fadeOut();

				// find image inside overlay
				var img = $("#" + conf.imgId, overlay);

				// or append it to the overlay
				if (!img.length) {
					img = $("<img/>").attr("id", conf.imgId).css("visibility", "hidden");
					overlay.prepend(img);
				}

				// make initially invisible to get it's dimensions
				img.attr("src", url).css("visibility", "hidden");

				// animate overlay to fit the image dimensions
				var width = image.width;
				var left = ($(window).width() - width) / 2;

				// calculate index number
				index = links.index(links.filter("[href=" +url+ "]"));

				// activate trigger
				links.removeClass(conf.activeClass).eq(index).addClass(conf.activeClass);

				// enable/disable next/prev links
				var cls = conf.disabledClass;
				els.removeClass(cls);

				if (index === 0) { prev.addClass(cls); }
				if (index == links.length -1) { next.addClass(cls); }


				// set info text & width
				var text = conf.template
					.replace("${title}", el.attr("title") || el.data("title"))
					.replace("${index}", index + 1)
					.replace("${total}", links.length);

				var padd = parseInt(info.css("paddingLeft"), 10) +  parseInt(info.css("paddingRight"), 10);
				info.html(text).css({width: width - padd});

				overlay.animate({
					width: width, height: image.height, left: left}, conf.speed, function() {

					// gradually show the image
					img.hide().css("visibility", "visible").fadeIn(function() {
						if (!conf.autohide) {
							els.fadeIn(); close.show();
						}
					});

				});
			};

			image.onerror = function() {
				overlay.fadeIn().html("Cannot find image " + url);
			};

			image.src = url;

			if (conf.preload) {
				links.filter(":eq(" +(index-1)+ "), :eq(" +(index+1)+ ")").each(function()  {
					var img = new Image();
					img.src = $(this).attr("href");
				});
			}

		}

//}}}


		// function to add click handlers to next/prev links
		function addClick(el, isNext)  {

			el.click(function() {

				if (el.hasClass(conf.disabledClass)) { return; }

				// find the triggering link
				var trigger = links.eq(i = index + (isNext ? 1 : -1));

				// if found load it's href
				if (trigger.length) { load(trigger); }

			});
		}

		// assign next/prev click handlers
		addClick(next, true);
		addClick(prev);


		// arrow keys
		$(document).keydown(function(evt) {

			if (!overlay.is(":visible") || evt.altKey || evt.ctrlKey) { return; }

			if (evt.keyCode == 37 || evt.keyCode == 39) {
				var btn = evt.keyCode == 37 ? prev : next;
				btn.click();
				return evt.preventDefault();
			}
			return true;
		});

		function showEls() {
			if (!overlay.is(":animated")) {
				els.show(); close.show();
			}
		}

		// autohide functionality
		if (conf.autohide) {
			overlay.hover(showEls, function() { els.fadeOut();	close.hide(); }).mousemove(showEls);
		}

		// load a proper gallery image when overlay trigger is clicked
		var ret;

		this.each(function() {

			var el = $(this), api = $(this).overlay(), ret = api;

			api.onBeforeLoad(function() {
				load(el);
			});

			api.onClose(function() {
				links.removeClass(conf.activeClass);
			});
		});

		return conf.api ? ret : this;

	};

})(jQuery);




/**
 * tools.overlay "Apple Effect" 1.0.1
 *
 * Copyright (c) 2009 Tero Piirainen
 * http://flowplayer.org/tools/overlay.html#apple
 *
 * Dual licensed under MIT and GPL 2+ licenses
 * http://www.opensource.org/licenses
 *
 * Since  : July 2009
 * Date: ${date}
 * Revision: ${revision}
 */
(function($) {

	// version number
	var t = $.tools.overlay;
	t.effects = t.effects || {};
	t.effects.apple = {version: '1.0.1'};

	// extend global configuragion with effect specific defaults
	$.extend(t.conf, {
		start: {
			absolute: true,
			top: null,
			left: null
		},

		fadeInSpeed: 'fast',
		zIndex: 9999
	});

	// utility function
	function getPosition(el) {
		var p = el.offset();
		return [p.top + el.height() / 2, p.left + el.width() / 2];
	}

//{{{ load

	var loadEffect = function(onLoad) {

		var overlay = this.getOverlay(),
			 opts = this.getConf(),
			 trigger = this.getTrigger(),
			 self = this,
			 oWidth = overlay.outerWidth({margin:true}),
			 img = overlay.data("img");


		// growing image is required.
		if (!img) {
			var bg = overlay.css("backgroundImage");

			if (!bg) {
				throw "background-image CSS property not set for overlay";
			}

			// url("bg.jpg") --> bg.jpg
			bg = bg.substring(bg.indexOf("(") + 1, bg.indexOf(")")).replace(/\"/g, "");
			overlay.css("backgroundImage", "none");

			img = $('<img src="' + bg + '"/>');
			img.css({border:0,position:'absolute',display:'none'}).width(oWidth);
			$('body').append(img);
			overlay.data("img", img);
		}

		// initial top & left
		var w = $(window),
			 itop = opts.start.top || Math.round(w.height() / 2),
			 ileft = opts.start.left || Math.round(w.width() / 2);

		if (trigger) {
			var p = getPosition(trigger);
			itop = p[0];
			ileft = p[1];
		}

		// adjust positioning relative toverlay scrolling position
		if (!opts.start.absolute) {
			itop += w.scrollTop();
			ileft += w.scrollLeft();
		}

		// initialize background image and make it visible
		img.css({
			top: itop,
			left: ileft,
			width: 0,
			zIndex: opts.zIndex
		}).show();

		// begin growing
		img.animate({
			top: overlay.css("top"),
			left: overlay.css("left"),
			width: oWidth}, opts.speed, function() {

			// set close button and content over the image
			overlay.css("zIndex", opts.zIndex + 1).fadeIn(opts.fadeInSpeed, function()  {

				if (self.isOpened() && !$(this).index(overlay)) {
					onLoad.call();
				} else {
					overlay.hide();
				}
			});
		});

	};
//}}}


	var closeEffect = function(onClose) {

		// variables
		var overlay = this.getOverlay(),
			 opts = this.getConf(),
			 trigger = this.getTrigger(),
			 top = opts.start.top,
			 left = opts.start.left;


		// hide overlay & closers
		overlay.hide();

		// trigger position
		if (trigger) {
			var p = getPosition(trigger);
			top = p[0];
			left = p[1];
		}

		// shrink image
		overlay.data("img").animate({top: top, left: left, width:0}, opts.closeSpeed, onClose);
	};


	// add overlay effect
	t.addEffect("apple", loadEffect, closeEffect);

})(jQuery);

/**
 * tools.expose 1.0.5 - Make HTML elements stand out
 *
 * Copyright (c) 2009 Tero Piirainen
 * http://flowplayer.org/tools/expose.html
 *
 * Dual licensed under MIT and GPL 2+ licenses
 * http://www.opensource.org/licenses
 *
 * Launch  : June 2008
 * Date: ${date}
 * Revision: ${revision}
 */
(function($) {

	// static constructs
	$.tools = $.tools || {};

	$.tools.expose = {
		version: '1.0.5',
		conf: {

			// mask settings
			maskId: null,
			loadSpeed: 'slow',
			closeSpeed: 'fast',
			closeOnClick: true,
			closeOnEsc: true,

			// css settings
			zIndex: 9998,
			opacity: 0.8,
			color: '#456',
			api: false
		}
	};

	/* one of the greatest headaches in the tool. finally made it */
	function viewport() {

		// the horror case
		if ($.browser.msie) {

			// if there are no scrollbars then use window.height
			var d = $(document).height(), w = $(window).height();

			return [
				window.innerWidth || 							// ie7+
				document.documentElement.clientWidth || 	// ie6
				document.body.clientWidth, 					// ie6 quirks mode
				d - w < 20 ? w : d
			];
		}

		// other well behaving browsers
		return [$(window).width(), $(document).height()];

	}

	function Expose(els, conf) {

		// private variables
		var self = this, $self = $(this), mask = null, loaded = false, origIndex = 0;

		// bind all callbacks from configuration
		$.each(conf, function(name, fn) {
			if ($.isFunction(fn)) { $self.bind(name, fn); }
		});

		// adjust mask size when window is resized (or firebug is toggled)
		$(window).resize(function() {
			self.fit();
		});


		// public methods
		$.extend(this, {

			getMask: function() {
				return mask;
			},

			getExposed: function() {
				return els;
			},

			getConf: function() {
				return conf;
			},

			isLoaded: function() {
				return loaded;
			},

			load: function(e) {

				// already loaded ?
				if (loaded) { return self;	}

				origIndex = els.eq(0).css("zIndex");

				// find existing mask
				if (conf.maskId) { mask = $("#" + conf.maskId);	}

				if (!mask || !mask.length) {

					var size = viewport();

					mask = $('<div/>').css({
						position:'absolute',
						top:0,
						left:0,
						width: size[0],
						height: size[1],
						display:'none',
						opacity: 0,
						zIndex:conf.zIndex
					});

					// id
					if (conf.maskId) { mask.attr("id", conf.maskId); }

					$("body").append(mask);


					// background color
					var bg = mask.css("backgroundColor");

					if (!bg || bg == 'transparent' || bg == 'rgba(0, 0, 0, 0)') {
						mask.css("backgroundColor", conf.color);
					}

					// esc button
					if (conf.closeOnEsc) {
						$(document).bind("keydown.unexpose", function(evt) {
							if (evt.keyCode == 27) {
								self.close();
							}
						});
					}

					// mask click closes
					if (conf.closeOnClick) {
						mask.bind("click.unexpose", function(e)  {
							self.close(e);
						});
					}
				}

				// possibility to cancel click action
				e = e || $.Event();
				e.type = "onBeforeLoad";
				$self.trigger(e);

				if (e.isDefaultPrevented()) { return self; }

				// make sure element is positioned absolutely or relatively
				$.each(els, function() {
					var el = $(this);
					if (!/relative|absolute|fixed/i.test(el.css("position"))) {
						el.css("position", "relative");
					}
				});

				// make elements sit on top of the mask
				els.css({zIndex:Math.max(conf.zIndex + 1, origIndex == 'auto' ? 0 : origIndex)});


				// reveal mask
				var h = mask.height();

				if (!this.isLoaded()) {

					mask.css({opacity: 0, display: 'block'}).fadeTo(conf.loadSpeed, conf.opacity, function() {

						// sometimes IE6 misses the height property on fadeTo method
						if (mask.height() != h) { mask.css("height", h); }
						e.type = "onLoad";
						$self.trigger(e);

					});
				}

				loaded = true;

				return self;
			},


			close: function(e) {

				if (!loaded) { return self; }

				e = e || $.Event();
				e.type = "onBeforeClose";
				$self.trigger(e);
				if (e.isDefaultPrevented()) { return self; }

				mask.fadeOut(conf.closeSpeed, function() {
					e.type = "onClose";
					$self.trigger(e);
					els.css({zIndex: $.browser.msie ? origIndex : null});
				});

				loaded = false;
				return self;
			},

			fit: function() {
				if (mask) {
					var size = viewport();
					mask.css({ width: size[0], height: size[1]});
				}
			},

			bind: function(name, fn) {
				$self.bind(name, fn);
				return self;
			},

			unbind: function(name) {
				$self.unbind(name);
				return self;
			}

		});

		// callbacks
		$.each("onBeforeLoad,onLoad,onBeforeClose,onClose".split(","), function(i, ev) {
			self[ev] = function(fn) {
				return self.bind(ev, fn);
			};
		});

	}


	// jQuery plugin implementation
	$.fn.expose = function(conf) {

		var el = this.eq(typeof conf == 'number' ? conf : 0).data("expose");
		if (el) { return el; }

		if (typeof conf == 'string') {
			conf = {color: conf};
		}

		var globals = $.extend({}, $.tools.expose.conf);
		conf = $.extend(globals, conf);

		// construct exposes
		this.each(function() {
			el = new Expose($(this), conf);
			$(this).data("expose", el);
		});

		return conf.api ? el: this;
	};


})(jQuery);

