plugin.js 24 KB

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