Skip to content
Permalink
Browse files

Merge branch 't/12141'

  • Loading branch information...
Reinmar committed Nov 7, 2014
2 parents 184dc7f + f9ab246 commit a1122531e851bc6315c97cc638d1f0d3365ba325
@@ -15,6 +15,7 @@ Fixed Issues:
* [#12601](http://dev.ckeditor.com/ticket/12601): Fixed: [Strikethrough](http://ckeditor.com/addon/basicstyles) button tooltip spelling.
* [#12546](http://dev.ckeditor.com/ticket/12546): Fixed: Preview tab in docprops dialog is always disabled.
* [#12300](http://dev.ckeditor.com/ticket/12300): Fixed: The [`editor.change`](http://docs.ckeditor.com/#!/api/CKEDITOR.editor-event-change) event fired on first navigation key press after typing.
* [#12141](http://dev.ckeditor.com/ticket/12141): Fixed: List items are lost when indenting a list item with a content wrapped with a block element.

Other Changes:
* [#12550](http://dev.ckeditor.com/ticket/12550): Added CKEDITOR.dtd.main.
@@ -14,7 +14,9 @@
TRISTATE_OFF = CKEDITOR.TRISTATE_OFF;

CKEDITOR.plugins.add( 'indent', {
// jscs:disable maximumLineLength
lang: 'af,ar,bg,bn,bs,ca,cs,cy,da,de,el,en,en-au,en-ca,en-gb,eo,es,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,id,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,tt,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE%
// jscs:enable maximumLineLength
icons: 'indent,indent-rtl,outdent,outdent-rtl', // %REMOVE_LINE_CORE%
hidpi: true, // %REMOVE_LINE_CORE%

@@ -454,7 +456,7 @@

// Housekeeping. Make sure selectionChange will be called.
// Also re-select previously saved bookmarks.
command.on( 'exec', function( evt ) {
command.on( 'exec', function() {
editor.forceNextSelectionCheck();
selection.selectBookmarks( bookmarks );
}, command, null, 100 );
@@ -27,7 +27,7 @@
outdentblock: new commandDefinition( editor, 'outdentblock' )
} );

function commandDefinition( editor, name ) {
function commandDefinition() {
globalHelpers.specificDefinition.apply( this, arguments );

this.allowedContent = {
@@ -53,24 +53,19 @@
refresh: function( editor, path ) {
var firstBlock = path.block || path.blockLimit;

// Switch context from somewhere inside list item to list item,
// if not found just assign self (doing nothing).
if ( !firstBlock.is( $listItem ) ) {
firstBlock = firstBlock.getAscendant( $listItem ) || firstBlock;
}

// Switch context from list item to list
// because indentblock can indent entire list
// but not a single list element.

if ( firstBlock.is( $listItem ) )
firstBlock = firstBlock.getParent();

// If firstBlock isn't list item, but still there's
// some ascendant (i.e. <ul>), then this is not
// a job for indentblock, e.g.:
//
// <ul>
// <li><p>foo</p></li>
// </ul>

else if ( firstBlock.getAscendant( $listItem ) )
return TRISTATE_DISABLED;

// [-] Context in the path or ENTER_BR
//
// Don't try to indent if the element is out of
@@ -18,16 +18,15 @@
CKEDITOR.plugins.add( 'indentlist', {
requires: 'indent',
init: function( editor ) {
var globalHelpers = CKEDITOR.plugins.indent,
editable = editor;
var globalHelpers = CKEDITOR.plugins.indent;

// Register commands.
globalHelpers.registerCommands( editor, {
indentlist: new commandDefinition( editor, 'indentlist', true ),
outdentlist: new commandDefinition( editor, 'outdentlist' )
} );

function commandDefinition( editor, name ) {
function commandDefinition( editor ) {
globalHelpers.specificDefinition.apply( this, arguments );

// Require ul OR ol list.
@@ -46,7 +45,7 @@
// Don't indent if in first list item of the parent.
// Outdent, however, can always be done to collapse
// the list into a paragraph (div).
if ( this.isIndent && firstItemInPath.call( this, editor.elementPath(), list ) )
if ( this.isIndent && CKEDITOR.plugins.indentList.firstItemInPath( this.context, editor.elementPath(), list ) )
return;

// Exec related global indentation command. Global
@@ -80,7 +79,7 @@
refresh: this.isIndent ?
function( editor, path ) {
var list = this.getContext( path ),
inFirstListItem = firstItemInPath.call( this, path, list );
inFirstListItem = CKEDITOR.plugins.indentList.firstItemInPath( this.context, path, list );

if ( !list || !this.isIndent || inFirstListItem )
return TRISTATE_DISABLED;
@@ -277,16 +276,6 @@
return 0;
}

// Check whether a first child of a list is in the path.
// The list can be extracted from path or given explicitly
// e.g. for better performance if cached.
function firstItemInPath( path, list ) {
if ( !list )
list = path.contains( this.context );

return list && path.block && path.block.equals( list.getFirst( listItem ) );
}

// Determines whether a node is a list <li> element.
function listItem( node ) {
return node.type == CKEDITOR.NODE_ELEMENT && node.is( 'li' );
@@ -295,4 +284,32 @@
function neitherWhitespacesNorBookmark( node ) {
return isNotWhitespaces( node ) && isNotBookmark( node );
}

/**
* Global namespace for methods exposed by the indentlist plugin.
*
* @singleton
* @class
*/
CKEDITOR.plugins.indentList = {};

/**
* Checks whether the first child of the list is in the path.
* The list can be extracted from the path or given explicitly
* e.g. for better performance if cached.
*
* @since 4.4.6
* @param {Object} query See the {@link CKEDITOR.dom.elementPath#contains} method arguments.
* @param {CKEDITOR.dom.elementPath} path
* @param {CKEDITOR.dom.element} [list]
* @returns {Boolean}
* @member CKEDITOR.plugins.indentList
*/
CKEDITOR.plugins.indentList.firstItemInPath = function( query, path, list ) {
var firstListItemInPath = path.contains( listItem );
if ( !list )
list = path.contains( query );

return list && firstListItemInPath && firstListItemInPath.equals( list.getFirst( listItem ) );
};
} )();
@@ -74,6 +74,34 @@ addTests( 'test outdent nest list keeps styles on list root', 'outdent', [
'<p>foo</p><ul style="font-size:24px;"><li>bar</li></ul>' ]
] );

// #12141
// { indentBlock: true, hasParagraph: false, caretAtFirst: true }
addTests( 'test indent add margin to the whole list when items are not wrapped in paragraph and caret is in the first one', 'indent', [
[ '<ul><li>f^oo</li><li>bar</li></ul>',
'<ul style="margin-left:40px;"><li>foo</li><li>bar</li></ul>' ]
] );

// #12141
// { indentBlock: true, hasParagraph: false, caretAtFirst: false }
addTests( 'test indent nests list item when items are not wrapped in paragraph and caret is in the second one', 'indent', [
[ '<ul><li>foo</li><li>b^ar</li></ul>',
'<ul><li>foo<ul><li>bar</li></ul></li></ul>' ]
] );

// #12141
// { indentBlock: true, hasParagraph: true, caretAtFirst: true }
addTests( 'test indent add margin to the whole list when items are wrapped in paragraph and caret is in the first one', 'indent', [
[ '<ul><li><p>f^oo</p></li><li><p>bar</p></li></ul>',
'<ul style="margin-left:40px;"><li><p>foo</p></li><li><p>bar</p></li></ul>' ]
] );

// #12141
// { indentBlock: true, hasParagraph: true, caretAtFirst: false }
addTests( 'test indent nest list item when items are wrapped in paragraph and caret is in the second one', 'indent', [
[ '<ul><li><p>foo</p></li><li><p>b^ar</p></li></ul>',
'<ul><li><p>foo</p><ul><li><p>bar</p></li></ul></li></ul>' ]
] );

// ### Finished adding tests.

function addTests( title, command, testsToAdd ) {
@@ -0,0 +1,29 @@
<div id="editor">
<h3>List item content without paragraph:</h3>
<ul>
<li>Relax</li>
<li>Take a deep breath</li>
</ul>

<h3>List item content wrapped in paragraph:</h3>
<ul>
<li><p>Smile</p></li>
<li><p>Be happy</p></li>
</ul>

<h3>List item content containing multiple paragraphs:</h3>
<ul>
<li>
<p>Relax</p>
<p>Take a deep breath</p>
</li>
<li>
<p>Smile</p>
<p>Be happy</p>
</li>
</ul>
</div>

<script>
CKEDITOR.replace( 'editor', { height: 400 } );
</script>
@@ -0,0 +1,31 @@
@bender-tags: 4.4.6, tc
@bender-ui: collapsed
@bender-ckeditor-plugins: wysiwygarea, toolbar, undo, clipboard, enterkey, htmlwriter, list, indentlist, sourcearea

General note: In this test case only indentlist plugin is enabled (indentblock is disabled).

----

1. Put caret at the first item in the first list.

**Expected:** Indent button should be disabled.

----

1. Put caret at the second item in the first list.
2. Click `indent` button at the toolbar.

**Expected:** Only second item should be indented, but not the whole list.

----

1. Put caret at the first item in the second list.

**Expected:** Indent button should be disabled.

----

1. Put caret at the second item in the second list.
2. Click `indent` button at the toolbar.

**Expected:** Only second item should be indented, but not the whole list.
@@ -0,0 +1,32 @@
@bender-tags: 4.4.6, tc
@bender-ui: collapsed
@bender-ckeditor-plugins: wysiwygarea, toolbar, undo, clipboard, enterkey, htmlwriter, list, indentlist, indentblock, sourcearea

General note: In this test case both indentlist and indentblock plugins are enabled.

----

1. Put caret at the first item in the first list.
2. Click `indent` button at the toolbar.

**Expected:** Whole list should be indented.

----

1. Put caret at the second item in the first list.
2. Click `indent` button at the toolbar.

**Expected:** Only second item should be indented, but not the whole list.

----

1. Put caret at the first item in the second list.

**Expected:** Whole list should be indented.

----

1. Put caret at the second item in the second list.
2. Click `indent` button at the toolbar.

**Expected:** Only second item should be indented, but not the whole list.
@@ -0,0 +1,59 @@
/* bender-tags: editor,unit */
/* bender-ckeditor-plugins: list,indentlist */

bender.editor = {
config: {
enterMode: CKEDITOR.ENTER_P,
allowedContent: true // Disable filter.
}
};

var tests = {};

// #12141
// { indentBlock: false, hasParagraph: false, caretAtFirst: true }
addTests( 'test indent does nothing when items are not wrapped in paragraph and caret is in the first one', 'indent', [
[ '<ul><li>f^oo</li><li>bar</li></ul>',
'<ul><li>foo</li><li>bar</li></ul>' ]
] );

// #12141
// { indentBlock: false, hasParagraph: false, caretAtFirst: false }
addTests( 'test indent does not remove second list item when items are not wrapped in paragraph and caret is in the second one', 'indent', [
[ '<ul><li>foo</li><li>b^ar</li></ul>',
'<ul><li>foo<ul><li>bar</li></ul></li></ul>' ]
] );

// #12141
// { indentBlock: false, hasParagraph: true, caretAtFirst: true }
addTests( 'test indent does not make changes when items are wrapped in paragraph and caret is in the first one', 'indent', [
[ '<ul><li><p>f^oo</p></li><li><p>bar</p></li></ul>',
'<ul><li><p>foo</p></li><li><p>bar</p></li></ul>' ]
] );

// #12141
// { indentBlock: false, hasParagraph: true, caretAtFirst: false }
addTests( 'test indent nests list when items are wrapped in paragraph and caret is in the second one', 'indent', [
[ '<ul><li><p>foo</p></li><li><p>b^ar</p></li></ul>',
'<ul><li><p>foo</p><ul><li><p>bar</p></li></ul></li></ul>' ]
] );

// ### Finished adding tests.

function addTests( title, command, testsToAdd ) {
for ( var i = 0 ; i < testsToAdd.length ; i++ ) {
var testTitle = title + ( testsToAdd.length > 1 ? ' [' + i + ']' : '' );
add( testTitle, command, testsToAdd[ i ][ 0 ], testsToAdd[ i ][ 1 ] );
}

function add( title, command, input, output ) {
tests[ testTitle ] = function() {
var bot = this.editorBot;
bot.setHtmlWithSelection( input );
bot.execCommand( command );
assert.areSame( output, bot.getData( true, true ) );
};
}
}

bender.test( tests );
@@ -0,0 +1,45 @@
/* bender-tags: editor,unit */
/* bender-ckeditor-plugins: indentlist */

( function() {
'use strict';

var query = { ul: 1, ol: 1 };

bender.test( {
'test firstItemInPath: element direct in list': function() {
var root = CKEDITOR.dom.element.createFromHtml( [
'<ul>',
'<li id="one">one</li>',
'<li id="two">two</li>',
'</ul>'
].join( '' ) ),
one = root.findOne( '#one' ),
two = root.findOne( '#two' ),
pathOne = new CKEDITOR.dom.elementPath( one, root ),
pathTwo = new CKEDITOR.dom.elementPath( two, root ),
firstItemInPath = CKEDITOR.plugins.indentList.firstItemInPath;

assert.isTrue( firstItemInPath( query, pathOne, root ) );
assert.isFalse( firstItemInPath( query, pathTwo, root ) );

},

'test firstItemInPath: element with paragraph in list': function() {
var root = CKEDITOR.dom.element.createFromHtml( [
'<ul>',
'<li><p id="one">one</p></li>',
'<li><p id="two">two</p></li>',
'</ul>'
].join( '' ) ),
one = root.findOne( '#one' ),
two = root.findOne( '#two' ),
pathOne = new CKEDITOR.dom.elementPath( one, root ),
pathTwo = new CKEDITOR.dom.elementPath( two, root ),
firstItemInPath = CKEDITOR.plugins.indentList.firstItemInPath;

assert.isTrue( firstItemInPath( query, pathOne, root ) );
assert.isFalse( firstItemInPath( query, pathTwo, root ) );
}
} );
} )();

0 comments on commit a112253

Please sign in to comment.
You can’t perform that action at this time.