Dopo aver installato CKEditor seguendo il thread http://www.drupalitalia.org/node/8326 devo dire che mi piace questo editor, ma devo fare due cose:
- Ridurre la forresta di bottone disponibile a qualcosa più umano e meno 'Word for Windows'
- Fornire una serie di snippets HTML usando templates
Prima di buttarmi alla ricerca, qualcuno ha già fatto un esperienza in questa direzione?
[Modified]
Mi spiego un pò meglio.
Per configurazione mi domando se è meglio usare Wysiwyg o creare un config in JavaScript? Immagino che l'API JavaScript sia molto più flessibile. Crea conflitti?
http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.config.html
http://groups.drupal.org/node/28640
Per templates, ho trovato solo documentazione per FCKEditor, è compatibile?
http://docs.cksource.com/FCKeditor_2.x/Users_Guide/Common_Tasks/Templates
http://docs.cksource.com/FCKeditor_2.x/Developers_Guide/Configuration/Te...
Ma
http://docs.cksource.com/ckeditor_api/symbols/src/plugins_templates_temp...
Ogni consiglio/informazione è il ben venuto.
TIA
John
A me i bottoni FCK piacciono ( io ne ho aggiunti parecchi ), poi apri in pagina in full-page e restano sopra : cmq basta modificarli / eliminarli : leggi il readme.txt e vai nel suo file di configurazione .. per farlo.
Per il resto non so, dovrei leggere, puoi anche abbinare Bueditor insieme a FCK e li metti bottoni con comandi personalizzati HTML o Php ( for example ) e puoi anche salvare i tuoi bottoni e snippet in un file CVS.
Grazie Lorenzo della risposta...
Già, se CKEditor avesse un readme.txt probabilmente l'avrei letto - ma non c'è.
Tu mi parli di FCK, cioè FCKEditor, ma io sto usando Wysiwyg insieme a CKEditor. Non credo che sono proprio la stessa cosa, anche se dallo stesso software house.
Comunque, oggi devo assolutamante risolvere questo problema, iniziando con una 'giusta' versione di Wysiwyg. Vediamo che succede...
John
Più imparo, più dubito.
Il rischio è che parlo con me stesso...
Ma, come dicevo il mio padre, almeno sarà una conversazione intelligente...
Per il punto 1, senza pesante modifiche a Wysiwyg, l'unico alternativo è di modificare il JavaScript, ma bisogna 'massaggiare' un pò il PHP...
Come dicevo in un altro thread sto usando CVS
DRUPAL-6--2 (6.x-2.x-dev)
di Wysiwyg.Ho fatto una copia di
ckeditor.inc
e ho rimosso i bottoni (rimane il linguaggio e Teaser break) chiamatosyger_ckeditor.inc
:<?php
// $Id
/**
* @file
* Editor integration functions for CKeditor.
*/
/**
* Plugin implementation of hook_editor().
*/
function wysiwyg_syger_ckeditor_editor() {
$editor['syger_ckeditor'] = array(
'title' => 'Syger CKeditor',
'vendor url' => 'http://ckeditor.com',
'download url' => 'http://ckeditor.com',
'libraries' => array(
'' => array(
'title' => 'Default',
'files' => array(
'ckeditor.js' => array('preprocess' => FALSE),
),
),
'src' => array(
'title' => 'Source',
'files' => array(
'ckeditor_source.js' => array('preprocess' => FALSE),
),
),
),
'version callback' => 'wysiwyg_syger_ckeditor_version',
'themes callback' => 'wysiwyg_syger_ckeditor_themes',
'settings callback' => 'wysiwyg_syger_ckeditor_settings',
'plugin callback' => 'wysiwyg_syger_ckeditor_plugins',
'plugin settings callback' => 'wysiwyg_syger_ckeditor_plugin_settings',
'proxy plugin' => array(
'drupal' => array(
'load' => TRUE,
'proxy' => TRUE,
),
),
'proxy plugin settings callback' => 'wysiwyg_syger_ckeditor_proxy_plugin_settings',
'versions' => array(
'3.0.0.4148' => array(
'js files' => array('syger_ckeditor-3.0.js'),
),
'3.0.0.3665' => array(
'js files' => array('syger_ckeditor-3.0.js'),
),
),
);
return $editor;
}
/**
* Detect editor version.
*
* @param $editor
* An array containing editor properties as returned from hook_editor().
*
* @return
* The installed editor version.
*/
function wysiwyg_syger_ckeditor_version($editor) {
$library = $editor['library path'] . '/ckeditor.js';
$library = fopen($library, 'r');
$max_lines = 8;
while ($max_lines && $line = fgets($library, 140)) {
// version:'CKEditor 3.0 SVN',revision:'3665'
// version:'3.0 RC',revision:'3753'
// version:'3.0.1',revision:'4391'
if (preg_match('@version:\'(?:CKEditor )?([\d\.]+)(?:.+revision:\'([\d]+))?@', $line, $version)) {
fclose($library);
// Version numbers need to have three parts since 3.0.1.
$version[1] = preg_replace('/^(\d+)\.(\d+)$/', '${1}.${2}.0', $version[1]);
return $version[1] . '.' . $version[2];
}
$max_lines--;
}
fclose($library);
}
/**
* Determine available editor themes or check/reset a given one.
*
* @param $editor
* A processed hook_editor() array of editor properties.
* @param $profile
* A wysiwyg editor profile.
*
* @return
* An array of theme names. The first returned name should be the default
* theme name.
*/
function wysiwyg_syger_ckeditor_themes($editor, $profile) {
// @todo Skins are not themes but this will do for now.
$path = $editor['library path'] . '/skins/';
$dir_handle = @opendir($path) or drupal_set_message('Unable to open ' . $path, $type = 'error');
$themes = array();
while ($file = readdir($dir_handle)) {
if($file!="." && $file!=".." && $file!="CVS" && $file!=".svn") {
$themes[] = $file;
}
}
closedir($dir_handle);
return $themes;
}
/**
* Return runtime editor settings for a given wysiwyg profile.
*
* @param $editor
* A processed hook_editor() array of editor properties.
* @param $config
* An array containing wysiwyg editor profile settings.
* @param $theme
* The name of a theme/GUI/skin to use.
*
* @return
* A settings array to be populated in
* Drupal.settings.wysiwyg.configs.{editor}
*/
function wysiwyg_syger_ckeditor_settings($editor, $config, $theme) {
$settings = array(
'baseHref' => base_path(),
'width' => '100%',
'height' => 420,
// Skin is not really the same as theme.
'theme' => 'default',
'skin' => 'kama', // $theme,
// By default, CKeditor converts most characters into HTML entities. Since
// it does not support a custom definition, but Drupal supports Unicode, we
// disable at least the additional character sets. CKeditor always converts
// XML default characters '&', '<', '>'.
// @todo Check whether completely disabling ProcessHTMLEntities is an option.
'entities_latin' => FALSE,
'entities_greek' => FALSE,
);
$extra_plugins = array();
if (isset($config['block_formats'])) {
// @todo This is now format_tags and needs format_[tag] settings per tag.
//$settings['FontFormats'] = strtr($config['block_formats'], array(',' => ';'));
}
if (isset($config['apply_source_formatting'])) {
$settings['apply_source_formatting'] = $config['apply_source_formatting'];
}
if (isset($config['css_setting'])) {
// Versions below 3.0.1 could only handle one stylesheet.
if (version_compare($editor['installed version'], '3.0.1.4391', '<')) {
if ($config['css_setting'] == 'theme') {
$settings['contentsCss'] = reset(wysiwyg_get_css());
}
elseif ($config['css_setting'] == 'self' && isset($config['css_path'])) {
$settings['contentsCss'] = strtr($config['css_path'], array('%b' => base_path(), '%t' => path_to_theme()));
}
}
else {
if ($config['css_setting'] == 'theme') {
$settings['contentsCss'] = wysiwyg_get_css();
}
elseif ($config['css_setting'] == 'self' && isset($config['css_path'])) {
$settings['contentsCss'] = explode(',', strtr($config['css_path'], array('%b' => base_path(), '%t' => path_to_theme())));
}
}
}
// Language
if (isset($config['language'])) {
$settings['language'] = $config['language'];
}
// Resizing button
if (isset($config['resizing'])) {
$settings['resize_enabled'] = $config['resizing'];
}
//Toolbar location
if (isset($config['toolbar_loc'])) {
$settings['toolbarLocation'] = $config['toolbar_loc'];
}
if (!empty($config['buttons'])) {
$settings['toolbar'] = array();
$plugins = wysiwyg_get_plugins($editor['name']);
foreach ($config['buttons'] as $plugin => $buttons) {
foreach ($buttons as $button => $enabled) {
// Iterate separately over buttons and extensions properties.
foreach (array('buttons', 'extensions') as $type) {
// Skip unavailable plugins.
if (!isset($plugins[$plugin][$type][$button])) {
continue;
}
// Add buttons.
if ($type == 'buttons') {
$settings['toolbar'][] = $button;
}
// Add external Drupal plugins to the list of extensions.
if ($type == 'buttons' && !empty($plugins[$plugin]['proxy'])) {
$extra_plugins[] = $button;
}
// Add external plugins to the list of extensions.
elseif ($type == 'buttons' && empty($plugins[$plugin]['internal'])) {
$extra_plugins[] = $plugin;
}
// Add internal buttons that also need to be loaded as extension.
elseif ($type == 'buttons' && !empty($plugins[$plugin]['load'])) {
$extra_plugins[] = $plugin;
}
// Add plain extensions.
elseif ($type == 'extensions' && !empty($plugins[$plugin]['load'])) {
$extra_plugins[] = $plugin;
}
// Allow plugins to add or override global configuration settings.
if (!empty($plugins[$plugin]['options'])) {
$settings = array_merge($settings, $plugins[$plugin]['options']);
}
}
}
}
if (!empty($extra_plugins)) {
$settings['extraPlugins'] = implode(',', $extra_plugins);
}
// For now, all buttons are placed into one row.
if (!empty($settings['toolbar'])) {
$settings['toolbar'] = array($settings['toolbar']);
}
}
return $settings;
}
/**
* Build a JS settings array of native external plugins that need to be loaded separately.
*/
function wysiwyg_syger_ckeditor_plugin_settings($editor, $profile, $plugins) {
$settings = array();
foreach ($plugins as $name => $plugin) {
// Register all plugins that need to be loaded.
if (!empty($plugin['load'])) {
$settings[$name] = array();
// Add path for native external plugins.
if (empty($plugin['internal']) && isset($plugin['path'])) {
$settings[$name]['path'] = base_path() . $plugin['path'];
}
// Force native internal plugins to use the standard path.
else {
$settings[$name]['path'] = base_path() . $editor['library path'] . '/plugins/' . $name . '/';
}
if (!empty($plugin['filename'])) {
$settings[$name]['fileName'] = $plugin['filename'];
}
}
}
return $settings;
}
/**
* Build a JS settings array for Drupal plugins loaded via the proxy plugin.
*/
function wysiwyg_syger_ckeditor_proxy_plugin_settings($editor, $profile, $plugins) {
$settings = array();
foreach ($plugins as $name => $plugin) {
// Populate required plugin settings.
$settings[$name] = $plugin['dialog settings'] + array(
'title' => $plugin['title'],
'icon' => base_path() . $plugin['icon path'] . '/' . $plugin['icon file'],
'iconTitle' => $plugin['icon title'],
// @todo These should only be set if the plugin defined them.
'css' => base_path() . $plugin['css path'] . '/' . $plugin['css file'],
);
}
return $settings;
}
/**
* Return internal plugins for this editor; semi-implementation of hook_wysiwyg_plugin().
*
* Excluded native plugins: About, Button, Checkbox, Form, HiddenField,
* ImageButton, NewPage, PageBreak, Print, Radio, Select, Save, TextField,
* Textarea, Templates.
*/
function wysiwyg_syger_ckeditor_plugins($editor) {
$plugins = array(
'default' => array(
'buttons' => array(
),
'internal' => TRUE,
),
);
return $plugins;
}
Poi ho fatto la stessa cosa per
ckeditor-3.0.js
, chiamatosyger_ckeditor-3.0.js
, ma aggiungendo i bottoni, come volevo io:// $Id
(function($) {
Drupal.wysiwyg.editor.init.syger_ckeditor = function(settings) {
// Plugins must only be loaded once. Only the settings from the first format
// will be used but they're identical anyway.
var registeredPlugins = {};
for (var format in settings) {
if (Drupal.settings.wysiwyg.plugins[format]) {
// Register native external plugins.
// Array syntax required; 'native' is a predefined token in JavaScript.
for (var pluginName in Drupal.settings.wysiwyg.plugins[format]['native']) {
if (!registeredPlugins[pluginName]) {
var plugin = Drupal.settings.wysiwyg.plugins[format]['native'][pluginName];
CKEDITOR.plugins.addExternal(pluginName, plugin.path, plugin.fileName);
registeredPlugins[pluginName] = true;
}
}
// Register Drupal plugins.
for (var pluginName in Drupal.settings.wysiwyg.plugins[format].drupal) {
if (!registeredPlugins[pluginName]) {
Drupal.wysiwyg.editor.instance.syger_ckeditor.addPlugin(pluginName, Drupal.settings.wysiwyg.plugins[format].drupal[pluginName], Drupal.settings.wysiwyg.plugins.drupal[pluginName]);
registeredPlugins[pluginName] = true;
}
}
}
}
};
/**
* Attach this editor to a target element.
*/
Drupal.wysiwyg.editor.attach.syger_ckeditor = function(context, params, settings) {
// Apply editor instance settings.
CKEDITOR.config.customConfig = '';
settings.on = {
// Event handlers.
instanceReady: function(ev) {
var editor = ev.editor;
var dtd = CKEDITOR.dtd;
var tags = CKEDITOR.tools.extend( {}, dtd.$block, dtd.$listItem, dtd.$tableContent );
if (settings.apply_source_formatting) {
// Mimic FCKeditor output.
for (var tag in tags) {
if (tag == 'pre') {
continue;
}
this.dataProcessor.writer.setRules(tag, {
indent: true,
breakBeforeOpen: true,
breakAfterOpen: false,
breakBeforeClose: false,
breakAfterClose: true
});
}
}
else {
// No indents or linebreaks;
for (var key in tags) {
if (tag == 'pre') {
continue;
}
this.dataProcessor.writer.setRules(tag, {
indent: false,
breakBeforeOpen: false,
breakAfterOpen: false,
breakBeforeClose: false,
breakAfterClose: false
});
}
}
},
pluginsLoaded: function(ev) {
// Override the conversion methods to let Drupal plugins modify the data.
var editor = ev.editor;
if (editor.dataProcessor) {
editor.dataProcessor.toHtml = CKEDITOR.tools.override(editor.dataProcessor.toHtml, function(originalToHtml) {
// Convert raw data for display in WYSIWYG mode.
return function(data, fixForBody) {
for (var plugin in Drupal.settings.wysiwyg.plugins[params.format].drupal) {
if (typeof Drupal.wysiwyg.plugins[plugin].attach == 'function') {
data = Drupal.wysiwyg.plugins[plugin].attach(data, Drupal.settings.wysiwyg.plugins.drupal[plugin], editor.name);
data = Drupal.wysiwyg.instances[params.field].prepareContent(data);
}
}
return originalToHtml.call(this, data, fixForBody);
};
});
editor.dataProcessor.toDataFormat = CKEDITOR.tools.override(editor.dataProcessor.toDataFormat, function(originalToDataFormat) {
// Convert WYSIWYG mode content to raw data.
return function(data, fixForBody) {
data = originalToDataFormat.call(this, data, fixForBody);
for (var plugin in Drupal.settings.wysiwyg.plugins[params.format].drupal) {
if (typeof Drupal.wysiwyg.plugins[plugin].detach == 'function') {
data = Drupal.wysiwyg.plugins[plugin].detach(data, Drupal.settings.wysiwyg.plugins.drupal[plugin], editor.name);
}
}
return data;
};
});
}
},
focus: function(ev) {
Drupal.wysiwyg.activeId = ev.editor.name;
}
};
// Attach editor, update settings.
var org_toolbar = settings.toolbar;
settings.toolbar = [
['Bold','Italic','Underline','Strike','-','Subscript','Superscript'],
['NumberedList','BulletedList','-','Outdent','Indent','Blockquote'],
['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'],
['Link','Unlink','Anchor'],
['Table','HorizontalRule','SpecialChar'],
'/',
// ['Templates'],
['Cut','Copy','Paste','PasteText','PasteFromWord','-','Print', 'SpellChecker', 'Scayt'],
['Undo','Redo','-','Find','Replace'],
['Styles','Format'],
['Maximize', '-', org_toolbar]
];
CKEDITOR.replace(params.field, settings);
};
/**
* Detach a single or all editors.
*
* @todo 3.x: editor.prototype.getInstances() should always return an array
* containing all instances or the passed in params.field instance, but
* always return an array to simplify all detach functions.
*/
Drupal.wysiwyg.editor.detach.syger_ckeditor = function(context, params) {
if (typeof params != 'undefined') {
var instance = CKEDITOR.instances[params.field];
if (instance) {
instance.destroy();
}
}
else {
for (var instanceName in CKEDITOR.instances) {
CKEDITOR.instances[instanceName].destroy();
}
}
};
Drupal.wysiwyg.editor.instance.syger_ckeditor = {
addPlugin: function(pluginName, settings, pluginSettings) {
CKEDITOR.plugins.add(pluginName, {
// Wrap Drupal plugin in a proxy pluygin.
init: function(editor) {
if (settings.css) {
editor.on('mode', function(ev) {
if (ev.editor.mode == 'wysiwyg') {
// Inject CSS files directly into the editing area head tag.
$('head', $('#cke_contents_' + ev.editor.name + ' iframe').eq(0).contents()).append('<link rel="stylesheet" href="' + settings.css + '" type="text/css" >');
}
});
}
if (typeof Drupal.wysiwyg.plugins[pluginName].invoke == 'function') {
var pluginCommand = {
exec: function(editor) {
var data = { format: 'html', node: editor.getSelection().getSelectedElement() };
// @todo This is NOT the same as data.node.
data.content = data.node ? data.node.innerHTML : '';
Drupal.wysiwyg.plugins[pluginName].invoke(data, pluginSettings, editor.name);
}
};
editor.addCommand(pluginName, pluginCommand);
}
editor.ui.addButton(pluginName, {
label: settings.iconTitle,
command: pluginName,
icon: settings.icon
});
// @todo Add button state handling.
}
});
},
prepareContent: function(content) {
// @todo Don't know if we need this yet.
return content;
},
insert: function(content) {
content = this.prepareContent(content);
CKEDITOR.instances[this.field].insertHtml(content);
}
};
})(jQuery);
In fine, perchè Wysiwyg vedi l'editor
syger_ckeditor
ho creato un symbolic link (utenti windows devono copiare il contenuto):ln -s ckeditor syger_ckeditor
ovviamante è un 'hack', ma funziona bene...
Il punto 2 deve aspettare un altro giorno...
John
Più imparo, più dubito.
Non rispetta tag <PRE>
<PRE>f("ciao")<PRE> viene Forzato senza alternative a <pre>f(& quot;ciao& quot;)</pre>
Ciao fa piacere trovare una discussione decente riguardo gli editor per Drupal.
Rinnovando il mio sito mi son buttato subito e con piacere sul nuovo CKeditor ma ora mi trovo una grossa gabola.
Sul mio sito ospito parecchi codici "C++", script e comandi Linux da dare da terminale..
Ora mi son accorto che CKeditor mi Distrugge i contenuti rendendoli inutilizzabili anche se li metto all'interno di tags
Ho passato la giornata a cercare e su un forum ho trovato una risposta dell'autore in persona di CKeditor che diceva che è giusto cosi e non aggiusterà perchè rispettare la validazione battilapesca in ogni parte del sorgente.
In pratica succede che se metto delle virgolette o altri simboli all'interno dei tags "ciao" queste vengono convertite in """ o altro..
..anche se scritto pulito in sorgente viene subito cambiato al volo appena esco dall'editor sorgente.. quindi non è un problema Drupal.
La stessa persona di prima consigliava eventualmete di disabilitare la formattazione nel config ma ho paura che questo non agisca solo nei "pre".
Ora cercavo il file di configurazione di CKeditor per vedere le opzioni e lo vedo vuoto.. nel Readme.txt non vedo info su dove reperire le opzioni possibili da inserire li.
D'accordo che ha fatto un bel lavoro ripulendo tutto ed ottimizzando ma qui si esagera un pò con le restrizioni volendo fare tutto Validato.
Tra l'altro mi risulta che i tags PRE sono da sempre definiti come "sezione preformattata che gli editor non devono intaccare" o no?
Grazie, ciao.
www.fixweb.it Fixus Friendly World: Tecno Consigli ^_^
Ciao
La discussione è vecchia ma aggiungo una nota per chi ci arrivasse da Google in cerca di "template ckeditor". La documentazione per la versione 3 è qui:
http://docs.cksource.com/CKEditor_3.x/Developers_Guide/Templates