diff options
author | Ismaël Bouya <ismael.bouya@normalesup.org> | 2016-01-25 17:45:33 +0100 |
---|---|---|
committer | Ismaël Bouya <ismael.bouya@normalesup.org> | 2016-01-25 18:00:33 +0100 |
commit | 7adcb81e4f83f98c468889aaa5a85558ba88c770 (patch) | |
tree | 0d6ede733777b29060b48df4afaa2c64bfbae276 /sources/plugins/wysiwygarea/plugin.js | |
download | connexionswing-ckeditor-component-4.5.6.tar.gz connexionswing-ckeditor-component-4.5.6.tar.zst connexionswing-ckeditor-component-4.5.6.zip |
Initial commit4.5.6
Diffstat (limited to 'sources/plugins/wysiwygarea/plugin.js')
-rw-r--r-- | sources/plugins/wysiwygarea/plugin.js | 708 |
1 files changed, 708 insertions, 0 deletions
diff --git a/sources/plugins/wysiwygarea/plugin.js b/sources/plugins/wysiwygarea/plugin.js new file mode 100644 index 00000000..9b24257b --- /dev/null +++ b/sources/plugins/wysiwygarea/plugin.js | |||
@@ -0,0 +1,708 @@ | |||
1 | /** | ||
2 | * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. | ||
3 | * For licensing, see LICENSE.md or http://ckeditor.com/license | ||
4 | */ | ||
5 | |||
6 | /** | ||
7 | * @fileOverview The WYSIWYG Area plugin. It registers the "wysiwyg" editing | ||
8 | * mode, which handles the main editing area space. | ||
9 | */ | ||
10 | |||
11 | ( function() { | ||
12 | CKEDITOR.plugins.add( 'wysiwygarea', { | ||
13 | init: function( editor ) { | ||
14 | if ( editor.config.fullPage ) { | ||
15 | editor.addFeature( { | ||
16 | allowedContent: 'html head title; style [media,type]; body (*)[id]; meta link [*]', | ||
17 | requiredContent: 'body' | ||
18 | } ); | ||
19 | } | ||
20 | |||
21 | editor.addMode( 'wysiwyg', function( callback ) { | ||
22 | var src = 'document.open();' + | ||
23 | // In IE, the document domain must be set any time we call document.open(). | ||
24 | ( CKEDITOR.env.ie ? '(' + CKEDITOR.tools.fixDomain + ')();' : '' ) + | ||
25 | 'document.close();'; | ||
26 | |||
27 | // With IE, the custom domain has to be taken care at first, | ||
28 | // for other browers, the 'src' attribute should be left empty to | ||
29 | // trigger iframe's 'load' event. | ||
30 | // Microsoft Edge throws "Permission Denied" if treated like an IE (#13441). | ||
31 | if ( CKEDITOR.env.air ) { | ||
32 | src = 'javascript:void(0)'; // jshint ignore:line | ||
33 | } else if ( CKEDITOR.env.ie && !CKEDITOR.env.edge ) { | ||
34 | src = 'javascript:void(function(){' + encodeURIComponent( src ) + '}())'; // jshint ignore:line | ||
35 | } else { | ||
36 | src = ''; | ||
37 | } | ||
38 | |||
39 | var iframe = CKEDITOR.dom.element.createFromHtml( '<iframe src="' + src + '" frameBorder="0"></iframe>' ); | ||
40 | iframe.setStyles( { width: '100%', height: '100%' } ); | ||
41 | iframe.addClass( 'cke_wysiwyg_frame' ).addClass( 'cke_reset' ); | ||
42 | |||
43 | var contentSpace = editor.ui.space( 'contents' ); | ||
44 | contentSpace.append( iframe ); | ||
45 | |||
46 | |||
47 | // Asynchronous iframe loading is only required in IE>8 and Gecko (other reasons probably). | ||
48 | // Do not use it on WebKit as it'll break the browser-back navigation. | ||
49 | var useOnloadEvent = ( CKEDITOR.env.ie && !CKEDITOR.env.edge ) || CKEDITOR.env.gecko; | ||
50 | if ( useOnloadEvent ) | ||
51 | iframe.on( 'load', onLoad ); | ||
52 | |||
53 | var frameLabel = editor.title, | ||
54 | helpLabel = editor.fire( 'ariaEditorHelpLabel', {} ).label; | ||
55 | |||
56 | if ( frameLabel ) { | ||
57 | if ( CKEDITOR.env.ie && helpLabel ) | ||
58 | frameLabel += ', ' + helpLabel; | ||
59 | |||
60 | iframe.setAttribute( 'title', frameLabel ); | ||
61 | } | ||
62 | |||
63 | if ( helpLabel ) { | ||
64 | var labelId = CKEDITOR.tools.getNextId(), | ||
65 | desc = CKEDITOR.dom.element.createFromHtml( '<span id="' + labelId + '" class="cke_voice_label">' + helpLabel + '</span>' ); | ||
66 | |||
67 | contentSpace.append( desc, 1 ); | ||
68 | iframe.setAttribute( 'aria-describedby', labelId ); | ||
69 | } | ||
70 | |||
71 | // Remove the ARIA description. | ||
72 | editor.on( 'beforeModeUnload', function( evt ) { | ||
73 | evt.removeListener(); | ||
74 | if ( desc ) | ||
75 | desc.remove(); | ||
76 | } ); | ||
77 | |||
78 | iframe.setAttributes( { | ||
79 | tabIndex: editor.tabIndex, | ||
80 | allowTransparency: 'true' | ||
81 | } ); | ||
82 | |||
83 | // Execute onLoad manually for all non IE||Gecko browsers. | ||
84 | !useOnloadEvent && onLoad(); | ||
85 | |||
86 | editor.fire( 'ariaWidget', iframe ); | ||
87 | |||
88 | function onLoad( evt ) { | ||
89 | evt && evt.removeListener(); | ||
90 | editor.editable( new framedWysiwyg( editor, iframe.$.contentWindow.document.body ) ); | ||
91 | editor.setData( editor.getData( 1 ), callback ); | ||
92 | } | ||
93 | } ); | ||
94 | } | ||
95 | } ); | ||
96 | |||
97 | /** | ||
98 | * Adds the path to a stylesheet file to the exisiting {@link CKEDITOR.config#contentsCss} value. | ||
99 | * | ||
100 | * **Note:** This method is available only with the `wysiwygarea` plugin and only affects | ||
101 | * classic editors based on it (so it does not affect inline editors). | ||
102 | * | ||
103 | * editor.addContentsCss( 'assets/contents.css' ); | ||
104 | * | ||
105 | * @since 4.4 | ||
106 | * @param {String} cssPath The path to the stylesheet file which should be added. | ||
107 | * @member CKEDITOR.editor | ||
108 | */ | ||
109 | CKEDITOR.editor.prototype.addContentsCss = function( cssPath ) { | ||
110 | var cfg = this.config, | ||
111 | curContentsCss = cfg.contentsCss; | ||
112 | |||
113 | // Convert current value into array. | ||
114 | if ( !CKEDITOR.tools.isArray( curContentsCss ) ) | ||
115 | cfg.contentsCss = curContentsCss ? [ curContentsCss ] : []; | ||
116 | |||
117 | cfg.contentsCss.push( cssPath ); | ||
118 | }; | ||
119 | |||
120 | function onDomReady( win ) { | ||
121 | var editor = this.editor, | ||
122 | doc = win.document, | ||
123 | body = doc.body; | ||
124 | |||
125 | // Remove helper scripts from the DOM. | ||
126 | var script = doc.getElementById( 'cke_actscrpt' ); | ||
127 | script && script.parentNode.removeChild( script ); | ||
128 | script = doc.getElementById( 'cke_shimscrpt' ); | ||
129 | script && script.parentNode.removeChild( script ); | ||
130 | script = doc.getElementById( 'cke_basetagscrpt' ); | ||
131 | script && script.parentNode.removeChild( script ); | ||
132 | |||
133 | body.contentEditable = true; | ||
134 | |||
135 | if ( CKEDITOR.env.ie ) { | ||
136 | // Don't display the focus border. | ||
137 | body.hideFocus = true; | ||
138 | |||
139 | // Disable and re-enable the body to avoid IE from | ||
140 | // taking the editing focus at startup. (#141 / #523) | ||
141 | body.disabled = true; | ||
142 | body.removeAttribute( 'disabled' ); | ||
143 | } | ||
144 | |||
145 | delete this._.isLoadingData; | ||
146 | |||
147 | // Play the magic to alter element reference to the reloaded one. | ||
148 | this.$ = body; | ||
149 | |||
150 | doc = new CKEDITOR.dom.document( doc ); | ||
151 | |||
152 | this.setup(); | ||
153 | this.fixInitialSelection(); | ||
154 | |||
155 | var editable = this; | ||
156 | |||
157 | // Without it IE8 has problem with removing selection in nested editable. (#13785) | ||
158 | if ( CKEDITOR.env.ie && !CKEDITOR.env.edge ) { | ||
159 | doc.getDocumentElement().addClass( doc.$.compatMode ); | ||
160 | } | ||
161 | |||
162 | // Prevent IE/Edge from leaving a new paragraph/div after deleting all contents in body. (#6966, #13142) | ||
163 | if ( CKEDITOR.env.ie && !CKEDITOR.env.edge && editor.enterMode != CKEDITOR.ENTER_P ) { | ||
164 | removeSuperfluousElement( 'p' ); | ||
165 | } else if ( CKEDITOR.env.edge && editor.enterMode != CKEDITOR.ENTER_DIV ) { | ||
166 | removeSuperfluousElement( 'div' ); | ||
167 | } | ||
168 | |||
169 | // Fix problem with cursor not appearing in Webkit and IE11+ when clicking below the body (#10945, #10906). | ||
170 | // Fix for older IEs (8-10 and QM) is placed inside selection.js. | ||
171 | if ( CKEDITOR.env.webkit || ( CKEDITOR.env.ie && CKEDITOR.env.version > 10 ) ) { | ||
172 | doc.getDocumentElement().on( 'mousedown', function( evt ) { | ||
173 | if ( evt.data.getTarget().is( 'html' ) ) { | ||
174 | // IE needs this timeout. Webkit does not, but it does not cause problems too. | ||
175 | setTimeout( function() { | ||
176 | editor.editable().focus(); | ||
177 | } ); | ||
178 | } | ||
179 | } ); | ||
180 | } | ||
181 | |||
182 | // Config props: disableObjectResizing and disableNativeTableHandles handler. | ||
183 | objectResizeDisabler( editor ); | ||
184 | |||
185 | // Enable dragging of position:absolute elements in IE. | ||
186 | try { | ||
187 | editor.document.$.execCommand( '2D-position', false, true ); | ||
188 | } catch ( e ) {} | ||
189 | |||
190 | if ( CKEDITOR.env.gecko || CKEDITOR.env.ie && editor.document.$.compatMode == 'CSS1Compat' ) { | ||
191 | this.attachListener( this, 'keydown', function( evt ) { | ||
192 | var keyCode = evt.data.getKeystroke(); | ||
193 | |||
194 | // PageUp OR PageDown | ||
195 | if ( keyCode == 33 || keyCode == 34 ) { | ||
196 | // PageUp/PageDown scrolling is broken in document | ||
197 | // with standard doctype, manually fix it. (#4736) | ||
198 | if ( CKEDITOR.env.ie ) { | ||
199 | setTimeout( function() { | ||
200 | editor.getSelection().scrollIntoView(); | ||
201 | }, 0 ); | ||
202 | } | ||
203 | // Page up/down cause editor selection to leak | ||
204 | // outside of editable thus we try to intercept | ||
205 | // the behavior, while it affects only happen | ||
206 | // when editor contents are not overflowed. (#7955) | ||
207 | else if ( editor.window.$.innerHeight > this.$.offsetHeight ) { | ||
208 | var range = editor.createRange(); | ||
209 | range[ keyCode == 33 ? 'moveToElementEditStart' : 'moveToElementEditEnd' ]( this ); | ||
210 | range.select(); | ||
211 | evt.data.preventDefault(); | ||
212 | } | ||
213 | } | ||
214 | } ); | ||
215 | } | ||
216 | |||
217 | if ( CKEDITOR.env.ie ) { | ||
218 | // [IE] Iframe will still keep the selection when blurred, if | ||
219 | // focus is moved onto a non-editing host, e.g. link or button, but | ||
220 | // it becomes a problem for the object type selection, since the resizer | ||
221 | // handler attached on it will mark other part of the UI, especially | ||
222 | // for the dialog. (#8157) | ||
223 | // [IE<8 & Opera] Even worse For old IEs, the cursor will not vanish even if | ||
224 | // the selection has been moved to another text input in some cases. (#4716) | ||
225 | // | ||
226 | // Now the range restore is disabled, so we simply force IE to clean | ||
227 | // up the selection before blur. | ||
228 | this.attachListener( doc, 'blur', function() { | ||
229 | // Error proof when the editor is not visible. (#6375) | ||
230 | try { | ||
231 | doc.$.selection.empty(); | ||
232 | } catch ( er ) {} | ||
233 | } ); | ||
234 | } | ||
235 | |||
236 | if ( CKEDITOR.env.iOS ) { | ||
237 | // [iOS] If touch is bound to any parent of the iframe blur happens on any touch | ||
238 | // event and body becomes the focused element (#10714). | ||
239 | this.attachListener( doc, 'touchend', function() { | ||
240 | win.focus(); | ||
241 | } ); | ||
242 | } | ||
243 | |||
244 | var title = editor.document.getElementsByTag( 'title' ).getItem( 0 ); | ||
245 | // document.title is malfunctioning on Chrome, so get value from the element (#12402). | ||
246 | title.data( 'cke-title', title.getText() ); | ||
247 | |||
248 | // [IE] JAWS will not recognize the aria label we used on the iframe | ||
249 | // unless the frame window title string is used as the voice label, | ||
250 | // backup the original one and restore it on output. | ||
251 | if ( CKEDITOR.env.ie ) | ||
252 | editor.document.$.title = this._.docTitle; | ||
253 | |||
254 | CKEDITOR.tools.setTimeout( function() { | ||
255 | // Editable is ready after first setData. | ||
256 | if ( this.status == 'unloaded' ) | ||
257 | this.status = 'ready'; | ||
258 | |||
259 | editor.fire( 'contentDom' ); | ||
260 | |||
261 | if ( this._.isPendingFocus ) { | ||
262 | editor.focus(); | ||
263 | this._.isPendingFocus = false; | ||
264 | } | ||
265 | |||
266 | setTimeout( function() { | ||
267 | editor.fire( 'dataReady' ); | ||
268 | }, 0 ); | ||
269 | }, 0, this ); | ||
270 | |||
271 | function removeSuperfluousElement( tagName ) { | ||
272 | var lockRetain = false; | ||
273 | |||
274 | // Superfluous elements appear after keydown | ||
275 | // and before keyup, so the procedure is as follows: | ||
276 | // 1. On first keydown mark all elements with | ||
277 | // a specified tag name as non-superfluous. | ||
278 | editable.attachListener( editable, 'keydown', function() { | ||
279 | var body = doc.getBody(), | ||
280 | retained = body.getElementsByTag( tagName ); | ||
281 | |||
282 | if ( !lockRetain ) { | ||
283 | for ( var i = 0; i < retained.count(); i++ ) { | ||
284 | retained.getItem( i ).setCustomData( 'retain', true ); | ||
285 | } | ||
286 | lockRetain = true; | ||
287 | } | ||
288 | }, null, null, 1 ); | ||
289 | |||
290 | // 2. On keyup remove all elements that were not marked | ||
291 | // as non-superfluous (which means they must have had appeared in the meantime). | ||
292 | editable.attachListener( editable, 'keyup', function() { | ||
293 | var elements = doc.getElementsByTag( tagName ); | ||
294 | if ( lockRetain ) { | ||
295 | if ( elements.count() == 1 && !elements.getItem( 0 ).getCustomData( 'retain' ) ) { | ||
296 | elements.getItem( 0 ).remove( 1 ); | ||
297 | } | ||
298 | lockRetain = false; | ||
299 | } | ||
300 | } ); | ||
301 | } | ||
302 | } | ||
303 | |||
304 | var framedWysiwyg = CKEDITOR.tools.createClass( { | ||
305 | $: function() { | ||
306 | this.base.apply( this, arguments ); | ||
307 | |||
308 | this._.frameLoadedHandler = CKEDITOR.tools.addFunction( function( win ) { | ||
309 | // Avoid opening design mode in a frame window thread, | ||
310 | // which will cause host page scrolling.(#4397) | ||
311 | CKEDITOR.tools.setTimeout( onDomReady, 0, this, win ); | ||
312 | }, this ); | ||
313 | |||
314 | this._.docTitle = this.getWindow().getFrame().getAttribute( 'title' ); | ||
315 | }, | ||
316 | |||
317 | base: CKEDITOR.editable, | ||
318 | |||
319 | proto: { | ||
320 | setData: function( data, isSnapshot ) { | ||
321 | var editor = this.editor; | ||
322 | |||
323 | if ( isSnapshot ) { | ||
324 | this.setHtml( data ); | ||
325 | this.fixInitialSelection(); | ||
326 | |||
327 | // Fire dataReady for the consistency with inline editors | ||
328 | // and because it makes sense. (#10370) | ||
329 | editor.fire( 'dataReady' ); | ||
330 | } | ||
331 | else { | ||
332 | this._.isLoadingData = true; | ||
333 | editor._.dataStore = { id: 1 }; | ||
334 | |||
335 | var config = editor.config, | ||
336 | fullPage = config.fullPage, | ||
337 | docType = config.docType; | ||
338 | |||
339 | // Build the additional stuff to be included into <head>. | ||
340 | var headExtra = CKEDITOR.tools.buildStyleHtml( iframeCssFixes() ).replace( /<style>/, '<style data-cke-temp="1">' ); | ||
341 | |||
342 | if ( !fullPage ) | ||
343 | headExtra += CKEDITOR.tools.buildStyleHtml( editor.config.contentsCss ); | ||
344 | |||
345 | var baseTag = config.baseHref ? '<base href="' + config.baseHref + '" data-cke-temp="1" />' : ''; | ||
346 | |||
347 | if ( fullPage ) { | ||
348 | // Search and sweep out the doctype declaration. | ||
349 | data = data.replace( /<!DOCTYPE[^>]*>/i, function( match ) { | ||
350 | editor.docType = docType = match; | ||
351 | return ''; | ||
352 | } ).replace( /<\?xml\s[^\?]*\?>/i, function( match ) { | ||
353 | editor.xmlDeclaration = match; | ||
354 | return ''; | ||
355 | } ); | ||
356 | } | ||
357 | |||
358 | // Get the HTML version of the data. | ||
359 | data = editor.dataProcessor.toHtml( data ); | ||
360 | |||
361 | if ( fullPage ) { | ||
362 | // Check if the <body> tag is available. | ||
363 | if ( !( /<body[\s|>]/ ).test( data ) ) | ||
364 | data = '<body>' + data; | ||
365 | |||
366 | // Check if the <html> tag is available. | ||
367 | if ( !( /<html[\s|>]/ ).test( data ) ) | ||
368 | data = '<html>' + data + '</html>'; | ||
369 | |||
370 | // Check if the <head> tag is available. | ||
371 | if ( !( /<head[\s|>]/ ).test( data ) ) | ||
372 | data = data.replace( /<html[^>]*>/, '$&<head><title></title></head>' ); | ||
373 | else if ( !( /<title[\s|>]/ ).test( data ) ) | ||
374 | data = data.replace( /<head[^>]*>/, '$&<title></title>' ); | ||
375 | |||
376 | // The base must be the first tag in the HEAD, e.g. to get relative | ||
377 | // links on styles. | ||
378 | baseTag && ( data = data.replace( /<head[^>]*?>/, '$&' + baseTag ) ); | ||
379 | |||
380 | // Inject the extra stuff into <head>. | ||
381 | // Attention: do not change it before testing it well. (V2) | ||
382 | // This is tricky... if the head ends with <meta ... content type>, | ||
383 | // Firefox will break. But, it works if we place our extra stuff as | ||
384 | // the last elements in the HEAD. | ||
385 | data = data.replace( /<\/head\s*>/, headExtra + '$&' ); | ||
386 | |||
387 | // Add the DOCTYPE back to it. | ||
388 | data = docType + data; | ||
389 | } else { | ||
390 | data = config.docType + | ||
391 | '<html dir="' + config.contentsLangDirection + '"' + | ||
392 | ' lang="' + ( config.contentsLanguage || editor.langCode ) + '">' + | ||
393 | '<head>' + | ||
394 | '<title>' + this._.docTitle + '</title>' + | ||
395 | baseTag + | ||
396 | headExtra + | ||
397 | '</head>' + | ||
398 | '<body' + ( config.bodyId ? ' id="' + config.bodyId + '"' : '' ) + | ||
399 | ( config.bodyClass ? ' class="' + config.bodyClass + '"' : '' ) + | ||
400 | '>' + | ||
401 | data + | ||
402 | '</body>' + | ||
403 | '</html>'; | ||
404 | } | ||
405 | |||
406 | if ( CKEDITOR.env.gecko ) { | ||
407 | // Hack to make Fx put cursor at the start of doc on fresh focus. | ||
408 | data = data.replace( /<body/, '<body contenteditable="true" ' ); | ||
409 | |||
410 | // Another hack which is used by onDomReady to remove a leading | ||
411 | // <br> which is inserted by Firefox 3.6 when document.write is called. | ||
412 | // This additional <br> is present because of contenteditable="true" | ||
413 | if ( CKEDITOR.env.version < 20000 ) | ||
414 | data = data.replace( /<body[^>]*>/, '$&<!-- cke-content-start -->' ); | ||
415 | } | ||
416 | |||
417 | // The script that launches the bootstrap logic on 'domReady', so the document | ||
418 | // is fully editable even before the editing iframe is fully loaded (#4455). | ||
419 | var bootstrapCode = | ||
420 | '<script id="cke_actscrpt" type="text/javascript"' + ( CKEDITOR.env.ie ? ' defer="defer" ' : '' ) + '>' + | ||
421 | 'var wasLoaded=0;' + // It must be always set to 0 as it remains as a window property. | ||
422 | 'function onload(){' + | ||
423 | 'if(!wasLoaded)' + // FF3.6 calls onload twice when editor.setData. Stop that. | ||
424 | 'window.parent.CKEDITOR.tools.callFunction(' + this._.frameLoadedHandler + ',window);' + | ||
425 | 'wasLoaded=1;' + | ||
426 | '}' + | ||
427 | ( CKEDITOR.env.ie ? 'onload();' : 'document.addEventListener("DOMContentLoaded", onload, false );' ) + | ||
428 | '</script>'; | ||
429 | |||
430 | // For IE<9 add support for HTML5's elements. | ||
431 | // Note: this code must not be deferred. | ||
432 | if ( CKEDITOR.env.ie && CKEDITOR.env.version < 9 ) { | ||
433 | bootstrapCode += | ||
434 | '<script id="cke_shimscrpt">' + | ||
435 | 'window.parent.CKEDITOR.tools.enableHtml5Elements(document)' + | ||
436 | '</script>'; | ||
437 | } | ||
438 | |||
439 | // IE<10 needs this hack to properly enable <base href="...">. | ||
440 | // See: http://stackoverflow.com/a/13373180/1485219 (#11910). | ||
441 | if ( baseTag && CKEDITOR.env.ie && CKEDITOR.env.version < 10 ) { | ||
442 | bootstrapCode += | ||
443 | '<script id="cke_basetagscrpt">' + | ||
444 | 'var baseTag = document.querySelector( "base" );' + | ||
445 | 'baseTag.href = baseTag.href;' + | ||
446 | '</script>'; | ||
447 | } | ||
448 | |||
449 | data = data.replace( /(?=\s*<\/(:?head)>)/, bootstrapCode ); | ||
450 | |||
451 | // Current DOM will be deconstructed by document.write, cleanup required. | ||
452 | this.clearCustomData(); | ||
453 | this.clearListeners(); | ||
454 | |||
455 | editor.fire( 'contentDomUnload' ); | ||
456 | |||
457 | var doc = this.getDocument(); | ||
458 | |||
459 | // Work around Firefox bug - error prune when called from XUL (#320), | ||
460 | // defer it thanks to the async nature of this method. | ||
461 | try { | ||
462 | doc.write( data ); | ||
463 | } catch ( e ) { | ||
464 | setTimeout( function() { | ||
465 | doc.write( data ); | ||
466 | }, 0 ); | ||
467 | } | ||
468 | } | ||
469 | }, | ||
470 | |||
471 | getData: function( isSnapshot ) { | ||
472 | if ( isSnapshot ) | ||
473 | return this.getHtml(); | ||
474 | else { | ||
475 | var editor = this.editor, | ||
476 | config = editor.config, | ||
477 | fullPage = config.fullPage, | ||
478 | docType = fullPage && editor.docType, | ||
479 | xmlDeclaration = fullPage && editor.xmlDeclaration, | ||
480 | doc = this.getDocument(); | ||
481 | |||
482 | var data = fullPage ? doc.getDocumentElement().getOuterHtml() : doc.getBody().getHtml(); | ||
483 | |||
484 | // BR at the end of document is bogus node for Mozilla. (#5293). | ||
485 | // Prevent BRs from disappearing from the end of the content | ||
486 | // while enterMode is ENTER_BR (#10146). | ||
487 | if ( CKEDITOR.env.gecko && config.enterMode != CKEDITOR.ENTER_BR ) | ||
488 | data = data.replace( /<br>(?=\s*(:?$|<\/body>))/, '' ); | ||
489 | |||
490 | data = editor.dataProcessor.toDataFormat( data ); | ||
491 | |||
492 | if ( xmlDeclaration ) | ||
493 | data = xmlDeclaration + '\n' + data; | ||
494 | if ( docType ) | ||
495 | data = docType + '\n' + data; | ||
496 | |||
497 | return data; | ||
498 | } | ||
499 | }, | ||
500 | |||
501 | focus: function() { | ||
502 | if ( this._.isLoadingData ) | ||
503 | this._.isPendingFocus = true; | ||
504 | else | ||
505 | framedWysiwyg.baseProto.focus.call( this ); | ||
506 | }, | ||
507 | |||
508 | detach: function() { | ||
509 | var editor = this.editor, | ||
510 | doc = editor.document, | ||
511 | iframe, | ||
512 | onResize; | ||
513 | |||
514 | // Trying to access window's frameElement property on Edge throws an exception | ||
515 | // when frame was already removed from DOM. (#13850, #13790) | ||
516 | try { | ||
517 | iframe = editor.window.getFrame(); | ||
518 | } catch ( e ) {} | ||
519 | |||
520 | framedWysiwyg.baseProto.detach.call( this ); | ||
521 | |||
522 | // Memory leak proof. | ||
523 | this.clearCustomData(); | ||
524 | doc.getDocumentElement().clearCustomData(); | ||
525 | CKEDITOR.tools.removeFunction( this._.frameLoadedHandler ); | ||
526 | |||
527 | // On IE, iframe is returned even after remove() method is called on it. | ||
528 | // Checking if parent is present fixes this issue. (#13850) | ||
529 | if ( iframe && iframe.getParent() ) { | ||
530 | iframe.clearCustomData(); | ||
531 | onResize = iframe.removeCustomData( 'onResize' ); | ||
532 | onResize && onResize.removeListener(); | ||
533 | |||
534 | // IE BUG: When destroying editor DOM with the selection remains inside | ||
535 | // editing area would break IE7/8's selection system, we have to put the editing | ||
536 | // iframe offline first. (#3812 and #5441) | ||
537 | iframe.remove(); | ||
538 | } else { | ||
539 | CKEDITOR.warn( 'editor-destroy-iframe' ); | ||
540 | } | ||
541 | } | ||
542 | } | ||
543 | } ); | ||
544 | |||
545 | function objectResizeDisabler( editor ) { | ||
546 | if ( CKEDITOR.env.gecko ) { | ||
547 | // FF allows to change resizing preferences by calling execCommand. | ||
548 | try { | ||
549 | var doc = editor.document.$; | ||
550 | doc.execCommand( 'enableObjectResizing', false, !editor.config.disableObjectResizing ); | ||
551 | doc.execCommand( 'enableInlineTableEditing', false, !editor.config.disableNativeTableHandles ); | ||
552 | } catch ( e ) {} | ||
553 | } else if ( CKEDITOR.env.ie && CKEDITOR.env.version < 11 && editor.config.disableObjectResizing ) { | ||
554 | // It's possible to prevent resizing up to IE10. | ||
555 | blockResizeStart( editor ); | ||
556 | } | ||
557 | |||
558 | // Disables resizing by preventing default action on resizestart event. | ||
559 | function blockResizeStart() { | ||
560 | var lastListeningElement; | ||
561 | |||
562 | // We'll attach only one listener at a time, instead of adding it to every img, input, hr etc. | ||
563 | // Listener will be attached upon selectionChange, we'll also check if there was any element that | ||
564 | // got listener before (lastListeningElement) - if so we need to remove previous listener. | ||
565 | editor.editable().attachListener( editor, 'selectionChange', function() { | ||
566 | var selectedElement = editor.getSelection().getSelectedElement(); | ||
567 | |||
568 | if ( selectedElement ) { | ||
569 | if ( lastListeningElement ) { | ||
570 | lastListeningElement.detachEvent( 'onresizestart', resizeStartListener ); | ||
571 | lastListeningElement = null; | ||
572 | } | ||
573 | |||
574 | // IE requires using attachEvent, because it does not work using W3C compilant addEventListener, | ||
575 | // tested with IE10. | ||
576 | selectedElement.$.attachEvent( 'onresizestart', resizeStartListener ); | ||
577 | lastListeningElement = selectedElement.$; | ||
578 | } | ||
579 | } ); | ||
580 | } | ||
581 | |||
582 | function resizeStartListener( evt ) { | ||
583 | evt.returnValue = false; | ||
584 | } | ||
585 | } | ||
586 | |||
587 | function iframeCssFixes() { | ||
588 | var css = []; | ||
589 | |||
590 | // IE>=8 stricts mode doesn't have 'contentEditable' in effect | ||
591 | // on element unless it has layout. (#5562) | ||
592 | if ( CKEDITOR.document.$.documentMode >= 8 ) { | ||
593 | css.push( 'html.CSS1Compat [contenteditable=false]{min-height:0 !important}' ); | ||
594 | |||
595 | var selectors = []; | ||
596 | |||
597 | for ( var tag in CKEDITOR.dtd.$removeEmpty ) | ||
598 | selectors.push( 'html.CSS1Compat ' + tag + '[contenteditable=false]' ); | ||
599 | |||
600 | css.push( selectors.join( ',' ) + '{display:inline-block}' ); | ||
601 | } | ||
602 | // Set the HTML style to 100% to have the text cursor in affect (#6341) | ||
603 | else if ( CKEDITOR.env.gecko ) { | ||
604 | css.push( 'html{height:100% !important}' ); | ||
605 | css.push( 'img:-moz-broken{-moz-force-broken-image-icon:1;min-width:24px;min-height:24px}' ); | ||
606 | } | ||
607 | |||
608 | // #6341: The text cursor must be set on the editor area. | ||
609 | // #6632: Avoid having "text" shape of cursor in IE7 scrollbars. | ||
610 | css.push( 'html{cursor:text;*cursor:auto}' ); | ||
611 | |||
612 | // Use correct cursor for these elements | ||
613 | css.push( 'img,input,textarea{cursor:default}' ); | ||
614 | |||
615 | return css.join( '\n' ); | ||
616 | } | ||
617 | } )(); | ||
618 | |||
619 | /** | ||
620 | * Disables the ability to resize objects (images and tables) in the editing area. | ||
621 | * | ||
622 | * config.disableObjectResizing = true; | ||
623 | * | ||
624 | * **Note:** Because of incomplete implementation of editing features in browsers | ||
625 | * this option does not work for inline editors (see ticket [#10197](http://dev.ckeditor.com/ticket/10197)), | ||
626 | * does not work in Internet Explorer 11+ (see [#9317](http://dev.ckeditor.com/ticket/9317#comment:16) and | ||
627 | * [IE11+ issue](https://connect.microsoft.com/IE/feedback/details/742593/please-respect-execcommand-enableobjectresizing-in-contenteditable-elements)). | ||
628 | * In Internet Explorer 8-10 this option only blocks resizing, but it is unable to hide the resize handles. | ||
629 | * | ||
630 | * @cfg | ||
631 | * @member CKEDITOR.config | ||
632 | */ | ||
633 | CKEDITOR.config.disableObjectResizing = false; | ||
634 | |||
635 | /** | ||
636 | * Disables the "table tools" offered natively by the browser (currently | ||
637 | * Firefox only) to perform quick table editing operations, like adding or | ||
638 | * deleting rows and columns. | ||
639 | * | ||
640 | * config.disableNativeTableHandles = false; | ||
641 | * | ||
642 | * @cfg | ||
643 | * @member CKEDITOR.config | ||
644 | */ | ||
645 | CKEDITOR.config.disableNativeTableHandles = true; | ||
646 | |||
647 | /** | ||
648 | * Disables the built-in spell checker if the browser provides one. | ||
649 | * | ||
650 | * **Note:** Although word suggestions provided natively by the browsers will | ||
651 | * not appear in CKEditor's default context menu, | ||
652 | * users can always reach the native context menu by holding the | ||
653 | * *Ctrl* key when right-clicking if {@link #browserContextMenuOnCtrl} | ||
654 | * is enabled or you are simply not using the | ||
655 | * [context menu](http://ckeditor.com/addon/contextmenu) plugin. | ||
656 | * | ||
657 | * config.disableNativeSpellChecker = false; | ||
658 | * | ||
659 | * @cfg | ||
660 | * @member CKEDITOR.config | ||
661 | */ | ||
662 | CKEDITOR.config.disableNativeSpellChecker = true; | ||
663 | |||
664 | /** | ||
665 | * Language code of the writing language which is used to author the editor | ||
666 | * content. This option accepts one single entry value in the format defined in the | ||
667 | * [Tags for Identifying Languages (BCP47)](http://www.ietf.org/rfc/bcp/bcp47.txt) | ||
668 | * IETF document and is used in the `lang` attribute. | ||
669 | * | ||
670 | * config.contentsLanguage = 'fr'; | ||
671 | * | ||
672 | * @cfg {String} [contentsLanguage=same value with editor's UI language] | ||
673 | * @member CKEDITOR.config | ||
674 | */ | ||
675 | |||
676 | /** | ||
677 | * The base href URL used to resolve relative and absolute URLs in the | ||
678 | * editor content. | ||
679 | * | ||
680 | * config.baseHref = 'http://www.example.com/path/'; | ||
681 | * | ||
682 | * @cfg {String} [baseHref=''] | ||
683 | * @member CKEDITOR.config | ||
684 | */ | ||
685 | |||
686 | /** | ||
687 | * Whether to automatically create wrapping blocks around inline content inside the document body. | ||
688 | * This helps to ensure the integrity of the block *Enter* mode. | ||
689 | * | ||
690 | * **Note:** This option is deprecated. Changing the default value might introduce unpredictable usability issues and is | ||
691 | * highly unrecommended. | ||
692 | * | ||
693 | * config.autoParagraph = false; | ||
694 | * | ||
695 | * @deprecated | ||
696 | * @since 3.6 | ||
697 | * @cfg {Boolean} [autoParagraph=true] | ||
698 | * @member CKEDITOR.config | ||
699 | */ | ||
700 | |||
701 | /** | ||
702 | * Fired when some elements are added to the document. | ||
703 | * | ||
704 | * @event ariaWidget | ||
705 | * @member CKEDITOR.editor | ||
706 | * @param {CKEDITOR.editor} editor This editor instance. | ||
707 | * @param {CKEDITOR.dom.element} data The element being added. | ||
708 | */ | ||