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:
parent
712104cd99
commit
0d5398868f
4 changed files with 48 additions and 84 deletions
|
@ -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
|
@ -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-- ) {
|
||||||
|
|
|
@ -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 ) );
|
||||||
|
|
Loading…
Reference in a new issue