fckeditor-2.6.js 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. (function($) {
  2. /**
  3. * Attach this editor to a target element.
  4. */
  5. Drupal.wysiwyg.editor.attach.fckeditor = function(context, params, settings) {
  6. var FCKinstance = new FCKeditor(params.field, settings.Width, settings.Height, settings.ToolbarSet);
  7. // Apply editor instance settings.
  8. FCKinstance.BasePath = settings.EditorPath;
  9. FCKinstance.Config.wysiwygFormat = params.format;
  10. FCKinstance.Config.CustomConfigurationsPath = settings.CustomConfigurationsPath;
  11. // Load Drupal plugins and apply format specific settings.
  12. // @see fckeditor.config.js
  13. // @see Drupal.wysiwyg.editor.instance.fckeditor.init()
  14. // Attach editor.
  15. FCKinstance.ReplaceTextarea();
  16. };
  17. /**
  18. * Detach a single or all editors.
  19. */
  20. Drupal.wysiwyg.editor.detach.fckeditor = function(context, params) {
  21. var instances = [];
  22. if (typeof params != 'undefined' && typeof FCKeditorAPI != 'undefined') {
  23. var instance = FCKeditorAPI.GetInstance(params.field);
  24. if (instance) {
  25. instances[params.field] = instance;
  26. }
  27. }
  28. else {
  29. instances = FCKeditorAPI.__Instances;
  30. }
  31. for (var instanceName in instances) {
  32. var instance = instances[instanceName];
  33. instance.UpdateLinkedField();
  34. // Since we already detach the editor and update the textarea, the submit
  35. // event handler needs to be removed to prevent data loss (in IE).
  36. // FCKeditor uses 2 nested iFrames; instance.EditingArea.Window is the
  37. // deepest. Its parent is the iFrame containing the editor.
  38. var instanceScope = instance.EditingArea.Window.parent;
  39. instanceScope.FCKTools.RemoveEventListener(instance.GetParentForm(), 'submit', instance.UpdateLinkedField);
  40. // Run cleanups before forcing an unload of the iFrames or IE crashes.
  41. // This also deletes the instance from the FCKeditorAPI.__Instances array.
  42. instanceScope.FCKTools.RemoveEventListener(instanceScope, 'unload', instanceScope.FCKeditorAPI_Cleanup);
  43. instanceScope.FCKTools.RemoveEventListener(instanceScope, 'beforeunload', instanceScope.FCKeditorAPI_ConfirmCleanup);
  44. if (jQuery.isFunction(instanceScope.FCKIECleanup_Cleanup)) {
  45. instanceScope.FCKIECleanup_Cleanup();
  46. }
  47. instanceScope.FCKeditorAPI_ConfirmCleanup();
  48. instanceScope.FCKeditorAPI_Cleanup();
  49. // Remove the editor elements.
  50. $('#' + instanceName + '___Config').remove();
  51. $('#' + instanceName + '___Frame').remove();
  52. $('#' + instanceName).show();
  53. }
  54. };
  55. Drupal.wysiwyg.editor.instance.fckeditor = {
  56. init: function(instance) {
  57. // Track which editor instance is active.
  58. instance.FCK.Events.AttachEvent('OnFocus', function(editorInstance) {
  59. Drupal.wysiwyg.activeId = editorInstance.Name;
  60. });
  61. // Create a custom data processor to wrap the default one and allow Drupal
  62. // plugins modify the editor contents.
  63. var wysiwygDataProcessor = function() {};
  64. wysiwygDataProcessor.prototype = new instance.FCKDataProcessor();
  65. // Attach: Convert text into HTML.
  66. wysiwygDataProcessor.prototype.ConvertToHtml = function(data) {
  67. // Called from SetData() with stripped comments/scripts, revert those
  68. // manipulations and attach Drupal plugins.
  69. var data = instance.FCKConfig.ProtectedSource.Revert(data);
  70. if (Drupal.settings.wysiwyg.plugins[instance.wysiwygFormat] && Drupal.settings.wysiwyg.plugins[instance.wysiwygFormat].drupal) {
  71. for (var plugin in Drupal.settings.wysiwyg.plugins[instance.wysiwygFormat].drupal) {
  72. if (typeof Drupal.wysiwyg.plugins[plugin].attach == 'function') {
  73. data = Drupal.wysiwyg.plugins[plugin].attach(data, Drupal.settings.wysiwyg.plugins.drupal[plugin], instance.FCK.Name);
  74. data = Drupal.wysiwyg.editor.instance.fckeditor.prepareContent(data);
  75. }
  76. }
  77. }
  78. // Re-protect the source and use the original data processor to convert it
  79. // into XHTML.
  80. data = instance.FCKConfig.ProtectedSource.Protect(data);
  81. return instance.FCKDataProcessor.prototype.ConvertToHtml.call(this, data);
  82. };
  83. // Detach: Convert HTML into text.
  84. wysiwygDataProcessor.prototype.ConvertToDataFormat = function(rootNode, excludeRoot, ignoreIfEmptyParagraph, format) {
  85. // Called from GetData(), convert the content's DOM into a XHTML string
  86. // using the original data processor and detach Drupal plugins.
  87. var data = instance.FCKDataProcessor.prototype.ConvertToDataFormat.call(this, rootNode, excludeRoot, ignoreIfEmptyParagraph, format);
  88. if (Drupal.settings.wysiwyg.plugins[instance.wysiwygFormat] && Drupal.settings.wysiwyg.plugins[instance.wysiwygFormat].drupal) {
  89. for (var plugin in Drupal.settings.wysiwyg.plugins[instance.wysiwygFormat].drupal) {
  90. if (typeof Drupal.wysiwyg.plugins[plugin].detach == 'function') {
  91. data = Drupal.wysiwyg.plugins[plugin].detach(data, Drupal.settings.wysiwyg.plugins.drupal[plugin], instance.FCK.Name);
  92. }
  93. }
  94. }
  95. return data;
  96. };
  97. instance.FCK.DataProcessor = new wysiwygDataProcessor();
  98. },
  99. addPlugin: function(plugin, settings, pluginSettings, instance) {
  100. if (typeof Drupal.wysiwyg.plugins[plugin] != 'object') {
  101. return;
  102. }
  103. if (Drupal.settings.wysiwyg.plugins[instance.wysiwygFormat].drupal[plugin].css) {
  104. instance.FCKConfig.EditorAreaCSS += ',' + Drupal.settings.wysiwyg.plugins[instance.wysiwygFormat].drupal[plugin].css;
  105. }
  106. // @see fckcommands.js, fck_othercommands.js, fckpastewordcommand.js
  107. instance.FCKCommands.RegisterCommand(plugin, {
  108. // Invoke the plugin's button.
  109. Execute: function () {
  110. if (typeof Drupal.wysiwyg.plugins[plugin].invoke == 'function') {
  111. var data = { format: 'html', node: instance.FCKSelection.GetParentElement() };
  112. // @todo This is NOT the same as data.node.
  113. data.content = data.node.innerHTML;
  114. Drupal.wysiwyg.plugins[plugin].invoke(data, pluginSettings, instance.FCK.Name);
  115. }
  116. },
  117. // isNode: Return whether the plugin button should be enabled for the
  118. // current selection.
  119. // @see FCKUnlinkCommand.prototype.GetState()
  120. GetState: function () {
  121. // Always disabled if not in WYSIWYG mode.
  122. if (instance.FCK.EditMode != FCK_EDITMODE_WYSIWYG) {
  123. return FCK_TRISTATE_DISABLED;
  124. }
  125. var state = instance.FCK.GetNamedCommandState(this.Name);
  126. // FCKeditor sets the wrong state in WebKit browsers.
  127. if (!$.support.queryCommandEnabled && state == FCK_TRISTATE_DISABLED) {
  128. state = FCK_TRISTATE_OFF;
  129. }
  130. if (state == FCK_TRISTATE_OFF && instance.FCK.EditMode == FCK_EDITMODE_WYSIWYG) {
  131. if (typeof Drupal.wysiwyg.plugins[plugin].isNode == 'function') {
  132. var node = instance.FCKSelection.GetSelectedElement();
  133. state = Drupal.wysiwyg.plugins[plugin].isNode(node) ? FCK_TRISTATE_ON : FCK_TRISTATE_OFF;
  134. }
  135. }
  136. return state;
  137. },
  138. /**
  139. * Return information about the plugin as a name/value array.
  140. */
  141. Name: plugin
  142. });
  143. // Register the plugin button.
  144. // Arguments: commandName, label, tooltip, style, sourceView, contextSensitive, icon.
  145. instance.FCKToolbarItems.RegisterItem(plugin, new instance.FCKToolbarButton(plugin, settings.iconTitle, settings.iconTitle, null, false, true, settings.icon));
  146. },
  147. openDialog: function(dialog, params) {
  148. // @todo Implement open dialog.
  149. },
  150. closeDialog: function(dialog) {
  151. // @todo Implement close dialog.
  152. },
  153. prepareContent: function(content) {
  154. // @todo Not needed for FCKeditor?
  155. return content;
  156. },
  157. insert: function(content) {
  158. var instance = FCKeditorAPI.GetInstance(this.field);
  159. // @see FCK.InsertHtml(), FCK.InsertElement()
  160. instance.InsertHtml(content);
  161. }
  162. };
  163. })(jQuery);