0
Fork 0
mirror of https://github.com/fastmail/Squire.git synced 2024-12-22 15:23:29 -05:00

Clean up empty inlines when deleting selection.

Fixes #6
This commit is contained in:
Neil Jenkins 2014-12-25 15:09:46 +07:00
parent 5b52467815
commit 90623a51a2
5 changed files with 54 additions and 42 deletions

View file

@ -16,6 +16,8 @@ var START_TO_END = 1; // Range.START_TO_END
var END_TO_END = 2; // Range.END_TO_END var END_TO_END = 2; // Range.END_TO_END
var END_TO_START = 3; // Range.END_TO_START var END_TO_START = 3; // Range.END_TO_START
var ZWS = '\u200B';
var win = doc.defaultView; var win = doc.defaultView;
var ua = navigator.userAgent; var ua = navigator.userAgent;
@ -324,7 +326,7 @@ function fixCursor ( node ) {
} }
if ( !child ) { if ( !child ) {
if ( cantFocusEmptyTextNodes ) { if ( cantFocusEmptyTextNodes ) {
fixer = doc.createTextNode( '\u200B' ); fixer = doc.createTextNode( ZWS );
// Find the relevant Squire instance and notify // Find the relevant Squire instance and notify
l = instances.length; l = instances.length;
while ( l-- ) { while ( l-- ) {
@ -1372,11 +1374,11 @@ var removeZWS = function ( root ) {
}, false ), }, false ),
node, index; node, index;
while ( node = walker.nextNode() ) { while ( node = walker.nextNode() ) {
while ( ( index = node.data.indexOf( '\u200B' ) ) > -1 ) { while ( ( index = node.data.indexOf( ZWS ) ) > -1 ) {
node.deleteData( index, 1 ); node.deleteData( index, 1 );
} }
} }
} };
proto._didAddZWS = function () { proto._didAddZWS = function () {
this._hasZWS = true; this._hasZWS = true;
@ -1739,7 +1741,7 @@ proto._removeFormat = function ( tag, attributes, range, partial ) {
fixer; fixer;
if ( range.collapsed ) { if ( range.collapsed ) {
if ( cantFocusEmptyTextNodes ) { if ( cantFocusEmptyTextNodes ) {
fixer = doc.createTextNode( '\u200B' ); fixer = doc.createTextNode( ZWS );
this._didAddZWS(); this._didAddZWS();
} else { } else {
fixer = doc.createTextNode( '' ); fixer = doc.createTextNode( '' );
@ -2690,33 +2692,41 @@ var mapKeyToFormat = function ( tag, remove ) {
// replace it with a <font> tag (!). If you delete all the text inside a // replace it with a <font> tag (!). If you delete all the text inside a
// link in Opera, it won't delete the link. Let's make things consistent. If // link in Opera, it won't delete the link. Let's make things consistent. If
// you delete all text inside an inline tag, remove the inline tag. // you delete all text inside an inline tag, remove the inline tag.
var afterDelete = function ( self ) { var afterDelete = function ( self, range ) {
try { try {
var range = self.getSelection(), if ( !range ) { range = self.getSelection(); }
node = range.startContainer, var node = range.startContainer,
parent; parent;
// Climb the tree from the focus point while we are inside an empty
// inline element
if ( node.nodeType === TEXT_NODE ) { if ( node.nodeType === TEXT_NODE ) {
node = node.parentNode; node = node.parentNode;
} }
parent = node;
while ( isInline( parent ) &&
( !parent.textContent || parent.textContent === ZWS ) ) {
node = parent;
parent = node.parentNode;
}
// If focussed in empty inline element // If focussed in empty inline element
if ( isInline( node ) && !node.textContent ) { if ( node !== parent ) {
do { // Move focus to just before empty inline(s)
parent = node.parentNode;
} while ( isInline( parent ) &&
!parent.textContent && ( node = parent ) );
range.setStart( parent, range.setStart( parent,
indexOf.call( parent.childNodes, node ) ); indexOf.call( parent.childNodes, node ) );
range.collapse( true ); range.collapse( true );
// Remove empty inline(s)
parent.removeChild( node ); parent.removeChild( node );
// Fix cursor in block
if ( !isBlock( parent ) ) { if ( !isBlock( parent ) ) {
parent = getPreviousBlock( parent ); parent = getPreviousBlock( parent );
} }
fixCursor( parent ); fixCursor( parent );
// Move cursor into text node
moveRangeBoundariesDownTree( range ); moveRangeBoundariesDownTree( range );
self.setSelection( range );
self._updatePath( range );
} }
self._ensureBottomLine(); self._ensureBottomLine();
self.setSelection( range );
self._updatePath( range, true );
} catch ( error ) { } catch ( error ) {
self.didError( error ); self.didError( error );
} }
@ -2901,9 +2911,7 @@ var keyHandlers = {
if ( !range.collapsed ) { if ( !range.collapsed ) {
event.preventDefault(); event.preventDefault();
deleteContentsOfRange( range ); deleteContentsOfRange( range );
self._ensureBottomLine(); afterDelete( self, range );
self.setSelection( range );
self._updatePath( range, true );
} }
// If at beginning of block, merge with previous // If at beginning of block, merge with previous
else if ( rangeDoesStartAtBlockBoundary( range ) ) { else if ( rangeDoesStartAtBlockBoundary( range ) ) {
@ -2963,9 +2971,7 @@ var keyHandlers = {
if ( !range.collapsed ) { if ( !range.collapsed ) {
event.preventDefault(); event.preventDefault();
deleteContentsOfRange( range ); deleteContentsOfRange( range );
self._ensureBottomLine(); afterDelete( self, range );
self.setSelection( range );
self._updatePath( range, true );
} }
// If at end of block, merge next into this block // If at end of block, merge next into this block
else if ( rangeDoesEndAtBlockBoundary( range ) ) { else if ( rangeDoesEndAtBlockBoundary( range ) ) {

File diff suppressed because one or more lines are too long

View file

@ -11,6 +11,8 @@ var START_TO_END = 1; // Range.START_TO_END
var END_TO_END = 2; // Range.END_TO_END var END_TO_END = 2; // Range.END_TO_END
var END_TO_START = 3; // Range.END_TO_START var END_TO_START = 3; // Range.END_TO_START
var ZWS = '\u200B';
var win = doc.defaultView; var win = doc.defaultView;
var ua = navigator.userAgent; var ua = navigator.userAgent;

View file

@ -287,11 +287,11 @@ var removeZWS = function ( root ) {
}, false ), }, false ),
node, index; node, index;
while ( node = walker.nextNode() ) { while ( node = walker.nextNode() ) {
while ( ( index = node.data.indexOf( '\u200B' ) ) > -1 ) { while ( ( index = node.data.indexOf( ZWS ) ) > -1 ) {
node.deleteData( index, 1 ); node.deleteData( index, 1 );
} }
} }
} };
proto._didAddZWS = function () { proto._didAddZWS = function () {
this._hasZWS = true; this._hasZWS = true;
@ -654,7 +654,7 @@ proto._removeFormat = function ( tag, attributes, range, partial ) {
fixer; fixer;
if ( range.collapsed ) { if ( range.collapsed ) {
if ( cantFocusEmptyTextNodes ) { if ( cantFocusEmptyTextNodes ) {
fixer = doc.createTextNode( '\u200B' ); fixer = doc.createTextNode( ZWS );
this._didAddZWS(); this._didAddZWS();
} else { } else {
fixer = doc.createTextNode( '' ); fixer = doc.createTextNode( '' );
@ -1605,33 +1605,41 @@ var mapKeyToFormat = function ( tag, remove ) {
// replace it with a <font> tag (!). If you delete all the text inside a // replace it with a <font> tag (!). If you delete all the text inside a
// link in Opera, it won't delete the link. Let's make things consistent. If // link in Opera, it won't delete the link. Let's make things consistent. If
// you delete all text inside an inline tag, remove the inline tag. // you delete all text inside an inline tag, remove the inline tag.
var afterDelete = function ( self ) { var afterDelete = function ( self, range ) {
try { try {
var range = self.getSelection(), if ( !range ) { range = self.getSelection(); }
node = range.startContainer, var node = range.startContainer,
parent; parent;
// Climb the tree from the focus point while we are inside an empty
// inline element
if ( node.nodeType === TEXT_NODE ) { if ( node.nodeType === TEXT_NODE ) {
node = node.parentNode; node = node.parentNode;
} }
parent = node;
while ( isInline( parent ) &&
( !parent.textContent || parent.textContent === ZWS ) ) {
node = parent;
parent = node.parentNode;
}
// If focussed in empty inline element // If focussed in empty inline element
if ( isInline( node ) && !node.textContent ) { if ( node !== parent ) {
do { // Move focus to just before empty inline(s)
parent = node.parentNode;
} while ( isInline( parent ) &&
!parent.textContent && ( node = parent ) );
range.setStart( parent, range.setStart( parent,
indexOf.call( parent.childNodes, node ) ); indexOf.call( parent.childNodes, node ) );
range.collapse( true ); range.collapse( true );
// Remove empty inline(s)
parent.removeChild( node ); parent.removeChild( node );
// Fix cursor in block
if ( !isBlock( parent ) ) { if ( !isBlock( parent ) ) {
parent = getPreviousBlock( parent ); parent = getPreviousBlock( parent );
} }
fixCursor( parent ); fixCursor( parent );
// Move cursor into text node
moveRangeBoundariesDownTree( range ); moveRangeBoundariesDownTree( range );
self.setSelection( range );
self._updatePath( range );
} }
self._ensureBottomLine(); self._ensureBottomLine();
self.setSelection( range );
self._updatePath( range, true );
} catch ( error ) { } catch ( error ) {
self.didError( error ); self.didError( error );
} }
@ -1816,9 +1824,7 @@ var keyHandlers = {
if ( !range.collapsed ) { if ( !range.collapsed ) {
event.preventDefault(); event.preventDefault();
deleteContentsOfRange( range ); deleteContentsOfRange( range );
self._ensureBottomLine(); afterDelete( self, range );
self.setSelection( range );
self._updatePath( range, true );
} }
// If at beginning of block, merge with previous // If at beginning of block, merge with previous
else if ( rangeDoesStartAtBlockBoundary( range ) ) { else if ( rangeDoesStartAtBlockBoundary( range ) ) {
@ -1878,9 +1884,7 @@ var keyHandlers = {
if ( !range.collapsed ) { if ( !range.collapsed ) {
event.preventDefault(); event.preventDefault();
deleteContentsOfRange( range ); deleteContentsOfRange( range );
self._ensureBottomLine(); afterDelete( self, range );
self.setSelection( range );
self._updatePath( range, true );
} }
// If at end of block, merge next into this block // If at end of block, merge next into this block
else if ( rangeDoesEndAtBlockBoundary( range ) ) { else if ( rangeDoesEndAtBlockBoundary( range ) ) {

View file

@ -186,7 +186,7 @@ function fixCursor ( node ) {
} }
if ( !child ) { if ( !child ) {
if ( cantFocusEmptyTextNodes ) { if ( cantFocusEmptyTextNodes ) {
fixer = doc.createTextNode( '\u200B' ); fixer = doc.createTextNode( ZWS );
// Find the relevant Squire instance and notify // Find the relevant Squire instance and notify
l = instances.length; l = instances.length;
while ( l-- ) { while ( l-- ) {