diff --git a/editors/ckeditor.inc b/editors/ckeditor.inc
index e3c6027..fcf168e 100644
--- a/editors/ckeditor.inc
+++ b/editors/ckeditor.inc
@@ -31,6 +31,7 @@ function wysiwyg_ckeditor_editor() {
     'version callback' => 'wysiwyg_ckeditor_version',
     'themes callback' => 'wysiwyg_ckeditor_themes',
     'settings form callback' => 'wysiwyg_ckeditor_settings_form',
+    'init callback' => 'wysiwyg_ckeditor_init',
     'settings callback' => 'wysiwyg_ckeditor_settings',
     'plugin callback' => 'wysiwyg_ckeditor_plugins',
     'plugin settings callback' => 'wysiwyg_ckeditor_plugin_settings',
@@ -155,6 +156,35 @@ function wysiwyg_ckeditor_settings_form_validate_css_classes($element, &$form_st
 }
 
 /**
+ * Returns an initialization JavaScript for this editor library.
+ *
+ * @param array $editor
+ *   The editor library definition.
+ * @param string $library
+ *   The library variant key from $editor['libraries'].
+ * @param object $profile
+ *   The (first) wysiwyg editor profile.
+ *
+ * @return string
+ *   A string containing inline JavaScript to execute before the editor library
+ *   script is loaded.
+ */
+function wysiwyg_ckeditor_init($editor) {
+  // CKEditor unconditionally searches for its library filename in SCRIPT tags
+  // on the page upon loading the library in order to determine the base path to
+  // itself. When JavaScript aggregation is enabled, this search fails and all
+  // relative constructed paths within CKEditor are broken. The library has a
+  // CKEditor.basePath property, but it is not publicly documented and thus not
+  // reliable. The official documentation suggests to solve the issue through
+  // the global window variable.
+  // @see http://docs.cksource.com/CKEditor_3.x/Developers_Guide/Specifying_the_Editor_Path
+  $library_path = base_path() . $editor['library path'] . '/';
+  return <<<EOL
+window.CKEDITOR_BASEPATH = '$library_path';
+EOL;
+}
+
+/**
  * Return runtime editor settings for a given wysiwyg profile.
  *
  * @param $editor
@@ -170,8 +200,6 @@ function wysiwyg_ckeditor_settings_form_validate_css_classes($element, &$form_st
  */
 function wysiwyg_ckeditor_settings($editor, $config, $theme) {
   $settings = array(
-    'baseHref' => $GLOBALS['base_url'] . '/',
-    'global_basepath_var' => 'CKEDITOR_BASEPATH',
     'width' => 'auto',
     // For better compatibility with smaller textareas.
     'resize_minWidth' => 450,
diff --git a/editors/js/ckeditor-3.0.js b/editors/js/ckeditor-3.0.js
index e3745a5..f288928 100644
--- a/editors/js/ckeditor-3.0.js
+++ b/editors/js/ckeditor-3.0.js
@@ -1,10 +1,6 @@
 (function($) {
 
 Drupal.wysiwyg.editor.init.ckeditor = function(settings) {
-  // CKEditor loses its base path info in case of Ajax.
-  window.CKEDITOR_BASEPATH = settings.global.editorBasePath + '/';
-  CKEDITOR.basePath = window.CKEDITOR_BASEPATH;
-
   // Plugins must only be loaded once. Only the settings from the first format
   // will be used but they're identical anyway.
   var registeredPlugins = {};
diff --git a/editors/js/tinymce-2.js b/editors/js/tinymce-2.js
index 406cdcb..52cc495 100644
--- a/editors/js/tinymce-2.js
+++ b/editors/js/tinymce-2.js
@@ -10,13 +10,6 @@
  *   An object containing editor settings for each input format.
  */
 Drupal.wysiwyg.editor.init.tinymce = function(settings) {
-  // If JS compression is enabled, TinyMCE is unable to autodetect its global
-  // settinge, hence we need to define them manually.
-  // @todo Move global library settings somewhere else.
-  tinyMCE.baseURL = settings.global.editorBasePath;
-  tinyMCE.srcMode = (settings.global.execMode == 'src' ? '_src' : '');
-  tinyMCE.gzipMode = (settings.global.execMode == 'gzip');
-
   // Initialize editor configurations.
   for (var format in settings) {
     if (format == 'global') {
diff --git a/editors/js/tinymce-3.js b/editors/js/tinymce-3.js
index b83815f..d920024 100644
--- a/editors/js/tinymce-3.js
+++ b/editors/js/tinymce-3.js
@@ -11,13 +11,6 @@
  *   An object containing editor settings for each input format.
  */
 Drupal.wysiwyg.editor.init.tinymce = function(settings) {
-  // If JS compression is enabled, TinyMCE is unable to autodetect its global
-  // settinge, hence we need to define them manually.
-  // @todo Move global library settings somewhere else.
-  tinyMCE.baseURL = settings.global.editorBasePath;
-  tinyMCE.srcMode = (settings.global.execMode == 'src' ? '_src' : '');
-  tinyMCE.gzipMode = (settings.global.execMode == 'gzip');
-
   // Fix Drupal toolbar obscuring editor toolbar in fullscreen mode.
   var $drupalToolbar = $('#toolbar', Drupal.overlayChild ? window.parent.document : document);
   tinyMCE.onAddEditor.add(function (mgr, ed) {
diff --git a/editors/tinymce.inc b/editors/tinymce.inc
index bf0cd11..5359c0f 100644
--- a/editors/tinymce.inc
+++ b/editors/tinymce.inc
@@ -28,6 +28,7 @@ function wysiwyg_tinymce_editor() {
     ),
     'version callback' => 'wysiwyg_tinymce_version',
     'themes callback' => 'wysiwyg_tinymce_themes',
+    'init callback' => 'wysiwyg_tinymce_init',
     'settings callback' => 'wysiwyg_tinymce_settings',
     'plugin callback' => 'wysiwyg_tinymce_plugins',
     'plugin settings callback' => 'wysiwyg_tinymce_plugin_settings',
@@ -126,6 +127,32 @@ function wysiwyg_tinymce_themes($editor, $profile) {
 }
 
 /**
+ * Returns an initialization JavaScript for this editor library.
+ *
+ * @param array $editor
+ *   The editor library definition.
+ * @param string $library
+ *   The library variant key from $editor['libraries'].
+ * @param object $profile
+ *   The (first) wysiwyg editor profile.
+ *
+ * @return string
+ *   A string containing inline JavaScript to execute before the editor library
+ *   script is loaded.
+ */
+function wysiwyg_tinymce_init($editor, $library) {
+  // http://www.tinymce.com/wiki.php/API3:event.tinymce.Editor.onPreInit ???   
+  $settings = drupal_json_encode(array(
+    'base' => base_path() . $editor['library path'],
+    'suffix' => (empty($library) ? '' : '_' . $library),
+    'query' => '',
+  ));
+  return <<<EOL
+window.tinyMCEPreInit = $settings;
+EOL;
+}
+
+/**
  * Return runtime editor settings for a given wysiwyg profile.
  *
  * @param $editor
diff --git a/wysiwyg.api.php b/wysiwyg.api.php
index 9b4811a..c4d8857 100644
--- a/wysiwyg.api.php
+++ b/wysiwyg.api.php
@@ -211,6 +211,14 @@ function hook_INCLUDE_editor() {
     // (optional) A callback to perform editor-specific adjustments or
     // enhancements for the administrative editor profile settings form.
     'settings form callback' => 'wysiwyg_ckeditor_settings_form',
+    // (optional) A callback to return an initialization JavaScript snippet for
+    // this editor library, loaded before the actual library files. The returned
+    // JavaScript is executed as inline script in a primitive environment,
+    // before the DOM is loaded; typically used to prime a base path and other
+    // global window variables for the editor library before it is loaded.
+    // All implementations should verbosely document what they are doing and
+    // why that is required.
+    'init callback' => 'wysiwyg_ckeditor_init',
     // A callback to convert administrative profile/editor settings into
     // JavaScript settings.
     'settings callback' => 'wysiwyg_ckeditor_settings',
diff --git a/wysiwyg.js b/wysiwyg.js
index d542a3b..29e2c54 100644
--- a/wysiwyg.js
+++ b/wysiwyg.js
@@ -11,18 +11,6 @@ Drupal.wysiwygInit = function() {
   if (/KDE/.test(navigator.vendor)) {
     return;
   }
-  // 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 + '/';
-        }
-      });
-    });
-  }
-
   jQuery.each(Drupal.wysiwyg.editor.init, function(editor) {
     // Clone, so original settings are not overwritten.
     this(jQuery.extend(true, {}, Drupal.settings.wysiwyg.configs[editor]));
diff --git a/wysiwyg.module b/wysiwyg.module
index b6a4027..22130ea 100644
--- a/wysiwyg.module
+++ b/wysiwyg.module
@@ -302,6 +302,7 @@ function wysiwyg_get_profile($format) {
 function wysiwyg_load_editor($profile) {
   static $settings_added;
   static $loaded = array();
+  $path = drupal_get_path('module', 'wysiwyg');
 
   $name = $profile->editor;
   // Library files must be loaded only once.
@@ -309,6 +310,13 @@ function wysiwyg_load_editor($profile) {
     // Load editor.
     $editor = wysiwyg_get_editor($name);
     if ($editor) {
+      $default_library_options = array(
+        'type' => 'file',
+        'scope' => 'header',
+        'defer' => FALSE,
+        'cache' => TRUE,
+        'preprocess' => TRUE,
+      );
       // Determine library files to load.
       // @todo Allow to configure the library/execMode to use.
       if (isset($profile->settings['library']) && isset($editor['libraries'][$profile->settings['library']])) {
@@ -321,9 +329,33 @@ function wysiwyg_load_editor($profile) {
         $files = array_shift($editor['libraries']);
         $files = $files['files'];
       }
+
+      // Check whether the editor requires an initialization script.
+      if (!empty($editor['init callback'])) {
+        $init = $editor['init callback']($editor, $library, $profile);
+        if (!empty($init)) {
+          // Build a file for each of the editors to hold the init scripts.
+          // @todo Aggregate all initialization scripts into one file.
+          $uri = 'public://js/wysiwyg/wysiwyg_' . $name . '_' . drupal_hash_base64($init) . '.js';
+          $init_exists = file_exists($uri);
+          if (!$init_exists) {
+            $js_path = dirname($uri);
+            file_prepare_directory($js_path, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
+          }
+          // Attempt to create the file, or fall back to an inline script (which
+          // will not work in Ajax calls).
+          if (!$init_exists && !file_unmanaged_save_data($init, $uri, FILE_EXISTS_REPLACE)) {
+            drupal_add_js($init, array('type' => 'inline') + $default_library_options);
+          }
+          else {
+            drupal_add_js(file_create_url($uri), $default_library_options);
+          }
+        }
+      }
+
       foreach ($files as $file => $options) {
         if (is_array($options)) {
-          $options += array('type' => 'file', 'scope' => 'header', 'defer' => FALSE, 'cache' => TRUE, 'preprocess' => TRUE);
+          $options += $default_library_options;
           drupal_add_js($editor['library path'] . '/' . $file, $options);
         }
         else {
@@ -351,17 +383,6 @@ function wysiwyg_load_editor($profile) {
       foreach ($files as $file) {
         drupal_add_css($editor['css path'] . '/' . $file);
       }
-
-      drupal_add_js(array('wysiwyg' => array(
-        'configs' => array($editor['name'] => array('global' => array(
-          // @todo Move into (global) editor settings.
-          // If JS compression is enabled, at least TinyMCE is unable to determine
-          // its own base path and exec mode since it can't find the script name.
-          'editorBasePath' => base_path() . $editor['library path'],
-          'execMode' => $library,
-        ))),
-      )), 'setting');
-
       $loaded[$name] = TRUE;
     }
     else {
@@ -378,7 +399,6 @@ function wysiwyg_load_editor($profile) {
       'enable' => t('Enable rich-text'),
     )), 'setting');
 
-    $path = drupal_get_path('module', 'wysiwyg');
     // Initialize our namespaces in the *header* to do not force editor
     // integration scripts to check and define Drupal.wysiwyg on its own.
     drupal_add_js($path . '/wysiwyg.init.js', array('group' => JS_LIBRARY));
