diff --git a/ctools_ajax_sample/ctools_ajax_sample.module b/ctools_ajax_sample/ctools_ajax_sample.module index 2a30c2a..44172a3 100644 --- a/ctools_ajax_sample/ctools_ajax_sample.module +++ b/ctools_ajax_sample/ctools_ajax_sample.module @@ -137,9 +137,39 @@ 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( + //'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, + ), + ), ); drupal_add_js($sample_style, 'setting'); + drupal_add_library('system', 'ui.dialog'); + ctools_add_js('modal-jquery', 'ctools', 'js'); // 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 +187,7 @@ 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'); + $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 +195,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-jquery.js b/js/modal-jquery.js new file mode 100644 index 0000000..ec55ec6 --- /dev/null +++ b/js/modal-jquery.js @@ -0,0 +1,171 @@ +(function ($) { + + // Boolean saying if we're using jQuery dialog or not. + var modalJQuery = null; + // Shortcut. + var modal = Drupal.CTools.Modal; + // Save old functions to use if modalJQuery === false. + var overriden = { + 'show': modal.show, + 'modalContent': modal.modalContent, + 'unmodalContent': modal.unmodalContent, + 'modal_display': modal.modal_display, + 'modal_loading': modal.modal_loading + }; + + // show function get special treatment + modal.show = function (choice) { + modalJQuery = (choice === 'ctools-ui-dialog'); + + // Call old modal function. + if (!modalJQuery) { + overriden.show.apply(this, arguments); + } + // New jQuery dialog. + else { + var settings = $.extend(true, { + throbberTheme: 'CToolsModalThrobber', + loadingText: Drupal.t('Loading…'), + options: {}, + modalSize: { + //type: 'scale', + //width: '80%', + //height: '80%' + } + }, Drupal.settings[choice]); + + if (modal.modal && ('dialog' in modal.modal)) { + modal.modal.dialog('close'); + modal.modal = null; + } + modal.currentSettings = settings; + modal.modalContent(Drupal.theme(settings.throbberTheme), settings); + } + }; + + /** + * Helper method, replace a method in Drupal.CTools.Modal without breaking + * + * @param method + * name of the overriden method + * @param callback + * new function replacing the old one. + */ + function override (method, callback) { + modal[method] = function () { + var func = (modalJQuery === true) ? callback : overriden[method]; + if ($.isFunction(func)) { + func.apply(this, arguments); + } + }; + } + + override('modalContent', function ($content, 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 = $.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(); + } + }); + + // 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); + // @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]); + modal.modal = $modalContent; + }); + + override('unmodalContent', function (content, settings) { + modal.modal.dialog('close'); + }); + + override('modal_display', function (ajax, response, status) { + var $modalContent = modal.modal; + if ($modalContent.length === 0) { + modal.show(modal.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'); + }); + + // Fix parameters number, can get rid of it once it's fixed in modal.js. + override('modal_loading', function (command) { + modal.modal_display({}, { + output: Drupal.theme(modal.currentSettings.throbberTheme), + title: modal.currentSettings.loadingText + }); + }); + + + // 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'); + }; + }); + + $(this).closest('#modalContent').dialog('option', 'buttons', buttons); + }); + }); + + }); + +}(jQuery));