/*!
* VisualEditor UserInterface LinkAnnotationInspector class.
*
* @copyright See AUTHORS.txt
*/
/**
* Inspector for linked content.
*
* @class
* @extends ve.ui.AnnotationInspector
*
* @constructor
* @param {Object} [config] Configuration options
*/
ve.ui.LinkAnnotationInspector = function VeUiLinkAnnotationInspector() {
// Parent constructor
ve.ui.LinkAnnotationInspector.super.apply( this, arguments );
};
/* Inheritance */
OO.inheritClass( ve.ui.LinkAnnotationInspector, ve.ui.AnnotationInspector );
/* Static properties */
ve.ui.LinkAnnotationInspector.static.name = 'link';
ve.ui.LinkAnnotationInspector.static.modelClasses = [ ve.dm.LinkAnnotation ];
/* Methods */
/**
* Handle annotation input change events
*/
ve.ui.LinkAnnotationInspector.prototype.onAnnotationInputChange = function () {
this.labelInput.$input.attr( 'placeholder', this.getInsertionText() );
this.updateActions();
};
/**
* Update the actions based on the annotation state
*/
ve.ui.LinkAnnotationInspector.prototype.updateActions = function () {
const annotation = this.annotationInput.getAnnotation();
let isValid = false;
this.annotationInput.getTextInputWidget().getValidity()
.then( () => {
isValid = true;
} )
.always( () => {
isValid = isValid && !!annotation;
this.actions.forEach( { actions: [ 'done', 'insert' ] }, ( action ) => {
action.setDisabled( !isValid );
} );
} );
};
/**
* @inheritdoc
*/
ve.ui.LinkAnnotationInspector.prototype.shouldRemoveAnnotation = function () {
return !this.annotationInput.getAnnotation();
};
/**
* @inheritdoc
*/
ve.ui.LinkAnnotationInspector.prototype.getInsertionText = function () {
return this.labelInput.getValue().trim() || this.annotationInput.getHref();
};
/**
* @inheritdoc
*/
ve.ui.LinkAnnotationInspector.prototype.getAnnotation = function () {
return this.annotationInput.getAnnotation();
};
/**
* @inheritdoc
*/
ve.ui.LinkAnnotationInspector.prototype.getAnnotationFromFragment = function ( fragment ) {
const text = fragment.getText();
return text ? new ve.dm.LinkAnnotation( {
type: 'link',
attributes: { href: text }
} ) : null;
};
/**
* @inheritdoc
*/
ve.ui.LinkAnnotationInspector.prototype.initialize = function () {
// Parent method
ve.ui.LinkAnnotationInspector.super.prototype.initialize.call( this );
// Properties
this.labelInput = this.createLabelInput();
this.annotationInput = this.createAnnotationInput();
this.labelField = new OO.ui.FieldLayout(
this.labelInput,
{
align: 'top',
label: ve.msg( 'visualeditor-linkcontext-label-label' )
}
);
this.annotationField = new OO.ui.FieldLayout(
this.annotationInput,
{
align: 'top',
label: ve.msg( 'visualeditor-linkinspector-title' )
}
);
// Events
this.annotationInput.connect( this, { change: 'onAnnotationInputChange' } );
this.annotationInput.getTextInputWidget().connect( this, { enter: 'onFormSubmit' } );
this.labelInput.connect( this, { enter: 'onFormSubmit' } );
this.labelInput.connect( this, { change: 'onAnnotationInputChange' } );
// Initialization
this.form.$element.append(
this.labelField.$element,
this.annotationField.$element
);
if ( !OO.ui.isMobile() ) {
this.annotationField.setLabel( null );
this.labelField.$element.detach();
}
};
/**
* Create a link label widget
*
* @return {OO.ui.TextInputWidget} Link label widget
*/
ve.ui.LinkAnnotationInspector.prototype.createLabelInput = function () {
return new OO.ui.TextInputWidget();
};
/**
* Create a link annotation widget
*
* @return {ve.ui.LinkAnnotationWidget} Link annotation widget
*/
ve.ui.LinkAnnotationInspector.prototype.createAnnotationInput = function () {
return new ve.ui.LinkAnnotationWidget();
};
/**
* @inheritdoc
*/
ve.ui.LinkAnnotationInspector.prototype.shouldInsertText = function () {
if ( ve.ui.LinkAnnotationInspector.super.prototype.shouldInsertText.call( this ) ) {
// Adding a new link
return true;
}
if ( OO.ui.isMobile() ) {
return !this.labelInput.isDisabled() &&
// Don't touch it if the plaintext value hasn't changed, to preserve internal annotations if possible
this.labelInput.getValue().trim() !== this.initialLabel.trim();
}
return false;
};
/**
* @inheritdoc
*/
ve.ui.LinkAnnotationInspector.prototype.getSetupProcess = function ( data ) {
return ve.ui.LinkAnnotationInspector.super.prototype.getSetupProcess.call( this, data )
.next( () => {
const title = ve.msg(
this.isReadOnly() ?
'visualeditor-linkinspector-title' : (
this.isNew ?
'visualeditor-linkinspector-title-add' :
'visualeditor-linkinspector-title-edit'
)
),
fragment = this.getFragment();
this.title.setLabel( title ).setTitle( title );
this.initialLabel = fragment.getText();
this.labelInput.setDisabled( !fragment.containsOnlyText() );
this.labelInput.setValue( this.initialLabel );
this.annotationInput.setAnnotation( this.initialAnnotation );
this.annotationInput.setReadOnly( this.isReadOnly() );
this.updateActions();
} );
};
/**
* @inheritdoc
*/
ve.ui.LinkAnnotationInspector.prototype.getReadyProcess = function ( data ) {
return ve.ui.LinkAnnotationInspector.super.prototype.getReadyProcess.call( this, data )
.next( () => {
if ( !OO.ui.isMobile() ) {
this.annotationInput.getTextInputWidget().focus().select();
}
// Clear validation state, so that we don't get "invalid" state immediately on focus
this.annotationInput.getTextInputWidget().setValidityFlag( true );
} );
};
/**
* @inheritdoc
*/
ve.ui.LinkAnnotationInspector.prototype.getHoldProcess = function ( data ) {
return ve.ui.LinkAnnotationInspector.super.prototype.getHoldProcess.call( this, data )
.next( () => {
this.annotationInput.getTextInputWidget().blur();
} );
};
/**
* @inheritdoc
*/
ve.ui.LinkAnnotationInspector.prototype.getTeardownProcess = function ( data ) {
return ve.ui.LinkAnnotationInspector.super.prototype.getTeardownProcess.call( this, data )
.next( () => {
this.annotationInput.setAnnotation( null );
this.labelInput.$input.attr( 'placeholder', '' );
this.labelInput.setValue( '' );
} );
};
/* Registration */
ve.ui.windowFactory.register( ve.ui.LinkAnnotationInspector );