diff --git a/CHANGES.md b/CHANGES.md index 8a15e0b7b30..9816814f9a6 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,6 +4,7 @@ CKEditor 4 Changelog ## CKEditor 4.1 * [#9907](http://dev.ckeditor.com/ticket/9907): Added contentPreview event for preview data manipulation. +* [#9713](http://dev.ckeditor.com/ticket/9713): Introduced `sourcedialog` plugin that brings raw HTML editing for inline editor instances. ## CKEditor 4.0.2 diff --git a/core/dom/node.js b/core/dom/node.js index c08bcd3eb85..f991518aa18 100644 --- a/core/dom/node.js +++ b/core/dom/node.js @@ -560,7 +560,11 @@ CKEDITOR.tools.extend( CKEDITOR.dom.node.prototype, { if ( $.nodeName && ( name = $.nodeName.toLowerCase(), ( typeof reference == 'string' ? name == reference : name in reference ) ) ) return new CKEDITOR.dom.node( $ ); - $ = $.parentNode; + try { + $ = $.parentNode; + } catch( e ) { + $ = null; + } } return null; }, diff --git a/core/selection.js b/core/selection.js index fd501bbff4e..3827fb208f9 100644 --- a/core/selection.js +++ b/core/selection.js @@ -1288,7 +1288,7 @@ if ( restore ) { // Saved selection may be outdated (e.g. anchored in offline nodes). // Avoid getting broken by such. - var common = selectedElement || ranges[ 0 ].getCommonAncestor(); + var common = selectedElement || ranges[ 0 ] && ranges[ 0 ].getCommonAncestor(); if ( !( common && common.getAscendant( 'body', 1 ) ) ) return; diff --git a/plugins/dialogui/plugin.js b/plugins/dialogui/plugin.js index bb66d9d3355..3eb78b1c536 100644 --- a/plugins/dialogui/plugin.js +++ b/plugins/dialogui/plugin.js @@ -279,13 +279,15 @@ CKEDITOR.plugins.add( 'dialogui', { attributes.rows = elementDefinition.rows || 5; attributes.cols = elementDefinition.cols || 20; + attributes[ 'class' ] = 'cke_dialog_ui_input_textarea ' + ( elementDefinition[ 'class' ] || '' ); + if ( typeof elementDefinition.inputStyle != 'undefined' ) attributes.style = elementDefinition.inputStyle; var innerHTML = function() { attributes[ 'aria-labelledby' ] = this._.labelId; this._.required && ( attributes[ 'aria-required' ] = this._.required ); - var html = [ '' ); diff --git a/plugins/sourcedialog/dialogs/sourcedialog.js b/plugins/sourcedialog/dialogs/sourcedialog.js new file mode 100755 index 00000000000..e3b566b5e24 --- /dev/null +++ b/plugins/sourcedialog/dialogs/sourcedialog.js @@ -0,0 +1,76 @@ +/** + * @license Copyright (c) 2003-2013, CKSource - Frederico Knabben. All rights reserved. + * For licensing, see LICENSE.html or http://ckeditor.com/license + */ + +CKEDITOR.dialog.add( 'sourcedialog', function( editor ) { + var size = CKEDITOR.document.getWindow().getViewPaneSize(); + + // Make it maximum 800px wide, but still fully visible in the viewport. + var width = Math.min( size.width - 70, 800); + + // Make it use 2/3 of the viewport height. + var height = size.height / 1.5; + + // Store old editor data to avoid unnecessary setData. + var oldData; + + return { + title: editor.lang.sourcedialog.title, + minWidth: 100, + minHeight: 100, + + onShow: function() { + this.setValueOf( 'main', 'data', oldData = editor.getData() ); + }, + + onOk: (function() { + function setData( newData ) { + var that = this; + + editor.setData( newData, function() { + that.hide(); + + // Ensure correct selection. + var range = editor.createRange(); + range.moveToElementEditStart( editor.editable() ); + range.select(); + } ); + } + + return function( event ) { + // Remove CR from input data for reliable comparison with editor data. + var newData = this.getValueOf( 'main', 'data' ).replace( /\r/g, '' ); + + // Avoid unnecessary setData. Also preserve selection + // when user changed his mind and goes back to wysiwyg editing. + if ( newData === oldData ) + return true; + + // Set data asynchronously to avoid errors in IE. + CKEDITOR.env.ie ? + CKEDITOR.tools.setTimeout( setData, 0, this, newData ) + : + setData.call( this, newData ); + + // Don't let the dialog close before setData is over. + return false; + }; + })(), + + contents: [{ + id: 'main', + label: editor.lang.sourcedialog.title, + elements: [{ + type: 'textarea', + type: 'textarea', + id: 'data', + inputStyle: 'cursor:auto;' + + 'width:' + width + 'px;' + + 'height:' + height + 'px;' + + 'tab-size:4;', + 'class': 'cke_source' + }] + }] + }; +}); diff --git a/plugins/sourcedialog/icons/sourcedialog-rtl.png b/plugins/sourcedialog/icons/sourcedialog-rtl.png new file mode 100644 index 00000000000..2efa25dd584 Binary files /dev/null and b/plugins/sourcedialog/icons/sourcedialog-rtl.png differ diff --git a/plugins/sourcedialog/icons/sourcedialog.png b/plugins/sourcedialog/icons/sourcedialog.png new file mode 100644 index 00000000000..ffd830df39c Binary files /dev/null and b/plugins/sourcedialog/icons/sourcedialog.png differ diff --git a/plugins/sourcedialog/lang/en.js b/plugins/sourcedialog/lang/en.js new file mode 100644 index 00000000000..d41d8f70223 --- /dev/null +++ b/plugins/sourcedialog/lang/en.js @@ -0,0 +1,9 @@ +/* +Copyright (c) 2003-2013, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.html or http://ckeditor.com/license +*/ + +CKEDITOR.plugins.setLang( 'sourcedialog', 'en', { + toolbar: 'Source', + title: 'Source' +}); diff --git a/plugins/sourcedialog/plugin.js b/plugins/sourcedialog/plugin.js new file mode 100644 index 00000000000..38ebe1ec3d8 --- /dev/null +++ b/plugins/sourcedialog/plugin.js @@ -0,0 +1,26 @@ +/** + * @license Copyright (c) 2003-2013, CKSource - Frederico Knabben. All rights reserved. + * For licensing, see LICENSE.html or http://ckeditor.com/license + */ + +CKEDITOR.plugins.add( 'sourcedialog', { + lang: 'en', // %REMOVE_LINE_CORE% + icons: 'sourcedialog,sourcedialog-rtl', // %REMOVE_LINE_CORE% + + init: function( editor ) { + // Register the "source" command, which simply opens the "source" dialog. + editor.addCommand( 'sourcedialog', new CKEDITOR.dialogCommand( 'sourcedialog' ) ); + + // Register the "source" dialog. + CKEDITOR.dialog.add( 'sourcedialog', this.path + 'dialogs/sourcedialog.js' ); + + // If the toolbar is available, create the "Source" button. + if ( editor.ui.addButton ) { + editor.ui.addButton( 'Sourcedialog', { + label: editor.lang.sourcedialog.toolbar, + command: 'sourcedialog', + toolbar: 'mode,10' + }); + } + } +}); diff --git a/plugins/sourcedialog/samples/sourcedialog.html b/plugins/sourcedialog/samples/sourcedialog.html new file mode 100644 index 00000000000..aa2a1172d69 --- /dev/null +++ b/plugins/sourcedialog/samples/sourcedialog.html @@ -0,0 +1,118 @@ + + + + + Raw HTML editing with dialog-based source editor — CKEditor Sample + + + + + + + + + + +

+ CKEditor Samples » Raw HTML editing with dialog-based source editor +

+
+

+ Sourcedialog plugin provides an easy way to edit raw HTML content + of an editor, similarly to what is possible with Sourcearea + plugin for framed instances but using dialogs. Thanks to that, it's also possible + to manipulate raw content of inline editor instances. +

+

+ This plugin extends the toolbar with a button, + which opens a dialog window with a source code editor. It works with both framed + and inline instances. To enable this + plugin, basically add extraPlugins: 'sourcedialog' to editor's + config: +

+
+// Inline editor.
+CKEDITOR.inline( 'editable', {
+	extraPlugins: 'sourcedialog'
+});
+
+// Framed editor.
+CKEDITOR.replace( 'textarea_id', {
+	extraPlugins: 'sourcedialog',
+	removePlugins: 'sourcearea'
+});
+
+

+ Note that you may want to include removePlugins: 'sourcearea' + in your config when using Sourcedialog in framed instances. + This prevents feature redundancy. +

+

+ Note that editable in the code above is the id + attribute of the <div> element to be converted into an inline instance. +

+

+ Note that textarea_id in the code above is the id attribute of + the <textarea> element to be replaced with CKEditor. +

+
+
+ +
+

This is some sample text. You are using CKEditor.

+
+
+
+
+ + +
+ + + + diff --git a/samples/index.html b/samples/index.html index 1928ed5cab0..2d81a09b3f4 100644 --- a/samples/index.html +++ b/samples/index.html @@ -139,6 +139,9 @@

Output for Flash
Configuring CKEditor to produce HTML code that can be used with Adobe Flash.
+ +
Raw HTML editing with dialog-based source editor New!
+
Editing HTML content of both inline and framed editor instances.
diff --git a/skins/kama/presets.css b/skins/kama/presets.css index 2d99dfd4458..7889cf90d4e 100644 --- a/skins/kama/presets.css +++ b/skins/kama/presets.css @@ -4,7 +4,8 @@ For licensing, see LICENSE.html or http://ckeditor.com/license */ /* "Source" button label */ -.cke_button__source_label +.cke_button__source_label, +.cke_button__sourcedialog_label { display: inline; } diff --git a/skins/moono/presets.css b/skins/moono/presets.css index 2d99dfd4458..7889cf90d4e 100644 --- a/skins/moono/presets.css +++ b/skins/moono/presets.css @@ -4,7 +4,8 @@ For licensing, see LICENSE.html or http://ckeditor.com/license */ /* "Source" button label */ -.cke_button__source_label +.cke_button__source_label, +.cke_button__sourcedialog_label { display: inline; }