diff --git a/editors/ckeditor.inc b/editors/ckeditor.inc index 12949af..fee3587 100644 --- a/editors/ckeditor.inc +++ b/editors/ckeditor.inc @@ -30,6 +30,7 @@ function wysiwyg_ckeditor_editor() { 'install note callback' => 'wysiwyg_ckeditor_install_note', 'version callback' => 'wysiwyg_ckeditor_version', 'themes callback' => 'wysiwyg_ckeditor_themes', + 'settings form callback' => 'wysiwyg_ckeditor_settings_form', 'settings callback' => 'wysiwyg_ckeditor_settings', 'plugin callback' => 'wysiwyg_ckeditor_plugins', 'plugin settings callback' => 'wysiwyg_ckeditor_plugin_settings', @@ -120,6 +121,41 @@ function wysiwyg_ckeditor_themes($editor, $profile) { } /** + * Enhances the editor profile settings form for CKEditor. + * + * Adds support for CKEditor's advanced stylesSets, which are a more advanced + * implementation and combination of block formats and font styles that allow + * to adjust the HTML element, attributes, and CSS styles at once. + * + * @see http://docs.cksource.com/CKEditor_3.x/Developers_Guide/Styles + * @see http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.config.html#.stylesSet + */ +function wysiwyg_ckeditor_settings_form(&$form, &$form_state) { + $editor = wysiwyg_get_editor($form['editor']['#value']); + if (version_compare($editor['installed version'], '3.2.1', '>=')) { + // Replace CSS classes element description to explain the advanced syntax. + $form['css']['css_classes']['#description'] = t('Optionally define CSS classes for the "Font style" dropdown list.
Enter one class on each line in the format: !format. Example: !example
If left blank, CSS classes are automatically imported from loaded stylesheet(s).', array( + '!format' => '[label]=[element].[class]', + '!example' => 'Title=h1.title', + )); + $form['css']['css_classes']['#element_validate'][] = 'wysiwyg_ckeditor_settings_form_validate_css_classes'; + } + else { + // Versions below 3.2.1 do not support Font styles at all. + $form['css']['css_classes']['#access'] = FALSE; + } +} + +/** + * #element_validate handler for CSS classes element altered by wysiwyg_ckeditor_settings_form(). + */ +function wysiwyg_ckeditor_settings_form_validate_css_classes($element, &$form_state) { + if (wysiwyg_ckeditor_settings_parse_styles($element['#value']) === FALSE) { + form_error($element, t('The specified CSS classes are syntactically incorrect.')); + } +} + +/** * Return runtime editor settings for a given wysiwyg profile. * * @param $editor @@ -188,6 +224,15 @@ function wysiwyg_ckeditor_settings($editor, $config, $theme) { } } + // Parse and define the styles set for the Styles plugin (3.2.1+). + // @todo This should be a plugin setting, but Wysiwyg does not support + // plugin-specific settings yet. + if (!empty($config['buttons']['default']['Styles']) && version_compare($editor['installed version'], '3.2.1', '>=')) { + if ($styles = wysiwyg_ckeditor_settings_parse_styles($config['css_classes'])) { + $settings['stylesSet'] = $styles; + } + } + if (isset($config['language'])) { $settings['language'] = $config['language']; } @@ -249,6 +294,51 @@ function wysiwyg_ckeditor_settings($editor, $config, $theme) { } /** + * Parses CSS classes settings string into a stylesSet JavaScript settings array. + * + * @param string $css_classes + * A string containing CSS class definitions to add to the Style dropdown + * list, separated by newlines. + * + * @return array|false + * An array containing the parsed stylesSet definition, or FALSE on parse + * error. + * + * @see wysiwyg_ckeditor_settings_form() + * @see wysiwyg_ckeditor_settings_form_validate_css_classes() + * + * @todo This should be a plugin setting, but Wysiwyg does not support + * plugin-specific settings yet. + */ +function wysiwyg_ckeditor_settings_parse_styles($css_classes) { + $set = array(); + $input = trim($css_classes); + if (empty($input)) { + return $set; + } + // Handle both Unix and Windows line-endings. + foreach (explode("\n", str_replace("\r", '', $input)) as $line) { + $line = trim($line); + // [label]=[element].[class][.[class]][...] pattern expected. + if (!preg_match('@^.+= *[a-zA-Z0-9]+(\.[a-zA-Z0-9_ -]+)*$@', $line)) { + return FALSE; + } + list($label, $selector) = explode('=', $line, 2); + $classes = explode('.', $selector); + $element = array_shift($classes); + + $style = array(); + $style['name'] = trim($label); + $style['element'] = trim($element); + if (!empty($classes)) { + $style['attributes']['class'] = implode(' ', array_map('trim', $classes)); + } + $set[] = $style; + } + return $set; +} + +/** * Build a JS settings array of native external plugins that need to be loaded separately. */ function wysiwyg_ckeditor_plugin_settings($editor, $profile, $plugins) { diff --git a/editors/js/ckeditor-3.0.js b/editors/js/ckeditor-3.0.js index 56a1e6f..9915308 100644 --- a/editors/js/ckeditor-3.0.js +++ b/editors/js/ckeditor-3.0.js @@ -23,6 +23,10 @@ Drupal.wysiwyg.editor.init.ckeditor = function(settings) { } } } + // Register Font styles (versions 3.2.1 and above). + if (Drupal.settings.wysiwyg.configs.ckeditor[format].stylesSet) { + CKEDITOR.stylesSet.add(format, Drupal.settings.wysiwyg.configs.ckeditor[format].stylesSet); + } } };