--- wysiwyg/editors/js/jwysiwyg.js 2010-02-14 00:58:41.000000000 +0100 +++ wysiwyg_dev/editors/js/jwysiwyg.js 2010-07-24 09:06:23.000000000 +0200 @@ -2,11 +2,138 @@ (function($) { /** + * Initialize editor instances. + * + * @param editorSettings + * An object containing editor settings for each input format. + */ +Drupal.wysiwyg.editor.init.jwysiwyg = function(editorSettings) { + // Add Drupal plugin button styles to the document header. + var editorStyle = ''; + var checkedPlugins = []; + for (var format in editorSettings) { + for (var buttonName in editorSettings[format].buttons) { + if (Drupal.settings.wysiwyg.plugins.drupal[buttonName] && !checkedPlugins[buttonName]) { + editorStyle += "div.wysiwyg ul.panel li a." + buttonName + " { background: url('" + Drupal.settings.wysiwyg.plugins[format].drupal[buttonName].icon + "') no-repeat 0px 0px; }\n"; + checkedPlugins[buttonName] = true; + } + } + } + $('head').append(''); +}; + +/** * Attach this editor to a target element. */ Drupal.wysiwyg.editor.attach.jwysiwyg = function(context, params, settings) { + var $field = $('#' + params.field); + var css = []; + + // Setup editor buttons for Drupal plugins. + // @todo: Make sure buttons are always named same as the Drupal plugin. + // @todo: Update if Drupal plugins can provide multiple buttons. + var buttonSettings = {}; + for (var buttonName in settings.buttons) { + buttonSettings[buttonName] = { + visible: settings.buttons[buttonName] + } + if (Drupal.settings.wysiwyg.plugins.drupal[buttonName]) { + // This is a Drupal plugin and needs a custom function. + var pluginSettings = Drupal.settings.wysiwyg.plugins[params.format].drupal[buttonName]; + if (pluginSettings.css) { + css.push(pluginSettings.css); + } + buttonSettings[buttonName].exec = function(fieldName, buttonName) { + // Use a closure to store the value of fieldName and buttonName. + return function() { + var $field = $('#' + fieldName); + if (typeof Drupal.wysiwyg.plugins[buttonName].invoke == 'function') { + var element = $field.data('wysiwyg').editor[0]; + var selectedRange = Drupal.wysiwyg.editor.instance.jwysiwyg.getSelectedRange(element.contentWindow); + var selectedNode = (selectedRange.commonAncestorContainer ? selectedRange.commonAncestorContainer : selectedRange.parentElement()); + var data = { format: 'html', node: selectedNode, content : $field.data('wysiwyg').getContent() }; + Drupal.wysiwyg.plugins[buttonName].invoke(data, Drupal.settings.wysiwyg.plugins.drupal[buttonName], params.field); + } + }; + }(params.field, buttonName); + } + } + delete settings.buttons; + settings.controls = buttonSettings; + + if (settings.content_css) { + css.push(settings.content_css); + } + delete settings.content_css; + + // jWysiwyg only supports a single css file, so we'll change the template. + var htmlTemplate = '<' + '?xml version="1.0" encoding="UTF-8"?' + '>' + + '' + + '' + + '' + + '' + + 'STYLE_SHEETINITIAL_CONTENT'; + settings.html = htmlTemplate; + // Attach editor. - $('#' + params.field).wysiwyg(); +// $('#' + params.field).wysiwyg(); + $field.wysiwyg(settings); + + var editor = $field.data('wysiwyg'); + + // Inject proxy methods to handle plugins attaching/detaching plugins and + // activating their buttons. + var pluginSettings = Drupal.settings.wysiwyg.plugins; + var pluginInstances = Drupal.wysiwyg.plugins; + + // Use the jWysiwyg editor area document as key for the field name. + $(editor.editorDoc).data('wysiwyg_field', params.field); + $(editor.editorDoc).focus(function (){ + Drupal.wysiwyg.activeId = $(this).data('wysiwyg_field'); + }); + + var oldGetContent = editor.getContent; + editor.getContent = function() { + var content = oldGetContent.call(this); + for (var plugin in pluginSettings[params.format].drupal) if (typeof pluginInstances[plugin].detach == 'function') { + content = pluginInstances[plugin].detach(content, pluginSettings[plugin], params.field); + } + return content; + }; + + var oldSetContent = editor.setContent; + editor.setContent = function(newContent) { + for (var plugin in Drupal.settings.wysiwyg.plugins[params.format].drupal) if (typeof pluginInstances[plugin].attach == 'function') { + newContent = pluginInstances[plugin].attach(newContent, pluginSettings.drupal[plugin], params.field); + } + oldSetContent.call(this, newContent); + }; + + var oldCheckTargets = editor.checkTargets; + editor.checkTargets = function(element) { + var foundTarget = false; + for (var plugin in pluginSettings[params.format].drupal) { + if (typeof pluginInstances[plugin].isNode == 'function') { + if (pluginInstances[plugin].isNode(element)) { + foundTarget = true; + break; + } + } + } + + if (!foundTarget) { + oldCheckTargets.call(this, element); + } + else { + // Deactivate all buttons by passing the body element. + oldCheckTargets.call(this, element.ownerDocument.body); + // Activate the Drupal plugin button. + $('.' + plugin, this.panel).addClass('active'); + } + }; + // Because we could not proxy the setContent method before it was defined + // we need to run it again to allow Drupal plugins to attach themselves. + editor.setContent(editor.getContent()); }; /** @@ -23,4 +150,61 @@ Drupal.wysiwyg.editor.detach.jwysiwyg = $field.show(); }; +Drupal.wysiwyg.editor.instance.jwysiwyg = { + openDialog: function(dialog, params) { + alert("Drupal plugin dialogs are not yet supported by jWysiwyg."); + }, + + closeDialog: function(dialog) { + }, + + getSelection: function(targetWindow) { + return targetWindow.getSelection ? targetWindow.getSelection() : targetWindow.document.selection.createRange(); + }, + + getSelectedRange: function(targetWindow) { + var selection = this.getSelection(targetWindow); + if (selection.getRangeAt) { + return selection.getRangeAt(0); + } + // Safari. + else { + var range = document.createRange(); + range.setStart(selection.anchorNode,selection.anchorOffset); + range.setEnd(selection.focusNode,selection.focusOffset); + return range; + } + }, + + /** + * Insert content at the current caret position. + */ + insert: function(content) { + var $field = $('#' + this.field); + var editor = $field.data('wysiwyg'); + var editorWindow = editor.editor[0].contentWindow; + + // jWysiwyg does not provide an insert method. + // Using simplified code from QuirksMode.org + var selectionRange = this.getSelectedRange(editorWindow); + if (selectionRange.insertNode) { + // Delete and insert new node. + selectionRange.deleteContents(); + selectionRange.insertNode(selectionRange.createContextualFragment(content)); + } + else if (editor.selectionStart || editor.selectionStart == '0') { + if (selectionRange.item) { + // Delete content and get caret text selection. + editor.editorDoc.execCommand('Delete', false, null); + selectionRange = this.getSelectedRange(editorWindow); + } + selectionRange.pasteHTML(content); + } + else { + editor.setContent(editor.getContent() + content); + } + } +}; + + })(jQuery);