diff options
Diffstat (limited to 'www/wiki/extensions/Cite/modules/ve-cite/ve.ui.MWCitationDialog.js')
-rw-r--r-- | www/wiki/extensions/Cite/modules/ve-cite/ve.ui.MWCitationDialog.js | 241 |
1 files changed, 241 insertions, 0 deletions
diff --git a/www/wiki/extensions/Cite/modules/ve-cite/ve.ui.MWCitationDialog.js b/www/wiki/extensions/Cite/modules/ve-cite/ve.ui.MWCitationDialog.js new file mode 100644 index 00000000..31bb6020 --- /dev/null +++ b/www/wiki/extensions/Cite/modules/ve-cite/ve.ui.MWCitationDialog.js @@ -0,0 +1,241 @@ +/* + * 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.actions.forEach( { actions: 'insert' }, function ( action ) { + action.setLabel( ve.msg( 'visualeditor-dialog-action-insert' ) ); + } ); + }, this ); +}; + +ve.ui.MWCitationDialog.prototype.onTransclusionReady = function () { + // Parent method + ve.ui.MWCitationDialog.super.prototype.onTransclusionReady.call( this ); + + if ( !this.hasUsefulParameter() ) { + this.actions.setAbilities( { apply: false, insert: false } ); + } +}; + +/** + * @inheritdoc + */ +ve.ui.MWCitationDialog.prototype.setPageByName = function ( param ) { + var hasUsefulParameter = this.hasUsefulParameter(); + + // Parent method + ve.ui.MWCitationDialog.super.prototype.setPageByName.call( this, param ); + + this.actions.setAbilities( { apply: hasUsefulParameter, insert: hasUsefulParameter } ); +}; + +/** + * @inheritdoc + */ +ve.ui.MWCitationDialog.prototype.onAddParameterBeforeLoad = function ( page ) { + var dialog = this, + hasUsefulParameter = this.hasUsefulParameter(); + + page.preLoad = true; + page.valueInput.on( 'change', function () { + dialog.actions.setAbilities( { apply: hasUsefulParameter, insert: hasUsefulParameter } ); + } ); +}; + +/** + * Works out whether there are any set parameters that aren't just placeholders + * + * @return {boolean} + */ +ve.ui.MWCitationDialog.prototype.hasUsefulParameter = function () { + var foundUseful = false; + $.each( this.bookletLayout.pages, function () { + if ( + this instanceof ve.ui.MWParameterPage && + ( !this.preLoad || this.valueInput.getValue() !== '' ) + ) { + foundUseful = true; + return false; + } + } ); + return foundUseful; +}; + +/** + * @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( doc, 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 ); +}; |