/** * @file * * Implement a modal form. * * @see modal.inc for documentation. * * This javascript relies on the CTools ajax responder. */ (function ($) { // Make sure our objects are defined. Drupal.CTools = Drupal.CTools || {}; Drupal.CTools.Modal = Drupal.CTools.Modal || {}; /** * Display the modal * * @todo -- document the settings. */ Drupal.CTools.Modal.show = function (choice) { var opts = {}; if (choice && typeof choice == 'string' && Drupal.settings[choice]) { // This notation guarantees we are actually copying it. $.extend(true, opts, Drupal.settings[choice]); } else if (choice) { $.extend(true, opts, choice); } var defaults = { modalTheme: 'CToolsModalDialog', throbberTheme: 'CToolsModalThrobber', animation: 'show', animationSpeed: 'fast', modalSize: { type: 'scale', width: .8, height: .8, addWidth: 0, addHeight: 0, // How much to remove from the inner content to make space for the // theming. contentRight: 25, contentBottom: 45 }, modalOptions: { opacity: .55, background: '#fff' } }; var settings = {}; $.extend(true, settings, defaults, Drupal.settings.CToolsModal, opts); if (Drupal.CTools.Modal.currentSettings && Drupal.CTools.Modal.currentSettings != settings) { Drupal.CTools.Modal.modal.dialog('destroy').remove(); Drupal.CTools.Modal.modal = null; } Drupal.CTools.Modal.currentSettings = settings; if (!Drupal.CTools.Modal.modal) { Drupal.CTools.Modal.modal = $(Drupal.theme(settings.modalTheme)); } Drupal.CTools.Modal.modal.html(Drupal.theme(settings.throbberTheme)); $el = Drupal.CTools.Modal.modalContent(Drupal.CTools.Modal.modal, settings.modalOptions, settings); $el.dialog('option', 'title', settings.loadingText); /* var resize = function(e) { // When creating the modal, it actually exists only in a theoretical // place that is not in the DOM. But once the modal exists, it is in the // DOM so the context must be set appropriately. var context = e ? document : Drupal.CTools.Modal.modal; if (Drupal.CTools.Modal.currentSettings.modalSize.type == 'scale') { var width = $(window).width() * Drupal.CTools.Modal.currentSettings.modalSize.width; var height = $(window).height() * Drupal.CTools.Modal.currentSettings.modalSize.height; } else { var width = Drupal.CTools.Modal.currentSettings.modalSize.width; var height = Drupal.CTools.Modal.currentSettings.modalSize.height; } // Use the additionol pixels for creating the width and height. $('div.ctools-modal-content', context).css({ 'width': width + Drupal.CTools.Modal.currentSettings.modalSize.addWidth + 'px', 'height': height + Drupal.CTools.Modal.currentSettings.modalSize.addHeight + 'px' }); $('div.ctools-modal-content .modal-content', context).css({ 'width': (width - Drupal.CTools.Modal.currentSettings.modalSize.contentRight) + 'px', 'height': (height - Drupal.CTools.Modal.currentSettings.modalSize.contentBottom) + 'px' }); }; if (!Drupal.CTools.Modal.modal) { Drupal.CTools.Modal.modal = $(Drupal.theme(settings.modalTheme)); if (settings.modalSize.type == 'scale') { //$(window).bind('resize', resize); } } resize(); $('span.modal-title', Drupal.CTools.Modal.modal).html(Drupal.CTools.Modal.currentSettings.loadingText); Drupal.CTools.Modal.modalContent(Drupal.CTools.Modal.modal, settings.modalOptions, settings.animation, settings.animationSpeed); $('#modalContent .modal-content').html(Drupal.theme(settings.throbberTheme)); */ }; /** * Hide the modal */ Drupal.CTools.Modal.dismiss = function () { if (Drupal.CTools.Modal.modal) { Drupal.CTools.Modal.unmodalContent(Drupal.CTools.Modal.modal); } }; /** * Provide the HTML to create the modal dialog. * This is pretty much useless now. */ Drupal.theme.prototype.CToolsModalDialog = function () { return ''; }; /** * Provide the HTML to create the throbber. */ Drupal.theme.prototype.CToolsModalThrobber = function () { var html = ''; html += ' '; return html; }; /** * Figure out what settings string to use to display a modal. */ Drupal.CTools.Modal.getSettings = function (object) { var match = $(object).attr('class').match(/ctools-modal-(\S+)/); if (match) { return match[1]; } }; /** * Click function for modals that can be cached. */ Drupal.CTools.Modal.clickAjaxCacheLink = function () { Drupal.CTools.Modal.show(Drupal.CTools.Modal.getSettings(this)); return Drupal.CTools.AJAX.clickAJAXCacheLink.apply(this); }; /** * Handler to prepare the modal for the response */ Drupal.CTools.Modal.clickAjaxLink = function (e) { e.preventDefault(); Drupal.CTools.Modal.show(Drupal.CTools.Modal.getSettings(this)); }; /** * Submit responder to do an AJAX submit on all modal forms. */ Drupal.CTools.Modal.submitAjaxForm = function (e) { e.preventDefault(); var url = $(this).attr('action'); var form = $(this); Drupal.CTools.AJAX.ajaxSubmit(form, url); }; /** * Bind links that will open modals to the appropriate function. */ Drupal.behaviors.ZZCToolsModal = { attach: function(context) { // Bind links // Note that doing so in this order means that the two classes can be // used together safely. /* * @todo remimplement the warm caching feature $('a.ctools-use-modal-cache:not(.ctools-use-modal-processed)', context) .addClass('ctools-use-modal-processed') .click(Drupal.CTools.Modal.clickAjaxCacheLink) .each(function () { Drupal.CTools.AJAX.warmCache.apply(this); }); */ // register this before the rest to have loadStart trigger before AJAX calls $(context).find('#modalContent') .find('.use-ajax, form') .once('modal-trigger-load') .bind('click submit', function (e) { // Triggers a loadStart event and send original event data. $(this).closest('#modalContent').trigger('loadStart', [e, this]); }); $(context).find('a.ctools-use-modal').once('ctools-use-modal') .click(Drupal.CTools.Modal.clickAjaxLink) .each(function () { // Create a drupal ajax object var element_settings = {}; if ($(this).attr('href')) { element_settings.url = $(this).attr('href'); element_settings.event = 'click'; element_settings.progress = { type: 'throbber' }; } var base = $(this).attr('href'); Drupal.ajax[base] = new Drupal.ajax(base, this, element_settings); } ); // Bind buttons $(context).find('input.ctools-use-modal, button.ctools-use-modal').once('ctools-use-modal') .click(Drupal.CTools.Modal.clickAjaxLink) .each(function() { var button = this; var element_settings = {}; // AJAX submits specified in this manner automatically submit to the // normal form action. element_settings.url = Drupal.CTools.Modal.findURL(this); element_settings.event = 'click'; var base = $(this).attr('id'); Drupal.ajax[base] = new Drupal.ajax(base, this, element_settings); // Make sure changes to settings are reflected in the URL. $('.' + $(button).attr('id') + '-url').change(function() { Drupal.ajax[base].options.url = Drupal.CTools.Modal.findURL(button); }); }); // Bind our custom event to the form submit $(context).find('#modalContent form').once('ctools-use-modal', function() { var element_settings = {}; element_settings.url = $(this).attr('action'); element_settings.event = 'submit'; element_settings.progress = { 'type': 'throbber' } var base = $(this).attr('id'); Drupal.ajax[base] = new Drupal.ajax(base, this, element_settings); Drupal.ajax[base].form = $(this); var buttons = {}; // Transform submit in dialog buttons. $(this).find('input[type=submit], button') .each(function () { var $that = $(this).hide(); var text = $(this).html() || $(this).attr('value'); buttons[text] = function (e) { var that = $that[0]; var base = $(that.form).attr('id'); Drupal.ajax[base].element = that; that.form.clk = that; $(that.form).trigger('submit'); }; }); $(this).closest('#modalContent').dialog('option', 'buttons', buttons); }); } }; // The following are implementations of AJAX responder commands. /** * AJAX responder command to place HTML within the modal. * * Events: * load : content behaviors detached and modal was emptied * loadStop : modal is filled with new content from AJAX response */ Drupal.CTools.Modal.modal_display = function (ajax, response, status) { var $modalContent = $('#modalContent'); if ($modalContent.length == 0) { Drupal.CTools.Modal.show(Drupal.CTools.Modal.getSettings(ajax.element)); } Drupal.detachBehaviors($modalContent[0], null, 'unload'); $modalContent.html(''); $modalContent.trigger('load'); $modalContent.dialog('option', 'title', response.title); $modalContent.html(response.output); // Triggers a event to allow other scripts to react. $modalContent.trigger('loadStop'); } /** * AJAX responder command to dismiss the modal. */ Drupal.CTools.Modal.modal_dismiss = function (command) { Drupal.CTools.Modal.dismiss(); $('link.ctools-temporary-css').remove(); } /** * Display loading */ //Drupal.CTools.AJAX.commands.modal_loading = function(command) { Drupal.CTools.Modal.modal_loading = function (command) { Drupal.CTools.Modal.modal_display({ output: Drupal.theme(Drupal.CTools.Modal.currentSettings.throbberTheme), title: Drupal.CTools.Modal.currentSettings.loadingText }); }; /** * Find a URL for an AJAX button. * * The URL for this gadget will be composed of the values of items by * taking the ID of this item and adding -url and looking for that * class. They need to be in the form in order since we will * concat them all together using '/'. */ Drupal.CTools.Modal.findURL = function(item) { var url = ''; var url_class = '.' + $(item).attr('id') + '-url'; $(url_class).each( function() { if (url && $(this).val()) { url += '/'; } url += $(this).val(); }); return url; }; /** * modalContent * * Events triggered on "window": * modalBeforeCreate : allow DOM element and settings to be tweaked * modalAfterCreate : allow dialog object modification * * * @param content string to display in the content box * @param css obj of css attributes * @param animation (fadeIn, slideDown, show) * @param speed (valid animation speeds slow, medium, fast or # in ms) */ Drupal.CTools.Modal.modalContent = function(content, css, settings) { var $modalContent = $('
').html(content); var scale = (settings.modalSize.type === 'scale'); var widthScale = scale ? $(window).width() : 1; var heightScale = scale ? $(window).height() : 1; var options = { modal: true, show: null,// animation || null, width: parseInt(widthScale * settings.modalSize.width, 10), height: parseInt(heightScale * settings.modalSize.height, 10), dialogClass: '', close: function (e) { Drupal.detachBehaviors(e.target, null, 'unload'); // remove everything from the DOM like the previous modal dialog. $(e.target).dialog('destroy').remove(); } }; // remove leftover buttons $modalContent.bind('load', function () { $(this).dialog('option', 'buttons', null); }); // attach behaviors to the new AJAX content. $modalContent.bind('loadStop', function () { Drupal.attachBehaviors($(this).parent()); }); // trigger a global event to allow scripts to bind events to the dialog $(window).trigger('modalBeforeCreate', [$modalContent, options]); // $modalContent.bind('loadStart load loadStop', function () { console.log(arguments); }); $modalContent.dialog(options); // @TODO unbind event if user resize the thing himself. if (scale) { $(window).resize(function () { $modalContent.dialog('option', { width: parseInt($(window).width() * settings.modalSize.width, 10), height: parseInt($(window).height() * settings.modalSize.height, 10), position: 'center' }); }); } $(window).trigger('modalAfterCreate', [$modalContent, options]); return $modalContent; }; //$(window).bind('modalAfterCreate', function (e, $modal, options) { // console.log($modal); //}); /** * unmodalContent * @param content (The jQuery object to remove) * @param animation (fadeOut, slideUp, show) * @param speed (valid animation speeds slow, medium, fast or # in ms) */ Drupal.CTools.Modal.unmodalContent = function(content, animation, speed) { $('#modalContent').dialog('close'); }; $(function() { Drupal.ajax.prototype.commands.modal_display = Drupal.CTools.Modal.modal_display; Drupal.ajax.prototype.commands.modal_dismiss = Drupal.CTools.Modal.modal_dismiss; }); })(jQuery);