From 0fd2b619c91d743659c90365bc0ae2fbd4877edf Mon Sep 17 00:00:00 2001 From: Moriel Schottlender Date: Sat, 10 Aug 2013 05:27:20 -0400 Subject: [PATCH] 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 --- .../inspectors/ve.ui.AnnotationInspector.js | 2 +- .../ui/inspectors/ve.ui.LanguageInspector.js | 115 +++++++++++++++++- .../ve/ui/inspectors/ve.ui.LinkInspector.js | 10 ++ .../ui/widgets/ve.ui.LanguageInputWidget.js | 107 +++++----------- 4 files changed, 153 insertions(+), 81 deletions(-) diff --git a/modules/ve/ui/inspectors/ve.ui.AnnotationInspector.js b/modules/ve/ui/inspectors/ve.ui.AnnotationInspector.js index c5f4c9cd8d..7f5ca7ed2f 100644 --- a/modules/ve/ui/inspectors/ve.ui.AnnotationInspector.js +++ b/modules/ve/ui/inspectors/ve.ui.AnnotationInspector.js @@ -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 ), diff --git a/modules/ve/ui/inspectors/ve.ui.LanguageInspector.js b/modules/ve/ui/inspectors/ve.ui.LanguageInspector.js index 9f9fc1a92d..41ee0c4cb0 100644 --- a/modules/ve/ui/inspectors/ve.ui.LanguageInspector.js +++ b/modules/ve/ui/inspectors/ve.ui.LanguageInspector.js @@ -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 ); diff --git a/modules/ve/ui/inspectors/ve.ui.LinkInspector.js b/modules/ve/ui/inspectors/ve.ui.LinkInspector.js index 6c8298c033..73c5a8cf9a 100644 --- a/modules/ve/ui/inspectors/ve.ui.LinkInspector.js +++ b/modules/ve/ui/inspectors/ve.ui.LinkInspector.js @@ -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 */ diff --git a/modules/ve/ui/widgets/ve.ui.LanguageInputWidget.js b/modules/ve/ui/widgets/ve.ui.LanguageInputWidget.js index c76e0bca5d..5605c77174 100644 --- a/modules/ve/ui/widgets/ve.ui.LanguageInputWidget.js +++ b/modules/ve/ui/widgets/ve.ui.LanguageInputWidget.js @@ -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 ''; };