ckeditor-3.0.js 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. (function($) {
  2. Drupal.wysiwyg.editor.init.ckeditor = function(settings) {
  3. // Plugins must only be loaded once. Only the settings from the first format
  4. // will be used but they're identical anyway.
  5. var registeredPlugins = {};
  6. for (var format in settings) {
  7. if (Drupal.settings.wysiwyg.plugins[format]) {
  8. // Register native external plugins.
  9. // Array syntax required; 'native' is a predefined token in JavaScript.
  10. for (var pluginName in Drupal.settings.wysiwyg.plugins[format]['native']) {
  11. if (!registeredPlugins[pluginName]) {
  12. var plugin = Drupal.settings.wysiwyg.plugins[format]['native'][pluginName];
  13. CKEDITOR.plugins.addExternal(pluginName, plugin.path, plugin.fileName);
  14. registeredPlugins[pluginName] = true;
  15. }
  16. }
  17. // Register Drupal plugins.
  18. for (var pluginName in Drupal.settings.wysiwyg.plugins[format].drupal) {
  19. if (!registeredPlugins[pluginName]) {
  20. Drupal.wysiwyg.editor.instance.ckeditor.addPlugin(pluginName, Drupal.settings.wysiwyg.plugins[format].drupal[pluginName], Drupal.settings.wysiwyg.plugins.drupal[pluginName]);
  21. registeredPlugins[pluginName] = true;
  22. }
  23. }
  24. }
  25. // Register Font styles (versions 3.2.1 and above).
  26. if (Drupal.settings.wysiwyg.configs.ckeditor[format].stylesSet) {
  27. CKEDITOR.stylesSet.add(format, Drupal.settings.wysiwyg.configs.ckeditor[format].stylesSet);
  28. }
  29. }
  30. };
  31. /**
  32. * Attach this editor to a target element.
  33. */
  34. Drupal.wysiwyg.editor.attach.ckeditor = function(context, params, settings) {
  35. // Apply editor instance settings.
  36. CKEDITOR.config.customConfig = '';
  37. var $drupalToolbar = $('#toolbar', Drupal.overlayChild ? window.parent.document : document);
  38. settings.on = {
  39. instanceReady: function(ev) {
  40. var editor = ev.editor;
  41. // Get a list of block, list and table tags from CKEditor's XHTML DTD.
  42. // @see http://docs.cksource.com/CKEditor_3.x/Developers_Guide/Output_Formatting.
  43. var dtd = CKEDITOR.dtd;
  44. var tags = CKEDITOR.tools.extend({}, dtd.$block, dtd.$listItem, dtd.$tableContent);
  45. // Set source formatting rules for each listed tag except <pre>.
  46. // Linebreaks can be inserted before or after opening and closing tags.
  47. if (settings.apply_source_formatting) {
  48. // Mimic FCKeditor output, by breaking lines between tags.
  49. for (var tag in tags) {
  50. if (tag == 'pre') {
  51. continue;
  52. }
  53. this.dataProcessor.writer.setRules(tag, {
  54. indent: true,
  55. breakBeforeOpen: true,
  56. breakAfterOpen: false,
  57. breakBeforeClose: false,
  58. breakAfterClose: true
  59. });
  60. }
  61. }
  62. else {
  63. // CKEditor adds default formatting to <br>, so we want to remove that
  64. // here too.
  65. tags.br = 1;
  66. // No indents or linebreaks;
  67. for (var tag in tags) {
  68. if (tag == 'pre') {
  69. continue;
  70. }
  71. this.dataProcessor.writer.setRules(tag, {
  72. indent: false,
  73. breakBeforeOpen: false,
  74. breakAfterOpen: false,
  75. breakBeforeClose: false,
  76. breakAfterClose: false
  77. });
  78. }
  79. }
  80. },
  81. pluginsLoaded: function(ev) {
  82. // Override the conversion methods to let Drupal plugins modify the data.
  83. var editor = ev.editor;
  84. if (editor.dataProcessor && Drupal.settings.wysiwyg.plugins[params.format]) {
  85. editor.dataProcessor.toHtml = CKEDITOR.tools.override(editor.dataProcessor.toHtml, function(originalToHtml) {
  86. // Convert raw data for display in WYSIWYG mode.
  87. return function(data, fixForBody) {
  88. for (var plugin in Drupal.settings.wysiwyg.plugins[params.format].drupal) {
  89. if (typeof Drupal.wysiwyg.plugins[plugin].attach == 'function') {
  90. data = Drupal.wysiwyg.plugins[plugin].attach(data, Drupal.settings.wysiwyg.plugins.drupal[plugin], editor.name);
  91. data = Drupal.wysiwyg.instances[params.field].prepareContent(data);
  92. }
  93. }
  94. return originalToHtml.call(this, data, fixForBody);
  95. };
  96. });
  97. editor.dataProcessor.toDataFormat = CKEDITOR.tools.override(editor.dataProcessor.toDataFormat, function(originalToDataFormat) {
  98. // Convert WYSIWYG mode content to raw data.
  99. return function(data, fixForBody) {
  100. data = originalToDataFormat.call(this, data, fixForBody);
  101. for (var plugin in Drupal.settings.wysiwyg.plugins[params.format].drupal) {
  102. if (typeof Drupal.wysiwyg.plugins[plugin].detach == 'function') {
  103. data = Drupal.wysiwyg.plugins[plugin].detach(data, Drupal.settings.wysiwyg.plugins.drupal[plugin], editor.name);
  104. }
  105. }
  106. return data;
  107. };
  108. });
  109. }
  110. },
  111. selectionChange: function (event) {
  112. var pluginSettings = Drupal.settings.wysiwyg.plugins[params.format];
  113. if (pluginSettings && pluginSettings.drupal) {
  114. $.each(pluginSettings.drupal, function (name) {
  115. var plugin = Drupal.wysiwyg.plugins[name];
  116. if ($.isFunction(plugin.isNode)) {
  117. var node = event.data.selection.getSelectedElement();
  118. var state = plugin.isNode(node ? node.$ : null) ? CKEDITOR.TRISTATE_ON : CKEDITOR.TRISTATE_OFF;
  119. event.editor.getCommand(name).setState(state);
  120. }
  121. });
  122. }
  123. },
  124. focus: function(ev) {
  125. Drupal.wysiwyg.activeId = ev.editor.name;
  126. },
  127. afterCommandExec: function(ev) {
  128. // Fix Drupal toolbar obscuring editor toolbar in fullscreen mode.
  129. if (ev.data.name != 'maximize') {
  130. return;
  131. }
  132. if (ev.data.command.state == CKEDITOR.TRISTATE_ON) {
  133. $drupalToolbar.hide();
  134. }
  135. else {
  136. $drupalToolbar.show();
  137. }
  138. }
  139. };
  140. // Attach editor.
  141. CKEDITOR.replace(params.field, settings);
  142. };
  143. /**
  144. * Detach a single or all editors.
  145. *
  146. * @todo 3.x: editor.prototype.getInstances() should always return an array
  147. * containing all instances or the passed in params.field instance, but
  148. * always return an array to simplify all detach functions.
  149. */
  150. Drupal.wysiwyg.editor.detach.ckeditor = function (context, params, trigger) {
  151. var method = (trigger == 'serialize') ? 'updateElement' : 'destroy';
  152. if (typeof params != 'undefined') {
  153. var instance = CKEDITOR.instances[params.field];
  154. if (instance) {
  155. instance[method]();
  156. }
  157. }
  158. else {
  159. for (var instanceName in CKEDITOR.instances) {
  160. if (CKEDITOR.instances.hasOwnProperty(instanceName)) {
  161. CKEDITOR.instances[instanceName][method]();
  162. }
  163. }
  164. }
  165. };
  166. Drupal.wysiwyg.editor.instance.ckeditor = {
  167. addPlugin: function(pluginName, settings, pluginSettings) {
  168. CKEDITOR.plugins.add(pluginName, {
  169. // Wrap Drupal plugin in a proxy pluygin.
  170. init: function(editor) {
  171. if (settings.css) {
  172. editor.on('mode', function(ev) {
  173. if (ev.editor.mode == 'wysiwyg') {
  174. // Inject CSS files directly into the editing area head tag.
  175. $('head', $('#cke_contents_' + ev.editor.name + ' iframe').eq(0).contents()).append('<link rel="stylesheet" href="' + settings.css + '" type="text/css" >');
  176. }
  177. });
  178. }
  179. if (typeof Drupal.wysiwyg.plugins[pluginName].invoke == 'function') {
  180. var pluginCommand = {
  181. exec: function (editor) {
  182. var data = { format: 'html', node: null, content: '' };
  183. var selection = editor.getSelection();
  184. if (selection) {
  185. data.node = selection.getSelectedElement();
  186. if (data.node) {
  187. data.node = data.node.$;
  188. }
  189. if (selection.getType() == CKEDITOR.SELECTION_TEXT) {
  190. if (CKEDITOR.env.ie) {
  191. data.content = selection.getNative().createRange().text;
  192. }
  193. else {
  194. data.content = selection.getNative().toString();
  195. }
  196. }
  197. else if (data.node) {
  198. // content is supposed to contain the "outerHTML".
  199. data.content = data.node.parentNode.innerHTML;
  200. }
  201. }
  202. Drupal.wysiwyg.plugins[pluginName].invoke(data, pluginSettings, editor.name);
  203. }
  204. };
  205. editor.addCommand(pluginName, pluginCommand);
  206. }
  207. editor.ui.addButton(pluginName, {
  208. label: settings.iconTitle,
  209. command: pluginName,
  210. icon: settings.icon
  211. });
  212. // @todo Add button state handling.
  213. }
  214. });
  215. },
  216. prepareContent: function(content) {
  217. // @todo Don't know if we need this yet.
  218. return content;
  219. },
  220. insert: function(content) {
  221. content = this.prepareContent(content);
  222. CKEDITOR.instances[this.field].insertHtml(content);
  223. },
  224. setContent: function (content) {
  225. CKEDITOR.instances[this.field].setData(content);
  226. },
  227. getContent: function () {
  228. return CKEDITOR.instances[this.field].getData();
  229. }
  230. };
  231. })(jQuery);