Skip to content
This repository was archived by the owner on Jun 26, 2020. It is now read-only.

Commit 64a0dbc

Browse files
author
Piotr Jasiun
authored
Merge pull request #72 from ckeditor/t/56
Fix: The value of the `AttributeCommand` is taken from the first allowed node. Closes #56.
2 parents e19c90a + b782e9a commit 64a0dbc

File tree

2 files changed

+57
-7
lines changed

2 files changed

+57
-7
lines changed

src/attributecommand.js

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export default class AttributeCommand extends Command {
4141
* Flag indicating whether the command is active. The command is active when the
4242
* {@link module:engine/model/selection~Selection#hasAttribute selection has the attribute} which means that:
4343
*
44-
* * If the selection is not empty – That it starts in a text (or another node) which has the attribute set.
44+
* * If the selection is not empty – That the attribute is set on the first node in the selection that allows this attribute.
4545
* * If the selection is empty – That the selection has the attribute itself (which means that newly typed
4646
* text will have this attribute, too).
4747
*
@@ -58,7 +58,7 @@ export default class AttributeCommand extends Command {
5858
const model = this.editor.model;
5959
const doc = model.document;
6060

61-
this.value = doc.selection.hasAttribute( this.attributeKey );
61+
this.value = this._getValueFromFirstAllowedNode();
6262
this.isEnabled = model.schema.checkAttributeInSelection( doc.selection, this.attributeKey );
6363
}
6464

@@ -108,4 +108,31 @@ export default class AttributeCommand extends Command {
108108
}
109109
} );
110110
}
111+
112+
/**
113+
* Checks the attribute value of the first node in the selection that allows the attribute.
114+
* For the collapsed selection returns the selection attribute.
115+
*
116+
* @private
117+
* @returns {Boolean} The attribute value.
118+
*/
119+
_getValueFromFirstAllowedNode() {
120+
const model = this.editor.model;
121+
const schema = model.schema;
122+
const selection = model.document.selection;
123+
124+
if ( selection.isCollapsed ) {
125+
return selection.hasAttribute( this.attributeKey );
126+
}
127+
128+
for ( const range of selection.getRanges() ) {
129+
for ( const item of range.getItems() ) {
130+
if ( schema.checkAttribute( item, this.attributeKey ) ) {
131+
return item.hasAttribute( this.attributeKey );
132+
}
133+
}
134+
}
135+
136+
return false;
137+
}
111138
}

tests/attributecommand.js

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,15 @@ describe( 'AttributeCommand', () => {
4949
} );
5050

5151
describe( 'value', () => {
52-
it( 'is true when selection has the attribute', () => {
52+
it( 'is true when collapsed selection has the attribute', () => {
5353
model.change( writer => {
5454
writer.setSelectionAttribute( attrKey, true );
5555
} );
5656

5757
expect( command.value ).to.be.true;
5858
} );
5959

60-
it( 'is false when selection does not have the attribute', () => {
60+
it( 'is false when collapsed selection does not have the attribute', () => {
6161
model.change( writer => {
6262
writer.setSelectionAttribute( attrKey, true );
6363
} );
@@ -69,8 +69,31 @@ describe( 'AttributeCommand', () => {
6969
expect( command.value ).to.be.false;
7070
} );
7171

72-
// See https://github.com/ckeditor/ckeditor5-core/issues/73#issuecomment-311572827.
73-
it( 'is false when selection contains object with nested editable', () => {
72+
it( 'is true when the first item that allows attribute has the attribute set #1', () => {
73+
setData( model, '<p><$text bold="true">fo[o</$text></p><h1>b]ar</h1>' );
74+
75+
expect( command.value ).to.be.true;
76+
} );
77+
78+
it( 'is true when the first item that allows attribute has the attribute set #2', () => {
79+
setData( model, '<h1>fo[o</h1><p><$text bold="true">f</$text>o]o</p>' );
80+
81+
expect( command.value ).to.be.true;
82+
} );
83+
84+
it( 'is false when the first item that allows attribute does not have the attribute set #1', () => {
85+
setData( model, '<p>b[a<$text bold="true">r</$text></p><h1>fo]o</h1>' );
86+
87+
expect( command.value ).to.be.false;
88+
} );
89+
90+
it( 'is false when the first item that allows attribute does not have the attribute set #2', () => {
91+
setData( model, '<h1>fo[o</h1><p>b<$text bold="true">r</$text>r]</p>' );
92+
93+
expect( command.value ).to.be.false;
94+
} );
95+
96+
it( 'is true when the first item that allows attribute has the attribute set - object with nested editable', () => {
7497
model.schema.register( 'caption', {
7598
allowContentOf: '$block',
7699
allowIn: 'img',
@@ -85,7 +108,7 @@ describe( 'AttributeCommand', () => {
85108

86109
expect( command.value ).to.be.false;
87110
command.execute();
88-
expect( command.value ).to.be.false;
111+
expect( command.value ).to.be.true;
89112

90113
expect( getData( model ) ).to.equal(
91114
'<p>[<img><caption><$text bold="true">Some caption inside the image.</$text></caption></img>]</p>'

0 commit comments

Comments
 (0)