LanguageInputWidget Generalization

This commit prepares the LanguageInputWidget to handle both annotation
and node, so it can be used as the GUI for both the LanguageInspector
and the LanguageBlockInspector that's coming up.

Cleaned up the way annotations are read into LanguageInspector and
AnnotationInspector. The attributes are kept in the Widget (without regard
to what datamodel they will serve) and are then read from the inspector.
The LinkInspector had to be adjusted slightly to accomodate a small change
in the AnnotationInspector too.

Change-Id: I17954707c00ffc4c32fbb44a6807a61760ad573c
This commit is contained in:
Moriel Schottlender 2013-08-10 05:27:20 -04:00
parent 6e413de883
commit 0fd2b619c9
4 changed files with 153 additions and 81 deletions

View file

@ -121,7 +121,7 @@ ve.ui.AnnotationInspector.prototype.onClose = function ( action ) {
clear = false,
set = false,
target = this.targetInput.getValue(),
annotation = this.targetInput.getAnnotation(),
annotation = this.getAnnotation(),
remove = target === '' || ( action === 'remove' && !!annotation ),
surfaceModel = this.surface.getModel(),
fragment = surfaceModel.getFragment( this.initialSelection, false ),

View file

@ -19,8 +19,12 @@ ve.ui.LanguageInspector = function VeUiLanguageInspector( surface, config ) {
// Parent constructor
ve.ui.AnnotationInspector.call( this, surface, config );
// Placeholder for the dm properties:
this.initLang = '';
this.initDir = '';
// Placeholder for the annotation:
this.annotation = null;
};
/* Inheritance */
@ -54,7 +58,8 @@ ve.ui.LanguageInspector.prototype.initialize = function () {
// Properties
this.targetInput = new ve.ui.LanguageInputWidget( {
'$$': this.frame.$$, '$overlay': this.surface.$localOverlay
'$$': this.frame.$$,
'$overlay': this.surface.$localOverlay
} );
// Initialization
@ -71,14 +76,14 @@ ve.ui.LanguageInspector.prototype.onOpen = function () {
// Wait for animation to complete
setTimeout( ve.bind( function () {
// Setup annotation
this.targetInput.setAnnotation( this.initialAnnotation );
this.setAnnotation( this.initialAnnotation );
}, this ), 200 );
};
/**
* Handle the inspector being setup.
* Make sure the initial language and direction are set by the parent of the DOM
* element of the selected fragment before the rest of the onSetup method is
* processed by the parent ve.ui.AnnotationInspector
* Handle the inspector being set up.
* Make sure the initial language and direction are set by the parent
* of the DOM element of the selected fragment before the rest of the
* onSetup method is processed by the parent ve.ui.AnnotationInspector
*/
ve.ui.LanguageInspector.prototype.onSetup = function () {
var fragDOM,
@ -98,6 +103,90 @@ ve.ui.LanguageInspector.prototype.onSetup = function () {
// Parent method
ve.ui.AnnotationInspector.prototype.onSetup.call( this );
};
/**
* Handle the inspector being closed: refresh the annotation
* from the widget values
*
* @param {string} action Action that caused the window to be closed
*/
ve.ui.LanguageInspector.prototype.onClose = function ( action ) {
// Read the annotation values from the widget:
var attrs = this.targetInput.getAttributes();
// Set the annotation with the new attributes:
this.annotation = new ve.dm.LanguageAnnotation( {
'type': 'language',
'attributes': attrs
} );
// Call parent method
ve.ui.AnnotationInspector.prototype.onClose.call( this, action );
};
/**
* Gets the annotation value.
*
* @method
* @returns {ve.dm.LanguageAnnotation} Language annotation
*/
ve.ui.LanguageInspector.prototype.getAnnotation = function () {
return this.annotation;
};
/**
* Validates and sets the annotation value
* Then updates the attributes and the widget table display
*
* @method
* @param {ve.dm.LanguageAnnotation} annotation Language annotation
* @chainable
*/
ve.ui.LanguageInspector.prototype.setAnnotation = function ( annotation ) {
var langCode = '',
langDir = '';
// Validate the given annotation:
// Give precedence to dir value if it already exists
// in the annotation:
if ( annotation.getAttribute( 'dir' ) ) {
langDir = annotation.getAttribute( 'dir' );
}
// Set language according to the one in the given annotation
// or leave blank if element has no language set
if ( annotation.getAttribute( 'lang' ) ) {
langCode = annotation.getAttribute( 'lang' );
}
// If language exists, but dir is undefined/null,
// fix the dir in terms of language:
if ( langCode && !langDir ) {
langDir = $.uls.data.getDir( this.lang );
}
this.lang = langCode;
this.dir = langDir;
// Update the widget:
this.targetInput.setAttributes( this.lang, this.dir );
// Set the annotation:
this.annotation = new ve.dm.LanguageAnnotation( {
'type': 'language',
'attributes': {
'lang': this.lang,
'dir': this.dir
}
} );
return this;
};
/**
* @inheritdoc
*/
@ -111,6 +200,20 @@ ve.ui.LanguageInspector.prototype.getAnnotationFromText = function () {
} );
};
/**
* Gets a language from the annotation.
*
* @method
* @param {ve.dm.LanguageAnnotation} annotation Language annotation
* @returns {string} Language
*/
ve.ui.LanguageInspector.prototype.getLanguageFromAnnotation = function ( annotation ) {
if ( annotation instanceof ve.dm.LanguageAnnotation ) {
return annotation.getAttribute( 'lang' );
}
return '';
};
/* Registration */
ve.ui.inspectorFactory.register( 'language', ve.ui.LanguageInspector );

View file

@ -79,6 +79,16 @@ ve.ui.LinkInspector.prototype.onOpen = function () {
}, this ), 200 );
};
/**
* Get the annotation from the input (so AnnotationInspector can request the value
* from the inspector rather than the widget)
* @method
* @returns {ve.dm.LinkAnnotation} Link annotation
*/
ve.ui.LinkInspector.prototype.getAnnotation = function () {
return this.targetInput.annotation;
};
/**
* @inheritdoc
*/

View file

@ -20,13 +20,12 @@ ve.ui.LanguageInputWidget = function VeUiLanguageInputWidget( config ) {
// Parent constructor
ve.ui.Widget.call( this, config );
// Properties
// Visual Properties
this.$langCodeDisp = this.getDisplayElement( config ); // language code
this.$langNameDisp = this.getDisplayElement( config ); // human-readable language name
this.$dirDisp = this.getDisplayElement( config );
// Placeholders for annotation value
this.annotation = null;
// Placeholders for attribute values
this.lang = '';
this.dir = '';
@ -65,7 +64,8 @@ ve.ui.LanguageInputWidget = function VeUiLanguageInputWidget( config ) {
ulsParams = {
onSelect: function( language ) {
langInpObj.setValue( language );
// Save the attributes:
langInpObj.setAttributes( language, $.uls.data.getDir( language ) );
},
compact: true,
// Temporary Quicklist for the Prototype:
@ -89,7 +89,10 @@ ve.ui.LanguageInputWidget = function VeUiLanguageInputWidget( config ) {
ve.inheritClass( ve.ui.LanguageInputWidget, ve.ui.Widget );
/* Static properties */
/* Methods */
/**
* Get display element. This replaces the 'getInputElement'
* of the InputWidget
@ -103,98 +106,54 @@ ve.ui.LanguageInputWidget.prototype.getDisplayElement = function () {
};
/**
* Set the value of the language display
* Return the current language attributes
*
* Overrides setValue to keep annotations in sync.
*
* @method
* @param {string} value New value
*/
ve.ui.LanguageInputWidget.prototype.setValue = function ( value ) {
// Keep annotation in sync with value
if ( value === '' ) {
this.annotation = null;
} else {
// Set up the annotation:
this.setAnnotation( new ve.dm.LanguageAnnotation( {
'type': 'language',
'attributes': {
'lang': value,
'dir': $.uls.data.getDir( value )
}
} ) );
}
ve.ui.LanguageInputWidget.prototype.getAttributes = function () {
return {
'lang': this.lang,
'dir': this.dir
};
};
/**
* Get the value of the current annotation
* Set the current language attributes
*
*/
ve.ui.LanguageInputWidget.prototype.setAttributes = function ( lang, dir ) {
this.lang = lang;
this.dir = dir;
// Update the view:
this.updateLanguageTable();
};
/**
* Get the language value of the current annotation
* This is required by the AnnotationInspector onClose method
*/
ve.ui.LanguageInputWidget.prototype.getValue = function () {
// Specifically to be displayed
return this.lang;
};
/**
* Sets the annotation value.
* Updates the language value in the display table
*
* The input value will automatically be updated.
* This shouldn't be used directly. It is called from the
* setAttributes method after receiving annotation details
* to make sure the annotation and the table are synchronized.
*
* @method
* @param {ve.dm.LanguageAnnotation} annotation Language annotation
* @chainable
*/
ve.ui.LanguageInputWidget.prototype.setAnnotation = function ( annotation ) {
ve.ui.LanguageInputWidget.prototype.updateLanguageTable = function () {
var langNameDisp = '';
this.annotation = annotation;
// Give precedence to dir value if it already exists:
if ( annotation.element.attributes.dir ) {
this.dir = annotation.element.attributes.dir;
}
// Set language according to currently set language
// or leave blank if element has no language set
if ( annotation.element.attributes.lang ) {
this.lang = annotation.element.attributes.lang;
// Take the full name of the language from its code:
if ( this.lang ) {
langNameDisp = $.uls.data.getAutonym( this.lang );
} else {
this.lang = '';
}
// If language exists, but dir is undefined/null,
// fix the dir in terms of language:
if ( this.lang && !this.dir ) {
this.dir = $.uls.data.getDir( this.lang );
}
// Display the information in the table:
this.$langCodeDisp.html( this.lang );
this.$langNameDisp.html( langNameDisp );
this.$dirDisp.html( this.dir );
return this;
};
/**
* Gets the annotation value.
*
* @method
* @returns {ve.dm.LanguageAnnotation} Language annotation
*/
ve.ui.LanguageInputWidget.prototype.getAnnotation = function () {
return this.annotation;
};
/**
* Gets a target from an annotation.
*
* @method
* @param {ve.dm.LanguageAnnotation} annotation Language annotation
* @returns {string} Language
*/
ve.ui.LanguageInputWidget.prototype.getLanguageFromAnnotation = function ( annotation ) {
if ( annotation instanceof ve.dm.LanguageAnnotation ) {
return annotation.getAttribute( 'lang' );
}
return '';
};