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

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

    var userAgent = navigator.userAgent.toLowerCase();
    //var browserVersion = (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [0,'0'])[1];
    var browserVersion = (userAgent.match(/.+(?:rv|webkit|khtml|opera|msie)[\/: ]([\d.]+)/ ) || [0,'0'])[1];

    var isIE6 = (/msie/.test(userAgent) && !/opera/.test(userAgent) && parseInt(browserVersion) < 7 && !window.XMLHttpRequest);
    var body = $('body');

    var currentSettings;

    var shouldResize = false;
	
    var gallery = {};

    // 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,
    resizing: 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,
    windowResizing: false
    };
	
    var initSettingsSize = {
    width: null,
    height: null,
    windowResizing: true
    };
	
    var windowResizeTimeout;


    // -------------------------------------------------------
    // 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() {
	  var me = $(this);
	  if (this.nodeName.toLowerCase() == 'form') {
	    me
	      .unbind('submit.nyroModal')
	      .bind('submit.nyroModal', function(e) {
		  if (me.data('nyroModalprocessing'))
		    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 {
	    me
	      .unbind('click.nyroModal')
	      .bind('click.nyroModal', 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 (!deep1 && modal.started) {
	if (modal.bg && settings.bgColor)
	  currentSettings.updateBgColor(modal, currentSettings, function(){});

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

	if (!modal.error && (settings.windowResizing || (!modal.resizing && (('width' in settings && settings.width == currentSettings.width) || ('height' in settings && settings.height == currentSettings.height))))) {
	  modal.resizing = true;
	  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() {
		currentSettings.windowResizing = false;
		modal.resizing = false;
		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

    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: 160, // Minimum width
    minHeight: 160, // 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: 20, // padding for the max modal size

    regexImg: '[^\.]\.(jpg|jpeg|png|tiff|gif|bmp)\s*$', // Regex to find images
    addImageDivTitle: true, // Indicate if the div title should be inserted
    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
    galleryCounts: galleryCounts, // Callback to show the gallery count
		
    zIndexStart: 100,

    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="ajaxWrapper"></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: '.popup', // selector for open a new modal. will be used to parse automaticly at page loading
    closeSelector: '#theImage,#closeWindowButton', // 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;

      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;

      initSettingsSize.width = currentSettings.width;
      initSettingsSize.height = currentSettings.height;

      if (currentSettings.type == 'swf') {
	// Swf is transforming as a raw content
	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: jFrom.attr('method') ? jFrom.attr('method') : 'get',
				  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" src="javascript:false;"></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') {
	  debug('Image Load: '+url);
	  var title = jFrom.attr('title') || currentSettings.defaultImgAlt;
	  initModal();
	  modal.tmp.html('<img id="nyroModalImg" />').find('img').attr('alt', title);
	  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
		      });
		initSettingsSize.width = w;
		initSettingsSize.height = 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="javascript:false;" 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());
	  }
	  initSettingsSize.width = w;
	  initSettingsSize.height = h;
	  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) {
      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 ('width' in settings) {
	      if (!modal.resizing) {
		settings.setWidth = settings.width;
		shouldResize = true;
	      }
	      delete settings['width'];
	    }
	    if ('height' in settings) {
	      if (!modal.resizing) {
		settings.setHeight = settings.height;
		shouldResize = true;
	      }
	      delete settings['height'];
	    }
	  }
	  $.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() {
      debug('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;
      }
      debug('top: ' +currentSettings.marginTop);
      debug('left: '+currentSettings.marginLeft);
/*       currentSettings.marginLeft = -200; */
/*       currentSettings.marginTop  = -200; */

      debug('width: ' +currentSettings.width);
      debug('height: '+currentSettings.height);

    }

    // Set the margin for the current loading
    function setMarginLoading() {
      debug('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>');
    }

    function setHeader() {
      var headerHtml = '<div id="nyroModalHeader">';
      headerHtml += '<div id="closeLinks">';
      headerHtml += '<a href="#" id="closeWindowButton" title="'+msg_modal_close_title+'">'+msg_modal_close_link+'</a>';
      headerHtml += ' '+msg_modal_esc_key;
      headerHtml += '</div>';
      headerHtml += '</div>';

      $header = $(headerHtml);
      $header.unbind('click');

      $("#iptcLink").click(function() {manageCaption($.caption);return false;});
      $('#info-image').click(function() {removeModal();document.location=this.href;});
      $('#nyroModalWrapper td.tags a').click(function() {removeModal();document.location=this.href;});
      
      $header.prepend($('#info-image'));
      $header.prepend($('#iptcLink'));

      $.caption = $("#nyroModalWrapper .caption");
      if (modal_caption_direction=='bottom') {
	$.caption.addClass('bottom');
      } else {
	$.caption.addClass('top');
      }
      $.caption.hide();

      caddy_link = $(currentSettings.from).parent().parent().find('a.caddy');
      if (caddy_link.length>0) {
	$header.prepend('<span class="separator">|</span>');
	modal.contentWrapper.prepend($header.prepend(caddy_link.clone(true)));
	caddy_link.attr('id', 'cloned');
      } else {
	modal.contentWrapper.prepend($header);
      }
    }

    function manageCaption(caption) {
      if (caption.is(":hidden")) {
	caption.slideDown(1000);
      } else if (!caption.is(":hidden")) {
	caption.slideUp(1000);
      }
      return true;
    }


    // 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: currentSettings.zIndexStart,
	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: currentSettings.zIndexStart+1,
		    height: '110%',
		    width: '110%',
		    top: currentSettings.marginScrollTop+'px',
		    left: currentSettings.marginScrollLeft+'px'
		    },
		  wrapper: { zIndex: currentSettings.zIndexStart+2 },
		  loading: { zIndex: currentSettings.zIndexStart+3 }
	      }
	    });

	  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).bind('keydown.nyroModal', keyHandler);
	modal.content.css({width: 'auto', height: 'auto'});
	modal.contentWrapper.css({width: 'auto', height: 'auto'});
			
	if (!currentSettings.blocker) {
	  $(window).bind('resize.nyroModal', function() {
	      window.clearTimeout(windowResizeTimeout);
	      windowResizeTimeout = window.setTimeout(windowResizeHandler, 200);
	    });
	}
      }
    }
	
    function windowResizeHandler() {
      $.nyroModalSettings(initSettingsSize);
    }

    // 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);
			
	url = jFrom.attr(from.nodeName.toLowerCase() == 'form' ? 'action' : 'href');
	if (!url)
	  url = location.href.substring(window.location.host.length+7);
	currentSettings.url = url;

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

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

	if (from && from.rel && from.rel.toLowerCase() != 'nofollow')
	  currentSettings.gallery = from.rel;

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

	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;
				
	if (isSwf(url))
	  return 'swf';

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

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

      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 isSwf(url) {
      var swf = new RegExp('[^\.]\.(swf)\s*$', 'i');
      return swf.test(url);
    }

    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)
	.unbind('click.nyroModal')
	.bind('click.nyroModal', 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());
      
      currentSettings.width = popup_imageWidth;
      currentSettings.height = popup_imageHeight;
      setHeader();

      modal.tmp.empty();
      wrapContent();

      if (currentSettings.type == 'iframeForm') {
	$(currentSettings.from)
	  .attr('target', 'nyroModalIframe')
	  .data('nyroModalprocessing', 1)
	  .submit()
	  .attr('target', '_blank')
	  .removeData('nyroModalprocessing');
      }
		
      if (!currentSettings.modal)
	modal.wrapper.prepend(currentSettings.closeButton);
				
      if ($.isFunction(currentSettings.endFillContent))
	currentSettings.endFillContent(modal, currentSettings);

      modal.content.append(modal.scripts);

      $(currentSettings.closeSelector, modal.contentWrapper)
	.unbind('click.nyroModal')
	.bind('click.nyroModal', 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;
      else
	currentSettingsNew.width = initSettingsSize.width;
      if (resized.height)
	currentSettingsNew.height = null;
      else
	currentSettingsNew.height = initSettingsSize.height;
      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);
			
	gallery.links = $('[rel="'+currentSettings.gallery+'"]');
	gallery.index = gallery.links.index(currentSettings.from);
			
	if (currentSettings.galleryCounts && $.isFunction(currentSettings.galleryCounts))
	  currentSettings.galleryCounts(gallery.index + 1, gallery.links.length, modal, currentSettings);

	var currentSettingsNew = getCurrentSettingsNew();

	var linkPrev = getGalleryLink(-1);
	if (linkPrev) {
	  var prev = $('.nyroModalPrev', modal.contentWrapper)
	    .attr('href', linkPrev.attr('href'))
	    .click(function(e) {
		e.preventDefault();
		$.nyroModalPrev();
		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'))
	    .click(function(e) {
		e.preventDefault();
		$.nyroModalNext();
		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;
	var index = gallery.index + dir;
	if (index >= 0 && index < gallery.links.length)
	  return gallery.links.eq(index);
      }
      return false;
    }

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

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

      resized.width = false;
      resized.height = false;
      if (false && !currentSettings.windowResizing) {
	initSettingsSize.width = currentSettings.width;
	initSettingsSize.height = currentSettings.height;
      }
		
      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.css({opacity: 1});
	if (!resizing)
	  modal.contentWrapper.hide();
      }

      if (currentSettings.type != 'image' && currentSettings.type != 'swf') {
	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' || currentSettings.type == 'swf') {
	    // An image is resized proportionnaly
	    var useW = currentSettings.imgWidth?currentSettings.imgWidth : currentSettings.width;
	    var useH = currentSettings.imgHeight?currentSettings.imgHeight : currentSettings.height;
	    var diffW = tmp.content.width - useW;
	    var diffH = tmp.content.height - useH;
	    if (diffH < 0) diffH = 0;
	    if (diffW < 0) diffW = 0;
	    var calcH = maxHeight - diffH;
	    var calcW = maxWidth - diffW;
	    var ratio = Math.min(calcH/useH, calcW/useW);
	    calcW = Math.floor(useW*ratio);
	    calcH = Math.floor(useH*ratio);
	    tmp.content.height = calcH + diffH;
	    tmp.content.width = calcW + diffW;
	  } else {
	    debug('html content');
	    // 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
	  };
	}
      }
		
      if (currentSettings.type == 'swf') {
	$('object, embed', modal.content)
	  .attr('width', tmp.content.width)
	  .attr('height', tmp.content.height);
      } else if (currentSettings.type == 'image') {
	$('img', modal.content).css({
	  width: tmp.content.width,
	      height: tmp.content.height
	      });
      }

      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' && currentSettings.addImageDivTitle) {
	// Adding the title for the image
	$('img', modal.content).removeAttr('alt');
	var divTitle = $('div', modal.content);
	if (currentSettings.title != currentSettings.defaultImgAlt && currentSettings.title) {
	  if (divTitle.length == 0) {
	    divTitle = $('<div>'+currentSettings.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'});
	  }
	} else if (divTitle.length = 0) {
	  divTitle.remove();
	}
      }

      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) {
	$(document).unbind('keydown.nyroModal');
	if (!currentSettings.blocker)
	  $(window).unbind('resize.nyroModal');
	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) {
	if ($('#cloned').length>0) {
	  $('#cloned').attr('id','');
	}
	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)
	    .unbind('click.nyroModal')
	    .bind('click.nyroModal', 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();
    }
	
    function galleryCounts(nb, total, elts, settings) {
      settings.title+= (settings.title?' - ':'') +nb+'/'+total;
    }


    // -------------------------------------------------------
    // 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();
		
      gallery = {};
		
      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 />');
}

