0
Fork 0
mirror of https://github.com/fastmail/Squire.git synced 2025-01-03 05:00:13 -05:00

Better, simpler cleanup of zero-width space placeholders.

Fixes issue applying multiple inline formats at the same time with a collapsed
selection in WebKit. Much more robust than previous method.
This commit is contained in:
Neil Jenkins 2014-04-16 18:06:10 +10:00
parent 712104cd99
commit 0d5398868f
4 changed files with 48 additions and 84 deletions

View file

@ -318,7 +318,7 @@ function fixCursor ( node ) {
if ( cantFocusEmptyTextNodes ) { if ( cantFocusEmptyTextNodes ) {
fixer = doc.createTextNode( '\u200B' ); fixer = doc.createTextNode( '\u200B' );
if ( win.editor ) { if ( win.editor ) {
win.editor._setPlaceholderTextNode( fixer ); win.editor._didAddZWS();
} }
} else { } else {
fixer = doc.createTextNode( '' ); fixer = doc.createTextNode( '' );
@ -445,7 +445,7 @@ function mergeInlines ( node, range ) {
} }
detach( child ); detach( child );
if ( child.nodeType === TEXT_NODE ) { if ( child.nodeType === TEXT_NODE ) {
prev.appendData( child.data.replace( /\u200B/g, '' ) ); prev.appendData( child.data );
} }
else { else {
frags.push( empty( child ) ); frags.push( empty( child ) );
@ -1145,9 +1145,7 @@ function Squire ( doc ) {
this.addEventListener( 'beforedeactivate', this.getSelection ); this.addEventListener( 'beforedeactivate', this.getSelection );
} }
this._placeholderTextNode = null; this._hasZWS = false;
this._mayRemovePlaceholder = true;
this._willEnablePlaceholderRemoval = false;
this._lastAnchorNode = null; this._lastAnchorNode = null;
this._lastFocusNode = null; this._lastFocusNode = null;
@ -1376,50 +1374,28 @@ proto.getPath = function () {
// WebKit bug: https://bugs.webkit.org/show_bug.cgi?id=15256 // WebKit bug: https://bugs.webkit.org/show_bug.cgi?id=15256
proto._enablePlaceholderRemoval = function () { proto._didAddZWS = function () {
this._mayRemovePlaceholder = true; this._hasZWS = true;
this._willEnablePlaceholderRemoval = false;
this.removeEventListener( 'keydown', this._enablePlaceholderRemoval );
}; };
proto._removeZWS = function () {
proto._removePlaceholderTextNode = function () { if ( !this._hasZWS ) {
if ( !this._mayRemovePlaceholder ) { return; } return;
}
var node = this._placeholderTextNode, var walker = new TreeWalker( this._body, SHOW_TEXT, function () {
index; return FILTER_ACCEPT;
}, false ),
this._placeholderTextNode = null; node, index;
while ( node = walker.nextNode() ) {
if ( node.parentNode ) {
while ( ( index = node.data.indexOf( '\u200B' ) ) > -1 ) { while ( ( index = node.data.indexOf( '\u200B' ) ) > -1 ) {
node.deleteData( index, 1 ); node.deleteData( index, 1 );
} }
if ( !node.data && !node.nextSibling && !node.previousSibling &&
isInline( node.parentNode ) ) {
detach( node.parentNode );
}
} }
}; this._hasZWS = false;
proto._setPlaceholderTextNode = function ( node ) {
if ( this._placeholderTextNode ) {
this._mayRemovePlaceholder = true;
this._removePlaceholderTextNode();
}
if ( !this._willEnablePlaceholderRemoval ) {
this.addEventListener( 'keydown', this._enablePlaceholderRemoval );
this._willEnablePlaceholderRemoval = true;
}
this._mayRemovePlaceholder = false;
this._placeholderTextNode = node;
}; };
// --- Path change events --- // --- Path change events ---
proto._updatePath = function ( range, force ) { proto._updatePath = function ( range, force ) {
if ( this._placeholderTextNode && !force ) {
this._removePlaceholderTextNode( range );
}
var anchor = range.startContainer, var anchor = range.startContainer,
focus = range.endContainer, focus = range.endContainer,
newPath; newPath;
@ -1763,7 +1739,7 @@ proto._removeFormat = function ( tag, attributes, range, partial ) {
if ( range.collapsed ) { if ( range.collapsed ) {
if ( cantFocusEmptyTextNodes ) { if ( cantFocusEmptyTextNodes ) {
fixer = doc.createTextNode( '\u200B' ); fixer = doc.createTextNode( '\u200B' );
this._setPlaceholderTextNode( fixer ); this._didAddZWS();
} else { } else {
fixer = doc.createTextNode( '' ); fixer = doc.createTextNode( '' );
} }
@ -3039,6 +3015,12 @@ var keyHandlers = {
addLinks( range.startContainer ); addLinks( range.startContainer );
self._getRangeAndRemoveBookmark( range ); self._getRangeAndRemoveBookmark( range );
self.setSelection( range ); self.setSelection( range );
},
left: function ( self ) {
self._removeZWS();
},
right: function ( self ) {
self._removeZWS();
} }
}; };
// Firefox incorrectly handles Cmd-left/Cmd-right on Mac: // Firefox incorrectly handles Cmd-left/Cmd-right on Mac:
@ -3137,7 +3119,7 @@ proto.getHTML = function ( withBookMark ) {
} }
} }
} }
html = this._getHTML(); html = this._getHTML().replace( /\u200B/g, '' );
if ( useTextFixer ) { if ( useTextFixer ) {
l = brs.length; l = brs.length;
while ( l-- ) { while ( l-- ) {

File diff suppressed because one or more lines are too long

View file

@ -83,9 +83,7 @@ function Squire ( doc ) {
this.addEventListener( 'beforedeactivate', this.getSelection ); this.addEventListener( 'beforedeactivate', this.getSelection );
} }
this._placeholderTextNode = null; this._hasZWS = false;
this._mayRemovePlaceholder = true;
this._willEnablePlaceholderRemoval = false;
this._lastAnchorNode = null; this._lastAnchorNode = null;
this._lastFocusNode = null; this._lastFocusNode = null;
@ -314,50 +312,28 @@ proto.getPath = function () {
// WebKit bug: https://bugs.webkit.org/show_bug.cgi?id=15256 // WebKit bug: https://bugs.webkit.org/show_bug.cgi?id=15256
proto._enablePlaceholderRemoval = function () { proto._didAddZWS = function () {
this._mayRemovePlaceholder = true; this._hasZWS = true;
this._willEnablePlaceholderRemoval = false;
this.removeEventListener( 'keydown', this._enablePlaceholderRemoval );
}; };
proto._removeZWS = function () {
proto._removePlaceholderTextNode = function () { if ( !this._hasZWS ) {
if ( !this._mayRemovePlaceholder ) { return; } return;
}
var node = this._placeholderTextNode, var walker = new TreeWalker( this._body, SHOW_TEXT, function () {
index; return FILTER_ACCEPT;
}, false ),
this._placeholderTextNode = null; node, index;
while ( node = walker.nextNode() ) {
if ( node.parentNode ) {
while ( ( index = node.data.indexOf( '\u200B' ) ) > -1 ) { while ( ( index = node.data.indexOf( '\u200B' ) ) > -1 ) {
node.deleteData( index, 1 ); node.deleteData( index, 1 );
} }
if ( !node.data && !node.nextSibling && !node.previousSibling &&
isInline( node.parentNode ) ) {
detach( node.parentNode );
}
} }
}; this._hasZWS = false;
proto._setPlaceholderTextNode = function ( node ) {
if ( this._placeholderTextNode ) {
this._mayRemovePlaceholder = true;
this._removePlaceholderTextNode();
}
if ( !this._willEnablePlaceholderRemoval ) {
this.addEventListener( 'keydown', this._enablePlaceholderRemoval );
this._willEnablePlaceholderRemoval = true;
}
this._mayRemovePlaceholder = false;
this._placeholderTextNode = node;
}; };
// --- Path change events --- // --- Path change events ---
proto._updatePath = function ( range, force ) { proto._updatePath = function ( range, force ) {
if ( this._placeholderTextNode && !force ) {
this._removePlaceholderTextNode( range );
}
var anchor = range.startContainer, var anchor = range.startContainer,
focus = range.endContainer, focus = range.endContainer,
newPath; newPath;
@ -701,7 +677,7 @@ proto._removeFormat = function ( tag, attributes, range, partial ) {
if ( range.collapsed ) { if ( range.collapsed ) {
if ( cantFocusEmptyTextNodes ) { if ( cantFocusEmptyTextNodes ) {
fixer = doc.createTextNode( '\u200B' ); fixer = doc.createTextNode( '\u200B' );
this._setPlaceholderTextNode( fixer ); this._didAddZWS();
} else { } else {
fixer = doc.createTextNode( '' ); fixer = doc.createTextNode( '' );
} }
@ -1977,6 +1953,12 @@ var keyHandlers = {
addLinks( range.startContainer ); addLinks( range.startContainer );
self._getRangeAndRemoveBookmark( range ); self._getRangeAndRemoveBookmark( range );
self.setSelection( range ); self.setSelection( range );
},
left: function ( self ) {
self._removeZWS();
},
right: function ( self ) {
self._removeZWS();
} }
}; };
// Firefox incorrectly handles Cmd-left/Cmd-right on Mac: // Firefox incorrectly handles Cmd-left/Cmd-right on Mac:
@ -2075,7 +2057,7 @@ proto.getHTML = function ( withBookMark ) {
} }
} }
} }
html = this._getHTML(); html = this._getHTML().replace( /\u200B/g, '' );
if ( useTextFixer ) { if ( useTextFixer ) {
l = brs.length; l = brs.length;
while ( l-- ) { while ( l-- ) {

View file

@ -176,7 +176,7 @@ function fixCursor ( node ) {
if ( cantFocusEmptyTextNodes ) { if ( cantFocusEmptyTextNodes ) {
fixer = doc.createTextNode( '\u200B' ); fixer = doc.createTextNode( '\u200B' );
if ( win.editor ) { if ( win.editor ) {
win.editor._setPlaceholderTextNode( fixer ); win.editor._didAddZWS();
} }
} else { } else {
fixer = doc.createTextNode( '' ); fixer = doc.createTextNode( '' );
@ -303,7 +303,7 @@ function mergeInlines ( node, range ) {
} }
detach( child ); detach( child );
if ( child.nodeType === TEXT_NODE ) { if ( child.nodeType === TEXT_NODE ) {
prev.appendData( child.data.replace( /\u200B/g, '' ) ); prev.appendData( child.data );
} }
else { else {
frags.push( empty( child ) ); frags.push( empty( child ) );