mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/VisualEditor
synced 2024-11-12 09:09:25 +00:00
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
This commit is contained in:
parent
3e1e544e48
commit
fc8c46dd74
|
@ -55,14 +55,14 @@ $messages['en'] = array(
|
|||
'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 @@ See also:
|
|||
{{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}}',
|
||||
|
|
|
@ -585,20 +585,21 @@ $wgResourceModules += array(
|
|||
'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(
|
||||
|
|
|
@ -129,7 +129,7 @@ ve.ce.MWReferenceListNode.prototype.update = function () {
|
|||
// 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
|
||||
|
|
|
@ -245,7 +245,8 @@ ve.ce.ResizableNode.prototype.onDocumentMouseUp = function () {
|
|||
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 @@ ve.ce.ResizableNode.prototype.onDocumentMouseUp = function () {
|
|||
|
||||
// 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 @@ ve.ce.ResizableNode.prototype.onDocumentMouseUp = function () {
|
|||
|
||||
// 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' );
|
||||
|
|
|
@ -110,6 +110,19 @@ ve.dm.MWReferenceNode.static.toDomElements = function ( dataElement, doc, conver
|
|||
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 @@ ve.dm.MWReferenceNode.prototype.getInternalItem = function () {
|
|||
* @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 @@ ve.dm.MWReferenceNode.prototype.onRoot = function () {
|
|||
};
|
||||
|
||||
/**
|
||||
* 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,
|
||||
|
|
|
@ -401,7 +401,7 @@ ve.dm.SurfaceFragment.prototype.getCoveredNodes = function () {
|
|||
if ( !this.surface ) {
|
||||
return [];
|
||||
}
|
||||
return this.document.selectNodes( this.getRange(), 'coveredNodes' );
|
||||
return this.document.selectNodes( this.getRange(), 'covered' );
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -449,6 +449,48 @@ ve.dm.SurfaceFragment.prototype.select = function () {
|
|||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
|
|
|
@ -179,20 +179,21 @@ ve.dm.Transaction.newFromNodeReplacement = function ( doc, nodeOrRange, newData
|
|||
};
|
||||
|
||||
/**
|
||||
* 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 @@ ve.dm.Transaction.newFromAttributeChange = function ( doc, offset, key, value )
|
|||
// 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;
|
||||
|
|
|
@ -261,4 +261,4 @@ QUnit.test( 'getItemInsertion', 4, function ( assert ) {
|
|||
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' );
|
||||
} );
|
||||
} );
|
||||
|
|
|
@ -224,6 +224,18 @@ QUnit.test( 'insertContent', 4, function ( assert ) {
|
|||
);
|
||||
} );
|
||||
|
||||
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(),
|
||||
|
|
|
@ -689,12 +689,11 @@ QUnit.test( 'newFromNodeReplacement', function ( assert ) {
|
|||
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 @@ QUnit.test( 'newFromAttributeChange', function ( assert ) {
|
|||
]
|
||||
},
|
||||
'middle element': {
|
||||
'args': [doc, 17, 'style', 'number'],
|
||||
'args': [doc, 17, { 'style': 'number'} ],
|
||||
'ops': [
|
||||
{ 'type': 'retain', 'length': 17 },
|
||||
{
|
||||
|
@ -718,17 +717,36 @@ QUnit.test( 'newFromAttributeChange', function ( assert ) {
|
|||
{ '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 ) {
|
||||
|
|
|
@ -56,8 +56,8 @@ ve.ui.ListAction.prototype.wrap = function ( style ) {
|
|||
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
|
||||
);
|
||||
|
|
|
@ -106,7 +106,7 @@ ve.ui.MWReferenceDialog.prototype.initialize = function () {
|
|||
* @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 @@ ve.ui.MWReferenceDialog.prototype.onOpen = function () {
|
|||
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 @@ ve.ui.MWReferenceDialog.prototype.onOpen = function () {
|
|||
];
|
||||
}
|
||||
|
||||
// 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 @@ ve.ui.MWReferenceDialog.prototype.onOpen = function () {
|
|||
* @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 @@ ve.ui.MWReferenceDialog.prototype.onClose = function ( action ) {
|
|||
// 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' }
|
||||
|
|
Loading…
Reference in a new issue