jenkins-bot has submitted this change and it was merged.
Change subject: Handle deletion programmatically always
......................................................................
Handle deletion programmatically always
Change-Id: Ic68f80d92d32169ff60258b81a438e342b136128
---
M modules/ve/ce/ve.ce.Surface.js
M modules/ve/dm/ve.dm.Surface.js
2 files changed, 51 insertions(+), 135 deletions(-)
Approvals:
Catrope: Looks good to me, approved
jenkins-bot: Verified
diff --git a/modules/ve/ce/ve.ce.Surface.js b/modules/ve/ce/ve.ce.Surface.js
index c45e8b7..4680273 100644
--- a/modules/ve/ce/ve.ce.Surface.js
+++ b/modules/ve/ce/ve.ce.Surface.js
@@ -449,9 +449,11 @@
this.handleEnter( e );
break;
case ve.Keys.BACKSPACE:
+ e.preventDefault();
this.handleDelete( e, true );
break;
case ve.Keys.DELETE:
+ e.preventDefault();
this.handleDelete( e, false );
break;
default:
@@ -1195,147 +1197,56 @@
* @param {boolean} backspace Key was a backspace
*/
ve.ce.Surface.prototype.handleDelete = function ( e, backspace ) {
- var sourceOffset, targetOffset, sourceSplitableNode,
targetSplitableNode, tx, cursorAt,
- sourceNode, targetNode, sourceData, nodeToDelete, adjacentData,
adjacentText, adjacentChar,
- adjacentTextAfterMatch, endOffset, i, containsComplexElements =
false,
- selection = this.model.getSelection();
+ var rangeToRemove = this.model.getSelection(),
+ tx, endNode, endNodeData, nodeToDelete;
- if ( selection.isCollapsed() ) {
- // Set source and target linmod offsets
- if ( backspace ) {
- sourceOffset = selection.to;
- targetOffset = this.getNearestCorrectOffset(
sourceOffset - 1, -1 );
-
- // At the beginning of the document - don't do anything
and preventDefault
- if ( sourceOffset === targetOffset ) {
- e.preventDefault();
- return;
+ if ( rangeToRemove.isCollapsed() ) {
+ // In case when the range is collapsed use the same logic that
is used for cursor left and
+ // right movement in order to figure out range to remove.
+ rangeToRemove = this.getDocument().getRelativeRange(
+ rangeToRemove,
+ backspace ? -1 : 1,
+ ( e.altKey === true || e.ctrlKey === true ) ? 'word' :
'character',
+ true
+ );
+ if ( rangeToRemove.isCollapsed() ) {
+ // For instance beginning or end of the document.
+ return;
+ }
+ }
+ tx = ve.dm.Transaction.newFromRemoval( this.documentView.model,
rangeToRemove );
+ this.model.change( tx );
+ rangeToRemove = tx.translateRange( rangeToRemove );
+ if ( !rangeToRemove.isCollapsed() ) {
+ // If after processing removal transaction range is not
collapsed it means that not
+ // everything got merged nicely (at this moment transaction
processor is capable of merging
+ // nodes of the same type and at the same depth level only), so
we process with another
+ // merging that takes remaing data from "endNode" and inserts
it at the end of "startNode",
+ // "endNode" or recrusivly its parent (if have only one child)
gets removed.
+ endNode = this.documentView.getNodeFromOffset(
rangeToRemove.end, false );
+ endNodeData = this.documentView.model.getData(
endNode.model.getRange() );
+ nodeToDelete = endNode;
+ nodeToDelete.traverseUpstream( function ( node ) {
+ if ( node.getParent().children.length === 1 ) {
+ nodeToDelete = node.getParent();
+ return true;
+ } else {
+ return false;
}
-
- } else {
- sourceOffset =
this.model.getDocument().data.getRelativeContentOffset( selection.to, 1 );
- targetOffset = selection.to;
-
- // At the end of the document - don't do anything and
preventDefault
- if ( sourceOffset <= targetOffset ) {
- e.preventDefault();
- return;
- }
- }
-
- // Set source and target nodes
- sourceNode = this.documentView.getNodeFromOffset( sourceOffset,
false ),
- targetNode = this.documentView.getNodeFromOffset( targetOffset,
false );
-
- if ( sourceNode.type === targetNode.type ) {
- sourceSplitableNode = ve.ce.Node.getSplitableNode(
sourceNode );
- targetSplitableNode = ve.ce.Node.getSplitableNode(
targetNode );
- }
- //ve.log(sourceSplitableNode, targetSplitableNode);
-
- // Save target location of cursor
- cursorAt = targetOffset;
-
- // Get text from cursor location to end of node in the proper
direction
- adjacentData = null;
- adjacentText = '';
-
- if ( backspace ) {
- adjacentData = sourceNode.model.doc.data.slice(
- sourceNode.model.getOffset() + (
sourceNode.model.isWrapped() ? 1 : 0 ) ,
- sourceOffset
- );
- } else {
- endOffset = targetNode.model.getOffset() +
- targetNode.model.getLength() +
- ( targetNode.model.isWrapped() ? 1 : 0 );
- adjacentData = targetNode.model.doc.data.slice(
targetOffset, endOffset );
- }
-
- for ( i = 0; i < adjacentData.length; i++ ) {
- if ( adjacentData[i].type !== undefined ) {
- containsComplexElements = true;
- break;
- }
- adjacentChar = ve.isArray( adjacentData[i] ) ?
adjacentData[i][0] : adjacentData[i];
- if ( adjacentChar.length > 1 ) {
- containsComplexElements = true;
- break;
- }
- adjacentText += adjacentChar;
- }
-
- if ( !containsComplexElements ) {
- adjacentTextAfterMatch = adjacentText.match(
this.constructor.static.textPattern );
- // If there are "normal" characters in the adjacent
text let the browser handle natively
- if ( adjacentTextAfterMatch !== null &&
adjacentTextAfterMatch.length ) {
- return;
- }
- }
-
- ve.log('handleDelete programatically');
- e.preventDefault();
- this.surfaceObserver.stop();
-
- if (
- // Source and target are the same node
- sourceNode === targetNode ||
- (
- // Source and target have the same parent (list
items)
- sourceSplitableNode !== undefined &&
- sourceSplitableNode.getParent() ===
targetSplitableNode.getParent()
- )
- ) {
- // Simple removal
- tx = ve.dm.Transaction.newFromRemoval(
- this.documentView.model, new ve.Range(
targetOffset, sourceOffset )
- );
- this.model.change( tx, new ve.Range( cursorAt ) );
- } else if ( sourceNode.getType() === 'document' ) {
- // Source is a slug - move the cursor somewhere useful
- this.model.change( null, new ve.Range( cursorAt ) );
- } else {
- // Source and target are different nodes or do not
share a parent, perform tricky merge
- // Get the data for the source node
- sourceData = this.documentView.model.getData(
sourceNode.model.getRange() );
-
- // Find the node that should be completely removed
- nodeToDelete = sourceNode;
- nodeToDelete.traverseUpstream( function ( node ) {
- if ( node.getParent().children.length === 1 ) {
- nodeToDelete = node.getParent();
- return true;
- } else {
- return false;
- }
- } );
-
- this.model.change(
- [
- // Remove source node or source node
ancestor
- ve.dm.Transaction.newFromRemoval(
- this.documentView.model,
nodeToDelete.getModel().getOuterRange()
- ),
- // Append source data to target
- ve.dm.Transaction.newFromInsertion(
- this.documentView.model,
targetOffset, sourceData
- )
- ],
- new ve.Range( cursorAt )
- );
- }
- } else {
- // Selection removal
- ve.log('selection removal - handle programatically');
- e.preventDefault();
+ } );
this.model.change(
- ve.dm.Transaction.newFromRemoval(
this.documentView.model, selection ),
- new ve.Range( selection.start )
+ [
+ ve.dm.Transaction.newFromRemoval(
+ this.documentView.model,
nodeToDelete.getModel().getOuterRange()
+ ),
+ ve.dm.Transaction.newFromInsertion(
+ this.documentView.model,
rangeToRemove.start, endNodeData
+ )
+ ]
);
}
-
+ this.model.change( null, new ve.Range( rangeToRemove.start ) );
this.surfaceObserver.clear();
- this.surfaceObserver.start();
};
/**
diff --git a/modules/ve/dm/ve.dm.Surface.js b/modules/ve/dm/ve.dm.Surface.js
index 9b3f779..bb71756 100644
--- a/modules/ve/dm/ve.dm.Surface.js
+++ b/modules/ve/dm/ve.dm.Surface.js
@@ -315,6 +315,11 @@
this.truncateUndoStack();
this.smallStack.push( transactions[i] );
this.documentModel.commit( transactions[i] );
+ if ( !selection ) {
+ // translateRange only if selection is
not provided because otherwise we are
+ // going to overwrite it
+ this.selection =
transactions[i].translateRange( this.selection );
+ }
}
}
}
--
To view, visit https://gerrit.wikimedia.org/r/68332
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: Ic68f80d92d32169ff60258b81a438e342b136128
Gerrit-PatchSet: 6
Gerrit-Project: mediawiki/extensions/VisualEditor
Gerrit-Branch: master
Gerrit-Owner: Inez <[email protected]>
Gerrit-Reviewer: Catrope <[email protected]>
Gerrit-Reviewer: Trevor Parscal <[email protected]>
Gerrit-Reviewer: jenkins-bot
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits