654 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
		
		
			
		
	
	
			654 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
|  | /** | |||
|  |  * @license Copyright (c) 2003-2014, 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 src="' + src + '" frameBorder="0"></iframe>' ); | |||
|  | 				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( '<span id="' + labelId + '" class="cke_voice_label">' + frameDesc + '</span>' ); | |||
|  | 
 | |||
|  | 				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 <br> which is between the <body> and the comment.
 | |||
|  | 			// This one fixes Firefox 3.6 bug: the browser inserts a leading <br>
 | |||
|  | 			// on document.write if the body has contenteditable="true".
 | |||
|  | 			if ( CKEDITOR.env.version < 20000 ) { | |||
|  | 				body.innerHTML = body.innerHTML.replace( /^.*<!-- cke-content-start -->/, '' ); | |||
|  | 
 | |||
|  | 				// The above hack messes up the selection in FF36.
 | |||
|  | 				// To clean this up, manually select collapsed range that
 | |||
|  | 				// starts within the body.
 | |||
|  | 				setTimeout( function() { | |||
|  | 					var range = new CKEDITOR.dom.range( new CKEDITOR.dom.document( doc ) ); | |||
|  | 					range.setStart( new CKEDITOR.dom.node( body ), 0 ); | |||
|  | 					editor.getSelection().selectRanges( [ range ] ); | |||
|  | 				}, 0 ); | |||
|  | 			} | |||
|  | 		} | |||
|  | 
 | |||
|  | 		body.contentEditable = true; | |||
|  | 
 | |||
|  | 		if ( CKEDITOR.env.ie ) { | |||
|  | 			// Don't display the focus border.
 | |||
|  | 			body.hideFocus = true; | |||
|  | 
 | |||
|  | 			// Disable and re-enable the body to avoid IE from
 | |||
|  | 			// taking the editing focus at startup. (#141 / #523)
 | |||
|  | 			body.disabled = true; | |||
|  | 			body.removeAttribute( 'disabled' ); | |||
|  | 		} | |||
|  | 
 | |||
|  | 		delete this._.isLoadingData; | |||
|  | 
 | |||
|  | 		// Play the magic to alter element reference to the reloaded one.
 | |||
|  | 		this.$ = body; | |||
|  | 
 | |||
|  | 		doc = new CKEDITOR.dom.document( doc ); | |||
|  | 
 | |||
|  | 		this.setup(); | |||
|  | 
 | |||
|  | 		if ( CKEDITOR.env.ie ) { | |||
|  | 			doc.getDocumentElement().addClass( doc.$.compatMode ); | |||
|  | 
 | |||
|  | 			// Prevent IE from leaving new paragraph after deleting all contents in body. (#6966)
 | |||
|  | 			editor.config.enterMode != CKEDITOR.ENTER_P && this.attachListener( doc, 'selectionchange', function() { | |||
|  | 				var body = doc.getBody(), | |||
|  | 					sel = editor.getSelection(), | |||
|  | 					range = sel && sel.getRanges()[ 0 ]; | |||
|  | 
 | |||
|  | 				if ( range && body.getHtml().match( /^<p>(?: |<br>)<\/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 ); | |||
|  | 				} | |||
|  | 			} ); | |||
|  | 		} | |||
|  | 
 | |||
|  | 		// Fix problem with cursor not appearing in Webkit and IE11+ when clicking below the body (#10945, #10906).
 | |||
|  | 		// Fix for older IEs (8-10 and QM) is placed inside selection.js.
 | |||
|  | 		if ( CKEDITOR.env.webkit || ( CKEDITOR.env.ie && CKEDITOR.env.version > 10 ) ) { | |||
|  | 			doc.getDocumentElement().on( 'mousedown', function( evt ) { | |||
|  | 				if ( evt.data.getTarget().is( 'html' ) ) { | |||
|  | 					// IE needs this timeout. Webkit does not, but it does not cause problems too.
 | |||
|  | 					setTimeout( function() { | |||
|  | 						editor.editable().focus(); | |||
|  | 					} ); | |||
|  | 				} | |||
|  | 			} ); | |||
|  | 		} | |||
|  | 
 | |||
|  | 		// ## 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 <head>.
 | |||
|  | 					var headExtra = CKEDITOR.tools.buildStyleHtml( iframeCssFixes() ) | |||
|  | 						                .replace( /<style>/, '<style data-cke-temp="1">' ); | |||
|  | 
 | |||
|  | 					if ( !fullPage ) | |||
|  | 						headExtra += CKEDITOR.tools.buildStyleHtml( editor.config.contentsCss ); | |||
|  | 
 | |||
|  | 					var baseTag = config.baseHref ? '<base href="' + config.baseHref + '" data-cke-temp="1" />' : ''; | |||
|  | 
 | |||
|  | 					if ( fullPage ) { | |||
|  | 						// Search and sweep out the doctype declaration.
 | |||
|  | 						data = data.replace( /<!DOCTYPE[^>]*>/i, function( match ) { | |||
|  | 							editor.docType = docType = match; | |||
|  | 							return ''; | |||
|  | 						} ).replace( /<\?xml\s[^\?]*\?>/i, function( match ) { | |||
|  | 							editor.xmlDeclaration = match; | |||
|  | 							return ''; | |||
|  | 						} ); | |||
|  | 					} | |||
|  | 
 | |||
|  | 					// Get the HTML version of the data.
 | |||
|  | 					data = editor.dataProcessor.toHtml( data ); | |||
|  | 
 | |||
|  | 					if ( fullPage ) { | |||
|  | 						// Check if the <body> tag is available.
 | |||
|  | 						if ( !( /<body[\s|>]/ ).test( data ) ) | |||
|  | 							data = '<body>' + data; | |||
|  | 
 | |||
|  | 						// Check if the <html> tag is available.
 | |||
|  | 						if ( !( /<html[\s|>]/ ).test( data ) ) | |||
|  | 							data = '<html>' + data + '</html>'; | |||
|  | 
 | |||
|  | 						// Check if the <head> tag is available.
 | |||
|  | 						if ( !( /<head[\s|>]/ ).test( data ) ) | |||
|  | 							data = data.replace( /<html[^>]*>/, '$&<head><title></title></head>' ); | |||
|  | 						else if ( !( /<title[\s|>]/ ).test( data ) ) | |||
|  | 							data = data.replace( /<head[^>]*>/, '$&<title></title>' ); | |||
|  | 
 | |||
|  | 						// The base must be the first tag in the HEAD, e.g. to get relative
 | |||
|  | 						// links on styles.
 | |||
|  | 						baseTag && ( data = data.replace( /<head>/, '$&' + baseTag ) ); | |||
|  | 
 | |||
|  | 						// Inject the extra stuff into <head>.
 | |||
|  | 						// Attention: do not change it before testing it well. (V2)
 | |||
|  | 						// This is tricky... if the head ends with <meta ... content type>,
 | |||
|  | 						// Firefox will break. But, it works if we place our extra stuff as
 | |||
|  | 						// the last elements in the HEAD.
 | |||
|  | 						data = data.replace( /<\/head\s*>/, headExtra + '$&' ); | |||
|  | 
 | |||
|  | 						// Add the DOCTYPE back to it.
 | |||
|  | 						data = docType + data; | |||
|  | 					} else { | |||
|  | 						data = config.docType + | |||
|  | 							'<html dir="' + config.contentsLangDirection + '"' + | |||
|  | 								' lang="' + ( config.contentsLanguage || editor.langCode ) + '">' + | |||
|  | 							'<head>' + | |||
|  | 								'<title>' + this._.docTitle + '</title>' + | |||
|  | 								baseTag + | |||
|  | 								headExtra + | |||
|  | 							'</head>' + | |||
|  | 							'<body' + ( config.bodyId ? ' id="' + config.bodyId + '"' : '' ) + | |||
|  | 								( config.bodyClass ? ' class="' + config.bodyClass + '"' : '' ) + | |||
|  | 							'>' + | |||
|  | 								data + | |||
|  | 							'</body>' + | |||
|  | 							'</html>'; | |||
|  | 					} | |||
|  | 
 | |||
|  | 					if ( CKEDITOR.env.gecko ) { | |||
|  | 						// Hack to make Fx put cursor at the start of doc on fresh focus.
 | |||
|  | 						data = data.replace( /<body/, '<body contenteditable="true" ' ); | |||
|  | 
 | |||
|  | 						// Another hack which is used by onDomReady to remove a leading
 | |||
|  | 						// <br> which is inserted by Firefox 3.6 when document.write is called.
 | |||
|  | 						// This additional <br> is present because of contenteditable="true"
 | |||
|  | 						if ( CKEDITOR.env.version < 20000 ) | |||
|  | 							data = data.replace( /<body[^>]*>/, '$&<!-- cke-content-start -->'  ); | |||
|  | 					} | |||
|  | 
 | |||
|  | 					// The script that launches the bootstrap logic on 'domReady', so the document
 | |||
|  | 					// is fully editable even before the editing iframe is fully loaded (#4455).
 | |||
|  | 					var bootstrapCode = | |||
|  | 						'<script id="cke_actscrpt" type="text/javascript"' + ( CKEDITOR.env.ie ? ' defer="defer" ' : '' ) + '>' + | |||
|  | 							'var wasLoaded=0;' +	// It must be always set to 0 as it remains as a window property.
 | |||
|  | 							'function onload(){' + | |||
|  | 								'if(!wasLoaded)' +	// FF3.6 calls onload twice when editor.setData. Stop that.
 | |||
|  | 									'window.parent.CKEDITOR.tools.callFunction(' + this._.frameLoadedHandler + ',window);' + | |||
|  | 								'wasLoaded=1;' + | |||
|  | 							'}' + | |||
|  | 							( CKEDITOR.env.ie ? 'onload();' : 'document.addEventListener("DOMContentLoaded", onload, false );' ) + | |||
|  | 						'</script>'; | |||
|  | 
 | |||
|  | 					// For IE<9 add support for HTML5's elements.
 | |||
|  | 					// Note: this code must not be deferred.
 | |||
|  | 					if ( CKEDITOR.env.ie && CKEDITOR.env.version < 9 ) { | |||
|  | 						bootstrapCode += | |||
|  | 							'<script id="cke_shimscrpt">' + | |||
|  | 								'window.parent.CKEDITOR.tools.enableHtml5Elements(document)' + | |||
|  | 							'</script>'; | |||
|  | 					} | |||
|  | 
 | |||
|  | 					data = data.replace( /(?=\s*<\/(:?head)>)/, bootstrapCode ); | |||
|  | 
 | |||
|  | 					// Current DOM will be deconstructed by document.write, cleanup required.
 | |||
|  | 					this.clearCustomData(); | |||
|  | 					this.clearListeners(); | |||
|  | 
 | |||
|  | 					editor.fire( 'contentDomUnload' ); | |||
|  | 
 | |||
|  | 					var doc = this.getDocument(); | |||
|  | 
 | |||
|  | 					// Work around Firefox bug - error prune when called from XUL (#320),
 | |||
|  | 					// defer it thanks to the async nature of this method.
 | |||
|  | 					try { doc.write( data ); } catch ( e ) { | |||
|  | 						setTimeout( function() { doc.write( data ); }, 0 ); | |||
|  | 					} | |||
|  | 				} | |||
|  | 			}, | |||
|  | 
 | |||
|  | 			getData: function( isSnapshot ) { | |||
|  | 				if ( isSnapshot ) | |||
|  | 					return this.getHtml(); | |||
|  | 				else { | |||
|  | 					var editor = this.editor, | |||
|  | 						config = editor.config, | |||
|  | 						fullPage = config.fullPage, | |||
|  | 						docType = fullPage && editor.docType, | |||
|  | 						xmlDeclaration = fullPage && editor.xmlDeclaration, | |||
|  | 						doc = this.getDocument(); | |||
|  | 
 | |||
|  | 					var data = fullPage ? doc.getDocumentElement().getOuterHtml() : doc.getBody().getHtml(); | |||
|  | 
 | |||
|  | 					// BR at the end of document is bogus node for Mozilla. (#5293).
 | |||
|  | 					// Prevent BRs from disappearing from the end of the content
 | |||
|  | 					// while enterMode is ENTER_BR (#10146).
 | |||
|  | 					if ( CKEDITOR.env.gecko && config.enterMode != CKEDITOR.ENTER_BR ) | |||
|  | 						data = data.replace( /<br>(?=\s*(:?$|<\/body>))/, '' ); | |||
|  | 
 | |||
|  | 					data = editor.dataProcessor.toDataFormat( data ); | |||
|  | 
 | |||
|  | 					if ( xmlDeclaration ) | |||
|  | 						data = xmlDeclaration + '\n' + data; | |||
|  | 					if ( docType ) | |||
|  | 						data = docType + '\n' + data; | |||
|  | 
 | |||
|  | 					return data; | |||
|  | 				} | |||
|  | 			}, | |||
|  | 
 | |||
|  | 			focus: function() { | |||
|  | 				if ( this._.isLoadingData ) | |||
|  | 					this._.isPendingFocus = true; | |||
|  | 				else | |||
|  | 					framedWysiwyg.baseProto.focus.call( this ); | |||
|  | 			}, | |||
|  | 
 | |||
|  | 			detach: function() { | |||
|  | 				var editor = this.editor, | |||
|  | 					doc = editor.document, | |||
|  | 					iframe = editor.window.getFrame(); | |||
|  | 
 | |||
|  | 				framedWysiwyg.baseProto.detach.call( this ); | |||
|  | 
 | |||
|  | 				// Memory leak proof.
 | |||
|  | 				this.clearCustomData(); | |||
|  | 				doc.getDocumentElement().clearCustomData(); | |||
|  | 				iframe.clearCustomData(); | |||
|  | 				CKEDITOR.tools.removeFunction( this._.frameLoadedHandler ); | |||
|  | 
 | |||
|  | 				var onResize = iframe.removeCustomData( 'onResize' ); | |||
|  | 				onResize && onResize.removeListener(); | |||
|  | 
 | |||
|  | 				// IE BUG: When destroying editor DOM with the selection remains inside
 | |||
|  | 				// editing area would break IE7/8's selection system, we have to put the editing
 | |||
|  | 				// iframe offline first. (#3812 and #5441)
 | |||
|  | 				iframe.remove(); | |||
|  | 			} | |||
|  | 		} | |||
|  | 	} ); | |||
|  | 
 | |||
|  | 	// DOM modification here should not bother dirty flag.(#4385)
 | |||
|  | 	function restoreDirty( editor ) { | |||
|  | 		if ( !editor.checkDirty() ) | |||
|  | 			setTimeout( function() { | |||
|  | 			editor.resetDirty(); | |||
|  | 		}, 0 ); | |||
|  | 	} | |||
|  | 
 | |||
|  | 	function iframeCssFixes() { | |||
|  | 		var css = []; | |||
|  | 
 | |||
|  | 		// IE>=8 stricts mode doesn't have 'contentEditable' in effect
 | |||
|  | 		// on element unless it has layout. (#5562)
 | |||
|  | 		if ( CKEDITOR.document.$.documentMode >= 8 ) { | |||
|  | 			css.push( 'html.CSS1Compat [contenteditable=false]{min-height:0 !important}' ); | |||
|  | 
 | |||
|  | 			var selectors = []; | |||
|  | 
 | |||
|  | 			for ( var tag in CKEDITOR.dtd.$removeEmpty ) | |||
|  | 				selectors.push( 'html.CSS1Compat ' + tag + '[contenteditable=false]' ); | |||
|  | 
 | |||
|  | 			css.push( selectors.join( ',' ) + '{display:inline-block}' ); | |||
|  | 		} | |||
|  | 		// Set the HTML style to 100% to have the text cursor in affect (#6341)
 | |||
|  | 		else if ( CKEDITOR.env.gecko ) { | |||
|  | 			css.push( 'html{height:100% !important}' ); | |||
|  | 			css.push( 'img:-moz-broken{-moz-force-broken-image-icon:1;min-width:24px;min-height:24px}' ); | |||
|  | 		} | |||
|  | 
 | |||
|  | 		// #6341: The text cursor must be set on the editor area.
 | |||
|  | 		// #6632: Avoid having "text" shape of cursor in IE7 scrollbars.
 | |||
|  | 		css.push( 'html{cursor:text;*cursor:auto}' ); | |||
|  | 
 | |||
|  | 		// Use correct cursor for these elements
 | |||
|  | 		css.push( 'img,input,textarea{cursor:default}' ); | |||
|  | 
 | |||
|  | 		return css.join( '\n' ); | |||
|  | 	} | |||
|  | } )(); | |||
|  | 
 | |||
|  | /** | |||
|  |  * Disables the ability of resize objects (image and tables) in the editing area. | |||
|  |  * | |||
|  |  *		config.disableObjectResizing = true; | |||
|  |  * | |||
|  |  * @cfg | |||
|  |  * @member CKEDITOR.config | |||
|  |  */ | |||
|  | CKEDITOR.config.disableObjectResizing = false; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Disables the "table tools" offered natively by the browser (currently | |||
|  |  * Firefox only) to make quick table editing operations, like adding or | |||
|  |  * deleting rows and columns. | |||
|  |  * | |||
|  |  *		config.disableNativeTableHandles = false; | |||
|  |  * | |||
|  |  * @cfg | |||
|  |  * @member CKEDITOR.config | |||
|  |  */ | |||
|  | CKEDITOR.config.disableNativeTableHandles = true; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Disables the built-in words spell checker if browser provides one. | |||
|  |  * | |||
|  |  * **Note:** Although word suggestions provided by browsers (natively) will | |||
|  |  * not appear in CKEditor's default context menu, | |||
|  |  * users can always reach the native context menu by holding the | |||
|  |  * *Ctrl* key when right-clicking if {@link #browserContextMenuOnCtrl} | |||
|  |  * is enabled or you're simply not using the context menu plugin. | |||
|  |  * | |||
|  |  *		config.disableNativeSpellChecker = false; | |||
|  |  * | |||
|  |  * @cfg | |||
|  |  * @member CKEDITOR.config | |||
|  |  */ | |||
|  | CKEDITOR.config.disableNativeSpellChecker = true; | |||
|  | 
 | |||
|  | /** | |||
|  |  * The CSS file(s) to be used to apply style to the contents. It should | |||
|  |  * reflect the CSS used in the final pages where the contents are to be | |||
|  |  * used. | |||
|  |  * | |||
|  |  *		config.contentsCss = '/css/mysitestyles.css'; | |||
|  |  *		config.contentsCss = ['/css/mysitestyles.css', '/css/anotherfile.css']; | |||
|  |  * | |||
|  |  * @cfg {String/Array} [contentsCss=CKEDITOR.getUrl( 'contents.css' )] | |||
|  |  * @member CKEDITOR.config | |||
|  |  */ | |||
|  | CKEDITOR.config.contentsCss = CKEDITOR.getUrl( 'contents.css' ); | |||
|  | 
 | |||
|  | /** | |||
|  |  * Language code of  the writting language which is used to author the editor | |||
|  |  * contents. | |||
|  |  * | |||
|  |  *		config.contentsLanguage = 'fr'; | |||
|  |  * | |||
|  |  * @cfg {String} [contentsLanguage=same value with editor's UI language] | |||
|  |  * @member CKEDITOR.config | |||
|  |  */ | |||
|  | 
 | |||
|  | /** | |||
|  |  * The base href URL used to resolve relative and absolute URLs in the | |||
|  |  * editor content. | |||
|  |  * | |||
|  |  *		config.baseHref = 'http://www.example.com/path/'; | |||
|  |  * | |||
|  |  * @cfg {String} [baseHref=''] | |||
|  |  * @member CKEDITOR.config | |||
|  |  */ | |||
|  | 
 | |||
|  | /** | |||
|  |  * Whether automatically create wrapping blocks around inline contents inside document body, | |||
|  |  * this helps to ensure the integrality of the block enter mode. | |||
|  |  * | |||
|  |  * **Note:** Changing the default value might introduce unpredictable usability issues. | |||
|  |  * | |||
|  |  *		config.autoParagraph = false; | |||
|  |  * | |||
|  |  * @since 3.6 | |||
|  |  * @cfg {Boolean} [autoParagraph=true] | |||
|  |  * @member CKEDITOR.config | |||
|  |  */ | |||
|  | 
 | |||
|  | /** | |||
|  |  * Fired when some elements are added to the document. | |||
|  |  * | |||
|  |  * @event ariaWidget | |||
|  |  * @member CKEDITOR.editor | |||
|  |  * @param {CKEDITOR.editor} editor This editor instance. | |||
|  |  * @param {CKEDITOR.dom.element} data The element being added. | |||
|  |  */ |