/* * nyroModal - jQuery Plugin * http://nyromodal.nyrodev.com * * Copyright (c) 2008 Cedric Nirousset (nyrodev.com) * Licensed under the MIT license * * $Date: 2008-11-29 (Sat, 29 Nov 2008) $ * $version: 1.3.1 */ jQuery(function($) { // ------------------------------------------------------- // Private Variables // ------------------------------------------------------- var isIE6 = ($.browser.msie && parseInt($.browser.version.substr(0,1)) < 7); var body = $('body'); var currentSettings; // 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, loadingShown: false, transition: false, error: false, full: null, bg: null, loading: null, tmp: null, content: null, wrapper: null, closing: false, contentWrapper: null, scripts: 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.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 (!deep1 && modal.started) { if (modal.bg && settings.bgColor) currentSettings.updateBgColor(modal, currentSettings, function(){}); if (modal.contentWrapper && settings.title) { title = $('h1#nyroModalTitle', modal.contentWrapper); if (title.length) title.text(settings.title); else modal.contentWrapper.prepend('

'+settings.title+'

'); } if (modal.content && (modal.dataReady && !modal.anim && !modal.transition) && (settings.width || settings.height)) { calculateSize(true); 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(currentSettings); 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(currentSettings); return false; }; // ------------------------------------------------------- // Default Settings // ------------------------------------------------------- $.fn.nyroModal.settings = { debug: false, // Show the debug in the background 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: 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)\s*$', // Regex to find images 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 css: { // Default CSS option for the nyroModal Div. Some will be overwritten or updated when using IE6 bg: { zIndex: 100, position: 'fixed', top: 0, left: 0, height: '100%', width: '100%' }, wrapper: { zIndex: 101, position: 'fixed', top: '50%', left: '50%' }, wrapper2: { }, content: { overflow: 'auto' }, loading: { zIndex: 102, position: 'fixed', top: '50%', left: '50%', marginTop: '-50px', marginLeft: '-50px' } }, wrap: { // Wrapper div used to style the modal regarding the content type div: '
', ajax: '
', form: '
', formData: '
', image: '
', gallery: '
PrevNext
', // Use .nyroModalPrev and .nyroModalNext to set the navigation link swf: '
', iframe: '
', manual: '
' }, closeButton: 'Close', // 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: 'Cancel', // Loading div content errorClass: 'error', // CSS Error class added to the loading div in case of error contentError: 'The requested content cannot be loaded.
Please try again later.
Close', // 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); modal.error = false; modal.closing = false; modal.dataReady = false; modal.scripts = 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 = ''; var tmp = ''; $.each(currentSettings.swf, function(name, val) { currentSettings.content+= ''; tmp+= ' '+name+'="'+val+'"'; }); currentSettings.content+= ''; } 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(''); if (currentSettings.selector) jFrom.prepend(''); modal.tmp.html(''); $('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' || currentSettings.type == 'gallery') { var title = jFrom.attr('title') || currentSettings.defaultImgAlt; initModal(); modal.tmp.html('').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: ''}); 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 == 'iframe') { initModal(); modal.tmp.html(''); debug('Iframe Load: '+url); $('iframe', modal.tmp).eq(0) .css({ width: '100%', height: isDoctypeStrict()? '99%' : '100%' }) .load(function(e) { if (currentSettings.titleFromIframe && url.indexOf(window.location.hostname) > -1) $.nyroModalSettings({title: $('iframe', modal.full).contents().find('title').text()}); }); currentSettings.autoSizable = false; 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(); showModal(); showContentOrLoading(); } 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($('
').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({}, $.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(currentSettings[deep1][deep2], settings); } else if (deep1) { $.extend(currentSettings[deep1], settings); } else { $.extend(currentSettings, settings); } } else { if (deep1 && deep2) { $.extend($.fn.nyroModal.settings[deep1][deep2], settings); } else if (deep1) { $.extend($.fn.nyroModal.settings[deep1], settings); } else { $.extend($.fn.nyroModal.settings, settings); } } } // Set the margin for postionning the element. Useful for IE6 function setMarginScroll() { if (isIE6) { 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.marginScrollLeft; currentSettings.marginTop = -(currentSettings.height+currentSettings.borderH)/2 + 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.marginScrollTop; currentSettings.marginLeftLoading = -(modal.loading.width() + outer.w.border + outer.w.padding)/2 + currentSettings.marginScrollLeft; } // 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 iframeHideIE = ''; if (isIE6) { body.css({ height: body.height()+'px', width: body.width()+'px', position: 'static', overflow: 'hidden' }); $('html').css({overflow: 'hidden'}); setCurrentSettings({ position: 'absolute', height: '110%', width: '110%', top: currentSettings.marginScrollTop+'px', left: currentSettings.marginScrollLeft+'px' }, 'css', 'bg'); setCurrentSettings({position: 'absolute'}, 'css', 'loading'); setCurrentSettings({position: 'absolute'}, 'css', 'wrapper'); iframeHideIE = $('') .css($.extend({}, currentSettings.css.bg, { opacity: 0, zIndex: 50, border: 'none' })); } body.append($('
').hide()); modal.full = $('#nyroModalFull').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.type == 'gallery' && modal.ready && modal.dataReady && !modal.anim && !modal.transition) { if (e.keyCode == 39 || e.keyCode == 40) { e.preventDefault(); $('.nyroModalNext', modal.content).eq(0).trigger('click'); return false; } else if (e.keyCode == 37 || e.keyCode == 38) { e.preventDefault(); $('.nyroModalPrev', modal.content).eq(0).trigger('click'); 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; if (jFrom.attr('rev') == 'modal') currentSettings.modal = true; if (jFrom.attr('title')) currentSettings.title = jFrom.attr('title'); var imgType = imageType(url, from); if (imgType) return imgType; if (from.target && from.target.toLowerCase() == '_blank' || (from.hostname && from.hostname.replace(/:\d*$/,'') != window.location.hostname.replace(/:\d*$/,''))) { return 'iframe'; } else if (from.nodeName.toLowerCase() == 'form') { setCurrentSettings(extractUrlSel(url)); if (jFrom.attr('enctype') == 'multipart/form-data') return 'formData'; return 'form'; } } 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)) { if (from && from.rel) return 'gallery'; else 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 ($.isFunction(currentSettings.endFillContent)) currentSettings.endFillContent(modal, currentSettings); modal.content.append(modal.scripts); var currentSettingsNew = $.extend({}, currentSettings); if (resized.width) currentSettingsNew.width = null; if (resized.height) currentSettingsNew.height = null; $(currentSettings.closeSelector, modal.contentWrapper).click(removeModal); $(currentSettings.openSelector, modal.contentWrapper).nyroModal(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.type == 'gallery') { // Set the action for the next and prev button (or remove them) var linkPrev = getGalleryLink(-1); if (linkPrev) { $('.nyroModalPrev', modal.contentWrapper) .attr('href', linkPrev.attr('href')) .click(function(e) { e.preventDefault(); linkPrev.nyroModalManual(currentSettings); return false; }); } else { $('.nyroModalPrev', modal.contentWrapper).remove(); } var linkNext = getGalleryLink(1); if (linkNext) { $('.nyroModalNext', modal.contentWrapper) .attr('href', linkNext.attr('href')) .click(function(e) { e.preventDefault(); linkNext.nyroModalManual(currentSettings); return false; }); } else { $('.nyroModalNext', modal.contentWrapper).remove(); } } calculateSize(); } function getGalleryLink(dir) { if (currentSettings.type == 'gallery') { if (!currentSettings.ltr) dir *= -1; // next var gallery = $('[rel="'+currentSettings.from.rel+'"]'); 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}).show(); var tmp = { width: 'auto', height: 'auto' }; if (currentSettings.width) tmp.width = currentSettings.width; if (currentSettings.height) tmp.height = currentSettings.height; modal.content.css(tmp); if (!currentSettings.width) { currentSettings.width = modal.content.width(); resized.width = true; } if (!currentSettings.height) { currentSettings.height = modal.content.height(); 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 = $(window).height() - currentSettings.padding*2 - outerWrapper.h.border - (tmp.wrapper.height - currentSettings.height); var maxWidth = $(window).width() - currentSettings.padding*2 - outerWrapper.w.border - (tmp.wrapper.width - currentSettings.width); 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 == 'gallery') { // 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' || currentSettings.type == 'gallery') { // Adding the title for the image var title = $('img', modal.content).attr('alt'); $('img', modal.content).removeAttr('alt'); if (title != currentSettings.defaultImgAlt) { var divTitle = $('
'+title+'
'); 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); } if (currentSettings.title) modal.contentWrapper.prepend('

'+currentSettings.title+'

'); 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(); 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(); currentSettings.showContent(modal, $.extend({}, 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($('
'+data+'
').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 .empty() .removeAttr('style'); 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.contentWrapper.css({opacity: ''}); // for the close button in IE fixFF = $.browser.mozilla && parseFloat($.browser.version) < 1.9 && currentSettings.type != 'gallery' && currentSettings.type != 'image'; if (fixFF) modal.content.css({position: 'fixed'}); // Fix Issue #10 if ($.isFunction(currentSettings.endShowContent)) currentSettings.endShowContent(modal, currentSettings); 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') 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; } function isDoctypeStrict() { var doctype = ''; if ($.browser.opera) { return true; } else if ($.browser.msie) { var re = /\s+(X?HTML)\s+([\d\.]+)\s*([^\/]+)*\//gi; var res = false; if($.browser.msie) res = document.all[0].nodeType == 8 ? re.test(document.all[0].nodeValue) : false; if (res) doctype = RegExp.$3; } else doctype = document.doctype.systemId; return doctype.toLowerCase().indexOf('strict') > -1 } // 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', marginLeft: settings.marginLeft+'px', height: settings.height+'px', marginTop: settings.marginTop+'px', opacity: 1 }); elts.loading .animate({ width: settings.width+'px', marginLeft: settings.marginLeft+'px', height: settings.height+'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', marginLeft: settings.marginLeft+'px', height: settings.height+'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) { console.log(msg); if (elts.full) elts.bg.prepend(msg+'
'); }