/**
* @license Copyright (c) 2003-2013, CKSource - Frederico Knabben. All rights reserved.
* For licensing, see LICENSE.md or http://ckeditor.com/license
*/
/**
* @fileOverview The "wysiwygarea" plugin. It registers the "wysiwyg" editing
* mode, which handles the main editing area space.
*/
(function() {
CKEDITOR.plugins.add( 'wysiwygarea', {
init: function( editor ) {
if ( editor.config.fullPage ) {
editor.addFeature( {
allowedContent: 'html head title; style [media,type]; body (*)[id]; meta link [*]',
requiredContent: 'body'
} );
}
editor.addMode( 'wysiwyg', function( callback ) {
var src = 'document.open();' +
// In IE, the document domain must be set any time we call document.open().
( CKEDITOR.env.ie ? '(' + CKEDITOR.tools.fixDomain + ')();' : '' ) +
'document.close();';
// With IE, the custom domain has to be taken care at first,
// for other browers, the 'src' attribute should be left empty to
// trigger iframe's 'load' event.
src = CKEDITOR.env.air ? 'javascript:void(0)' : CKEDITOR.env.ie ? 'javascript:void(function(){' + encodeURIComponent( src ) + '}())'
:
'';
var iframe = CKEDITOR.dom.element.createFromHtml( '' );
iframe.setStyles( { width: '100%', height: '100%' } );
iframe.addClass( 'cke_wysiwyg_frame cke_reset' );
var contentSpace = editor.ui.space( 'contents' );
contentSpace.append( iframe );
// Asynchronous iframe loading is only required in IE>8 and Gecko (other reasons probably).
// Do not use it on WebKit as it'll break the browser-back navigation.
var useOnloadEvent = CKEDITOR.env.ie || CKEDITOR.env.gecko;
if ( useOnloadEvent )
iframe.on( 'load', onLoad );
var frameLabel = editor.title,
frameDesc = editor.lang.common.editorHelp;
if ( frameLabel ) {
if ( CKEDITOR.env.ie )
frameLabel += ', ' + frameDesc;
iframe.setAttribute( 'title', frameLabel );
}
var labelId = CKEDITOR.tools.getNextId(),
desc = CKEDITOR.dom.element.createFromHtml( '' + frameDesc + '' );
contentSpace.append( desc, 1 );
// Remove the ARIA description.
editor.on( 'beforeModeUnload', function( evt ) {
evt.removeListener();
desc.remove();
});
iframe.setAttributes({
'aria-describedby': labelId,
tabIndex: editor.tabIndex,
allowTransparency: 'true'
});
// Execute onLoad manually for all non IE||Gecko browsers.
!useOnloadEvent && onLoad();
if ( CKEDITOR.env.webkit ) {
// Webkit: iframe size doesn't auto fit well. (#7360)
var onResize = function() {
// Hide the iframe to get real size of the holder. (#8941)
contentSpace.setStyle( 'width', '100%' );
iframe.hide();
iframe.setSize( 'width', contentSpace.getSize( 'width' ) );
contentSpace.removeStyle( 'width' );
iframe.show();
};
iframe.setCustomData( 'onResize', onResize );
CKEDITOR.document.getWindow().on( 'resize', onResize );
}
editor.fire( 'ariaWidget', iframe );
function onLoad( evt ) {
evt && evt.removeListener();
editor.editable( new framedWysiwyg( editor, iframe.$.contentWindow.document.body ) );
editor.setData( editor.getData( 1 ), callback );
}
});
}
});
function onDomReady( win ) {
var editor = this.editor,
doc = win.document,
body = doc.body;
// Remove helper scripts from the DOM.
var script = doc.getElementById( 'cke_actscrpt' );
script && script.parentNode.removeChild( script );
script = doc.getElementById( 'cke_shimscrpt' );
script && script.parentNode.removeChild( script );
if ( CKEDITOR.env.gecko ) {
// Force Gecko to change contentEditable from false to true on domReady
// (because it's previously set to true on iframe's body creation).
// Otherwise del/backspace and some other editable features will be broken in Fx <4
// See: #107 and https://bugzilla.mozilla.org/show_bug.cgi?id=440916
body.contentEditable = false;
// Remove any leading
which is between the
<\/p>$/i ) && range.startContainer.equals( body ) ) { // Avoid the ambiguity from a real user cursor position. setTimeout( function() { range = editor.getSelection().getRanges()[ 0 ]; if ( !range.startContainer.equals( 'body' ) ) { body.getFirst().remove( 1 ); range.moveToElementEditEnd( body ); range.select(); } }, 0 ); } }); } // ## START : disableNativeTableHandles and disableObjectResizing settings. // Enable dragging of position:absolute elements in IE. try { editor.document.$.execCommand( '2D-position', false, true ); } catch ( e ) {} // IE, Opera and Safari may not support it and throw errors. try { editor.document.$.execCommand( 'enableInlineTableEditing', false, !editor.config.disableNativeTableHandles ); } catch ( e ) {} if ( editor.config.disableObjectResizing ) { try { this.getDocument().$.execCommand( 'enableObjectResizing', false, false ); } catch ( e ) { // For browsers in which the above method failed, we can cancel the resizing on the fly (#4208) this.attachListener( this, CKEDITOR.env.ie ? 'resizestart' : 'resize', function( evt ) { evt.data.preventDefault(); }); } } if ( CKEDITOR.env.gecko || CKEDITOR.env.ie && editor.document.$.compatMode == 'CSS1Compat' ) { this.attachListener( this, 'keydown', function( evt ) { var keyCode = evt.data.getKeystroke(); // PageUp OR PageDown if ( keyCode == 33 || keyCode == 34 ) { // PageUp/PageDown scrolling is broken in document // with standard doctype, manually fix it. (#4736) if ( CKEDITOR.env.ie ) { setTimeout( function() { editor.getSelection().scrollIntoView(); }, 0 ); } // Page up/down cause editor selection to leak // outside of editable thus we try to intercept // the behavior, while it affects only happen // when editor contents are not overflowed. (#7955) else if ( editor.window.$.innerHeight > this.$.offsetHeight ) { var range = editor.createRange(); range[ keyCode == 33 ? 'moveToElementEditStart' : 'moveToElementEditEnd' ]( this ); range.select(); evt.data.preventDefault(); } } }); } if ( CKEDITOR.env.ie ) { // [IE] Iframe will still keep the selection when blurred, if // focus is moved onto a non-editing host, e.g. link or button, but // it becomes a problem for the object type selection, since the resizer // handler attached on it will mark other part of the UI, especially // for the dialog. (#8157) // [IE<8 & Opera] Even worse For old IEs, the cursor will not vanish even if // the selection has been moved to another text input in some cases. (#4716) // // Now the range restore is disabled, so we simply force IE to clean // up the selection before blur. this.attachListener( doc, 'blur', function() { // Error proof when the editor is not visible. (#6375) try { doc.$.selection.empty(); } catch ( er ) {} }); } // ## END var title = editor.document.getElementsByTag( 'title' ).getItem( 0 ); title.data( 'cke-title', editor.document.$.title ); // [IE] JAWS will not recognize the aria label we used on the iframe // unless the frame window title string is used as the voice label, // backup the original one and restore it on output. if ( CKEDITOR.env.ie ) editor.document.$.title = this._.docTitle; CKEDITOR.tools.setTimeout( function() { editor.fire( 'contentDom' ); if ( this._.isPendingFocus ) { editor.focus(); this._.isPendingFocus = false; } setTimeout( function() { editor.fire( 'dataReady' ); }, 0 ); // IE BUG: IE might have rendered the iframe with invisible contents. // (#3623). Push some inconsequential CSS style changes to force IE to // refresh it. // // Also, for some unknown reasons, short timeouts (e.g. 100ms) do not // fix the problem. :( if ( CKEDITOR.env.ie ) { setTimeout( function() { if ( editor.document ) { var $body = editor.document.$.body; $body.runtimeStyle.marginBottom = '0px'; $body.runtimeStyle.marginBottom = ''; } }, 1000 ); } }, 0, this ); } var framedWysiwyg = CKEDITOR.tools.createClass({ $: function( editor ) { this.base.apply( this, arguments ); this._.frameLoadedHandler = CKEDITOR.tools.addFunction( function( win ) { // Avoid opening design mode in a frame window thread, // which will cause host page scrolling.(#4397) CKEDITOR.tools.setTimeout( onDomReady, 0, this, win ); }, this ); this._.docTitle = this.getWindow().getFrame().getAttribute( 'title' ); }, base: CKEDITOR.editable, proto: { setData: function( data, isSnapshot ) { var editor = this.editor; if ( isSnapshot ) { this.setHtml( data ); // Fire dataReady for the consistency with inline editors // and because it makes sense. (#10370) editor.fire( 'dataReady' ); } else { this._.isLoadingData = true; editor._.dataStore = { id:1 }; var config = editor.config, fullPage = config.fullPage, docType = config.docType; // Build the additional stuff to be included into
. var headExtra = CKEDITOR.tools.buildStyleHtml( iframeCssFixes() ) .replace( /