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