1 /* 2 * CKEditor - The text editor for Internet - http://ckeditor.com 3 * Copyright (C) 2003-2008 Frederico Caldeira Knabben 4 * 5 * == BEGIN LICENSE == 6 * 7 * Licensed under the terms of any of the following licenses at your 8 * choice: 9 * 10 * - GNU General Public License Version 2 or later (the "GPL") 11 * http://www.gnu.org/licenses/gpl.html 12 * 13 * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") 14 * http://www.gnu.org/licenses/lgpl.html 15 * 16 * - Mozilla Public License Version 1.1 or later (the "MPL") 17 * http://www.mozilla.org/MPL/MPL-1.1.html 18 * 19 * == END LICENSE == 20 */ 21 22 /** 23 * @fileOverview The "wysiwygarea" plugin. It registers the "wysiwyg" editing 24 * mode, which handles the main editing area space. 25 */ 26 27 CKEDITOR.plugins.add( 'wysiwygarea', 28 { 29 init : function( editor, pluginPath ) 30 { 31 editor.on( 'editingBlockReady', function() 32 { 33 var mainElement, 34 iframe, 35 isLoadingData, 36 isPendingFocus; 37 38 // The following information is needed for IE only. 39 var isCustomDomain = CKEDITOR.env.ie && document.domain != window.location.hostname; 40 41 // Creates the iframe that holds the editable document. 42 var createIFrame = function() 43 { 44 if ( iframe ) 45 iframe.remove(); 46 47 iframe = new CKEDITOR.dom.element( 'iframe' ) 48 .setAttributes({ 49 frameBorder : 0, 50 allowTransparency : true }) 51 .setStyles({ 52 width : '100%', 53 height : '100%' }); 54 55 if ( CKEDITOR.env.ie ) 56 { 57 if ( isCustomDomain ) 58 { 59 // The document domain must be set within the src 60 // attribute. 61 iframe.setAttribute( 'src', 62 'javascript:void( (function(){' + 63 'document.open();' + 64 'document.domain="' + document.domain + '";' + 65 'document.write( window.parent._cke_htmlToLoad_' + editor.name + ' );' + 66 'document.close();' + 67 'window.parent._cke_htmlToLoad_' + editor.name + ' = null;' + 68 '})() )' ); 69 } 70 else 71 // To avoid HTTPS warnings. 72 iframe.setAttribute( 'src', 'javascript:void(0)' ); 73 } 74 75 // Append the new IFRAME to the main element. For IE, it 76 // must be done after setting the "src", to avoid the 77 // "secure/unsecure" message under HTTPS. 78 mainElement.append( iframe ); 79 }; 80 81 // The script that is appended to the data being loaded. It 82 // enables editing, and makes some 83 var activationScript = 84 '<script id="cke_actscrpt" type="text/javascript">' + 85 'window.onload = function()' + 86 '{' + 87 // Remove this script from the DOM. 88 'var s = document.getElementById( "cke_actscrpt" );' + 89 's.parentNode.removeChild( s );' + 90 91 // Call the temporary function for the editing 92 // boostrap. 93 'window.parent.CKEDITOR.instances.' + editor.name + '._.contentDomReady( window );' + 94 '}' + 95 '</script>'; 96 97 // Editing area bootstrap code. 98 var contentDomReady = function( domWindow ) 99 { 100 delete editor._.contentDomReady; 101 102 var domDocument = domWindow.document, 103 body = domDocument.body; 104 105 body.spellcheck = !editor.config.disableNativeSpellChecker; 106 107 if ( CKEDITOR.env.ie ) 108 { 109 // Disable and re-enable the body to avoid IE from 110 // taking the editing focus at startup. (#141 / #523) 111 body.disabled = true; 112 body.contentEditable = true; 113 body.removeAttribute( 'disabled' ); 114 } 115 else 116 domDocument.designMode = 'on'; 117 118 // IE, Opera and Safari may not support it and throw 119 // errors. 120 try { domDocument.execCommand( 'enableObjectResizing', false, !editor.config.disableObjectResizing ) ; } catch(e) {} 121 try { domDocument.execCommand( 'enableInlineTableEditing', false, !editor.config.disableNativeTableHandles ) ; } catch(e) {} 122 123 editor.window = new CKEDITOR.dom.window( domWindow ); 124 editor.document = new CKEDITOR.dom.document( domDocument ); 125 126 editor.fire( 'contentDom' ); 127 128 isLoadingData = false; 129 130 if ( isPendingFocus ) 131 editor.focus(); 132 }; 133 134 editor.addMode( 'wysiwyg', 135 { 136 load : function( holderElement, data, isSnapshot ) 137 { 138 mainElement = holderElement; 139 140 // Create the iframe at load for all browsers 141 // except FF and IE with custom domain. 142 if ( !isCustomDomain || !CKEDITOR.env.gecko ) 143 createIFrame(); 144 145 if ( isSnapshot ) 146 this.loadSnapshotData( data ); 147 else 148 this.loadData( data ); 149 }, 150 151 loadData : function( data ) 152 { 153 isLoadingData = true; 154 155 data = 156 CKEDITOR.config.docType + 157 '<html dir="' + CKEDITOR.config.contentLangDirection + '">' + 158 '<head>' + 159 '<link href="' + CKEDITOR.config.contentsCss + '" type="text/css" rel="stylesheet" _fcktemp="true"/>' + 160 '</head>' + 161 '<body>' + 162 editor.dataProcessor.toHtml( data ) + 163 '</body>' + 164 '</html>' + 165 activationScript; 166 167 // For custom domain in IE, set the global variable 168 // that will temporarily hold the editor data. This 169 // reference will be used in the ifram src. 170 if ( isCustomDomain ) 171 window[ '_cke_htmlToLoad_' + editor.name ] = data; 172 173 editor._.contentDomReady = contentDomReady; 174 175 // We need to recreate the iframe in FF for every 176 // data load, otherwise the following spellcheck 177 // and execCommand features will be active only for 178 // the first time. 179 // The same is valid for IE with custom domain, 180 // because the iframe src must be reset every time. 181 if ( isCustomDomain || CKEDITOR.env.gecko ) 182 createIFrame(); 183 184 // For custom domain in IE, the data loading is 185 // done through the src attribute of the iframe. 186 if ( !isCustomDomain ) 187 { 188 var doc = iframe.$.contentWindow.document; 189 doc.open(); 190 doc.write( data ); 191 doc.close(); 192 } 193 }, 194 195 getData : function() 196 { 197 return editor.dataProcessor.toDataFormat( new CKEDITOR.dom.element( iframe.$.contentWindow.document.body ) ); 198 }, 199 200 getSnapshotData : function() 201 { 202 return iframe.$.contentWindow.document.body.innerHTML; 203 }, 204 205 loadSnapshotData : function( data ) 206 { 207 iframe.$.contentWindow.document.body.innerHTML = data; 208 }, 209 210 unload : function( holderElement ) 211 { 212 editor.window = editor.document = iframe = mainElement = isPendingFocus = null; 213 214 editor.fire( 'contentDomUnload' ); 215 }, 216 217 focus : function() 218 { 219 if ( isLoadingData ) 220 isPendingFocus = true; 221 else if ( editor.window ) 222 editor.window.focus(); 223 } 224 }); 225 }); 226 } 227 }); 228 229 /** 230 * Disables the ability of resize objects (image and tables) in the editing 231 * area 232 * @type Boolean 233 * @default false 234 * @example 235 * config.disableObjectResizing = true; 236 */ 237 CKEDITOR.config.disableObjectResizing = false; 238 239 /** 240 * Disables the "table tools" offered natively by the browser (currently 241 * Firefox only) to make quick table editing operations, like adding or 242 * deleting rows and columns. 243 * @type Boolean 244 * @default true 245 * @example 246 * config.disableNativeTableHandles = false; 247 */ 248 CKEDITOR.config.disableNativeTableHandles = true; 249 250 /** 251 * Disables the built-in spell checker while typing natively available in the 252 * browser (currently Firefox and Safari only).<br /><br /> 253 * 254 * Even if word suggestions will not appear in the FCKeditor context menu, this 255 * feature is useful to help quickly identifying misspelled words.<br /><br /> 256 * 257 * This setting is currently compatible with Firefox only due to limitations in 258 * other browsers. 259 * @type Boolean 260 * @default true 261 * @example 262 * config.disableNativeSpellChecker = false; 263 */ 264 CKEDITOR.config.disableNativeSpellChecker = true; 265