mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/Cite
synced 2024-11-15 10:59:56 +00:00
adc64b3002
This code was written in 2014 and it seems that some change to ve.ui.MWTemplateDialog since then made it not work. No idea why or when it broke. But we can implement the functionality much more easily now by overriding #setApplicableStatus, which works correctly. Bug: T210796 Change-Id: I6e87ca979a96785fc74f1a57f7d80ba4b43705f2
217 lines
6.1 KiB
JavaScript
217 lines
6.1 KiB
JavaScript
/*
|
|
* VisualEditor user interface MWCitationDialog class.
|
|
*
|
|
* @copyright 2011-2018 VisualEditor Team's Cite sub-team and others; see AUTHORS.txt
|
|
* @license MIT
|
|
*/
|
|
|
|
/**
|
|
* Dialog for inserting and editing MediaWiki citations.
|
|
*
|
|
* @class
|
|
* @extends ve.ui.MWTemplateDialog
|
|
*
|
|
* @constructor
|
|
* @param {Object} [config] Configuration options
|
|
*/
|
|
ve.ui.MWCitationDialog = function VeUiMWCitationDialog( config ) {
|
|
// Parent constructor
|
|
ve.ui.MWCitationDialog.super.call( this, config );
|
|
|
|
// Properties
|
|
this.referenceModel = null;
|
|
this.referenceNode = null;
|
|
this.inDialog = '';
|
|
};
|
|
|
|
/* Inheritance */
|
|
|
|
OO.inheritClass( ve.ui.MWCitationDialog, ve.ui.MWTemplateDialog );
|
|
|
|
/* Static Properties */
|
|
|
|
ve.ui.MWCitationDialog.static.name = 'citation';
|
|
|
|
/* Methods */
|
|
|
|
/**
|
|
* Get the reference node to be edited.
|
|
*
|
|
* @return {ve.dm.MWReferenceNode|null} Reference node to be edited, null if none exists
|
|
*/
|
|
ve.ui.MWCitationDialog.prototype.getReferenceNode = function () {
|
|
var selectedNode = this.getFragment().getSelectedNode();
|
|
|
|
if ( selectedNode instanceof ve.dm.MWReferenceNode ) {
|
|
return selectedNode;
|
|
}
|
|
|
|
return null;
|
|
};
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
ve.ui.MWCitationDialog.prototype.getSelectedNode = function () {
|
|
var branches, leaves, transclusionNode,
|
|
referenceNode = this.getReferenceNode();
|
|
|
|
if ( referenceNode ) {
|
|
branches = referenceNode.getInternalItem().getChildren();
|
|
leaves = branches &&
|
|
branches.length === 1 &&
|
|
branches[ 0 ].canContainContent() &&
|
|
branches[ 0 ].getChildren();
|
|
transclusionNode = leaves &&
|
|
leaves.length === 1 &&
|
|
leaves[ 0 ] instanceof ve.dm.MWTransclusionNode &&
|
|
leaves[ 0 ];
|
|
}
|
|
|
|
return transclusionNode || null;
|
|
};
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
ve.ui.MWCitationDialog.prototype.initialize = function ( data ) {
|
|
// Parent method
|
|
ve.ui.MWCitationDialog.super.prototype.initialize.call( this, data );
|
|
|
|
// HACK: Use the same styling as single-mode transclusion dialog - this should be generalized
|
|
this.$content.addClass( 've-ui-mwTransclusionDialog-single' );
|
|
};
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
ve.ui.MWCitationDialog.prototype.getSetupProcess = function ( data ) {
|
|
return ve.ui.MWCitationDialog.super.prototype.getSetupProcess.call( this, data )
|
|
.next( function () {
|
|
data = data || {};
|
|
this.inDialog = data.inDialog;
|
|
|
|
// Initialization
|
|
if ( this.selectedNode ) {
|
|
this.referenceNode = this.getReferenceNode();
|
|
if ( this.referenceNode ) {
|
|
this.referenceModel = ve.dm.MWReferenceModel.static.newFromReferenceNode(
|
|
this.referenceNode
|
|
);
|
|
}
|
|
}
|
|
}, this );
|
|
};
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
ve.ui.MWCitationDialog.prototype.setApplicableStatus = function () {
|
|
ve.ui.MWCitationDialog.super.prototype.setApplicableStatus.call( this );
|
|
// Parent method disables 'apply' if no changes were made (this is okay for us), and
|
|
// disables 'insert' if transclusion is empty (but it is never empty in our case).
|
|
// Instead, disable 'insert' if no parameters were added.
|
|
this.actions.setAbilities( { insert: this.hasUsefulParameter() } );
|
|
};
|
|
|
|
/**
|
|
* Works out whether there are any set parameters that aren't just placeholders
|
|
*
|
|
* @return {boolean}
|
|
*/
|
|
ve.ui.MWCitationDialog.prototype.hasUsefulParameter = function () {
|
|
var name, page;
|
|
|
|
for ( name in this.bookletLayout.pages ) {
|
|
page = this.bookletLayout.pages[ name ];
|
|
if (
|
|
page instanceof ve.ui.MWParameterPage &&
|
|
page.valueInput.getValue() !== ''
|
|
) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
ve.ui.MWCitationDialog.prototype.getActionProcess = function ( action ) {
|
|
var dialog = this;
|
|
if (
|
|
this.inDialog !== 'reference' &&
|
|
( action === 'apply' || action === 'insert' )
|
|
) {
|
|
return new OO.ui.Process( function () {
|
|
var deferred = $.Deferred();
|
|
dialog.checkRequiredParameters().done( function () {
|
|
var item,
|
|
surfaceModel = dialog.getFragment().getSurface(),
|
|
doc = surfaceModel.getDocument(),
|
|
internalList = doc.getInternalList(),
|
|
obj = dialog.transclusionModel.getPlainObject();
|
|
|
|
if ( !dialog.referenceModel ) {
|
|
// Collapse returns a new fragment, so update dialog.fragment
|
|
dialog.fragment = dialog.getFragment().collapseToEnd();
|
|
dialog.referenceModel = new ve.dm.MWReferenceModel( doc );
|
|
dialog.referenceModel.insertInternalItem( surfaceModel );
|
|
dialog.referenceModel.insertReferenceNode( dialog.getFragment() );
|
|
}
|
|
|
|
item = dialog.referenceModel.findInternalItem( surfaceModel );
|
|
if ( item ) {
|
|
if ( dialog.selectedNode ) {
|
|
dialog.transclusionModel.updateTransclusionNode(
|
|
surfaceModel, dialog.selectedNode
|
|
);
|
|
} else if ( obj !== null ) {
|
|
dialog.transclusionModel.insertTransclusionNode(
|
|
// HACK: This is trying to place the cursor inside the first content branch
|
|
// node but this theoretically not a safe assumption - in practice, the
|
|
// citation dialog will only reach this code if we are inserting (not
|
|
// updating) a transclusion, so the referenceModel will have already
|
|
// initialized the internal node with a paragraph - getting the range of the
|
|
// item covers the entire paragraph so we have to get the range of it's
|
|
// first (and empty) child
|
|
dialog.getFragment().clone(
|
|
new ve.dm.LinearSelection( item.getChildren()[ 0 ].getRange() )
|
|
),
|
|
'inline'
|
|
);
|
|
}
|
|
}
|
|
|
|
// HACK: Scorch the earth - this is only needed because without it, the references list
|
|
// won't re-render properly, and can be removed once someone fixes that
|
|
dialog.referenceModel.setDocument(
|
|
doc.cloneFromRange(
|
|
internalList.getItemNode( dialog.referenceModel.getListIndex() ).getRange()
|
|
)
|
|
);
|
|
dialog.referenceModel.updateInternalItem( surfaceModel );
|
|
|
|
dialog.close( { action: action } );
|
|
} ).always( deferred.resolve );
|
|
|
|
return deferred;
|
|
} );
|
|
}
|
|
|
|
// Parent method
|
|
return ve.ui.MWCitationDialog.super.prototype.getActionProcess.call( this, action );
|
|
};
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
ve.ui.MWCitationDialog.prototype.getTeardownProcess = function ( data ) {
|
|
return ve.ui.MWCitationDialog.super.prototype.getTeardownProcess.call( this, data )
|
|
.first( function () {
|
|
// Cleanup
|
|
this.referenceModel = null;
|
|
this.referenceNode = null;
|
|
}, this );
|
|
};
|