diff --git a/ctools_ajax_sample/ctools_ajax_sample.module b/ctools_ajax_sample/ctools_ajax_sample.module index 4638ac3..cb4fe83 100644 --- a/ctools_ajax_sample/ctools_ajax_sample.module +++ b/ctools_ajax_sample/ctools_ajax_sample.module @@ -14,10 +14,10 @@ */ function ctools_ajax_sample_menu() { $items['ctools_ajax_sample'] = array( - 'title' => 'Chaos Tools AJAX Demo', - 'page callback' => 'ctools_ajax_sample_page', - 'access callback' => TRUE, - 'type' => MENU_NORMAL_ITEM, + 'title' => 'Chaos Tools AJAX Demo', + 'page callback' => 'ctools_ajax_sample_page', + 'access callback' => TRUE, + 'type' => MENU_NORMAL_ITEM, ); $items['ctools_ajax_sample/simple_form'] = array( 'title' => 'Simple Form', @@ -26,39 +26,39 @@ function ctools_ajax_sample_menu() { 'type' => MENU_CALLBACK, ); $items['ctools_ajax_sample/%ctools_js/hello'] = array( - 'title' => 'Hello World', - 'page callback' => 'ctools_ajax_sample_hello', - 'page arguments' => array(1), - 'access callback' => TRUE, - 'type' => MENU_CALLBACK, + 'title' => 'Hello World', + 'page callback' => 'ctools_ajax_sample_hello', + 'page arguments' => array(1), + 'access callback' => TRUE, + 'type' => MENU_CALLBACK, ); $items['ctools_ajax_sample/%ctools_js/tablenix/%'] = array( - 'title' => 'Hello World', - 'page callback' => 'ctools_ajax_sample_tablenix', - 'page arguments' => array(1, 3), - 'access callback' => TRUE, - 'type' => MENU_CALLBACK, + 'title' => 'Hello World', + 'page callback' => 'ctools_ajax_sample_tablenix', + 'page arguments' => array(1, 3), + 'access callback' => TRUE, + 'type' => MENU_CALLBACK, ); $items['ctools_ajax_sample/%ctools_js/login'] = array( - 'title' => 'Login', - 'page callback' => 'ctools_ajax_sample_login', - 'page arguments' => array(1), - 'access callback' => TRUE, - 'type' => MENU_CALLBACK, + 'title' => 'Login', + 'page callback' => 'ctools_ajax_sample_login', + 'page arguments' => array(1), + 'access callback' => TRUE, + 'type' => MENU_CALLBACK, ); $items['ctools_ajax_sample/%ctools_js/animal'] = array( - 'title' => 'Animal', - 'page callback' => 'ctools_ajax_sample_animal', - 'page arguments' => array(1), - 'access callback' => TRUE, - 'type' => MENU_CALLBACK, + 'title' => 'Animal', + 'page callback' => 'ctools_ajax_sample_animal', + 'page arguments' => array(1), + 'access callback' => TRUE, + 'type' => MENU_CALLBACK, ); $items['ctools_ajax_sample/%ctools_js/login/%'] = array( - 'title' => 'Post-Login Action', - 'page callback' => 'ctools_ajax_sample_login_success', - 'page arguments' => array(1, 3), - 'access callback' => TRUE, - 'type' => MENU_CALLBACK, + 'title' => 'Post-Login Action', + 'page callback' => 'ctools_ajax_sample_login_success', + 'page arguments' => array(1, 3), + 'access callback' => TRUE, + 'type' => MENU_CALLBACK, ); $items['ctools_ajax_sample/jumped'] = array( 'title' => 'Successful Jumping', @@ -137,9 +137,44 @@ function ctools_ajax_sample_page() { 'modalTheme' => 'CToolsSampleModal', 'throbber' => theme('image', array('path' => ctools_image_path('ajax-loader.gif', 'ctools_ajax_sample'), 'alt' => t('Loading...'), 'title' => t('Loading'))), ), + 'ctools-ui-dialog' => array( + 'library' => 'ui.dialog', + //'modalTheme' => 'CToolsSampleModal', + 'throbber' => theme('image', array('path' => ctools_image_path('ajax-loader.gif', 'ctools_ajax_sample'), 'alt' => t('Loading...'), 'title' => t('Loading'))), + // This is jQuery's dialog default values not required, just for reference + 'options' => array( + 'disabled' => TRUE, + 'autoOpen' => TRUE, // Not the default! + //'buttons' => new stdClass(), + 'closeOnEscape' => TRUE, + 'closeText' => t('Close'), + 'dialogClass' => '', + 'draggable' => TRUE, + 'height' => 'auto', + 'hide' => NULL, + 'maxHeight' => FALSE, + 'maxWidth' => FALSE, + 'minHeight' => 300, + 'minWidth' => 600, + 'modal' => FALSE, + 'position' => FALSE, + 'resizable' => TRUE, + 'show' => 'fade', + 'stack' => TRUE, + //'title' => '', + 'width' => 300, + 'zIndex' => 1000, + ), + 'modalSize' => array( + 'type' => 'scale', + 'width' => 0.8, + 'height' => 0.8, + ), + ), ); drupal_add_js($sample_style, 'setting'); + drupal_add_library('system', 'ui.dialog'); // Since we have our js, css and images in well-known named directories, // CTools makes it easy for us to just use them without worrying about @@ -157,6 +192,8 @@ function ctools_ajax_sample_page() { // The extra class points to the info in ctools-sample-style which we added // to the settings, prefixed with 'ctools-modal'. $links[] = ctools_modal_text_button(t('Modal Login (custom style)'), 'ctools_ajax_sample/nojs/login', t('Login via modal'), 'ctools-modal-ctools-sample-style'); + // jQuery UI Dialog style + $links[] = ctools_modal_text_button(t('Modal Login (jQuery dialog'), 'ctools_ajax_sample/nojs/login', t('Login via modal'), 'ctools-modal-ctools-ui-dialog'); } // Four ways to do our animal picking wizard. @@ -164,6 +201,7 @@ function ctools_ajax_sample_page() { $links[] = l(t('Wizard (no modal)'), 'ctools_ajax_sample/nojs/animal'); $links[] = ctools_modal_text_button(t('Wizard (default modal)'), 'ctools_ajax_sample/nojs/animal', t('Pick an animal')); $links[] = ctools_modal_text_button(t('Wizard (custom modal)'), 'ctools_ajax_sample/nojs/animal', t('Pick an animal'), 'ctools-modal-ctools-sample-style'); + $links[] = ctools_modal_text_button(t('Wizard (jQuery dialog)'), 'ctools_ajax_sample/nojs/animal', t('Pick an animal'), 'ctools-modal-ctools-ui-dialog'); $links[] = drupal_render($button_form); $links[] = ctools_ajax_text_button(t('Hello world!'), "ctools_ajax_sample/nojs/hello", t('Replace text with "hello world"')); diff --git a/js/modal.js b/js/modal.js index 634595f..1bac047 100644 --- a/js/modal.js +++ b/js/modal.js @@ -13,12 +13,16 @@ Drupal.CTools = Drupal.CTools || {}; Drupal.CTools.Modal = Drupal.CTools.Modal || {}; + + var ctoolsModal = Drupal.CTools.Modal; + var modalJQuery = null; + /** * Display the modal * * @todo -- document the settings. */ - Drupal.CTools.Modal.show = function(choice) { + ctoolsModal.show = function(choice) { var opts = {}; if (choice && typeof choice == 'string' && Drupal.settings[choice]) { @@ -30,6 +34,7 @@ } var defaults = { + library: null, modalTheme: 'CToolsModalDialog', throbberTheme: 'CToolsModalThrobber', animation: 'show', @@ -49,47 +54,61 @@ opacity: .55, background: '#fff' }, + options: {}, modalClass: 'default' }; var settings = {}; $.extend(true, settings, defaults, Drupal.settings.CToolsModal, opts); - if (Drupal.CTools.Modal.currentSettings && Drupal.CTools.Modal.currentSettings != settings) { - Drupal.CTools.Modal.modal.remove(); - Drupal.CTools.Modal.modal = null; + if (ctoolsModal.currentSettings && ctoolsModal.currentSettings != settings) { + ctoolsModal.modal.remove(); + ctoolsModal.modal = null; } - Drupal.CTools.Modal.currentSettings = settings; + ctoolsModal.currentSettings = settings; + + // Set the library for jQuery UI + modalJQuery = ctoolsModal.currentSettings['library'] == 'ui.dialog'; + + if (modalJQuery) { + + if (ctoolsModal.modal && ('dialog' in ctoolsModal.modal)) { + ctoolsModal.modal.dialog('close'); + ctoolsModal.modal = null; + } + ctoolsModal.modalContent(Drupal.theme(settings.throbberTheme), settings); + return; + } 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; + var context = e ? document : ctoolsModal.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; + if (ctoolsModal.currentSettings.modalSize.type == 'scale') { + var width = $(window).width() * ctoolsModal.currentSettings.modalSize.width; + var height = $(window).height() * ctoolsModal.currentSettings.modalSize.height; } else { - var width = Drupal.CTools.Modal.currentSettings.modalSize.width; - var height = Drupal.CTools.Modal.currentSettings.modalSize.height; + var width = ctoolsModal.currentSettings.modalSize.width; + var height = ctoolsModal.currentSettings.modalSize.height; } - // Use the additionol pixels for creating the width and height. + // Use the additional 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' + 'width': width + ctoolsModal.currentSettings.modalSize.addWidth + 'px', + 'height': height + ctoolsModal.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' + 'width': (width - ctoolsModal.currentSettings.modalSize.contentRight) + 'px', + 'height': (height - ctoolsModal.currentSettings.modalSize.contentBottom) + 'px' }); } - if (!Drupal.CTools.Modal.modal) { - Drupal.CTools.Modal.modal = $(Drupal.theme(settings.modalTheme)); + if (!ctoolsModal.modal) { + ctoolsModal.modal = $(Drupal.theme(settings.modalTheme)); if (settings.modalSize.type == 'scale') { $(window).bind('resize', resize); } @@ -97,8 +116,8 @@ 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, settings.modalClass); + $('span.modal-title', ctoolsModal.modal).html(ctoolsModal.currentSettings.loadingText); + ctoolsModal.modalContent(Drupal.CTools.Modal.modal, settings.modalOptions, settings.animation, settings.animationSpeed, settings.modalClass); $('#modalContent .modal-content').html(Drupal.theme(settings.throbberTheme)).addClass('ctools-modal-loading'); // Position autocomplete results based on the scroll position of the modal. @@ -110,9 +129,9 @@ /** * Hide the modal */ - Drupal.CTools.Modal.dismiss = function() { - if (Drupal.CTools.Modal.modal) { - Drupal.CTools.Modal.unmodalContent(Drupal.CTools.Modal.modal); + ctoolsModal.dismiss = function() { + if (ctoolsModal.modal) { + ctoolsModal.unmodalContent(ctoolsModal.modal); } }; @@ -125,7 +144,7 @@ html += '
' // panels-modal-content html += ' '; @@ -144,7 +163,7 @@ var html = ''; html += ''; @@ -154,7 +173,7 @@ /** * Figure out what settings string to use to display a modal. */ - Drupal.CTools.Modal.getSettings = function (object) { + ctoolsModal.getSettings = function (object) { var match = $(object).attr('class').match(/ctools-modal-(\S+)/); if (match) { return match[1]; @@ -164,23 +183,23 @@ /** * Click function for modals that can be cached. */ - Drupal.CTools.Modal.clickAjaxCacheLink = function () { - Drupal.CTools.Modal.show(Drupal.CTools.Modal.getSettings(this)); + ctoolsModal.clickAjaxCacheLink = function () { + ctoolsModal.show(ctoolsModal.getSettings(this)); return Drupal.CTools.AJAX.clickAJAXCacheLink.apply(this); }; /** * Handler to prepare the modal for the response */ - Drupal.CTools.Modal.clickAjaxLink = function () { - Drupal.CTools.Modal.show(Drupal.CTools.Modal.getSettings(this)); + ctoolsModal.clickAjaxLink = function () { + ctoolsModal.show(ctoolsModal.getSettings(this)); return false; }; /** * Submit responder to do an AJAX submit on all modal forms. */ - Drupal.CTools.Modal.submitAjaxForm = function(e) { + ctoolsModal.submitAjaxForm = function(e) { var $form = $(this); var url = $form.attr('action'); @@ -206,7 +225,7 @@ $('area.ctools-use-modal, a.ctools-use-modal', context).once('ctools-use-modal', function() { var $this = $(this); - $this.click(Drupal.CTools.Modal.clickAjaxLink); + $this.click(ctoolsModal.clickAjaxLink); // Create a drupal ajax object var element_settings = {}; if ($this.attr('href')) { @@ -221,13 +240,13 @@ // Bind buttons $('input.ctools-use-modal, button.ctools-use-modal', context).once('ctools-use-modal', function() { var $this = $(this); - $this.click(Drupal.CTools.Modal.clickAjaxLink); + $this.click(ctoolsModal.clickAjaxLink); 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.url = ctoolsModal.findURL(this); if (element_settings.url == '') { element_settings.url = $(this).closest('form').attr('action'); } @@ -239,7 +258,7 @@ // 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); + Drupal.ajax[base].options.url = ctoolsModal.findURL(button); }); }); @@ -279,20 +298,75 @@ // class to close the modal. $('.ctools-close-modal', context).once('ctools-close-modal') .click(function() { - Drupal.CTools.Modal.dismiss(); + ctoolsModal.dismiss(); return false; }); } }; + // Register events here, example of how a custom script could work with it. Loose coupling win. + $(window).bind('modalAfterCreate', function (e, $modal, settings) { + // We don't want to use behaviors because it's very useless to run it that much. + $modal.bind('loadStop', function (e) { + // Bind our custom event to the form submit + $(this).find('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'); + }; + }); + + ctoolsModal.modal.dialog('option', 'buttons', buttons); + }); + }); + }); + // The following are implementations of AJAX responder commands. /** * AJAX responder command to place HTML within the modal. */ - Drupal.CTools.Modal.modal_display = function(ajax, response, status) { + ctoolsModal.modal_display = function(ajax, response, status) { + if (modalJQuery) { + var $modalContent = ctoolsModal.modal; + if ($modalContent.length === 0) { + ctoolsModal.show(ctoolsModal.getSettings(ajax.element)); + } + + Drupal.detachBehaviors($modalContent.get(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'); + return; + } + + if ($('#modalContent').length == 0) { - Drupal.CTools.Modal.show(Drupal.CTools.Modal.getSettings(ajax.element)); + ctoolsModal.show(ctoolsModal.getSettings(ajax.element)); } $('#modal-title').html(response.title); // Simulate an actual page load by scrolling to the top after adding the @@ -319,8 +393,8 @@ /** * AJAX responder command to dismiss the modal. */ - Drupal.CTools.Modal.modal_dismiss = function(command) { - Drupal.CTools.Modal.dismiss(); + ctoolsModal.modal_dismiss = function(command) { + ctoolsModal.dismiss(); $('link.ctools-temporary-css').remove(); } @@ -328,10 +402,10 @@ * 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 + ctoolsModal.modal_loading = function(command) { + ctoolsModal.modal_display({ + output: Drupal.theme(ctoolsModal.currentSettings.throbberTheme), + title: ctoolsModal.currentSettings.loadingText }); } @@ -343,7 +417,7 @@ * class. They need to be in the form in order since we will * concat them all together using '/'. */ - Drupal.CTools.Modal.findURL = function(item) { + ctoolsModal.findURL = function(item) { var url = ''; var url_class = '.' + $(item).attr('id') + '-url'; $(url_class).each( @@ -366,7 +440,44 @@ * @param speed (valid animation speeds slow, medium, fast or # in ms) * @param modalClass class added to div#modalContent */ - Drupal.CTools.Modal.modalContent = function(content, css, animation, speed, modalClass) { + ctoolsModal.modalContent = function(content, css, animation, speed, modalClass) { + if (modalJQuery) { + // Here content is $content. + var $content = content; + // And css is settings. + var settings = css; + var $modalContent = $('
').html($content); + var options = $.extend(true, {}, settings.options, { + title: settings.loadingText, + close: function (e) { + Drupal.detachBehaviors(e.target, null, 'unload'); + // Remove everything from the DOM like the previous modal dialog. + $(e.target).dialog('destroy').remove(); + } + }); + + if (ctoolsModal.currentSettings.modalSize.type == 'scale') { + options.width = $(window).width() * ctoolsModal.currentSettings.modalSize.width; + options.height = $(window).height() * ctoolsModal.currentSettings.modalSize.height; + } + + // 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.dialog(options); + $(window).trigger('modalAfterCreate', [$modalContent, options]); + ctoolsModal.modal = $modalContent; + return; + } + // If our animation isn't set, make it just show/pop if (!animation) { animation = 'show'; @@ -647,8 +758,12 @@ * @param animation (fadeOut, slideUp, show) * @param speed (valid animation speeds slow, medium, fast or # in ms) */ - Drupal.CTools.Modal.unmodalContent = function(content, animation, speed) - { + ctoolsModal.unmodalContent = function(content, animation, speed) { + if (modalJQuery) { + ctoolsModal.modal.dialog('close'); + return; + } + // If our animation isn't set, make it just show/pop if (!animation) { var animation = 'show'; } else { // If our animation isn't "fade" then it always is show @@ -692,8 +807,8 @@ }; $(function() { - Drupal.ajax.prototype.commands.modal_display = Drupal.CTools.Modal.modal_display; - Drupal.ajax.prototype.commands.modal_dismiss = Drupal.CTools.Modal.modal_dismiss; + Drupal.ajax.prototype.commands.modal_display = ctoolsModal.modal_display; + Drupal.ajax.prototype.commands.modal_dismiss = ctoolsModal.modal_dismiss; }); })(jQuery);