Trevor Parscal has uploaded a new change for review.
https://gerrit.wikimedia.org/r/197987
Change subject: [BREAKING CHANGE] Emit rerender for dead nodes
......................................................................
[BREAKING CHANGE] Emit rerender for dead nodes
ve.ce.GeneratedContentNode was only emitting rerender when live, but in some
cases we need this event even if the node is not live.
Specifically, we need this for rendering ve.ce.Nodes outside of the ce tree,
such as in ContextItems.
Breaking changes:
* Changing ve.ce.GeneratedContentNode to emit the 'rerender' event always means
it's upon the subscriber of the event to pay attention to whether the node is
live or not. Changes to ve.ce.FocusableNode and ve.ce.ResizableNode have been
made to deal with that.
Bonus:
* ve.ce.ResizableNode now caches its reference to this.root.getSurface(), the
same way that ve.ce.FocusableNode does
* The surface references and 'isSetup' states of both ve.ce.ResizableNode and
ve.ce.FocusableNode are now named more specifically to avoid conflicts and
shadowing.
* ve.BranchNode now has a static traverse utility function that does simple
depth-first recursive traversal over a branch node.
Bug: T91314
Change-Id: I2b95d068e0d6f1d293d95dc18ac5b4c7da0d3214
---
M src/ce/nodes/ve.ce.GeneratedContentNode.js
M src/ce/ve.ce.FocusableNode.js
M src/ce/ve.ce.ResizableNode.js
M src/ve.BranchNode.js
4 files changed, 82 insertions(+), 36 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor
refs/changes/87/197987/1
diff --git a/src/ce/nodes/ve.ce.GeneratedContentNode.js
b/src/ce/nodes/ve.ce.GeneratedContentNode.js
index a03ea44..bdcc7b8 100644
--- a/src/ce/nodes/ve.ce.GeneratedContentNode.js
+++ b/src/ce/nodes/ve.ce.GeneratedContentNode.js
@@ -175,8 +175,9 @@
if ( this.live ) {
this.emit( 'setup' );
- this.afterRender();
}
+
+ this.afterRender();
};
/**
diff --git a/src/ce/ve.ce.FocusableNode.js b/src/ce/ve.ce.FocusableNode.js
index 42d857c..f627897 100644
--- a/src/ce/ve.ce.FocusableNode.js
+++ b/src/ce/ve.ce.FocusableNode.js
@@ -27,10 +27,10 @@
// Properties
this.focused = false;
this.highlighted = false;
- this.isSetup = false;
+ this.isFocusableSetup = false;
this.$highlights = this.$( '<div>' ).addClass(
've-ce-focusableNode-highlights' );
this.$focusable = $focusable || this.$element;
- this.surface = null;
+ this.focusableSurface = null;
this.rects = null;
this.boundingRect = null;
this.startAndEndRects = null;
@@ -95,11 +95,11 @@
*/
ve.ce.FocusableNode.prototype.onFocusableSetup = function () {
// Exit if already setup or not attached
- if ( this.isSetup || !this.root ) {
+ if ( this.isFocusableSetup || !this.root ) {
return;
}
- this.surface = this.getRoot().getSurface();
+ this.focusableSurface = this.root.getSurface();
// DOM changes (duplicated from constructor in case this.$element is
replaced)
this.$element
@@ -121,7 +121,7 @@
} );
}
- this.isSetup = true;
+ this.isFocusableSetup = true;
};
/**
@@ -131,7 +131,7 @@
*/
ve.ce.FocusableNode.prototype.onFocusableTeardown = function () {
// Exit if not setup or not attached
- if ( !this.isSetup || !this.root ) {
+ if ( !this.isFocusableSetup || !this.root ) {
return;
}
@@ -147,8 +147,8 @@
.removeClass( 've-ce-focusableNode' )
.removeProp( 'contentEditable' );
- this.isSetup = false;
- this.surface = null;
+ this.focusableSurface = null;
+ this.isFocusableSetup = false;
};
/**
@@ -159,7 +159,7 @@
*/
ve.ce.FocusableNode.prototype.onFocusableMouseDown = function ( e ) {
var range,
- surfaceModel = this.surface.getModel(),
+ surfaceModel = this.focusableSurface.getModel(),
selection = surfaceModel.getSelection(),
nodeRange = this.model.getOuterRange();
@@ -203,7 +203,7 @@
}
var command = ve.ui.commandRegistry.getCommandForNode( this );
if ( command ) {
- command.execute( this.surface.getSurface() );
+ command.execute( this.focusableSurface.getSurface() );
}
};
@@ -214,9 +214,9 @@
* @param {jQuery.Event} e Drag start event
*/
ve.ce.FocusableNode.prototype.onFocusableDragStart = function () {
- if ( this.surface ) {
+ if ( this.focusableSurface ) {
// Allow dragging this node in the surface
- this.surface.startRelocation( this );
+ this.focusableSurface.startRelocation( this );
}
this.$highlights.addClass( 've-ce-focusableNode-highlights-relocating'
);
};
@@ -232,8 +232,8 @@
ve.ce.FocusableNode.prototype.onFocusableDragEnd = function () {
// endRelocation is usually triggered by onDocumentDrop in the surface,
but if it isn't
// trigger it here instead
- if ( this.surface ) {
- this.surface.endRelocation();
+ if ( this.focusableSurface ) {
+ this.focusableSurface.endRelocation();
}
this.$highlights.removeClass(
've-ce-focusableNode-highlights-relocating' );
};
@@ -302,10 +302,10 @@
* @method
*/
ve.ce.FocusableNode.prototype.onFocusableRerender = function () {
- if ( this.focused ) {
+ if ( this.focused && this.focusableSurface ) {
this.redrawHighlights();
// reposition menu
- this.surface.getSurface().getContext().updateDimensions( true );
+
this.focusableSurface.getSurface().getContext().updateDimensions( true );
}
};
@@ -335,8 +335,8 @@
this.emit( 'focus' );
this.$element.addClass( 've-ce-focusableNode-focused' );
this.createHighlights();
- this.surface.appendHighlights( this.$highlights,
this.focused );
- this.surface.$element.off( '.ve-ce-focusableNode' );
+ this.focusableSurface.appendHighlights(
this.$highlights, this.focused );
+ this.focusableSurface.$element.off(
'.ve-ce-focusableNode' );
} else {
this.emit( 'blur' );
this.$element.removeClass(
've-ce-focusableNode-focused' );
@@ -364,16 +364,16 @@
this.positionHighlights();
- this.surface.appendHighlights( this.$highlights, this.focused );
+ this.focusableSurface.appendHighlights( this.$highlights, this.focused
);
// Events
if ( !this.focused ) {
- this.surface.$element.on( {
+ this.focusableSurface.$element.on( {
'mousemove.ve-ce-focusableNode':
this.onSurfaceMouseMove.bind( this ),
'mouseout.ve-ce-focusableNode':
this.onSurfaceMouseOut.bind( this )
} );
}
- this.surface.connect( this, { position: 'positionHighlights' } );
+ this.focusableSurface.connect( this, { position: 'positionHighlights' }
);
};
/**
@@ -386,8 +386,8 @@
return;
}
this.$highlights.remove().empty();
- this.surface.$element.off( '.ve-ce-focusableNode' );
- this.surface.disconnect( this, { position: 'positionHighlights' } );
+ this.focusableSurface.$element.off( '.ve-ce-focusableNode' );
+ this.focusableSurface.disconnect( this, { position:
'positionHighlights' } );
this.highlighted = false;
this.boundingRect = null;
};
@@ -410,7 +410,7 @@
rects = [],
filteredRects = [],
webkitColumns = 'webkitColumnCount' in document.createElement(
'div' ).style,
- surfaceOffset =
this.surface.getSurface().getBoundingClientRect();
+ surfaceOffset =
this.focusableSurface.getSurface().getBoundingClientRect();
function contains( rect1, rect2 ) {
return rect2.left >= rect1.left &&
diff --git a/src/ce/ve.ce.ResizableNode.js b/src/ce/ve.ce.ResizableNode.js
index 33c3856..37b34c7 100644
--- a/src/ce/ve.ce.ResizableNode.js
+++ b/src/ce/ve.ce.ResizableNode.js
@@ -36,11 +36,13 @@
this.$sizeLabel = this.$( '<div>' ).addClass(
've-ce-resizableNode-sizeLabel' ).append( this.$sizeText );
}
this.resizableOffset = null;
+ this.resizableSurface = null;
// Events
this.connect( this, {
focus: 'onResizableFocus',
blur: 'onResizableBlur',
+ setup: 'onResizableSetup',
teardown: 'onResizableTeardown',
resizing: 'onResizableResizing',
resizeEnd: 'onResizableFocus',
@@ -97,7 +99,7 @@
ve.ce.ResizableNode.prototype.getResizableOffset = function () {
if ( !this.resizableOffset ) {
this.resizableOffset = OO.ui.Element.static.getRelativePosition(
- this.$resizable,
this.getRoot().getSurface().getSurface().$element
+ this.$resizable,
this.resizableSurface.getSurface().$element
);
}
return this.resizableOffset;
@@ -209,11 +211,9 @@
* @method
*/
ve.ce.ResizableNode.prototype.onResizableFocus = function () {
- var surface = this.getRoot().getSurface();
-
- this.$resizeHandles.appendTo( surface.getSurface().$controls );
+ this.$resizeHandles.appendTo(
this.resizableSurface.getSurface().$controls );
if ( this.$sizeLabel ) {
- this.$sizeLabel.appendTo( surface.getSurface().$controls );
+ this.$sizeLabel.appendTo(
this.resizableSurface.getSurface().$controls );
}
// Call getScalable to pre-fetch the extended data
@@ -241,7 +241,7 @@
this.onResizeHandlesCornerMouseDown.bind( this )
);
- surface.connect( this, { position: 'setResizableHandlesSizeAndPosition'
} );
+ this.resizableSurface.connect( this, { position:
'setResizableHandlesSizeAndPosition' } );
};
@@ -252,18 +252,16 @@
*/
ve.ce.ResizableNode.prototype.onResizableBlur = function () {
// Node may have already been torn down, e.g. after delete
- if ( !this.getRoot() ) {
+ if ( !this.root ) {
return;
}
-
- var surface = this.getRoot().getSurface();
this.$resizeHandles.detach();
if ( this.$sizeLabel ) {
this.$sizeLabel.detach();
}
- surface.disconnect( this, { position:
'setResizableHandlesSizeAndPosition' } );
+ this.resizableSurface.disconnect( this, { position:
'setResizableHandlesSizeAndPosition' } );
};
@@ -290,12 +288,34 @@
};
/**
+ * Handle setup event.
+ *
+ * @method
+ */
+ve.ce.ResizableNode.prototype.onResizableSetup = function () {
+ // Exit if already setup or not attached
+ if ( this.isResizableSetup || !this.root ) {
+ return;
+ }
+
+ this.resizableSurface = this.root.getSurface();
+ this.isResizableSetup = true;
+};
+
+/**
* Handle teardown event.
*
* @method
*/
ve.ce.ResizableNode.prototype.onResizableTeardown = function () {
+ // Exit if not setup or not attached
+ if ( !this.isResizableSetup || !this.root ) {
+ return;
+ }
+
this.onResizableBlur();
+ this.resizableSurface = null;
+ this.isResizableSetup = false;
};
/**
@@ -507,7 +527,7 @@
offset = this.model.getOffset(),
width = this.$resizeHandles.outerWidth(),
height = this.$resizeHandles.outerHeight(),
- surfaceModel = this.getRoot().getSurface().getModel(),
+ surfaceModel = this.resizableSurface.getModel(),
documentModel = surfaceModel.getDocument(),
selection = surfaceModel.getSelection();
diff --git a/src/ve.BranchNode.js b/src/ve.BranchNode.js
index 695075e..9ffbbfb 100644
--- a/src/ve.BranchNode.js
+++ b/src/ve.BranchNode.js
@@ -22,6 +22,31 @@
this.children = Array.isArray( children ) ? children : [];
};
+/* Setup */
+
+OO.initClass( ve.BranchNode );
+
+/* Static Methods */
+
+/**
+ * Traverse a branch node depth-first.
+ *
+ * @param {ve.BranchNode} node Branch node to traverse
+ * @param {Function} callback Callback to execute for each traversed node
+ * @param {ve.Node} callback.node Node being traversed
+ */
+ve.BranchNode.static.traverse = function ( node, callback ) {
+ var i, len,
+ children = node.getChildren();
+
+ for ( i = 0, len = children.length; i < len; i++ ) {
+ callback.call( this, children[i] );
+ if ( children[i] instanceof ve.ce.BranchNode ) {
+ this.traverse( children[i], callback );
+ }
+ }
+};
+
/* Methods */
/**
--
To view, visit https://gerrit.wikimedia.org/r/197987
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I2b95d068e0d6f1d293d95dc18ac5b4c7da0d3214
Gerrit-PatchSet: 1
Gerrit-Project: VisualEditor/VisualEditor
Gerrit-Branch: master
Gerrit-Owner: Trevor Parscal <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits