mirror of
https://github.com/fastmail/Squire.git
synced 2024-12-22 23:40:35 -05:00
parent
5b52467815
commit
90623a51a2
5 changed files with 54 additions and 42 deletions
|
@ -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
|
@ -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;
|
||||||
|
|
|
@ -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 ) ) {
|
||||||
|
|
|
@ -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-- ) {
|
||||||
|
|
Loading…
Reference in a new issue