diff --git a/editors/ckeditor.inc b/editors/ckeditor.inc index 896fc84..b46b345 100644 --- a/editors/ckeditor.inc +++ b/editors/ckeditor.inc @@ -142,6 +142,7 @@ function wysiwyg_ckeditor_settings($editor, $config, $theme) { // @todo Check whether completely disabling ProcessHTMLEntities is an option. 'entities_latin' => FALSE, 'entities_greek' => FALSE, + 'global_basepath_var' => 'CKEDITOR_BASEPATH', ); // Add HTML block format settings; common block formats are already predefined diff --git a/editors/js/ckeditor-3.0.js b/editors/js/ckeditor-3.0.js index d2cf300..e6594e8 100644 --- a/editors/js/ckeditor-3.0.js +++ b/editors/js/ckeditor-3.0.js @@ -1,6 +1,10 @@ (function($) { Drupal.wysiwyg.editor.init.ckeditor = function(settings) { + window.CKEDITOR_BASEPATH = settings.global.editorBasePath + '/'; + CKEDITOR.basePath = window.CKEDITOR_BASEPATH; +// Drupal.wysiwyg.editor['initialized']['ckeditor'] = true; + // Plugins must only be loaded once. Only the settings from the first format // will be used but they're identical anyway. var registeredPlugins = {}; @@ -31,6 +35,10 @@ Drupal.wysiwyg.editor.init.ckeditor = function(settings) { * Attach this editor to a target element. */ Drupal.wysiwyg.editor.attach.ckeditor = function(context, params, settings) { +// if (typeof Drupal.wysiwyg.editor.initialized.ckeditor == 'undefined') { +// Drupal.wysiwyg.editor.init.ckeditor(settings); +// } + // Apply editor instance settings. CKEDITOR.config.customConfig = ''; diff --git a/editors/js/tinymce-3.js b/editors/js/tinymce-3.js index b04a4ce..236d3c6 100644 --- a/editors/js/tinymce-3.js +++ b/editors/js/tinymce-3.js @@ -50,6 +50,8 @@ Drupal.wysiwyg.editor.attach.tinymce = function(context, params, settings) { ed.onEvent.add(function(ed, e) { Drupal.wysiwyg.activeId = ed.id; }); + // Tell TinyMCE DOM has been loaded for AJAX + tinymce.dom.Event.domLoaded = true; // Make toolbar buttons wrappable (required for IE). ed.onPostRender.add(function (ed) { var $toolbar = $('
'); diff --git a/tests/wysiwyg_test.module b/tests/wysiwyg_test.module index c908e29..215d1fe 100644 --- a/tests/wysiwyg_test.module +++ b/tests/wysiwyg_test.module @@ -5,3 +5,47 @@ * Testing functionality for Wysiwyg module. */ +/** + * Implements hook_menu(). + */ +function wysiwyg_test_menu() { + $items['wysiwyg-test/ajax'] = array( + 'title' => 'Ajaxified form', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('wysiwyg_test_ajax_form'), + 'access callback' => TRUE, + ); + return $items; +} + +/** + * Form constructor for an ajaxified form lazy-loading a textarea. + */ +function wysiwyg_test_ajax_form($form, &$form_state) { + $form['enable'] = array( + '#type' => 'checkbox', + '#title' => 'Load textarea', + '#ajax' => array( + 'callback' => 'wysiwyg_test_ajax_form_callback', + 'wrapper' => 'ajax-wrapper', + ), + ); + $form['wrapper'] = array( + '#type' => 'container', + '#id' => 'ajax-wrapper', + ); + return $form; +} + +/** + * #ajax callback for wysiwyg_test_ajax_form(). + */ +function wysiwyg_test_ajax_form_callback($form, &$form_state) { + $form['body'] = array( + '#type' => 'text_format', + '#default_value' => '', + ); + form_builder($form['form_id']['#value'], $form, $form_state); + return $form['body']; +} + diff --git a/wysiwyg.init.js b/wysiwyg.init.js index 6ccdb31..29f4777 100644 --- a/wysiwyg.init.js +++ b/wysiwyg.init.js @@ -6,6 +6,18 @@ Drupal.wysiwyg.editor = Drupal.wysiwyg.editor || { 'init': {}, 'attach': {}, 'de Drupal.wysiwyg.plugins = Drupal.wysiwyg.plugins || {}; (function ($) { + // See if the current editor requires a global basepath variable + // to be set before loading. + if (Drupal.settings.wysiwyg) { + $.each(Drupal.settings.wysiwyg.configs, function(editor_index, editor_value) { + $.each(editor_value, function(format_index, format_value){ + if (format_value.global_basepath_var) { + window[format_value.global_basepath_var] = Drupal.settings.wysiwyg.configs[editor_index].global.editorBasePath + '/'; + } + }); + }); + } + // Determine support for queryCommandEnabled(). // An exception should be thrown for non-existing commands. // Safari and Chrome (WebKit based) return -1 instead. diff --git a/wysiwyg.js b/wysiwyg.js index 72ca156..dbc7c53 100644 --- a/wysiwyg.js +++ b/wysiwyg.js @@ -45,11 +45,11 @@ Drupal.behaviors.attachWysiwyg = { } $('.wysiwyg', context).once('wysiwyg', function() { - if (!this.id || typeof Drupal.settings.wysiwyg.triggers[this.id] === 'undefined') { + if (!this.id || typeof settings.wysiwyg.triggers[this.id] === 'undefined') { return; } var $this = $(this); - var params = Drupal.settings.wysiwyg.triggers[this.id]; + var params = settings.wysiwyg.triggers[this.id]; for (var format in params) { params[format].format = format; params[format].trigger = this.id; @@ -59,7 +59,7 @@ Drupal.behaviors.attachWysiwyg = { // Directly attach this editor, if the input format is enabled or there is // only one input format at all. if ($this.is(':input')) { - Drupal.wysiwygAttach(context, params[format]); + Drupal.wysiwygAttach(context, params[format], settings); } // Attach onChange handlers to input format selector elements. if ($this.is('select')) { @@ -67,17 +67,40 @@ Drupal.behaviors.attachWysiwyg = { // If not disabled, detach the current and attach a new editor. Drupal.wysiwygDetach(context, params[format]); format = 'format' + this.value; - Drupal.wysiwygAttach(context, params[format]); + Drupal.wysiwygAttach(context, params[format], settings); }); } - // Detach any editor when the containing form is submitted. - $('#' + params.field).parents('form').submit(function (event) { - // Do not detach if the event was cancelled. - if (event.isDefaultPrevented()) { - return; + + var form_instance = $('#' + params.field).parents('form'); + var event_sources = [ {'instance' : form_instance, 'event' : 'submit'} ]; + + // CTools modal content support + var ctools_modal_content = $('#' + params.field).closest('div.ctools-modal-content'); + if (ctools_modal_content.length > 0) { + event_sources[0].index = 0; + var ctools_close_instance = ctools_modal_content.find('a.close'); + event_sources.push({'instance' : ctools_close_instance, 'event' : 'click', "index" : 0}); + } + + for (index = 0; index < event_sources.length; index++) { + var event_name = event_sources[index].event; + + // Append handler + event_sources[index].instance.bind(event_name, function (event) { + // Do not detach if the event was cancelled. + if (event.isDefaultPrevented()) { + return; + } + Drupal.wysiwygDetach(context, params[format]); + }); + + // Insert our handler at a specific position + var events_data = event_sources[index].instance.data('events'); + var event_handlers = events_data[event_name]; + if (typeof event_sources[index].index == 'number' && event_handlers.length > 1) { + event_handlers.splice(event_sources[index].index, 0, event_handlers.pop()); } - Drupal.wysiwygDetach(context, params[format]); - }); + } }); } }; @@ -95,7 +118,7 @@ Drupal.behaviors.attachWysiwyg = { * @param params * An object containing input format parameters. */ -Drupal.wysiwygAttach = function(context, params) { +Drupal.wysiwygAttach = function(context, params, settings) { if (typeof Drupal.wysiwyg.editor.attach[params.editor] == 'function') { // (Re-)initialize field instance. Drupal.wysiwyg.instances[params.field] = {}; @@ -138,6 +161,9 @@ Drupal.wysiwygAttach = function(context, params) { * An object containing input format parameters. */ Drupal.wysiwygDetach = function(context, params) { + if (typeof Drupal.wysiwyg.instances[params.field] == 'undefined') { + return; + } var editor = Drupal.wysiwyg.instances[params.field].editor; if (jQuery.isFunction(Drupal.wysiwyg.editor.detach[editor])) { Drupal.wysiwyg.editor.detach[editor](context, params);