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

Commit

Permalink
Merge pull request #883 from ckeditor/t/882
Browse files Browse the repository at this point in the history
Fix: Mutations inserting bogus BR on the end of the block element are filtered out by mutation observer. Closes #882.
  • Loading branch information
Piotr Jasiun authored Mar 21, 2017
2 parents e08b019 + 3ca9299 commit 3583cae
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 1 deletion.
24 changes: 23 additions & 1 deletion src/view/observer/mutationobserver.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ export default class MutationObserver extends Observer {
if ( mutation.type === 'childList' ) {
const element = domConverter.getCorrespondingViewElement( mutation.target );

if ( element ) {
if ( element && !this._isBogusBrMutation( mutation ) ) {
mutatedElements.add( element );
}
}
Expand Down Expand Up @@ -233,6 +233,28 @@ export default class MutationObserver extends Observer {
// view (which has not been changed). In order to "reset DOM" we render the view again.
this.document.render();
}

/**
* Checks if mutation was generated by the browser inserting bogus br on the end of the block element.
* Such mutations are generated while pressing space or performing native spellchecker correction
* on the end of the block element in Firefox browser.
*
* @private
* @param {Object} mutation Native mutation object.
* @returns {Boolean}
*/
_isBogusBrMutation( mutation ) {
let addedNode = null;

// Check if mutation added only one node on the end of its parent.
if ( mutation.nextSibling === null && mutation.removedNodes.length === 0 && mutation.addedNodes.length == 1 ) {
addedNode = this.domConverter.domToView( mutation.addedNodes[ 0 ], {
withChildren: false
} );
}

return addedNode && addedNode.is( 'element', 'br' );
}
}

/**
Expand Down
99 changes: 99 additions & 0 deletions tests/view/observer/mutationobserver.js
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,105 @@ describe( 'MutationObserver', () => {
expect( lastMutations[ 0 ].oldChildren.length ).to.equal( 0 );
} );

it( 'should ignore mutation with bogus br inserted on the end of the empty paragraph', () => {
viewRoot.appendChildren( parse( '<container:p></container:p>' ) );

viewDocument.render();

const domP = domEditor.childNodes[ 2 ];
domP.appendChild( document.createElement( 'br' ) );

mutationObserver.flush();

expect( lastMutations.length ).to.equal( 0 );
} );

it( 'should ignore mutation with bogus br inserted on the end of the paragraph with text', () => {
viewRoot.appendChildren( parse( '<container:p>foo</container:p>' ) );

viewDocument.render();

const domP = domEditor.childNodes[ 2 ];
domP.appendChild( document.createElement( 'br' ) );

mutationObserver.flush();

expect( lastMutations.length ).to.equal( 0 );
} );

it( 'should ignore mutation with bogus br inserted on the end of the paragraph while processing text mutations', () => {
viewRoot.appendChildren( parse( '<container:p>foo</container:p>' ) );

viewDocument.render();

const domP = domEditor.childNodes[ 2 ];
domP.childNodes[ 0 ].data = 'foo ';
domP.appendChild( document.createElement( 'br' ) );

mutationObserver.flush();

expect( lastMutations.length ).to.equal( 1 );

expect( lastMutations[ 0 ].oldText ).to.equal( 'foo' );
expect( lastMutations[ 0 ].newText ).to.equal( 'foo ' );
} );

it( 'should not ignore mutation with br inserted not on the end of the paragraph', () => {
viewRoot.appendChildren( parse( '<container:p>foo</container:p>' ) );

viewDocument.render();

const domP = domEditor.childNodes[ 2 ];
domP.insertBefore( document.createElement( 'br' ), domP.childNodes[ 0 ] );

mutationObserver.flush();

expect( lastMutations.length ).to.equal( 1 );

expect( lastMutations[ 0 ].newChildren.length ).to.equal( 2 );
expect( lastMutations[ 0 ].newChildren[ 0 ].name ).to.equal( 'br' );
expect( lastMutations[ 0 ].newChildren[ 1 ].data ).to.equal( 'foo' );

expect( lastMutations[ 0 ].oldChildren.length ).to.equal( 1 );
} );

it( 'should not ignore mutation inserting element different than br on the end of the empty paragraph', () => {
viewRoot.appendChildren( parse( '<container:p></container:p>' ) );

viewDocument.render();

const domP = domEditor.childNodes[ 2 ];
domP.appendChild( document.createElement( 'span' ) );

mutationObserver.flush();

expect( lastMutations.length ).to.equal( 1 );

expect( lastMutations[ 0 ].newChildren.length ).to.equal( 1 );
expect( lastMutations[ 0 ].newChildren[ 0 ].name ).to.equal( 'span' );

expect( lastMutations[ 0 ].oldChildren.length ).to.equal( 0 );
} );

it( 'should not ignore mutation inserting element different than br on the end of the paragraph with text', () => {
viewRoot.appendChildren( parse( '<container:p>foo</container:p>' ) );

viewDocument.render();

const domP = domEditor.childNodes[ 2 ];
domP.appendChild( document.createElement( 'span' ) );

mutationObserver.flush();

expect( lastMutations.length ).to.equal( 1 );

expect( lastMutations[ 0 ].newChildren.length ).to.equal( 2 );
expect( lastMutations[ 0 ].newChildren[ 0 ].data ).to.equal( 'foo' );
expect( lastMutations[ 0 ].newChildren[ 1 ].name ).to.equal( 'span' );

expect( lastMutations[ 0 ].oldChildren.length ).to.equal( 1 );
} );

function expectDomEditorNotToChange() {
expect( domEditor.childNodes.length ).to.equal( 2 );
expect( domEditor.childNodes[ 0 ].tagName ).to.equal( 'P' );
Expand Down

0 comments on commit 3583cae

Please sign in to comment.