jenkins-bot has submitted this change and it was merged.
Change subject: Reference name and group editing
......................................................................
Reference name and group editing
Objective:
* Allow editing reference groups and names in the reference dialog
Bonus:
* Modify attribute transaction builder to support multiple attribute
changes in a single transaction
Changes:
ve.ui.MWReferenceDialog.js
* Load ref name and group from model
* Save ref name and group, if changed, to model
ve.ui.ListAction.js, ve.ui.Transaction.test.js, ve.ce.ResizableNode.js
* Update use of newFromAttributeChange to newFromAttributeChanges
ve.dm.SurfaceFragment.test.js
* Add test for new changeAttributes method
ve.dm.InternalList.js
* Missing new line at end of file
ve.dm.Transaction.js
* Change newFromAttributeChange to accept an list of attribute changes and
produce a single transaction that applies one or more attribute changes
at once
ve.dm.SurfaceFragment.js
* Fix bug in getCoveredNodes where the wrong mode name was being used
* Add changeAttributes method, which applies attributes to all covered
nodes and allows filtering of which types of nodes the attributes are
applied to
ve.dm.MWReferenceNode.js
* Actually write key and group back to DOM
* Separate onRoot functionality into addToInternalList so it can be called
separately (similarly onUnroot/removeFromInternalList)
ve.ce.MWReferenceListNode.js
* Clone internal item CE node before appending to avoid rendering bug.
*.php
* Add links to messages and sort them
Change-Id: Ic4121e4fcfc09265d5863af6f078cdeb77926c8e
---
M VisualEditor.i18n.php
M VisualEditor.php
M modules/ve/ce/nodes/ve.ce.MWReferenceListNode.js
M modules/ve/ce/ve.ce.ResizableNode.js
M modules/ve/dm/nodes/ve.dm.MWReferenceNode.js
M modules/ve/dm/ve.dm.SurfaceFragment.js
M modules/ve/dm/ve.dm.Transaction.js
M modules/ve/test/dm/ve.dm.InternalList.test.js
M modules/ve/test/dm/ve.dm.SurfaceFragment.test.js
M modules/ve/test/dm/ve.dm.Transaction.test.js
M modules/ve/ui/actions/ve.ui.ListAction.js
M modules/ve/ui/dialogs/ve.ui.MWReferenceDialog.js
12 files changed, 219 insertions(+), 77 deletions(-)
Approvals:
Catrope: Looks good to me, approved
jenkins-bot: Verified
diff --git a/VisualEditor.i18n.php b/VisualEditor.i18n.php
index ee73510..2bace7b 100644
--- a/VisualEditor.i18n.php
+++ b/VisualEditor.i18n.php
@@ -55,14 +55,14 @@
'visualeditor-dialog-reference-options-group-label' => 'Use this group',
'visualeditor-dialog-reference-title' => 'Reference',
'visualeditor-dialog-media-title' => 'Media settings',
- 'visualeditor-dialog-transclusion-title' => 'Transclusion',
+ 'visualeditor-dialog-transclusion-add-param' => 'Add parameter',
'visualeditor-dialog-transclusion-content' => 'Content',
'visualeditor-dialog-transclusion-options' => 'Options',
- 'visualeditor-dialog-transclusion-remove-content' => 'Remove content',
- 'visualeditor-dialog-transclusion-remove-template' => 'Remove template',
- 'visualeditor-dialog-transclusion-remove-param' => 'Remove parameter',
- 'visualeditor-dialog-transclusion-add-param' => 'Add parameter',
'visualeditor-dialog-transclusion-param-name' => 'Parameter name',
+ 'visualeditor-dialog-transclusion-remove-content' => 'Remove content',
+ 'visualeditor-dialog-transclusion-remove-param' => 'Remove parameter',
+ 'visualeditor-dialog-transclusion-remove-template' => 'Remove template',
+ 'visualeditor-dialog-transclusion-title' => 'Transclusion',
'visualeditor-dialogbutton-media-tooltip' => 'Media',
'visualeditor-dialogbutton-meta-tooltip' => 'Page settings',
'visualeditor-dialogbutton-reference-tooltip' => 'Reference',
@@ -220,20 +220,24 @@
{{Identical|Language}}',
'visualeditor-dialog-meta-title' => 'MetaData dialog title text.
{{Identical|Page settings}}',
+ 'visualeditor-dialog-reference-content-section' => 'Label for the
reference content sub-section',
+ 'visualeditor-dialog-reference-options-section' => 'Label for the
reference options sub-section',
+ 'visualeditor-dialog-reference-options-name-label' => 'Label for the
reference name input',
+ 'visualeditor-dialog-reference-options-group-label' => 'Label for the
reference group input',
'visualeditor-dialog-reference-title' => '{{Identical|Reference}}',
- 'visualeditor-dialog-transclusion-title' =>
'{{Identical|Transclusion}}',
+ 'visualeditor-dialog-transclusion-add-param' => 'Label for button that
adds parameter a parameter to a template.
+{{Identical|Add parameter}}',
'visualeditor-dialog-transclusion-content' => 'Label for editor of
content between transclusion parts.
{{Identical|Content}}',
'visualeditor-dialog-transclusion-options' => 'Label for section with
options for templates, content or parameters.
{{Identical|Options}}',
- 'visualeditor-dialog-transclusion-remove-content' => 'Label for button
that removes content between transclusion parts',
- 'visualeditor-dialog-transclusion-remove-template' => 'Label for button
that removes a template from a transclusion.
-{{Identical|Remove template}}',
- 'visualeditor-dialog-transclusion-remove-param' => 'Label for button
that removes a parameter from a template',
- 'visualeditor-dialog-transclusion-add-param' => 'Label for button that
adds parameter a parameter to a template.
-{{Identical|Add parameter}}',
'visualeditor-dialog-transclusion-param-name' => 'Placeholder text
label for an input for adding a parameter to a template.
{{Identical|Parameter name}}',
+ 'visualeditor-dialog-transclusion-remove-content' => 'Label for button
that removes content between transclusion parts',
+ 'visualeditor-dialog-transclusion-remove-param' => 'Label for button
that removes a parameter from a template',
+ 'visualeditor-dialog-transclusion-remove-template' => 'Label for button
that removes a template from a transclusion.
+{{Identical|Remove template}}',
+ 'visualeditor-dialog-transclusion-title' =>
'{{Identical|Transclusion}}',
'visualeditor-dialogbutton-media-tooltip' => '{{Identical|Media}}',
'visualeditor-dialogbutton-meta-tooltip' => '{{Identical|Page
Settings}}',
'visualeditor-dialogbutton-reference-tooltip' =>
'{{Identical|Reference}}',
diff --git a/VisualEditor.php b/VisualEditor.php
index 2f01f88..b3bcfd6 100644
--- a/VisualEditor.php
+++ b/VisualEditor.php
@@ -585,20 +585,21 @@
'messages' => array(
// VE messages needed by code that is only in
experimental mode
'visualeditor-dialog-reference-content-section',
- 'visualeditor-dialog-reference-options-section',
- 'visualeditor-dialog-reference-options-name-label',
'visualeditor-dialog-reference-options-group-label',
+ 'visualeditor-dialog-reference-options-name-label',
+ 'visualeditor-dialog-reference-options-section',
'visualeditor-dialog-reference-title',
- 'visualeditor-dialog-transclusion-title',
- 'visualeditor-dialogbutton-reference-tooltip',
- 'visualeditor-dialogbutton-transclusion-tooltip',
+ 'visualeditor-dialog-transclusion-add-param',
'visualeditor-dialog-transclusion-content',
'visualeditor-dialog-transclusion-options',
- 'visualeditor-dialog-transclusion-remove-content',
- 'visualeditor-dialog-transclusion-remove-template',
- 'visualeditor-dialog-transclusion-remove-param',
- 'visualeditor-dialog-transclusion-add-param',
'visualeditor-dialog-transclusion-param-name',
+ 'visualeditor-dialog-transclusion-remove-content',
+ 'visualeditor-dialog-transclusion-remove-param',
+ 'visualeditor-dialog-transclusion-remove-template',
+ 'visualeditor-dialog-transclusion-title',
+ 'visualeditor-dialog-transclusion-wikitext-label',
+ 'visualeditor-dialogbutton-reference-tooltip',
+ 'visualeditor-dialogbutton-transclusion-tooltip',
),
),
'ext.visualEditor.icons-raster' => $wgVisualEditorResourceTemplate +
array(
diff --git a/modules/ve/ce/nodes/ve.ce.MWReferenceListNode.js
b/modules/ve/ce/nodes/ve.ce.MWReferenceListNode.js
index 0a165e4..f8ab16b 100644
--- a/modules/ve/ce/nodes/ve.ce.MWReferenceListNode.js
+++ b/modules/ve/ce/nodes/ve.ce.MWReferenceListNode.js
@@ -129,7 +129,7 @@
// HACK: ProtectedNode crashes when dealing with an
unattached node
this.attachedItems.push( itemNode );
itemNode.attach( this );
- $li.append( $( '<span class="reference-text">' ).html(
itemNode.$.show() ) );
+ $li.append( $( '<span class="reference-text">' ).html(
itemNode.$.clone().show() ) );
this.$reflist.append( $li );
}
} // TODO: Show a placeholder for an empty reference list in the 'else'
section
diff --git a/modules/ve/ce/ve.ce.ResizableNode.js
b/modules/ve/ce/ve.ce.ResizableNode.js
index 771b4ad..36bb9a5 100644
--- a/modules/ve/ce/ve.ce.ResizableNode.js
+++ b/modules/ve/ce/ve.ce.ResizableNode.js
@@ -245,7 +245,8 @@
height = this.$resizeHandles.outerHeight(),
surfaceModel = this.getRoot().getSurface().getModel(),
documentModel = surfaceModel.getDocument(),
- selection = surfaceModel.getSelection();
+ selection = surfaceModel.getSelection(),
+ attrChanges = {};
this.$resizeHandles.removeClass( 've-ce-resizableNode-handles-resizing'
);
$( this.getElementDocument() ).off( '.ve-ce-resizableNode' );
@@ -259,8 +260,6 @@
// Allow resize to occur before re-rendering
setTimeout( ve.bind( function () {
- var txs = [];
-
if ( transition ) {
// Prevent further transitioning
this.$resizable.removeClass(
've-ce-resizableNode-transitioning' );
@@ -268,17 +267,16 @@
// Apply changes to the model
if ( this.model.getAttribute( 'width' ) !== width ) {
- txs.push( ve.dm.Transaction.newFromAttributeChange(
- documentModel, offset, 'width', width
- ) );
+ attrChanges.width = width;
}
if ( this.model.getAttribute( 'height' ) !== height ) {
- txs.push( ve.dm.Transaction.newFromAttributeChange(
- documentModel, offset, 'height', height
- ) );
+ attrChanges.height = height;
}
- if ( txs.length > 0 ) {
- surfaceModel.change( txs, selection );
+ if ( !ve.isEmptyObject( attrChanges ) ) {
+ surfaceModel.change(
+ ve.dm.Transaction.newFromAttributeChanges(
documentModel, offset, attrChanges ),
+ selection
+ );
}
this.emit( 'resize' );
diff --git a/modules/ve/dm/nodes/ve.dm.MWReferenceNode.js
b/modules/ve/dm/nodes/ve.dm.MWReferenceNode.js
index 0a16b8e..2423a1a 100644
--- a/modules/ve/dm/nodes/ve.dm.MWReferenceNode.js
+++ b/modules/ve/dm/nodes/ve.dm.MWReferenceNode.js
@@ -110,6 +110,19 @@
ve.setProp( mwAttr, 'body', 'html', itemNodeHtml );
}
+ // Set or clear key
+ if ( dataElement.attributes.listKey !== null ) {
+ ve.setProp( mwAttr, 'attrs', 'name',
dataElement.attributes.listKey );
+ } else if ( mwAttr.attrs ) {
+ delete mwAttr.attrs.listKey;
+ }
+ // Set or clear group
+ if ( dataElement.attributes.refGroup !== '' ) {
+ ve.setProp( mwAttr, 'attrs', 'group',
dataElement.attributes.refGroup );
+ } else if ( mwAttr.attrs ) {
+ delete mwAttr.attrs.refGroup;
+ }
+
span.setAttribute( 'data-mw', JSON.stringify( mwAttr ) );
return [ span ];
@@ -135,6 +148,22 @@
* @method
*/
ve.dm.MWReferenceNode.prototype.onRoot = function () {
+ this.addToInternalList();
+};
+
+/**
+ * Handle the node being detatched from the root
+ * @method
+ */
+ve.dm.MWReferenceNode.prototype.onUnroot = function () {
+ this.removeFromInternalList();
+};
+
+/**
+ * Register the node with the internal list
+ * @method
+ */
+ve.dm.MWReferenceNode.prototype.addToInternalList = function () {
if ( this.getRoot() === this.getDocument().getDocumentNode() ) {
this.getDocument().getInternalList().addNode(
this.element.attributes.listGroup,
@@ -146,10 +175,10 @@
};
/**
- * Handle the node being detatched from the root
+ * Unregister the node from the internal list
* @method
*/
-ve.dm.MWReferenceNode.prototype.onUnroot = function () {
+ve.dm.MWReferenceNode.prototype.removeFromInternalList = function () {
this.getDocument().getInternalList().removeNode(
this.element.attributes.listGroup,
this.element.attributes.listKey,
diff --git a/modules/ve/dm/ve.dm.SurfaceFragment.js
b/modules/ve/dm/ve.dm.SurfaceFragment.js
index d672789..f38fdec 100644
--- a/modules/ve/dm/ve.dm.SurfaceFragment.js
+++ b/modules/ve/dm/ve.dm.SurfaceFragment.js
@@ -401,7 +401,7 @@
if ( !this.surface ) {
return [];
}
- return this.document.selectNodes( this.getRange(), 'coveredNodes' );
+ return this.document.selectNodes( this.getRange(), 'covered' );
};
/**
@@ -450,6 +450,48 @@
};
/**
+ * Change one or more attributes on covered nodes.
+ *
+ * @method
+ * @param {Object} attr List of attributes to change, use undefined to remove
an attribute
+ * @param {string} [type] Node type to restrict changes to
+ * @chainable
+ */
+ve.dm.SurfaceFragment.prototype.changeAttributes = function ( attr, type ) {
+ // Handle null fragment
+ if ( !this.surface ) {
+ return this;
+ }
+
+ var i, len, result,
+ txs = [],
+ covered = this.getCoveredNodes();
+
+ for ( i = 0, len = covered.length; i < len; i++ ) {
+ result = covered[i];
+ if (
+ // Non-wrapped nodes have no attributes
+ !result.node.isWrapped() ||
+ // Filtering by node type
+ ( type && result.node.getType() !== type ) ||
+ // Ignore zero-length results
+ ( result.range && result.range.isCollapsed() )
+ ) {
+ continue;
+ }
+ txs.push(
+ ve.dm.Transaction.newFromAttributeChanges(
+ this.document, result.nodeOuterRange.start, attr
+ )
+ );
+ }
+ if ( txs.length ) {
+ this.surface.change( txs );
+ }
+ return this;
+};
+
+/**
* Apply an annotation to content in the fragment.
*
* To avoid problems identified in bug 33108, use the
{ve.dm.SurfaceFragment.trimRange} method.
diff --git a/modules/ve/dm/ve.dm.Transaction.js
b/modules/ve/dm/ve.dm.Transaction.js
index e8e5dbe..3f64305 100644
--- a/modules/ve/dm/ve.dm.Transaction.js
+++ b/modules/ve/dm/ve.dm.Transaction.js
@@ -179,20 +179,21 @@
};
/**
- * Generate a transaction that changes an attribute.
+ * Generate a transaction that changes one or more attributes.
*
* @static
* @method
* @param {ve.dm.Document} doc Document to create transaction for
* @param {number} offset Offset of element
- * @param {string} key Attribute name
- * @param {Mixed} value New value, or undefined to remove the attribute
+ * @param {Object.<string,Mixed>} attr List of attribute key and value pairs,
use undefined value
+ * to remove an attribute
* @returns {ve.dm.Transaction} Transaction that changes an element
* @throws {Error} Cannot set attributes to non-element data
* @throws {Error} Cannot set attributes on closing element
*/
-ve.dm.Transaction.newFromAttributeChange = function ( doc, offset, key, value
) {
- var tx = new ve.dm.Transaction(),
+ve.dm.Transaction.newFromAttributeChanges = function ( doc, offset, attr ) {
+ var key,
+ tx = new ve.dm.Transaction(),
data = doc.getData();
// Verify element exists at offset
if ( data[offset].type === undefined ) {
@@ -205,9 +206,11 @@
// Retain up to element
tx.pushRetain( offset );
// Change attribute
- tx.pushReplaceElementAttribute(
- key, 'attributes' in data[offset] ?
data[offset].attributes[key] : undefined, value
- );
+ for ( key in attr ) {
+ tx.pushReplaceElementAttribute(
+ key, 'attributes' in data[offset] ?
data[offset].attributes[key] : undefined, attr[key]
+ );
+ }
// Retain to end of document
tx.pushRetain( data.length - offset );
return tx;
diff --git a/modules/ve/test/dm/ve.dm.InternalList.test.js
b/modules/ve/test/dm/ve.dm.InternalList.test.js
index 59e11a5..959eeaa 100644
--- a/modules/ve/test/dm/ve.dm.InternalList.test.js
+++ b/modules/ve/test/dm/ve.dm.InternalList.test.js
@@ -261,4 +261,4 @@
insertion = internalList.getItemInsertion( 'mwReference/', 'foo', [] );
assert.equal( insertion.index, index, 'Insertion with duplicate key
reuses old index' );
assert.equal( insertion.transaction, null, 'Insertion with duplicate
key has null transaction' );
-} );
\ No newline at end of file
+} );
diff --git a/modules/ve/test/dm/ve.dm.SurfaceFragment.test.js
b/modules/ve/test/dm/ve.dm.SurfaceFragment.test.js
index 93b8c1b..f50c96f 100644
--- a/modules/ve/test/dm/ve.dm.SurfaceFragment.test.js
+++ b/modules/ve/test/dm/ve.dm.SurfaceFragment.test.js
@@ -224,6 +224,18 @@
);
} );
+QUnit.test( 'changeAttributes', 1, function ( assert ) {
+ var doc = ve.dm.example.createExampleDocument(),
+ surface = new ve.dm.Surface( doc ),
+ fragment = new ve.dm.SurfaceFragment( surface, new ve.Range( 0,
5 ) );
+ fragment.changeAttributes( { 'level': 3 } );
+ assert.deepEqual(
+ doc.getData( new ve.Range( 0, 1 ) ),
+ [ { 'type': 'heading', 'attributes': { 'level': 3 } } ],
+ 'changing attributes affects covered nodes'
+ );
+} );
+
QUnit.test( 'wrapNodes/unwrapNodes', 10, function ( assert ) {
var doc = ve.dm.example.createExampleDocument(),
originalDoc = ve.dm.example.createExampleDocument(),
diff --git a/modules/ve/test/dm/ve.dm.Transaction.test.js
b/modules/ve/test/dm/ve.dm.Transaction.test.js
index dabbc9d..63e2c6c 100644
--- a/modules/ve/test/dm/ve.dm.Transaction.test.js
+++ b/modules/ve/test/dm/ve.dm.Transaction.test.js
@@ -689,12 +689,11 @@
QUnit.expect( ve.getObjectKeys( cases ).length );
runConstructorTests( assert, ve.dm.Transaction.newFromNodeReplacement,
cases );
} );
-
-QUnit.test( 'newFromAttributeChange', function ( assert ) {
+QUnit.test( 'newFromAttributeChanges', function ( assert ) {
var doc = ve.dm.example.createExampleDocument(),
cases = {
'first element': {
- 'args': [doc, 0, 'level', 2],
+ 'args': [doc, 0, { 'level': 2 }],
'ops': [
{
'type': 'attribute',
@@ -706,7 +705,7 @@
]
},
'middle element': {
- 'args': [doc, 17, 'style', 'number'],
+ 'args': [doc, 17, { 'style': 'number'} ],
'ops': [
{ 'type': 'retain', 'length': 17 },
{
@@ -718,17 +717,36 @@
{ 'type': 'retain', 'length': 44 }
]
},
+ 'multiple attributes': {
+ 'args': [doc, 17, { 'style': 'number', 'level':
1 } ],
+ 'ops': [
+ { 'type': 'retain', 'length': 17 },
+ {
+ 'type': 'attribute',
+ 'key': 'style',
+ 'from': 'bullet',
+ 'to': 'number'
+ },
+ {
+ 'type': 'attribute',
+ 'key': 'level',
+ 'from': undefined,
+ 'to': 1
+ },
+ { 'type': 'retain', 'length': 44 }
+ ]
+ },
'non-element': {
- 'args': [doc, 1, 'level', 2],
+ 'args': [doc, 1, { 'level': 2 }],
'exception': Error
},
'closing element': {
- 'args': [doc, 4, 'level', 2],
+ 'args': [doc, 4, { 'level': 2 }],
'exception': Error
}
};
QUnit.expect( ve.getObjectKeys( cases ).length );
- runConstructorTests( assert, ve.dm.Transaction.newFromAttributeChange,
cases );
+ runConstructorTests( assert, ve.dm.Transaction.newFromAttributeChanges,
cases );
} );
QUnit.test( 'newFromAnnotation', function ( assert ) {
diff --git a/modules/ve/ui/actions/ve.ui.ListAction.js
b/modules/ve/ui/actions/ve.ui.ListAction.js
index f17d0f9..38b26d9 100644
--- a/modules/ve/ui/actions/ve.ui.ListAction.js
+++ b/modules/ve/ui/actions/ve.ui.ListAction.js
@@ -56,8 +56,8 @@
if ( group.grandparent !== previousList ) {
// Change the list style
surfaceModel.change(
-
ve.dm.Transaction.newFromAttributeChange(
- documentModel,
group.grandparent.getOffset(), 'style', style
+
ve.dm.Transaction.newFromAttributeChanges(
+ documentModel,
group.grandparent.getOffset(), { 'style': style }
),
selection
);
diff --git a/modules/ve/ui/dialogs/ve.ui.MWReferenceDialog.js
b/modules/ve/ui/dialogs/ve.ui.MWReferenceDialog.js
index e179f10..9d4cc07 100644
--- a/modules/ve/ui/dialogs/ve.ui.MWReferenceDialog.js
+++ b/modules/ve/ui/dialogs/ve.ui.MWReferenceDialog.js
@@ -106,7 +106,7 @@
* @method
*/
ve.ui.MWReferenceDialog.prototype.onOpen = function () {
- var focusedNode, data,
+ var focusedNode, data, refGroup, listKey,
doc = this.surface.getModel().getDocument();
// Parent method
@@ -117,6 +117,8 @@
if ( focusedNode instanceof ve.ce.MWReferenceNode ) {
this.internalItem = focusedNode.getModel().getInternalItem();
data = doc.getData( this.internalItem.getRange(), true );
+ listKey = focusedNode.getModel().getAttribute( 'listKey' );
+ refGroup = focusedNode.getModel().getAttribute( 'refGroup' );
} else {
data = [
{ 'type': 'paragraph', 'internal': { 'generated':
'wrapper' } },
@@ -124,13 +126,14 @@
];
}
- // Properties
this.referenceSurface = new ve.ui.Surface(
new ve.dm.ElementLinearData( doc.getStore(), data ), { '$$':
this.frame.$$ }
);
this.referenceToolbar = new ve.ui.Toolbar( this.referenceSurface, {
'$$': this.frame.$$ } );
// Initialization
+ this.nameInput.setValue( listKey );
+ this.groupInput.setValue( refGroup );
this.referenceToolbar.$.addClass( 've-ui-mwReferenceDialog-toolbar' );
this.contentFieldset.$.append( this.referenceToolbar.$,
this.referenceSurface.$ );
this.referenceToolbar.addTools( this.constructor.static.toolbarTools );
@@ -146,8 +149,9 @@
* @param {string} action Action that caused the window to be closed
*/
ve.ui.MWReferenceDialog.prototype.onClose = function ( action ) {
- var data, doc, groupName, key, newItem,
- txs = [];
+ var data, doc, listIndex, listGroup, listKey, refGroup, newItem,
refNode, oldListGroup,
+ oldListKey, oldNodes, internalList, attrChanges,
+ surfaceModel = this.surface.getModel();
// Parent method
ve.ui.Dialog.prototype.onOpen.call( this );
@@ -155,32 +159,63 @@
// Save changes
if ( action === 'apply' ) {
data = this.referenceSurface.getModel().getDocument().getData();
- doc = this.surface.getModel().getDocument();
+ doc = surfaceModel.getDocument();
+ listKey = this.nameInput.getValue() !== '' ?
this.nameInput.getValue() : null;
+ refGroup = this.groupInput.getValue();
+ listGroup = 'mwReference/' + refGroup;
if ( this.internalItem ) {
- txs.push(
- ve.dm.Transaction.newFromNodeReplacement(
- doc, this.internalItem.getRange(), data
- )
- );
- this.surface.getModel().change( txs );
- } else {
- // TODO: pass in group and key from UI if they exist
- groupName = '';
- key = null;
- newItem = doc.getInternalList().getItemInsertion(
groupName, key, data );
- if ( newItem.transaction ) {
- txs.push( newItem.transaction );
+ // Edit reference: handle various replacement cases
+ refNode =
this.surface.getView().getFocusedNode().getModel();
+ oldListGroup = refNode.getAttribute( 'listGroup' );
+ oldListKey = refNode.getAttribute( 'listKey' );
+ // Group/key has changed
+ if ( listGroup !== oldListGroup || listKey !==
oldListKey ) {
+ internalList = doc.getInternalList();
+ oldNodes = internalList.getNodeGroup(
oldListGroup ).keyedNodes[oldListKey] || [];
+ listIndex = internalList.getKeyIndex(
listGroup, listKey );
+ attrChanges = {};
+ if ( listIndex !== undefined ) {
+ // If the new key exists, reuse its
internal node
+ attrChanges.listIndex = listIndex;
+ } else if ( oldNodes.length > 1 ) {
+ // If the old internal node was being
shared, create a new one
+ newItem =
internalList.getItemInsertion( listGroup, listKey, data );
+ attrChanges.listIndex = newItem.index;
+ }
+ attrChanges.listGroup = listGroup;
+ attrChanges.listKey = listKey;
+ attrChanges.refGroup = refGroup;
+
+ // Manually re-register the node before and
after change
+ refNode.removeFromInternalList();
+ surfaceModel.change(
+
ve.dm.Transaction.newFromAttributeChanges(
+ doc,
refNode.getOuterRange().start, attrChanges
+ )
+ );
+ refNode.addToInternalList();
}
- this.surface.getModel().change( txs );
-
this.surface.getModel().getFragment().collapseRangeToEnd().insertContent( [
+ // Process the internal node create/edit transaction
+ if ( !newItem ) {
+ surfaceModel.change(
+
ve.dm.Transaction.newFromNodeReplacement( doc, this.internalItem, data )
+ );
+ } else {
+ surfaceModel.change( newItem.transaction );
+ }
+ } else {
+ // Create reference: just create new nodes
+ newItem = doc.getInternalList().getItemInsertion(
listGroup, listKey, data );
+ surfaceModel.change( newItem.transaction );
+
surfaceModel.getFragment().collapseRangeToEnd().insertContent( [
{
'type': 'mwReference',
'attributes': {
'mw': { 'name': 'ref' },
'listIndex': newItem.index,
- 'listGroup': 'mwReference/' +
groupName,
- 'listKey': key,
- 'refGroup': groupName
+ 'listGroup': listGroup,
+ 'listKey': listKey,
+ 'refGroup': refGroup
}
},
{ 'type': '/mwReference' }
--
To view, visit https://gerrit.wikimedia.org/r/67466
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: Ic4121e4fcfc09265d5863af6f078cdeb77926c8e
Gerrit-PatchSet: 22
Gerrit-Project: mediawiki/extensions/VisualEditor
Gerrit-Branch: master
Gerrit-Owner: Trevor Parscal <[email protected]>
Gerrit-Reviewer: Catrope <[email protected]>
Gerrit-Reviewer: Esanders <[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