/*

PLEASE NOTE ... 
on line 214 the regex was changed. 
Originaly the regex was used to set mime type of content, tho due phpThumb having a .php extension the image was rendered as ascii
The regex now includes .php extensions (plus GET parameters) as image mime type. 

to get a second url passed (to the full image and not phpThumb) i've used the 'name' attribute to pass the url thru. 
the following lines (roughly) are where those changes were made ... 132, 214, 537, 785, 951, 975

 * nyroModal - jQuery Plugin
 * http://nyromodal.nyrodev.com
 *
 * Copyright (c) 2008 Cedric Nirousset (nyrodev.com)
 * Licensed under the MIT license
 *
 * $Date: 2009-02-19 (Thu, 19 Feb 2009) $
 * $version: 1.4.2
 */
jQuery(function($) { 


	// -------------------------------------------------------
	// Private Variables
	// -------------------------------------------------------

	var userAgent = navigator.userAgent.toLowerCase();
	var browserVersion = (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [0,'0'])[1];
	var isIE6 = (/msie/.test(userAgent) && !/opera/.test(userAgent) && parseInt(browserVersion) < 7);
	var body = $('body');

	var currentSettings;

	var shouldResize = false;

	// To know if the fix for the Issue 10 should be applied (or has been applied)
	var fixFF = false;

	// Used for retrieve the content from an hidden div
	var contentElt;
	var contentEltLast;

	// Contains info about nyroModal state and all div references
	var modal = {
		started: false,
		ready: false,
		dataReady: false,
		anim: false,
		animContent: false,
		loadingShown: false,
		transition: false,
		closing: false,
		error: false,
		blocker: null,
		blockerVars: null,
		full: null,
		bg: null,
		loading: null,
		tmp: null,
		content: null,
		wrapper: null,
		contentWrapper: null,
		scripts: new Array(),
		scriptsShown: new Array()
	};

	// Indicate of the height or the width was resized, to reinit the currentsettings related to null
	var resized = {
		width: false,
		height: false
	};


	// -------------------------------------------------------
	// Public function
	// -------------------------------------------------------

	// jQuery extension function. A paramater object could be used to overwrite the default settings
	$.fn.nyroModal = function(settings) {
		if (!this)
			return false;
		return this.each(function(){
			if (this.nodeName.toLowerCase() == 'form') {
				$(this).submit(function(e) {
					if ($(this).data('processing'))
						return true;
					if (this.enctype == 'multipart/form-data') {
						processModal($.extend(settings, {
							from: this
						}));
						return true;
					}
					e.preventDefault();
					processModal($.extend(settings, {
						from: this
					}));
					return false;
				});
			} else {
				$(this).click(function(e) {
					e.preventDefault();
					processModal($.extend(settings, {
						from: this
					}));
					return false;
				});
			}
		});
	};

	// jQuery extension function to call manually the modal. A paramater object could be used to overwrite the default settings
	$.fn.nyroModalManual = function(settings) {
		if (!this.length)
			processModal(settings);
		return this.each(function(){
			processModal($.extend(settings, {
				from: this
			}));
		});
	};

	$.nyroModalManual = function(settings) {
		processModal(settings);
	};

	// Update the current settings
	// object settings
	// string deep1 first key where overwrite the settings
	// string deep2 second key where overwrite the settings
	$.nyroModalSettings = function(settings, deep1, deep2) {
		setCurrentSettings(settings, deep1, deep2); 
		
		if(settings.dloadURL && settings.dloadURL == currentSettings.dloadURL) {
			currentSettings.dloadURL = settings.dloadURL;
		} 
		else { 
			currentSettings.dloadURL = settings.dloadURL; 
		}

		if (!deep1 && modal.started) {
			if (modal.bg && settings.bgColor)
				currentSettings.updateBgColor(modal, currentSettings, function(){});

			if (modal.contentWrapper && settings.title)
				setTitle();

			if (((settings.width && settings.width == currentSettings.width) || (settings.height && settings.height == currentSettings.height))) {
				if (modal.contentWrapper)
					calculateSize(true);
				if (modal.contentWrapper && modal.contentWrapper.is(':visible') && !modal.animContent) {
					if (fixFF)
						modal.content.css({position: ''});
					currentSettings.resize(modal, currentSettings, function() {
						if (fixFF)
							modal.content.css({position: 'fixed'});
						if ($.isFunction(currentSettings.endResize))
							currentSettings.endResize(modal, currentSettings);
					});
				}
			}
		}
	};

	// Remove the modal function
	$.nyroModalRemove = function() {
		removeModal();
	};

	// Go to the next image for a gallery
	// return false if nothing was done
	$.nyroModalNext = function() {
		var link = getGalleryLink(1);
		if (link)
			return link.nyroModalManual(getCurrentSettingsNew());
		return false;
	};

	// Go to the previous image for a gallery
	// return false if nothing was done
	$.nyroModalPrev = function() {
		var link = getGalleryLink(-1);
		if (link)
			return link.nyroModalManual(getCurrentSettingsNew());
		return false;
	};


	// -------------------------------------------------------
	// Default Settings
	// -------------------------------------------------------
	
	$.fn.nyroModal.settings = {
		debug: false, // Show the debug in the background

		blocker: false, // Element which will be blocked by the modal

		modal: false, // Esc key or click backgrdound enabling or not

		type: '', // nyroModal type (form, formData, iframe, image, etc...)
		from: '', // Dom object where the call come from
		hash: '', // Eventual hash in the url

		processHandler: null, // Handler just before the real process

		selIndicator: 'nyroModalSel', // Value added when a form or Ajax is sent with a filter content

		formIndicator: 'nyroModal', // Value added when a form is sent

		content: null, // Raw content if type content is used

		bgColor: '#000000', // Background color
		
		altURL: null, 
		
		dloadURL: null,
		
		ajax: {}, // Ajax option (url, data, type, success will be overwritten for a form, url and success only for an ajax call)

		swf: { // Swf player options if swf type is used.
			wmode: 'transparent'
		},

		width: null, // default Width If null, will be calculate automatically
		height: null, // default Height If null, will be calculate automatically

		minWidth: 400, // Minimum width
		minHeight: 300, // Minimum height

		resizable: true, // Indicate if the content is resizable. Will be set to false for swf
		autoSizable: true, // Indicate if the content is auto sizable. If not, the min size will be used

		padding: 25, // padding for the max modal size

		regexImg: '[^\.]\.(jpg|jpeg|png|tiff|gif|bmp|php)((\\?.+$)|(\s*$))', // Regex to find images ... added php extension for phpTumb ... orig regex is [^\.]\.(jpg|jpeg|png|tiff|gif|bmp)\s*$
		//defaultImgAlt: 'Image', // Default alt attribute for the images
		setWidthImgTitle: true, // Set the width to the image title
		ltr: true, // Left to Right by default. Put to false for Hebrew or Right to Left language

		gallery: null, // Gallery name if provided
		galleryLinks: '<a href="#" class="nyroModalPrev">Prev</a><a href="#" class="nyroModalNext">Next</a>', // Use .nyroModalPrev and .nyroModalNext to set the navigation link

		css: { // Default CSS option for the nyroModal Div. Some will be overwritten or updated when using IE6
			bg: {
				position: 'absolute',
				overflow: 'hidden',
				top: 0,
				left: 0,
				height: '100%',
				width: '100%'
			},
			wrapper: {
				position: 'absolute',
				top: '50%',
				left: '50%'
			},
			wrapper2: {
			},
			content: {
				overflow: 'auto'
			},
			loading: {
				position: 'absolute',
				top: '50%',
				left: '50%',
				marginTop: '-50px',
				marginLeft: '-50px'
			}
		},

		wrap: { // Wrapper div used to style the modal regarding the content type
			div: '<div class="wrapper"></div>',
			ajax: '<div class="wrapper"></div>',
			form: '<div class="wrapper"></div>',
			formData: '<div class="wrapper"></div>',
			image: '<div class="wrapperImg"></div>',
			swf: '<div class="wrapperSwf"></div>',
			iframe: '<div class="wrapperIframe"></div>',
			iframeForm: '<div class="wrapperIframe"></div>',
			manual: '<div class="wrapper"></div>'
		},

		closeButton: '<a href="#" class="nyroModalClose" id="closeBut" title="close">Close</a>', // Adding automaticly as the first child of #nyroModalWrapper
		
		title: null, // Modal title
		titleFromIframe: true, // When using iframe in the same domain, try to get the title from it

		openSelector: '.nyroModal', // selector for open a new modal. will be used to parse automaticly at page loading
		closeSelector: '.nyroModalClose', // selector to close the modal

		contentLoading: '<a href="#" class="nyroModalClose">Cancel</a>', // Loading div content

		errorClass: 'error', // CSS Error class added to the loading div in case of error
		contentError: 'The requested content cannot be loaded.<br />Please try again later.<br /><a href="#" class="nyroModalClose">Close</a>', // Content placed in the loading div in case of error

		handleError: null, // Callback in case of error

		showBackground: showBackground, // Show background animation function
		hideBackground: hideBackground, // Hide background animation function

		endFillContent: null, // Will be called after filling and wraping the content, before parsing closeSelector and openSelector and showing the content
		showContent: showContent, // Show content animation function
		endShowContent: null, // Will be called once the content is shown
		beforeHideContent: null, // Will be called just before the modal closing
		hideContent: hideContent, // Hide content animation function

		showTransition: showTransition, // Show the transition animation (a modal is already shown and a new one is requested)
		hideTransition: hideTransition, // Hide the transition animation to show the content

		showLoading: showLoading, // show loading animation function
		hideLoading: hideLoading, // hide loading animation function

		resize: resize, // Resize animation function
		endResize: null, // Will be called one the content is resized

		updateBgColor: updateBgColor, // Change background color animation function

		endRemove: null // Will be called once the modal is totally gone
	};
	
	
	
	
	
	// -------------------------------------------------------
	// Private function
	// -------------------------------------------------------

	// Main function
	function processModal(settings) {
		
		if (modal.loadingShown || modal.transition || modal.anim)
			return;
		debug('processModal');
		modal.started = true;
		setDefaultCurrentSettings(settings);
		if (!modal.full)
			modal.blockerVars = modal.blocker = null;
		modal.error = false;
		modal.closing = false;
		modal.dataReady = false;
		modal.scripts = new Array();
		modal.scriptsShown = new Array();

		currentSettings.type = fileType();

		if ($.isFunction(currentSettings.processHandler))
			currentSettings.processHandler(currentSettings);

		from = currentSettings.from;
		url = currentSettings.url;

		if (currentSettings.type == 'swf') {
			// Swf is transforming as a raw content
			currentSettings.resizable = false;
			setCurrentSettings({overflow: 'hidden'}, 'css', 'content');
			currentSettings.content = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="'+currentSettings.width+'" height="'+currentSettings.height+'"><param name="movie" value="'+url+'"></param>';
			var tmp = '';
			$.each(currentSettings.swf, function(name, val) {
				currentSettings.content+= '<param name="'+name+'" value="'+val+'"></param>';
				tmp+= ' '+name+'="'+val+'"';
			});
			currentSettings.content+= '<embed src="'+url+'" type="application/x-shockwave-flash" width="'+currentSettings.width+'" height="'+currentSettings.height+'"'+tmp+'></embed></object>';
		}

		if (from) {
			var jFrom = $(from);
			if (currentSettings.type == 'form') {
				var data = $(from).serializeArray();
				data.push({name: currentSettings.formIndicator, value: 1});
				if (currentSettings.selector)
					data.push({name: currentSettings.selIndicator, value: currentSettings.selector.substring(1)});
				$.ajax($.extend({}, currentSettings.ajax, {
						url: url,
						data: data,
						type: from.method,
						success: ajaxLoaded,
						error: loadingError
					}));
				debug('Form Ajax Load: '+jFrom.attr('action'));
				showModal();
			} else if (currentSettings.type == 'formData') {
				// Form with data. We're using a hidden iframe
				initModal();
				jFrom.attr('target', 'nyroModalIframe');
				jFrom.attr('action', url);
				jFrom.prepend('<input type="hidden" name="'+currentSettings.formIndicator+'" value="1" />');
				if (currentSettings.selector)
					jFrom.prepend('<input type="hidden" name="'+currentSettings.selIndicator+'" value="'+currentSettings.selector.substring(1)+'" />');
				modal.tmp.html('<iframe frameborder="0" hspace="0" name="nyroModalIframe"></iframe>');
				$('iframe', modal.tmp)
					.css({
						width: currentSettings.width,
						height: currentSettings.height
					})
					.error(loadingError)
					.load(formDataLoaded);
				debug('Form Data Load: '+jFrom.attr('action'));
				showModal();
				showContentOrLoading();
			} else if (currentSettings.type == 'image') {
				var title = jFrom.attr('title') || currentSettings.defaultImgAlt;
				initModal();
				modal.tmp.html('<img id="nyroModalImg" />').find('img').attr('alt', title);
				debug('Image Load: '+url);
				modal.tmp.css({lineHeight: 0});
				$('img', modal.tmp)
					.error(loadingError)
					.load(function() {
						debug('Image Loaded: '+this.src);
						$(this).unbind('load');
						var w = modal.tmp.width();
						var h = modal.tmp.height();
						modal.tmp.css({lineHeight: ''});
						resized.width = w;
						resized.height = h;
						setCurrentSettings({
							width: w,
							height: h,
							imgWidth: w,
							imgHeight: h
						});
						setCurrentSettings({overflow: 'hidden'}, 'css', 'content');
						modal.dataReady = true;
						if (modal.loadingShown || modal.transition)
							showContentOrLoading();
					})
					.attr('src', url);
				showModal();
			} else if (currentSettings.type == 'iframeForm') {
				initModal();
				modal.tmp.html('<iframe frameborder="0" hspace="0" src="" name="nyroModalIframe" id="nyroModalIframe"></iframe>');
				debug('Iframe Form Load: '+url);
				$('iframe', modal.tmp).eq(0)
					.css({
						width: '100%',
						height: $.support.boxModel? '99%' : '100%'
					})
					.load(function(e) {
						if (currentSettings.titleFromIframe && url.indexOf(window.location.hostname) > -1)
							$.nyroModalSettings({title: $('iframe', modal.full).contents().find('title').text()});
					});
				modal.dataReady = true;
				showModal();
			} else if (currentSettings.type == 'iframe') {
				initModal();
				modal.tmp.html('<iframe frameborder="0" hspace="0" src="'+url+'" name="nyroModalIframe" id="nyroModalIframe"></iframe>');
				debug('Iframe Load: '+url);
				$('iframe', modal.tmp).eq(0)
					.css({
						width: '100%',
						height: $.support.boxModel? '99%' : '100%'
					})
					.load(function(e) {
						if (currentSettings.titleFromIframe && url.indexOf(window.location.hostname) > -1)
							$.nyroModalSettings({title: $('iframe', modal.full).contents().find('title').text()});
					});
				modal.dataReady = true;
				showModal();
			} else if (currentSettings.type) {
				// Could be every other kind of type or a dom selector
				debug('Content: '+currentSettings.type);
				initModal();
				modal.tmp.html(currentSettings.content);
				var w = modal.tmp.width();
				var h = modal.tmp.height();
				var div = $(currentSettings.type);
				if (div.length) {
					setCurrentSettings({type: 'div'});
					w = div.width();
					h = div.height();
					if (contentElt)
						contentEltLast = contentElt;
					contentElt = div;
					modal.tmp.append(div.contents());
				}
				setCurrentSettings({
					width: w,
					height: h
				});
				if (modal.tmp.html())
					modal.dataReady = true;
				else
					loadingError();
				if (!modal.ready)
					showModal();
				else
					endHideContent();
			} else {
				debug('Ajax Load: '+url);
				setCurrentSettings({type: 'ajax'});
				var data = currentSettings.ajax.data || {};
				if (currentSettings.selector) {
					if (typeof data == "string") {
						data+= '&'+currentSettings.selIndicator+'='+currentSettings.selector.substring(1);
					} else {
						data[currentSettings.selIndicator] = currentSettings.selector.substring(1);
					}
				}
				$.ajax($.extend(true, currentSettings.ajax, {
					url: url,
					success: ajaxLoaded,
					error: loadingError,
					data: data
				}));
				showModal();
			}
		} else if (currentSettings.content) {
			// Raw content not from a DOM element
			debug('Content: '+currentSettings.type);
			setCurrentSettings({type: 'manual'});
			initModal();
			modal.tmp.html($('<div/>').html(currentSettings.content).contents());
			if (modal.tmp.html())
				modal.dataReady = true;
			else
				loadingError();
			showModal();
		} else {
			// What should we show here? nothing happen
		}
	}

	// Update the current settings
	// object settings
	// string deep1 first key where overwrite the settings
	// string deep2 second key where overwrite the settings
	function setDefaultCurrentSettings(settings) {
		debug('setDefaultCurrentSettings');
		currentSettings = $.extend(true, {}, $.fn.nyroModal.settings, settings);
		currentSettings.selector = '';
		currentSettings.borderW = 0;
		currentSettings.borderH = 0;
		currentSettings.resizable = true;
		setMargin();
	}

	function setCurrentSettings(settings, deep1, deep2) {
		downloadButton = '<a href="'+(currentSettings.dloadURL ? currentSettings.dloadURL : currentSettings.url)+'" target="_blank" class="link_download">Download</a>'; // Adding automaticly as the first child of #nyroModalWrapper
				
		if (modal.started) {
			if (deep1 && deep2) {
				$.extend(true, currentSettings[deep1][deep2], settings);
			} else if (deep1) {
				$.extend(true, currentSettings[deep1], settings);
			} else {
				if (modal.animContent) {
					if (settings.width) {
						settings.setWidth = settings.width;
						delete settings['width'];
						shouldResize = true;
					}
					if (settings.height) {
						settings.setHeight = settings.height;
						delete settings['height'];
						shouldResize = true;
					}
				}
				$.extend(true, currentSettings, settings);
			}
		} else {
			if (deep1 && deep2) {
				$.extend(true, $.fn.nyroModal.settings[deep1][deep2], settings);
			} else if (deep1) {
				$.extend(true, $.fn.nyroModal.settings[deep1], settings);
			} else {
				$.extend(true, $.fn.nyroModal.settings, settings);
			}
		}
	}

	// Set the margin for postionning the element. Useful for IE6
	function setMarginScroll() {
		if (isIE6 && !modal.blocker) {
			if (document.documentElement) {
				currentSettings.marginScrollLeft = document.documentElement.scrollLeft;
				currentSettings.marginScrollTop = document.documentElement.scrollTop;
			} else {
				currentSettings.marginScrollLeft = document.body.scrollLeft;
				currentSettings.marginScrollTop = document.body.scrollTop;
			}
		} else {
			currentSettings.marginScrollLeft = 0;
			currentSettings.marginScrollTop = 0;
		}
	}

	// Set the margin for the content
	function setMargin() {
		setMarginScroll();
		currentSettings.marginLeft = -(currentSettings.width+currentSettings.borderW)/2;
		currentSettings.marginTop = -(currentSettings.height+currentSettings.borderH)/2;
		if (!modal.blocker) {
			currentSettings.marginLeft+= currentSettings.marginScrollLeft;
			currentSettings.marginTop+= currentSettings.marginScrollTop;
		}
	}

	// Set the margin for the current loading
	function setMarginLoading() {
		setMarginScroll();
		var outer = getOuter(modal.loading);
		currentSettings.marginTopLoading = -(modal.loading.height() + outer.h.border + outer.h.padding)/2;
		currentSettings.marginLeftLoading = -(modal.loading.width() + outer.w.border + outer.w.padding)/2;
		if (!modal.blocker) {
			currentSettings.marginLefttLoading+= currentSettings.marginScrollLeft;
			currentSettings.marginTopLoading+= currentSettings.marginScrollTop;
		}
	}

	// Set the modal Title
	function setTitle() {
		var title = $('h1#nyroModalTitle', modal.contentWrapper);
		if (title.length)
			title.text(currentSettings.title);
		else
			modal.contentWrapper.prepend('<h1 id="nyroModalTitle">'+currentSettings.title+'</h1>');
	}

	// Init the nyroModal div by settings the CSS elements and hide needed elements
	function initModal() {
		debug('initModal');
		if (!modal.full) {
			if (currentSettings.debug)
				setCurrentSettings({color: 'white'}, 'css', 'bg');

			var full = {
				zIndex: 100,
				position: 'fixed',
				top: 0,
				left: 0,
				width: '100%',
				height: '100%'
			};

			var contain = body;
			var iframeHideIE = '';
			if (currentSettings.blocker) {
				modal.blocker = contain = $(currentSettings.blocker);
				var pos = modal.blocker.offset();
				var w = modal.blocker.outerWidth();
				var h = modal.blocker.outerHeight();
				if (isIE6) {
					setCurrentSettings({
						height: '100%',
						width: '100%',
						top: 0,
						left: 0
					}, 'css', 'bg');
				}
				modal.blockerVars = {
					top: pos.top,
					left: pos.left,
					width: w,
					height: h
				};
				var plusTop = (/msie/.test(userAgent) ?0:getCurCSS(body.get(0), 'borderTopWidth'));
				var plusLeft = (/msie/.test(userAgent) ?0:getCurCSS(body.get(0), 'borderLeftWidth'));
				full = {
					position: 'absolute',
					top: pos.top + plusTop,
					left: pos.left + plusLeft,
					width: w,
					height: h
				};
			} else if (isIE6) {
				body.css({
					height: body.height()+'px',
					width: body.width()+'px',
					position: 'static',
					overflow: 'hidden'
				});
				$('html').css({overflow: 'hidden'});
				setCurrentSettings({
					css: {
						bg: {
							position: 'absolute',
							zIndex: 101,
							height: '110%',
							width: '110%',
							top: currentSettings.marginScrollTop+'px',
							left: currentSettings.marginScrollLeft+'px'
						},
						wrapper: { zIndex: 102	},
						loading: { zIndex: 103	}
					}
				});

				iframeHideIE = $('<iframe id="nyroModalIframeHideIe"></iframe>')
								.css($.extend({},
									currentSettings.css.bg, {
										opacity: 0,
										zIndex: 50,
										border: 'none'
									}));
			}

			contain.append($('<div id="nyroModalFull"><div id="nyroModalBg"></div><div id="nyroModalWrapper"><div id="nyroModalContent"></div></div><div id="nyrModalTmp"></div><div id="nyroModalLoading"></div></div>').hide());

			modal.full = $('#nyroModalFull')
				.css(full)
				.show();
			modal.bg = $('#nyroModalBg')
				.css($.extend({
						backgroundColor: currentSettings.bgColor
					}, currentSettings.css.bg))
				.before(iframeHideIE);
			if (!currentSettings.modal)
				modal.bg.click(removeModal);
			modal.loading = $('#nyroModalLoading')
				.css(currentSettings.css.loading)
				.hide();
			modal.contentWrapper = $('#nyroModalWrapper')
				.css(currentSettings.css.wrapper)
				.hide();
			modal.content = $('#nyroModalContent');
			modal.tmp = $('#nyrModalTmp').hide();

			// To stop the mousewheel if the the plugin is available
			if ($.isFunction($.fn.mousewheel)) {
				modal.content.mousewheel(function(e, d) {
					var elt = modal.content.get(0);
					if ((d > 0 && elt.scrollTop == 0) ||
							(d < 0 && elt.scrollHeight - elt.scrollTop == elt.clientHeight)) {
						e.preventDefault();
						e.stopPropagation();
					}
				});
			}

			$(document).keydown(keyHandler);
			modal.content.css({width: 'auto', height: 'auto'});
			modal.contentWrapper.css({width: 'auto', height: 'auto'});
		}
	}

	// Show the modal (ie: the background and then the loading if needed or the content directly)
	function showModal() {
		debug('showModal');
		if (!modal.ready) {
			initModal();
			modal.anim = true;
			currentSettings.showBackground(modal, currentSettings, endBackground);
		} else {
			modal.anim = true;
			modal.transition = true;
			currentSettings.showTransition(modal, currentSettings, function(){endHideContent();modal.anim=false;showContentOrLoading();});
		}
	}

	// Used for the escape key or the arrow in the gallery type
	function keyHandler(e) {
		if (e.keyCode == 27) {
			if (!currentSettings.modal)
				removeModal();
		} else if (currentSettings.gallery && modal.ready && modal.dataReady && !modal.anim && !modal.transition) {
			if (e.keyCode == 39 || e.keyCode == 40) {
				e.preventDefault();
				$.nyroModalNext();
				return false;
			} else if (e.keyCode == 37 || e.keyCode == 38) {
				e.preventDefault();
				$.nyroModalPrev();
				return false;
			}
		}
	}

	// Determine the filetype regarding the link DOM element
	function fileType() {
		if (currentSettings.forceType) {
			var tmp = currentSettings.forceType;
			if (!currentSettings.content)
				currentSettings.from = true;
			currentSettings.forceType = null;
			return tmp;
		}

		var from = currentSettings.from;

		var url;

		if (from && from.nodeName) { 

			var jFrom = $(from);
			currentSettings.url = url = from.nodeName.toLowerCase() == 'form' ? jFrom.attr('action') : from.href;
			currentSettings.dloadURL = from.name;

			if (jFrom.attr('rev') == 'modal')
				currentSettings.modal = true;

			currentSettings.title = jFrom.attr('title');

			if (from && from.rel)
				currentSettings.gallery = from.rel;

			var imgType = imageType(url, from);
			if (imgType)
				return imgType;

			var iframe = false;
			if (from.target && from.target.toLowerCase() == '_blank' || (from.hostname && from.hostname.replace(/:\d*$/,'') != window.location.hostname.replace(/:\d*$/,''))) {
				iframe = true;
			}
			if (from.nodeName.toLowerCase() == 'form') {
				if (iframe)
					return 'iframeForm';
				setCurrentSettings(extractUrlSel(url));
				if (jFrom.attr('enctype') == 'multipart/form-data')
					return 'formData';
				return 'form';
			}
			if (iframe)
				return 'iframe';
		} else {
			url = currentSettings.url;
			if (!currentSettings.content)
				currentSettings.from = true;

			if (!url)
				return null;

			var reg1 = new RegExp("^http://", "g");
			if (url.match(reg1))
				return 'iframe';
		}

		var imgType = imageType(url, from);
		if (imgType)
			return imgType;

		var swf = new RegExp('[^\.]\.(swf)\s*$', 'i');
		if (swf.test(url))
			return 'swf';

		var tmp = extractUrlSel(url);
		setCurrentSettings(tmp);

		if (!tmp.url)
			return tmp.selector;
	}

	function imageType(url, from) {
		var image = new RegExp(currentSettings.regexImg, 'i');
		if (image.test(url)) {
			return 'image';
		}
	}

	function extractUrlSel(url) {
		var ret = {
			url: null,
			selector: null
		};

		if (url) {
			var hash = getHash(url);
			var hashLoc = getHash(window.location.href);
			var curLoc = window.location.href.substring(0, window.location.href.length - hashLoc.length);
			var req = url.substring(0, url.length - hash.length);

			if (req == curLoc) {
				ret.selector = hash;
			} else {
				ret.url = req;
				ret.selector = hash;
			}
		}
		return ret;
	}

	// Called when the content cannot be loaded or tiemout reached
	function loadingError() {
		debug('loadingError');

		modal.error = true;

		if (!modal.ready)
			return;

		if ($.isFunction(currentSettings.handleError))
			currentSettings.handleError(modal, currentSettings);

		modal.loading
			.addClass(currentSettings.errorClass)
			.html(currentSettings.contentError);
		$(currentSettings.closeSelector, modal.loading).click(removeModal);
		setMarginLoading();
		modal.loading
			.css({
				marginTop: currentSettings.marginTopLoading+'px',
				marginLeft: currentSettings.marginLeftLoading+'px'
			});
	}

	// Put the content from modal.tmp to modal.content
	function fillContent() {
		debug('fillContent');
		if (!modal.tmp.html())
			return;

		modal.content.html(modal.tmp.contents());
		modal.tmp.empty();
		wrapContent();

		if (currentSettings.type == 'iframeForm') {
			$(currentSettings.from)
				.attr('target', 'nyroModalIframe')
				.data('processing', 1)
				.submit()
				.attr('target', '_blank')
				.removeData('processing');
		}

		if ($.isFunction(currentSettings.endFillContent))
			currentSettings.endFillContent(modal, currentSettings);

		modal.content.append(modal.scripts);

		$(currentSettings.closeSelector, modal.contentWrapper).click(removeModal);
		$(currentSettings.openSelector, modal.contentWrapper).nyroModal(getCurrentSettingsNew());
	}

	// Get the current settings to be used in new links
	function getCurrentSettingsNew() {
		var currentSettingsNew = $.extend(true, {}, currentSettings);
		if (resized.width)
			currentSettingsNew.width = null;
		if (resized.height)
			currentSettingsNew.height = null;
		currentSettingsNew.css.content.overflow = 'auto';
		return currentSettingsNew;
	}

	// Wrap the content and update the modal size if needed
	function wrapContent() {
		debug('wrapContent');

		var wrap = $(currentSettings.wrap[currentSettings.type]);
		modal.content.append(wrap.children().remove());
		modal.contentWrapper.wrapInner(wrap);

		if (currentSettings.gallery) {
			// Set the action for the next and prev button (or remove them)
			modal.content.append(currentSettings.galleryLinks);

			var currentSettingsNew = getCurrentSettingsNew();

			var linkPrev = getGalleryLink(-1);
			if (linkPrev) {
				var prev = $('.nyroModalPrev', modal.contentWrapper)
					.attr('href', linkPrev.attr('href')) 
					.attr('name', linkPrev.attr('name'))
					.click(function(e) {
						e.preventDefault();
						linkPrev.nyroModalManual(currentSettingsNew);
						return false;
					});
				if (isIE6 && currentSettings.type == 'swf') {
					prev.before($('<iframe id="nyroModalIframeHideIeGalleryPrev"></iframe>').css({
											position: prev.css('position'),
											top: prev.css('top'),
											left: prev.css('left'),
											width: prev.width(),
											height: prev.height(),
											opacity: 0,
											border: 'none'
										}));
				}
			} else {
				$('.nyroModalPrev', modal.contentWrapper).remove();
			}
			var linkNext = getGalleryLink(1);
			if (linkNext) {
				var next = $('.nyroModalNext', modal.contentWrapper)
					.attr('href', linkNext.attr('href')) 
					.attr('name', linkNext.attr('name'))
					.click(function(e) {
						e.preventDefault();
						linkNext.nyroModalManual(currentSettingsNew);
						return false;
					});
				if (isIE6 && currentSettings.type == 'swf') {
					next.before($('<iframe id="nyroModalIframeHideIeGalleryNext"></iframe>')
									.css($.extend({}, {
											position: next.css('position'),
											top: next.css('top'),
											left: next.css('left'),
											width: next.width(),
											height: next.height(),
											opacity: 0,
											border: 'none'
										})));
				}
			} else {
				$('.nyroModalNext', modal.contentWrapper).remove();
			}
		}

		calculateSize();
	}

	function getGalleryLink(dir) {
		if (currentSettings.gallery) {
			if (!currentSettings.ltr)
				dir *= -1;
			// next
			var gallery = $('[rel="'+currentSettings.gallery+'"]');
			var currentIndex = gallery.index(currentSettings.from);
			var index = currentIndex + dir;
			if (index >= 0 && index < gallery.length)
				return gallery.eq(index);
		}
		return false;
	}

	// Calculate the size for the contentWrapper
	function calculateSize(resizing) {
		debug('calculateSize');

		if (!modal.wrapper)
			modal.wrapper = modal.contentWrapper.children(':first');

		resized.width = false;
		resized.height = false;
		if (currentSettings.autoSizable && (!currentSettings.width || !currentSettings.height)) {
			modal.contentWrapper
				.css({
					opacity: 0,
					width: 'auto',
					height: 'auto'
				})
				.show();
			var tmp = {
				width: 'auto',
				height: 'auto'
			};
			if (currentSettings.width) {
				tmp.width = currentSettings.width;
			} else if (currentSettings.type == 'iframe') {
				tmp.width = currentSettings.minWidth;
			}
				
			if (currentSettings.height) {
				tmp.height = currentSettings.height
			} else if (currentSettings.type == 'iframe') {
				tmp.height = currentSettings.minHeight;
			}
			
			modal.content.css(tmp);
			if (!currentSettings.width) {
				currentSettings.width = modal.content.outerWidth(true);
				resized.width = true;
			}
			if (!currentSettings.height) {
				currentSettings.height = modal.content.outerHeight(true);
				resized.height = true;
			}
			modal.contentWrapper.hide().css({opacity: 1});
		}

		currentSettings.width = Math.max(currentSettings.width, currentSettings.minWidth);
		currentSettings.height = Math.max(currentSettings.height, currentSettings.minHeight);

		var outerWrapper = getOuter(modal.contentWrapper);
		var outerWrapper2 = getOuter(modal.wrapper);
		var outerContent = getOuter(modal.content);

		var tmp = {
			content: {
				width: currentSettings.width,
				height: currentSettings.height
			},
			wrapper2: {
				width: currentSettings.width + outerContent.w.total,
				height: currentSettings.height + outerContent.h.total
			},
			wrapper: {
				width: currentSettings.width + outerContent.w.total + outerWrapper2.w.total,
				height: currentSettings.height + outerContent.h.total + outerWrapper2.h.total
			}
		};

		if (currentSettings.resizable) {
			var maxHeight = modal.blockerVars? modal.blockerVars.height : $(window).height()
								- outerWrapper.h.border
								- (tmp.wrapper.height - currentSettings.height);
			var maxWidth = modal.blockerVars? modal.blockerVars.width : $(window).width()
								- outerWrapper.w.border
								- (tmp.wrapper.width - currentSettings.width);
			maxHeight-= currentSettings.padding*2;
			maxWidth-= currentSettings.padding*2;

			if (tmp.content.height > maxHeight || tmp.content.width > maxWidth) {
				// We're gonna resize the modal as it will goes outside the view port
				if (currentSettings.type == 'image') {
					// An image is resized proportionnaly
					var diffW = tmp.content.width - currentSettings.imgWidth;
					var diffH = tmp.content.height - currentSettings.imgHeight;
						if (diffH < 0) diffH = 0;
						if (diffW < 0) diffW = 0;
					var calcH = maxHeight - diffH;
					var calcW = maxWidth - diffW;
					var ratio = Math.min(calcH/currentSettings.imgHeight, calcW/currentSettings.imgWidth);

					calcH = Math.floor(currentSettings.imgHeight*ratio);
					calcW = Math.floor(currentSettings.imgWidth*ratio);
					$('img#nyroModalImg', modal.content).css({
						height: calcH+'px',
						width: calcW+'px'
					});
					tmp.content.height = calcH + diffH;
					tmp.content.width = calcW + diffW;
				} else {
					// For an HTML content, we simply decrease the size
					tmp.content.height = Math.min(tmp.content.height, maxHeight);
					tmp.content.width = Math.min(tmp.content.width, maxWidth);
				}
				tmp.wrapper2 = {
						width: tmp.content.width + outerContent.w.total,
						height: tmp.content.height + outerContent.h.total
					};
				tmp.wrapper = {
						width: tmp.content.width + outerContent.w.total + outerWrapper2.w.total,
						height: tmp.content.height + outerContent.h.total + outerWrapper2.h.total
					};
			}
		}

		modal.content.css($.extend({}, tmp.content, currentSettings.css.content));
		modal.wrapper.css($.extend({}, tmp.wrapper2, currentSettings.css.wrapper2));

		if (!resizing) {
			modal.contentWrapper.css($.extend({}, tmp.wrapper, currentSettings.css.wrapper));
			if (currentSettings.type == 'image') {
				// Adding the title for the image
				var title = $('img', modal.content).attr('alt');
				$('img', modal.content).removeAttr('alt');
				if (title != currentSettings.defaultImgAlt) {
					var divTitle = $('<div>'+title+'</div>');
					modal.content.append(divTitle);
					if (currentSettings.setWidthImgTitle) {
						var outerDivTitle = getOuter(divTitle);
						divTitle.css({width: (tmp.content.width + outerContent.w.padding - outerDivTitle.w.total)+'px'});
					}
				}
			}

			if (!currentSettings.modal)
				//modal.contentWrapper.prepend(currentSettings.closeButton);
				modal.contentWrapper.prepend(currentSettings.closeButton, downloadButton);
		}

		if (currentSettings.title)
			setTitle();

		tmp.wrapper.borderW = outerWrapper.w.border;
		tmp.wrapper.borderH = outerWrapper.h.border;

		setCurrentSettings(tmp.wrapper);
		setMargin();
	}

	function removeModal(e) {
		debug('removeModal');
		if (e)
			e.preventDefault();
		if (modal.full && modal.ready) {
			modal.ready = false;
			modal.anim = true;
			modal.closing = true;
			if (modal.loadingShown || modal.transition) {
				currentSettings.hideLoading(modal, currentSettings, function() {
						modal.loading.hide();
						modal.loadingShown = false;
						modal.transition = false;
						currentSettings.hideBackground(modal, currentSettings, endRemove);
					});
			} else {
				if (fixFF)
					modal.content.css({position: ''}); // Fix Issue #10, remove the attribute
				modal.wrapper.css({overflow: 'hidden'}); // Used to fix a visual issue when hiding
				modal.content.css({overflow: 'hidden'}); // Used to fix a visual issue when hiding
				if ($.isFunction(currentSettings.beforeHideContent)) {
					currentSettings.beforeHideContent(modal, currentSettings, function() {
						currentSettings.hideContent(modal, currentSettings, function() {
							endHideContent();
							currentSettings.hideBackground(modal, currentSettings, endRemove);
						});
					});
				} else {
					currentSettings.hideContent(modal, currentSettings, function() {
							endHideContent();
							currentSettings.hideBackground(modal, currentSettings, endRemove);
						});
				}
			}
		}
		if (e)
			return false;
	}

	function showContentOrLoading() {
		debug('showContentOrLoading');
		if (modal.ready && !modal.anim) {
			if (modal.dataReady) {
				if (modal.tmp.html()) {
					modal.anim = true;
					if (modal.transition) {
						fillContent();
						modal.animContent = true;
						currentSettings.hideTransition(modal, currentSettings, function() {
							modal.loading.hide();
							modal.transition = false;
							modal.loadingShown = false;
							endShowContent();
						});
					} else {
						currentSettings.hideLoading(modal, currentSettings, function() {
								modal.loading.hide();
								modal.loadingShown = false;
								fillContent();
								setMarginLoading();
								setMargin();
								modal.animContent = true;
								currentSettings.showContent(modal, currentSettings, endShowContent);
							});
					}
				}
			} else if (!modal.loadingShown && !modal.transition) {
				modal.anim = true;
				modal.loadingShown = true;
				if (modal.error)
					loadingError();
				else
					modal.loading.html(currentSettings.contentLoading);
				$(currentSettings.closeSelector, modal.loading).click(removeModal);
				setMarginLoading();
				currentSettings.showLoading(modal, currentSettings, function(){modal.anim=false;showContentOrLoading();});
			}
		}
	}


	// -------------------------------------------------------
	// Private Data Loaded callback
	// -------------------------------------------------------

	function ajaxLoaded(data) {
		debug('AjaxLoaded: '+this.url);
		modal.tmp.html(currentSettings.selector
			?filterScripts($('<div>'+data+'</div>').find(currentSettings.selector).contents())
			:filterScripts(data));
		if (modal.tmp.html()) {
			modal.dataReady = true;
			showContentOrLoading();
		} else
			loadingError();
	}

	function formDataLoaded() {
		debug('formDataLoaded');
		var jFrom = $(currentSettings.from);
		jFrom.attr('action', jFrom.attr('action')+currentSettings.selector);
		jFrom.attr('target', '');
		$('input[name='+currentSettings.formIndicator+']', currentSettings.from).remove();
		var iframe = modal.tmp.children('iframe');
		var iframeContent = iframe.unbind('load').contents().find(currentSettings.selector || 'body').not('script[src]');
		iframe.attr('src', 'about:blank'); // Used to stop the loading in FF
		modal.tmp.html(iframeContent.html());
		if (modal.tmp.html()) {
			modal.dataReady = true;
			showContentOrLoading();
		} else
			loadingError();
	}


	// -------------------------------------------------------
	// Private Animation callback
	// -------------------------------------------------------

	function endHideContent() {
		debug('endHideContent');
		modal.anim = false;
		if (contentEltLast) {
			contentEltLast.append(modal.content.contents());
			contentEltLast= null;
		} else if (contentElt) {
			contentElt.append(modal.content.contents());
			contentElt= null;
		}
		modal.content.empty();
		
		modal.contentWrapper.hide().children().remove().empty().attr('style', '').hide();

		if (modal.closing || modal.transition)
			modal.contentWrapper.hide();

		modal.contentWrapper
			.css(currentSettings.css.wrapper)
			.append(modal.content);
		showContentOrLoading();
	}

	function endRemove() {
		debug('endRemove');
		$(document).unbind('keydown', keyHandler);
		modal.anim = false;
		modal.full.remove();
		modal.full = null;
		if (isIE6) {
			body.css({height: '', width: '', position: '', overflow: ''});
			$('html').css({overflow: ''});
		}
		if ($.isFunction(currentSettings.endRemove))
			currentSettings.endRemove(modal, currentSettings);
	}

	function endBackground() {
		debug('endBackground');
		modal.ready = true;
		modal.anim = false;
		showContentOrLoading();
	}

	function endShowContent() {
		debug('endShowContent');
		modal.anim = false;
		modal.animContent = false;
		modal.contentWrapper.css({opacity: ''}); // for the close button in IE
		fixFF = /mozilla/.test(userAgent) && !/(compatible|webkit)/.test(userAgent) && parseFloat(browserVersion) < 1.9 && currentSettings.type != 'image';
		if (fixFF)
			modal.content.css({position: 'fixed'}); // Fix Issue #10
		modal.content.append(modal.scriptsShown);
		if (currentSettings.autoSizable && currentSettings.type == 'iframe') {
			var iframe = modal.content.find('iframe');
			if (iframe.length && iframe.attr('src').indexOf(window.location.hostname) !== -1) {
				var body = iframe.contents().find('body');
			
				if (body.height() > 0) {
					var h = body.outerHeight(true)+1;
					var w = body.outerWidth(true)+1;
					$.nyroModalSettings({
						height: h,
						width: w
					});
				} else {
					iframe.bind('load', function() {
						var body = iframe.contents().find('body');
						if (body.length && body.height() > 0) {
							var h = body.outerHeight(true)+1;
							var w = body.outerWidth(true)+1;
							$.nyroModalSettings({
								height: h,
								width: w
							});
						}
					});
				}
			}
		}
		if ($.isFunction(currentSettings.endShowContent))
			currentSettings.endShowContent(modal, currentSettings);
		if (shouldResize) {
			shouldResize = false;
			$.nyroModalSettings({width: currentSettings.setWidth, height: currentSettings.setHeight});
			delete currentSettings['setWidth'];
			delete currentSettings['setHeight'];
		}
		if (resized.width)
			setCurrentSettings({width: null});
		if (resized.height)
			setCurrentSettings({height: null});
	}


	// -------------------------------------------------------
	// Utilities
	// -------------------------------------------------------

	// Get the selector from an url (as string)
	function getHash(url) {
		if (typeof url == 'string') {
			var hashPos = url.indexOf('#');
			if (hashPos > -1)
				return url.substring(hashPos);
		}
		return '';
	}

	// Filter an html content to remove the script[src]
	function filterScripts(data) {
		// Removing the body, head and html tag
		if (typeof data == 'string')
			data = data.replace(/<\/?(html|head|body)([^>]*)>/gi, '');
		var tmp = new Array();
		$.each($.clean({0:data}, this.ownerDocument), function() {
			if ($.nodeName(this, "script")) {
				if (!this.src || $(this).attr('rel') == 'forceLoad') {
					if ($(this).attr('rev') == 'shown')
						modal.scriptsShown.push(this);
					else
						modal.scripts.push(this);
				}
			} else
				tmp.push(this);
		});
		return tmp;
	}

	// Get the vertical and horizontal margin, padding and border dimension
	function getOuter(elm) {
		elm = elm.get(0);
		var ret = {
			h: {
				margin: getCurCSS(elm, 'marginTop') + getCurCSS(elm, 'marginBottom'),
				border: getCurCSS(elm, 'borderTopWidth') + getCurCSS(elm, 'borderBottomWidth'),
				padding: getCurCSS(elm, 'paddingTop') + getCurCSS(elm, 'paddingBottom')
			},
			w: {
				margin: getCurCSS(elm, 'marginLeft') + getCurCSS(elm, 'marginRight'),
				border: getCurCSS(elm, 'borderLeftWidth') + getCurCSS(elm, 'borderRightWidth'),
				padding: getCurCSS(elm, 'paddingLeft') + getCurCSS(elm, 'paddingRight')
			}
		};

		ret.h.outer = ret.h.margin + ret.h.border;
		ret.w.outer = ret.w.margin + ret.w.border;

		ret.h.inner = ret.h.padding + ret.h.border;
		ret.w.inner = ret.w.padding + ret.w.border;

		ret.h.total = ret.h.outer + ret.h.padding;
		ret.w.total = ret.w.outer + ret.w.padding;

		return ret;
	}

	function getCurCSS(elm, name) {
		var ret = parseInt($.curCSS(elm, name, true));
		if (isNaN(ret))
			ret = 0;
		return ret;
	}

	// Proxy Debug function
	function debug(msg) {
		if ($.fn.nyroModal.settings.debug || currentSettings && currentSettings.debug)
			nyroModalDebug(msg, modal, currentSettings || {});
	}

	// -------------------------------------------------------
	// Default animation function
	// -------------------------------------------------------

	function showBackground(elts, settings, callback) {
		elts.bg.css({opacity:0}).fadeTo(500, 0.75, callback);
	}

	function hideBackground(elts, settings, callback) {
		elts.bg.fadeOut(300, callback);
	}

	function showLoading(elts, settings, callback) {
		elts.loading
			.css({
				marginTop: settings.marginTopLoading+'px',
				marginLeft: settings.marginLeftLoading+'px',
				opacity: 0
			})
			.show()
			.animate({
				opacity: 1
			}, {complete: callback, duration: 400});
	}

	function hideLoading(elts, settings, callback) {
		callback();
	}

	function showContent(elts, settings, callback) {
		elts.loading
			.css({
				marginTop: settings.marginTopLoading+'px',
				marginLeft: settings.marginLeftLoading+'px'
			})
			.show()
			.animate({
				width: settings.width+'px',
				height: settings.height+'px',
				marginTop: settings.marginTop+'px',
				marginLeft: settings.marginLeft+'px'
			}, {duration: 350, complete: function() {
				elts.contentWrapper
					.css({
						width: settings.width+'px',
						height: settings.height+'px',
						marginTop: settings.marginTop+'px',
						marginLeft: settings.marginLeft+'px'
					})
					.show();
					elts.loading.fadeOut(200, callback);
				}
			});
	}

	function hideContent(elts, settings, callback) {
		elts.contentWrapper
			.animate({
				height: '50px',
				width: '50px',
				marginTop: (-(25+settings.borderH)/2 + settings.marginScrollTop)+'px',
				marginLeft: (-(25+settings.borderW)/2 + settings.marginScrollLeft)+'px'
			}, {duration: 350, complete: function() {
				elts.contentWrapper.hide();
				callback();
			}});
	}

	function showTransition(elts, settings, callback) {
		// Put the loading with the same dimensions of the current content
		elts.loading
			.css({
				marginTop: elts.contentWrapper.css('marginTop'),
				marginLeft: elts.contentWrapper.css('marginLeft'),
				height: elts.contentWrapper.css('height'),
				width: elts.contentWrapper.css('width'),
				opacity: 0
			})
			.show()
			.fadeTo(400, 1, function() {
					elts.contentWrapper.hide();
					callback();
				});
	}

	function hideTransition(elts, settings, callback) {
		// Place the content wrapper underneath the the loading with the right dimensions
		elts.contentWrapper
			.hide()
			.css({
				width: settings.width+'px',
				height: settings.height+'px',
				marginLeft: settings.marginLeft+'px',
				marginTop: settings.marginTop+'px',
				opacity: 1
			});
		elts.loading
			.animate({
				width: settings.width+'px',
				height: settings.height+'px',
				marginLeft: settings.marginLeft+'px',
				marginTop: settings.marginTop+'px'
			}, {complete: function() {
					elts.contentWrapper.show();
					elts.loading.fadeOut(400, function() {
						elts.loading.hide();
						callback();
					});
				}, duration: 350});
	}

	function resize(elts, settings, callback) {
		elts.contentWrapper
			.animate({
				width: settings.width+'px',
				height: settings.height+'px',
				marginLeft: settings.marginLeft+'px',
				marginTop: settings.marginTop+'px'
			}, {complete: callback, duration: 400});
	}

	function updateBgColor(elts, settings, callback) {
		if (!$.fx.step.backgroundColor) {
			elts.bg.css({backgroundColor: settings.bgColor});
			callback();
		} else
			elts.bg
				.animate({
					backgroundColor: settings.bgColor
				}, {complete: callback, duration: 400});
	}

	// -------------------------------------------------------
	// Default initialization
	// -------------------------------------------------------

	$($.fn.nyroModal.settings.openSelector).nyroModal();

});

// Default debug function, to be overwritten if needed
//      Be aware that the settings parameter could be empty
function nyroModalDebug(msg, elts, settings) {
	if (elts.full)
		elts.bg.prepend(msg+'<br />');
}
