PageSourceSearch

https://www.nasco.coop/sites/all/modules/wysiwyg/editors/js/ckeditor-3.0.js?tm6sfv

js nasco.coop collected 2026-10-01 12:20:38 UTC 12,952 bytes, 357 lines download raw bytes

1(function($) {
2
3CKEDITOR.disableAutoInline = true;
4
5// Exclude every id starting with 'cke_' in ajax_html_ids during AJAX requests.
6Drupal.wysiwyg.excludeIdSelectors.wysiwyg_ckeditor = ['[id^="cke_"]'];
7
8// Keeps track of private instance data.
9var instanceMap;
10
11/**
12 * Initialize the editor library.
13 *
14 * This method is called once the first time a library is needed. If new
15 * WYSIWYG fields are added later, update() will be called instead.
16 *
17 * @param settings
18 *   An object containing editor settings for each input format.
19 * @param pluginInfo
20 *   An object containing global plugin configuration.
21 */
22Drupal.wysiwyg.editor.init.ckeditor = function(settings, pluginInfo) {
23  instanceMap = {};
24
25  // Manually set the cache-busting string to the same value as Drupal.
26  if (Drupal.settings.wysiwyg.ckeditor.hasOwnProperty('timestamp')) {
27    CKEDITOR.timestamp = Drupal.settings.wysiwyg.ckeditor.timestamp;
28  }
29
30  // Nothing to do here other than register new plugins etc.
31  Drupal.wysiwyg.editor.update.ckeditor(settings, pluginInfo);
32};
33
34/**
35 * Update the editor library when new settings are available.
36 *
37 * This method is called instead of init() when at least one new WYSIWYG field
38 * has been added to the document and the library has already been initialized.
39 *
40 * $param settings
41 *   An object containing editor settings for each input format.
42 * $param pluginInfo
43 *   An object containing global plugin configuration.
44 */
45Drupal.wysiwyg.editor.update.ckeditor = function(settings, pluginInfo) {
46  // Register native external plugins.
47  // Array syntax required; 'native' is a predefined token in JavaScript.
48  for (var pluginId in pluginInfo['native']) {
49    if (pluginInfo['native'].hasOwnProperty(pluginId) && (!CKEDITOR.plugins.externals || !CKEDITOR.plugins.externals[pluginId])) {
50      var plugin = pluginInfo['native'][pluginId];
51      CKEDITOR.plugins.addExternal(pluginId, plugin.path, plugin.fileName);
52    }
53  }
54  // Build and register Drupal plugin wrappers.
55  for (var pluginId in pluginInfo.drupal) {
56    if (pluginInfo.drupal.hasOwnProperty(pluginId) && (!CKEDITOR.plugins.registered || !CKEDITOR.plugins.registered[pluginId])) {
57      Drupal.wysiwyg.editor.instance.ckeditor.addPlugin(pluginId, pluginInfo.drupal[pluginId]);
58    }
59  }
60  // Register Font styles (versions 3.2.1 and above).
61  for (var format in settings) {
62    if (settings[format].stylesSet && (!CKEDITOR.stylesSet || !CKEDITOR.stylesSet.registered[format])) {
63      CKEDITOR.stylesSet.add(format, settings[format].stylesSet);
64    }
65  }
66};
67
68/**
69 * Attach this editor to a target element.
70 */
71Drupal.wysiwyg.editor.attach.ckeditor = function(context, params, settings) {
72  // Apply editor instance settings.
73  CKEDITOR.config.customConfig = '';
74
75  if (!settings.height) {
76    settings.height = $('#' + params.field).height();
77  }
78  // Handler for any change-related event.
79  function changed(ev) {
80    instanceMap[ev.editor.name].contentsChanged();
81  }
82  settings.on = {
83    // Versions 4.x has a change event, 3.x does not.
84    change: function (ev) {
85      changed(ev);
86    },
87    contentDom: function (ev) {
88      var version_parts = CKEDITOR.version.split('.');
89      if (version_parts[0] === '3' || (version_parts[0] === '4' && parseInt(version_parts[1], 10) < 2)) {
90        ev.editor.on('key', function (ev) {
91          // Do not capture modifiers.
92          if (ev.data.ctrlKey || ev.data.metaKey)
93            return;
94
95          var keyCode = ev.data.keyCode;
96          // Filter out movement keys and related.
97          if (keyCode == 8 || keyCode == 13 || keyCode == 32
98            || (keyCode >= 46 && keyCode <= 90) || (keyCode >= 96 && keyCode <= 111)
99            || (keyCode >= 186 && keyCode <= 222) || keyCode == 229) {
100            changed(ev);
101          }
102        });
103        ev.editor.on('paste', changed);
104        ev.editor.on('saveSnapshot', function (ev) {
105          if (instanceMap[ev.editor.name].firstSaveSnapshot) {
106            // The first save snapshot event is triggered when the editor is
107            // focused and before anything has changed.
108            instanceMap[ev.editor.name].firstSaveSnapshot = false;
109            return;
110          }
111          changed(ev);
112        });
113      }
114    },
115    instanceReady: function(ev) {
116      var editor = ev.editor;
117      // Get a list of block, list and table tags from CKEditor's XHTML DTD.
118      // @see http://docs.cksource.com/CKEditor_3.x/Developers_Guide/Output_Formatting.
119      var dtd = CKEDITOR.dtd;
120      var tags = CKEDITOR.tools.extend({}, dtd.$block, dtd.$listItem, dtd.$tableContent);
121      // Set source formatting rules for each listed tag except <pre>.
122      // Linebreaks can be inserted before or after opening and closing tags.
123      if (settings.simple_source_formatting) {
124        // Mimic FCKeditor output, by breaking lines between tags.
125        for (var tag in tags) {
126          if (tag == 'pre') {
127            continue;
128          }
129          this.dataProcessor.writer.setRules(tag, {
130            indent: true,
131            breakBeforeOpen: true,
132            breakAfterOpen: false,
133            breakBeforeClose: false,
134            breakAfterClose: true
135          });
136        }
137      }
138      else {
139        // CKEditor adds default formatting to <br>, so we want to remove that
140        // here too.
141        tags.br = 1;
142        // No indents or linebreaks;
143        for (var tag in tags) {
144          if (tag == 'pre') {
145            continue;
146          }
147          this.dataProcessor.writer.setRules(tag, {
148            indent: false,
149            breakBeforeOpen: false,
150            breakAfterOpen: false,
151            breakBeforeClose: false,
152            breakAfterClose: false
153          });
154        }
155      }
156    },
157
158    pluginsLoaded: function(ev) {
159      var wysiwygInstance = instanceMap[this.name];
160      var enabledPlugins = wysiwygInstance.pluginInfo.instances.drupal;
161      // Override the conversion methods to let Drupal plugins modify the data.
162      var editor = ev.editor;
163      if (editor.dataProcessor && enabledPlugins) {
164        editor.dataProcessor.toHtml = CKEDITOR.tools.override(editor.dataProcessor.toHtml, function(originalToHtml) {
165          // Convert raw data for display in WYSIWYG mode.
166          return function(data, fixForBody) {
167            for (var plugin in enabledPlugins) {
168              if (typeof Drupal.wysiwyg.plugins[plugin].attach == 'function') {
169                data = Drupal.wysiwyg.plugins[plugin].attach(data, wysiwygInstance.pluginInfo.global.drupal[plugin], editor.name);
170                data = wysiwygInstance.prepareContent(data);
171              }
172            }
173            return originalToHtml.call(this, data, fixForBody);
174          };
175        });
176        editor.dataProcessor.toDataFormat = CKEDITOR.tools.override(editor.dataProcessor.toDataFormat, function(originalToDataFormat) {
177          // Convert WYSIWYG mode content to raw data.
178          return function(data, fixForBody) {
179            data = originalToDataFormat.call(this, data, fixForBody);
180            for (var plugin in enabledPlugins) {
181              if (typeof Drupal.wysiwyg.plugins[plugin].detach == 'function') {
182                data = Drupal.wysiwyg.plugins[plugin].detach(data, wysiwygInstance.pluginInfo.global.drupal[plugin], editor.name);
183              }
184            }
185            return data;
186          };
187        });
188      }
189    },
190
191    selectionChange: function (event) {
192      var wysiwygInstance = instanceMap[this.name];
193      var enabledPlugins = wysiwygInstance.pluginInfo.instances.drupal;
194      for (var name in enabledPlugins) {
195        var plugin = Drupal.wysiwyg.plugins[name];
196        if ($.isFunction(plugin.isNode)) {
197          var node = event.data.selection.getSelectedElement();
198          var state = plugin.isNode(node ? node.$ : null) ? CKEDITOR.TRISTATE_ON : CKEDITOR.TRISTATE_OFF;
199          event.editor.getCommand(name).setState(state);
200        }
201      }
202    },
203
204    focus: function(ev) {
205      Drupal.wysiwyg.activeId = ev.editor.name;
206    },
207
208    afterCommandExec: function(ev) {
209      // Fix Drupal toolbar obscuring editor toolbar in fullscreen mode.
210      if (ev.data.name != 'maximize') {
211        return;
212      }
213      if (ev.data.command.state == CKEDITOR.TRISTATE_ON) {
214        Drupal.wysiwyg.utilities.onFullscreenEnter();
215      }
216      else {
217        Drupal.wysiwyg.utilities.onFullscreenExit();
218      }
219    },
220
221    destroy: function (event) {
222      // Free our reference to the private instance to not risk memory leaks.
223      delete instanceMap[this.name];
224    }
225  };
226  instanceMap[params.field] = this;
227  // Attach editor.
228  var editorInstance = CKEDITOR.replace(params.field, settings);
229};
230
231/**
232 * Detach a single editor instance.
233 */
234Drupal.wysiwyg.editor.detach.ckeditor = function (context, params, trigger) {
235  var method = (trigger == 'serialize') ? 'updateElement' : 'destroy';
236  var instance = CKEDITOR.instances[params.field];
237  if (!instance) {
238    return;
239  }
240  instance[method]();
241};
242
243Drupal.wysiwyg.editor.instance.ckeditor = {
244
245  // Flag indicating if the first save snapshot event has fired.
246  firstSaveSnapshot: true,
247
248  addPlugin: function (pluginName, pluginSettings) {
249    CKEDITOR.plugins.add(pluginName, {
250      // Wrap Drupal plugin in a proxy plugin.
251      init: function(editor) {
252        if (pluginSettings.css) {
253          editor.on('mode', function(ev) {
254            if (ev.editor.mode == 'wysiwyg') {
255              // Inject CSS files directly into the editing area head tag.
256              var iframe = $('#cke_contents_' + ev.editor.name + ' iframe, #' + ev.editor.id + '_contents iframe');
257              $('head', iframe.eq(0).contents()).append('<link rel="stylesheet" href="' + pluginSettings.css + '" type="text/css" >');
258            }
259          });
260        }
261        if (typeof Drupal.wysiwyg.plugins[pluginName].invoke == 'function') {
262          var pluginCommand = {
263            exec: function (editor) {
264              var data = { format: 'html', node: null, content: '' };
265              var selection = editor.getSelection();
266              if (selection) {
267                data.node = selection.getSelectedElement();
268                if (data.node) {
269                  data.node = data.node.$;
270                }
271                if (selection.getType() == CKEDITOR.SELECTION_TEXT) {
272                  if (selection.getSelectedText) {
273                    data.content = selection.getSelectedText();
274                  }
275                  else {
276                    // Pre v3.6.1.
277                    if (CKEDITOR.env.ie) {
278                      data.content = selection.getNative().createRange().text;
279                    }
280                    else {
281                      data.content = selection.getNative().toString();
282                    }
283                  }
284                }
285                else if (data.node) {
286                  // content is supposed to contain the "outerHTML".
287                  data.content = data.node.parentNode.innerHTML;
288                }
289              }
290              Drupal.wysiwyg.plugins[pluginName].invoke(data, pluginSettings, editor.name);
291            }
292          };
293          editor.addCommand(pluginName, pluginCommand);
294        }
295        editor.ui.addButton(pluginName, {
296          label: pluginSettings.title,
297          command: pluginName,
298          icon: pluginSettings.icon
299        });
300
301        // @todo Add button state handling.
302      }
303    });
304  },
305  prepareContent: function(content) {
306    // @todo Don't know if we need this yet.
307    return content;
308  },
309
310  insert: function(content) {
311    content = this.prepareContent(content);
312    if (CKEDITOR.version.split('.')[0] === '3' && (CKEDITOR.env.webkit || CKEDITOR.env.chrome || CKEDITOR.env.opera || CKEDITOR.env.safari)) {
313      // Works around a WebKit bug which removes wrapper elements.
314      // @see https://drupal.org/node/1927968
315      var tmp = new CKEDITOR.dom.element('div'), children, skip = 0, item;
316      tmp.setHtml(content);
317      children = tmp.getChildren();
318      skip = 0;
319      while (children.count() > skip) {
320        item = children.getItem(skip);
321        switch(item.type) {
322          case 1:
323            CKEDITOR.instances[this.field].insertElement(item);
324            break;
325          case 3:
326            CKEDITOR.instances[this.field].insertText(item.getText());
327            skip++;
328            break;
329          case 8:
330            CKEDITOR.instances[this.field].insertHtml(item.getOuterHtml());
331            skip++;
332            break;
333          default:
334            skip++;
335        }
336      }
337    }
338    else {
339      CKEDITOR.instances[this.field].insertHtml(content);
340    }
341  },
342
343  setContent: function (content) {
344    CKEDITOR.instances[this.field].setData(content);
345  },
346
347  getContent: function () {
348    return CKEDITOR.instances[this.field].getData();
349  },
350
351  isFullscreen: function () {
352    var cmd = CKEDITOR.instances[this.field].commands.maximize;
353    return !!(cmd && cmd.state == CKEDITOR.TRISTATE_ON);
354  }
355};
356
357})(jQuery);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.