ckeditor-3.0.js 8.0 KB

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