jenkins-bot has submitted this change and it was merged.

Change subject: Implemented jQuery.wikibase.fingerprintview
......................................................................


Implemented jQuery.wikibase.fingerprintview

Change-Id: Id0a2457d4083ada7d2a705ca0c255f0e8f744016
---
M lib/resources/Resources.php
M lib/resources/jquery.wikibase/jquery.wikibase.descriptionview.js
A lib/resources/jquery.wikibase/jquery.wikibase.fingerprintview.js
M lib/resources/jquery.wikibase/jquery.wikibase.labelview.js
M lib/resources/jquery.wikibase/resources.php
A 
lib/resources/jquery.wikibase/themes/default/jquery.wikibase.fingerprintview.css
M lib/resources/jquery.wikibase/toolbar/toolbareditgroup.js
M lib/resources/templates.php
M lib/resources/wikibase.css
A lib/tests/qunit/jquery.wikibase/jquery.wikibase.fingerprintview.tests.js
M lib/tests/qunit/jquery.wikibase/resources.php
M repo/i18n/en.json
M repo/i18n/qqq.json
M repo/includes/View/TermBoxView.php
M repo/resources/Resources.php
M repo/resources/wikibase.initTermBox.js
M repo/resources/wikibase.ui.entityViewInit.js
17 files changed, 847 insertions(+), 367 deletions(-)

Approvals:
  Tobias Gritschacher: Looks good to me, approved
  Henning Snater: Checked
  jenkins-bot: Verified



diff --git a/lib/resources/Resources.php b/lib/resources/Resources.php
index 5a9708e..6836002 100644
--- a/lib/resources/Resources.php
+++ b/lib/resources/Resources.php
@@ -50,9 +50,10 @@
                        'styles' => array(
                                // Order must be hierarchical, do not order 
alphabetically
                                'wikibase.css',
-                               
'jquery.wikibase/themes/default/jquery.wikibase.labelview.css',
-                               
'jquery.wikibase/themes/default/jquery.wikibase.descriptionview.css',
                                
'jquery.wikibase/themes/default/jquery.wikibase.aliasesview.css',
+                               
'jquery.wikibase/themes/default/jquery.wikibase.descriptionview.css',
+                               
'jquery.wikibase/themes/default/jquery.wikibase.fingerprintview.css',
+                               
'jquery.wikibase/themes/default/jquery.wikibase.labelview.css',
                                
'jquery.wikibase/themes/default/jquery.wikibase.sitelinklistview.css',
                                
'jquery.wikibase/themes/default/jquery.wikibase.sitelinkview.css',
                        )
diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.descriptionview.js 
b/lib/resources/jquery.wikibase/jquery.wikibase.descriptionview.js
index 12b5e6a..c07841b 100644
--- a/lib/resources/jquery.wikibase/jquery.wikibase.descriptionview.js
+++ b/lib/resources/jquery.wikibase/jquery.wikibase.descriptionview.js
@@ -62,14 +62,8 @@
 
                this.options.value = this._checkValue( this.options.value );
 
-               PARENT.prototype._create.call( this );
-
                var self = this,
                        value = this.options.value;
-
-               if( value && value.description !== '' && this.$text.text() === 
'' ) {
-                       this._draw();
-               }
 
                this.element
                // TODO: Move that code to a sensible place (see 
jQuery.wikibase.entityview):
@@ -110,6 +104,12 @@
                                ] );
                        }
                } );
+
+               PARENT.prototype._create.call( this );
+
+               if( value && value.description !== '' && this.$text.text() === 
'' ) {
+                       this._draw();
+               }
        },
 
        /**
@@ -135,7 +135,9 @@
        _draw: function() {
                if( !this._isInEditMode ) {
                        this.element.removeClass( 'wb-edit' );
-                       this.$text.text( this.options.value.description );
+                       this.$text.text(
+                               this.options.value.description || mw.msg( 
'wikibase-description-empty' )
+                       );
                        return;
                }
 
diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.fingerprintview.js 
b/lib/resources/jquery.wikibase/jquery.wikibase.fingerprintview.js
new file mode 100644
index 0000000..188a9b2
--- /dev/null
+++ b/lib/resources/jquery.wikibase/jquery.wikibase.fingerprintview.js
@@ -0,0 +1,396 @@
+/**
+ * @licence GNU GPL v2+
+ * @author H. Snater < mediaw...@snater.com >
+ */
+( function( mw, wb, $ ) {
+       'use strict';
+
+       var PARENT = $.ui.TemplatedWidget;
+
+/**
+ * Displays and allows editing label and description in a specific language.
+ * @since 0.5
+ * @extends jQuery.ui.TemplatedWidget
+ *
+ * @option {Object|null} value
+ *         Object representing the widget's value.
+ *         Structure: { language: <{string}>, label: <{string|null}>, 
description: <{string|null> }
+ *
+ * @option {string} [helpMessage]
+ *         Default: mw.msg( 'wikibase-fingerprintview-input-help-message' )
+ *
+ * @options {string} entityId
+ *
+ * @option {wikibase.RepoApi} api
+ *
+ * @event change
+ *        - {jQuery.Event}
+ *
+ * @event afterstartediting
+ *       - [jQuery.Event}
+ *
+ * @event stopediting
+ *        - {jQuery.Event}
+ *        - {boolean} Whether to drop the value.
+ *        - {Function} Callback function.
+ *
+ * @event afterstopediting
+ *        - {jQuery.Event}
+ *        - {boolean} Whether to drop the value.
+ *
+ * @event toggleerror
+ *        - {jQuery.Event}
+ *        - {Error|null}
+ */
+$.widget( 'wikibase.fingerprintview', PARENT, {
+       options: {
+               template: 'wikibase-fingerprintview',
+               templateParams: [
+                       function() {
+                               return this.options.value.language;
+                       },
+                       function() {
+                               return wb.getLanguageNameByCode( 
this.options.value.language );
+                       },
+                       '', // label
+                       '', // description
+                       '', // label toolbar
+                       '', // description toolbar
+                       '', // additional label CSS classes
+                       '', // additional description CSS classes
+                       function() {
+                               var title = new mw.Title(
+                                       mw.config.get( 'wgTitle' ),
+                                       mw.config.get( 'wgNamespaceNumber' )
+                               );
+
+                               return title.getUrl( { setlang: 
this.options.value.language } );
+                       }
+               ],
+               templateShortCuts: {
+                       $language: '.wikibase-fingerprintview-language',
+                       $label: '.wikibase-fingerprintview-label',
+                       $description : '.wikibase-fingerprintview-description'
+               },
+               value: null,
+               helpMessage: mw.msg( 
'wikibase-fingerprintview-input-help-message' ),
+               entityId: null,
+               api: null
+       },
+
+       /**
+        * @type {boolean}
+        */
+       _isInEditMode: false,
+
+       /**
+        * @see jQuery.ui.TemplatedWidget._create
+        */
+       _create: function() {
+               this.options.value = this._checkValue( this.options.value );
+
+               PARENT.prototype._create.call( this );
+
+               this._createWidgets();
+       },
+
+       /**
+        * @see jQuery.ui.TemplatedWidget.destroy
+        */
+       destroy: function() {
+               var self = this;
+
+               function degrade() {
+                       if( self.$label ) {
+                               self.$label.data( 'labelview' ).destroy();
+                       }
+                       if( self.$description ) {
+                               self.$description.data( 'descriptionview' 
).destroy();
+                       }
+
+                       PARENT.prototype.destroy.call( self );
+               }
+
+               if( this._isInEditMode ) {
+                       this.element.one( this.widgetEventPrefix + 
'afterstopediting', function( event ) {
+                               degrade();
+                       } );
+
+                       this.cancelEditing();
+               } else {
+                       degrade();
+               }
+       },
+
+       /**
+        * Creates labelview and descriptionview widget.
+        */
+       _createWidgets: function() {
+               var self = this;
+
+               $.each( ['label', 'description'], function( i, subjectName ) {
+                       var widgetName = subjectName + 'view',
+                               $subject = self['$' + subjectName];
+
+                       // Fully encapsulate labelview and descriptionview by 
suppressing their events:
+                       $subject
+                       .on( widgetName + 'change', function( event ) {
+                               event.stopPropagation();
+                               self._trigger( 'change' );
+                       } )
+                       .on( widgetName + 'toggleerror.' + self.widgetName, 
function( event, error ) {
+                               event.stopPropagation();
+                               self.setError( error );
+                       } )
+                       .on(
+                               widgetName + 'create.' + self.widgetName + ' '
+                               + widgetName + 'afterstartediting.' + 
self.widgetName + ' '
+                               + widgetName + 'stopediting.' + self.widgetName 
+ ' '
+                               + widgetName + 'afterstopediting.' + 
self.widgetName,
+                               function( event ) {
+                                       event.stopPropagation();
+                               }
+                       );
+
+                       $subject[widgetName]( {
+                               value: self.options.value,
+                               helpMessage: mw.msg(
+                                       'wikibase-' + subjectName + 
'-input-help-message',
+                                       wb.getLanguageNameByCode( 
self.options.value.language )
+                               ),
+                               entityId: self.options.entityId,
+                               api: self.options.api
+                       } );
+               } );
+       },
+
+       /**
+        * @return {boolean}
+        */
+       isValid: function() {
+               return this.$label.data( 'labelview' ).isValid()
+                       && this.$description.data( 'descriptionview' 
).isValid();
+       },
+
+       /**
+        * @return {boolean}
+        */
+       isInitialValue: function() {
+               return this.$label.data( 'labelview' ).isInitialValue()
+                       && this.$description.data( 'descriptionview' 
).isInitialValue();
+       },
+
+       /**
+        * Puts the widget into edit mode.
+        */
+       startEditing: function() {
+               if( this._isInEditMode ) {
+                       return;
+               }
+
+               this._isInEditMode = true;
+               this.element.addClass( 'wb-edit' );
+
+               this.$label.data( 'labelview' ).startEditing();
+               this.$description.data( 'descriptionview' ).startEditing();
+
+               this._trigger( 'afterstartediting' );
+       },
+
+       /**
+        * Stops the widget's edit mode.
+        *
+        * @param {boolean} [dropValue]
+        */
+       stopEditing: function( dropValue ) {
+               var self = this;
+
+               if( !this._isInEditMode || ( !this.isValid() || 
this.isInitialValue() ) && !dropValue ) {
+                       return;
+               }
+
+               dropValue = !!dropValue;
+
+               this._trigger( 'stopediting', null, [dropValue] );
+
+               this.disable();
+
+               var labelview = this.$label.data( 'labelview' ),
+                       descriptionview = this.$description.data( 
'descriptionview' ),
+                       stoppedEditing = false;
+
+               function detectAfterStopEditing() {
+                       if( !stoppedEditing ) {
+                               stoppedEditing = true;
+                               return;
+                       }
+                       self._afterStopEditing( dropValue );
+               }
+
+               this.$label.one( 'labelviewafterstopediting', 
detectAfterStopEditing );
+               this.$description.one( 'descriptionviewafterstopediting', 
detectAfterStopEditing );
+
+               labelview.stopEditing( dropValue || labelview.isInitialValue() 
);
+               descriptionview.stopEditing( dropValue || 
descriptionview.isInitialValue() );
+       },
+
+       /**
+        * @param {boolean} [dropValue]
+        */
+       _afterStopEditing: function( dropValue ) {
+               this._isInEditMode = false;
+               this.enable();
+               this.element.removeClass( 'wb-edit' );
+               this._trigger( 'afterstopediting', null, [dropValue] );
+       },
+
+       /**
+        * Cancels editing.
+        */
+       cancelEditing: function() {
+               this.stopEditing( true );
+       },
+
+       /**
+        * Sets/Gets the widget's value.
+        *
+        * @param {Object} [value]
+        * @return {Object|undefined}
+        */
+       value: function( value ) {
+               if( value !== undefined ) {
+                       return this.option( 'value', value );
+               }
+
+               return {
+                       language: this.options.value.language,
+                       label: this.$label.data( 'labelview' ).value().label,
+                       description: this.$description.data( 'descriptionview' 
).value().description
+               };
+       },
+
+       /**
+        * @see jQuery.ui.TemplatedWidget._setOption
+        *
+        * @throws {Error} when trying to set value with a new language.
+        */
+       _setOption: function( key, value ) {
+               if( key === 'value' ) {
+                       value = this._checkValue( value );
+
+                       if( value.language !== this.options.value.language ) {
+                               throw new Error( 'Cannot alter language' );
+                       }
+
+                       this.$label.data( 'labelview' ).option( 'value', {
+                               language: value.language,
+                               label: value.label
+                       } );
+
+                       this.$description.data( 'descriptionview' ).option( 
'value', {
+                               language: value.language,
+                               description: value.description
+                       } );
+               }
+               return PARENT.prototype._setOption.call( this, key, value );
+       },
+
+       /**
+        * @param {*} value
+        * @return {Object}
+        *
+        * @throws {Error} if value is not defined properly.
+        */
+       _checkValue: function( value ) {
+               if( !$.isPlainObject( value ) ) {
+                       throw new Error( 'Value needs to be an object' );
+               } else if( !value.language ) {
+                       throw new Error( 'Value needs language to be specified' 
);
+               }
+
+               if( !value.label ) {
+                       value.label = null;
+               }
+
+               if( !value.description ) {
+                       value.description = null;
+               }
+
+               return value;
+       },
+
+       /**
+        * Sets keyboard focus on the first input element.
+        */
+       focus: function() {
+               this.$label.data( 'labelview' ).focus();
+       },
+
+       /**
+        * Applies/Removes error state.
+        *
+        * @param {Error} [error]
+        */
+       setError: function( error ) {
+               if( error ) {
+                       this.element.addClass( 'wb-error' );
+                       this._trigger( 'toggleerror', null, [error] );
+               } else {
+                       this.element.removeClass( 'wb-error' );
+                       this._trigger( 'toggleerror' );
+               }
+       }
+
+} );
+
+$.wikibase.toolbarcontroller.definition( 'edittoolbar', {
+       id: 'fingerprintview',
+       selector: ':' + $.wikibase.fingerprintview.prototype.namespace
+               + '-' + $.wikibase.fingerprintview.prototype.widgetName,
+       events: {
+               fingerprintviewcreate: function( event, toolbarcontroller ) {
+                       var $fingerprintview = $( event.target ),
+                               fingerprintview = $fingerprintview.data( 
'fingerprintview' );
+
+                       $fingerprintview.edittoolbar( {
+                               $container: $( '<td rowspan="2" />' )
+                                       .appendTo( $fingerprintview.children( 
'tr' ).first() ),
+                               interactionWidgetName: 
$.wikibase.fingerprintview.prototype.widgetName,
+                               enableRemove: false
+                       } );
+
+                       $fingerprintview.on( 'keyup', function( event ) {
+                               if( fingerprintview.option( 'disabled' ) ) {
+                                       return;
+                               }
+                               if( event.keyCode === $.ui.keyCode.ESCAPE ) {
+                                       fingerprintview.stopEditing( true );
+                               } else if( event.keyCode === $.ui.keyCode.ENTER 
) {
+                                       fingerprintview.stopEditing( false );
+                               }
+                       } );
+               },
+               'fingerprintviewchange fingerprintviewafterstartediting': 
function( event ) {
+                       var $fingerprintview = $( event.target ),
+                               fingerprintview = $fingerprintview.data( 
'fingerprintview' ),
+                               toolbar = $fingerprintview.data( 'edittoolbar' 
).toolbar,
+                               $btnSave = toolbar.editGroup.getButton( 'save' 
),
+                               btnSave = $btnSave.data( 'toolbarbutton' ),
+                               enable = fingerprintview.isValid() && 
!fingerprintview.isInitialValue();
+
+                       btnSave[enable ? 'enable' : 'disable']();
+               },
+               toolbareditgroupedit: function( event, toolbarcontroller ) {
+                       var $fingerprintview = $( event.target ).closest( 
':wikibase-edittoolbar' ),
+                               fingerprintview = $fingerprintview.data( 
'labelview' );
+
+                       if( !fingerprintview ) {
+                               return;
+                       }
+
+                       fingerprintview.focus();
+               }
+       }
+} );
+
+}( mediaWiki, wikibase, jQuery ) );
diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.labelview.js 
b/lib/resources/jquery.wikibase/jquery.wikibase.labelview.js
index 33e1341..f1c12ca 100644
--- a/lib/resources/jquery.wikibase/jquery.wikibase.labelview.js
+++ b/lib/resources/jquery.wikibase/jquery.wikibase.labelview.js
@@ -68,16 +68,10 @@
 
                this.options.value = this._checkValue( this.options.value );
 
-               PARENT.prototype._create.call( this );
-
                var self = this,
                        value = this.options.value;
 
                this.element.attr( 'id', 'wb-firstHeading-' + 
this.options.entityId );
-
-               if( value && value.label !== '' && this.$text.text() === '' ) {
-                       this._draw();
-               }
 
                this.element
                // TODO: Move that code to a sensible place (see 
jQuery.wikibase.entityview):
@@ -118,6 +112,12 @@
                                ] );
                        }
                } );
+
+               PARENT.prototype._create.call( this );
+
+               if( value && value.label !== '' && this.$text.text() === '' ) {
+                       this._draw();
+               }
        },
 
        /**
@@ -149,7 +149,7 @@
 
                if( !this._isInEditMode ) {
                        this.element.removeClass( 'wb-edit' );
-                       this.$text.text( this.options.value.label );
+                       this.$text.text( this.options.value.label || mw.msg( 
'wikibase-label-empty' ) );
                        return;
                }
 
diff --git a/lib/resources/jquery.wikibase/resources.php 
b/lib/resources/jquery.wikibase/resources.php
index 9eb2230..821a146 100644
--- a/lib/resources/jquery.wikibase/resources.php
+++ b/lib/resources/jquery.wikibase/resources.php
@@ -121,6 +121,7 @@
                        'messages' => array(
                                'wikibase-description-edit-placeholder',
                                
'wikibase-description-edit-placeholder-language-aware',
+                               'wikibase-description-empty',
                                'wikibase-description-input-help-message',
                        ),
                ),
@@ -180,10 +181,32 @@
                                'parentheses',
                                'wikibase-label-edit-placeholder',
                                
'wikibase-label-edit-placeholder-language-aware',
+                               'wikibase-label-empty',
                                'wikibase-label-input-help-message',
                        ),
                ),
 
+               'jquery.wikibase.fingerprintview' => $moduleTemplate + array(
+                       'scripts' => array(
+                               'jquery.wikibase.fingerprintview.js',
+                       ),
+                       'styles' => array(
+                               
'themes/default/jquery.wikibase.fingerprintview.css',
+                       ),
+                       'dependencies' => array(
+                               'mediawiki.Title',
+                               'wikibase',
+                               'jquery.ui.TemplatedWidget',
+                               'jquery.wikibase.descriptionview',
+                               'jquery.wikibase.edittoolbar',
+                               'jquery.wikibase.labelview',
+                               'jquery.wikibase.toolbarcontroller',
+                       ),
+                       'messages' => array(
+                               'wikibase-fingerprintview-input-help-message',
+                       ),
+               ),
+
                'jquery.wikibase.listview' => $moduleTemplate + array(
                        'scripts' => array(
                                'jquery.wikibase.listview.js',
diff --git 
a/lib/resources/jquery.wikibase/themes/default/jquery.wikibase.fingerprintview.css
 
b/lib/resources/jquery.wikibase/themes/default/jquery.wikibase.fingerprintview.css
new file mode 100644
index 0000000..7374fcb
--- /dev/null
+++ 
b/lib/resources/jquery.wikibase/themes/default/jquery.wikibase.fingerprintview.css
@@ -0,0 +1,83 @@
+/**
+ * @licence GNU GPL v2+
+ * @author H. Snater < mediaw...@snater.com >
+ */
+.wikibase-fingerprintview-language {
+       width: 25%;
+       word-wrap: break-word;
+       padding-left: 10px;
+       border-left: 1px solid #C9C9C9;
+}
+
+.wikibase-fingerprintview-label,
+.wikibase-fingerprintview-description {
+       width: 75%;
+       word-wrap: break-word;
+       padding-left: 10px;
+}
+
+.wikibase-fingerprintview tr td:first-child + td + td {
+       width: 25%;
+}
+
+.wikibase-fingerprintview td {
+       border-top: 1px solid #C9C9C9;
+}
+
+.wikibase-fingerprintview td:last-child {
+       padding-left: 10px;
+}
+
+.wikibase-fingerprintview-label {
+       padding: 10px;
+}
+
+.wikibase-fingerprintview input {
+       font-family: inherit;
+       width: 100%;
+}
+
+.wikibase-fingerprintview .wikibase-descriptionview 
.wikibase-descriptionview-text {
+       line-height: 1.4;
+       padding-right: 0;
+}
+
+.wikibase-fingerprintview .wikibase-labelview,
+.wikibase-fingerprintview .wikibase-descriptionview {
+       display: block;
+       float: none;
+       margin-top: 0;
+       padding: 10px;
+       width: auto;
+}
+
+.wikibase-fingerprintview.wb-edit .wikibase-labelview,
+.wikibase-fingerprintview.wb-edit .wikibase-descriptionview {
+       padding: 9px 8px 9px 7px;
+}
+
+.wikibase-fingerprintview .wb-error {
+       background-color: #FFDFC9;
+}
+
+/* the right column of the site links table (...-toolbarparent) should be 
treated as "action" column */
+.wikibase-fingerprintview .wb-editsection {
+       width: 18em;
+       position: static; /* clear absolute positioning */
+       float: none; /* overwrite edit section's float: right */
+       padding: 0;
+       margin-left: 0; /* reset edit section's margin which is set in the 
toolbar group instead;
+                       applying margin to the edit section cell should not 
have any effect at all */
+}
+
+.wikibase-fingerprintview .wb-editsection .wikibase-toolbar {
+       width: 18em; /* additionally assign width to toolbar to enforce width 
in no-JS version */
+}
+
+.wikibase-fingerprintview .wb-editsection .wikibase-toolbar .wikibase-toolbar {
+       margin-left: 1px; /* even out table cell's right border */
+}
+
+.wikibase-fingerprintview .wb-editsection .wikibase-toolbar .wikibase-toolbar {
+       margin-left: 0; /* do not apply margin to nested toolbar groups */
+}
diff --git a/lib/resources/jquery.wikibase/toolbar/toolbareditgroup.js 
b/lib/resources/jquery.wikibase/toolbar/toolbareditgroup.js
index 2c2e9b1..f851861 100644
--- a/lib/resources/jquery.wikibase/toolbar/toolbareditgroup.js
+++ b/lib/resources/jquery.wikibase/toolbar/toolbareditgroup.js
@@ -351,6 +351,22 @@
        },
 
        /**
+        * @param {string} state
+        */
+       _setState: function( state ) {
+               // TODO: This special handling should not be necessary: Resolve 
toolbar state handling.
+               var self = this;
+
+               $.each( this.options.buttonCharacteristics, function( 
buttonName ) {
+                       if( self._buttons[buttonName] ) {
+                               self._buttons[buttonName].data( 'toolbarbutton' 
)[state]();
+                       }
+               } );
+
+               return true;
+       },
+
+       /**
         * Clones the toolbar edit group circumventing jQuery widget creation 
process.
         * @since 0.4
         *
diff --git a/lib/resources/templates.php b/lib/resources/templates.php
index 7a829d1..d546723 100644
--- a/lib/resources/templates.php
+++ b/lib/resources/templates.php
@@ -263,19 +263,17 @@
 </table>
 HTML;
 
-// make the wb-value-row a wb-property-container to start with the edit button 
stuff
-// $1: language-code
-       $templates['wb-term'] =
+       $templates['wikibase-fingerprintview'] =
 <<<HTML
-<tbody>
-       <tr class="wb-terms-label wb-terms-$1">
-               <td class="wb-terms-language wb-terms-language-$1" 
rowspan="2"><a href="$9">$2</a><!-- language name --></td>
-               <td class="wb-terms-label wb-terms-label-$1 wb-value 
wb-value-lang-$1 $7">$3<!-- label --></td>
-               <td class="wb-editsection">$5<!-- label toolbar --></td>
+<tbody class="wikibase-fingerprintview wikibase-fingerprintview-$1" >
+       <tr>
+               <td class="wikibase-fingerprintview-language" rowspan="2"><a 
href="$9">$2</a></td>
+               <td class="wikibase-fingerprintview-label $7">$3</td>
+               <!-- wb-edisection -->$5
        </tr>
-       <tr class="wb-terms-description wb-terms-$1">
-               <td class="wb-terms-description wb-terms-description-$1 
wb-value wb-value-lang-$1 $8">$4<!-- description --></td>
-               <td class="wb-editsection">$6<!-- description toolbar --></td>
+       <tr>
+               <td class="wikibase-fingerprintview-description $8">$4</td>
+               <!-- wb-editsection -->$6
        </tr>
 </tbody>
 HTML;
diff --git a/lib/resources/wikibase.css b/lib/resources/wikibase.css
index cebdd8b..c10a7b6 100644
--- a/lib/resources/wikibase.css
+++ b/lib/resources/wikibase.css
@@ -171,10 +171,6 @@
 
 /********** TERMS **********/
 
-.wb-terms .wb-value {
-    display: block;
-}
-
 h2.wb-terms-heading {
     float: left;
     width: 100%;
@@ -188,91 +184,16 @@
     border-spacing: 0;
     width: 100%;
     border-bottom: 1px solid #C9C9C9;
-}
-
-table.wb-terms .wb-terms-language {
-    width: 25%;
-    word-wrap: break-word;
-    padding-left: 10px;
-    border-left: 1px solid #C9C9C9;
-}
-
-table.wb-terms .wb-terms-term {
-    width: 75%;
-    word-wrap: break-word;
-    padding-left: 10px;
-}
-
-table.wb-terms {
     clear: both;
     border-right: 1px solid #C9C9C9;
 }
 
-table.wb-terms td {
-       background: #F0F0F0;
-       border-top: 1px solid #C9C9C9;
-}
-table.wb-terms tr:nth-child(4n) td,
-table.wb-terms tr:nth-child(4n-1) td {
+.wb-terms tr td {
        background: #F8F8F8;
 }
 
-table.wb-terms td.wb-terms-label {
-       padding: 10px;
-}
-
-table.wb-terms .wb-edit td.wb-terms-label {
-       padding: 8px 8px 9px 7px;
-}
-
-/* the right column of the site links table (...-toolbarparent) should be 
treated as "action" column */
-table.wb-terms .wb-editsection {
-    width: 18em;
-    position: static; /* clear absolute positioning */
-    float: none; /* overwrite edit section's float: right */
-    padding: 0;
-    margin-left: 0; /* reset edit section's margin which is set in the toolbar 
group instead;
-                       applying margin to the edit section cell should not 
have any effect at all */
-}
-
-table.wb-terms .wb-editsection .wikibase-toolbar {
-    width: 18em; /* additionally assign width to toolbar to enforce width in 
no-JS version */
-}
-
-table.wb-terms .wb-editsection .wikibase-toolbar .wikibase-toolbar {
-    margin-left: 1px; /* even out table cell's right border */
-}
-
-table.wb-terms .wb-editsection .wikibase-toolbar .wikibase-toolbar {
-    margin-left: 0; /* do not apply margin to nested toolbar groups */
-}
-
-table.wb-terms input {
-       font-family: inherit;
-       width: 100%;
-}
-
-.wb-terms .wikibase-descriptionview .wikibase-descriptionview-text {
-       line-height: 1.4;
-       padding-right: 0;
-}
-
-.wb-terms .wikibase-labelview,
-.wb-terms .wikibase-descriptionview {
-       display: block;
-       float: none;
-       margin-top: 0;
-       padding: 10px;
-       width: auto;
-}
-
-.wb-terms .wikibase-labelview.wb-edit,
-.wb-terms .wikibase-descriptionview.wb-edit {
-       padding: 9px 8px 9px 7px;
-}
-
-.wb-terms .wb-error {
-       background-color: #FFDFC9;
+.wb-terms tbody:nth-child(even) td {
+       background: #F0F0F0;
 }
 
 /********** /TERMS **********/
diff --git 
a/lib/tests/qunit/jquery.wikibase/jquery.wikibase.fingerprintview.tests.js 
b/lib/tests/qunit/jquery.wikibase/jquery.wikibase.fingerprintview.tests.js
new file mode 100644
index 0000000..2531ff6
--- /dev/null
+++ b/lib/tests/qunit/jquery.wikibase/jquery.wikibase.fingerprintview.tests.js
@@ -0,0 +1,225 @@
+/**
+ * @licence GNU GPL v2+
+ * @author H. Snater < mediaw...@snater.com >
+ */
+
+( function( $, wb, QUnit ) {
+'use strict';
+
+/**
+ * @param {Object} [options]
+ * @param {jQuery} [$node]
+ * @return {jQuery}
+ */
+var createFingerprintview = function( options, $node ) {
+       options = $.extend( {
+               entityId: 'i am an entity id',
+               api: 'i am an api',
+               value: {
+                       language: 'en',
+                       label: 'test label',
+                       description: 'test description'
+               }
+       }, options || {} );
+
+       $node = $node || $( '<div/>' ).appendTo( 'body' );
+
+       var $fingerprintview = $node
+               .addClass( 'test_fingerprintview' )
+               .fingerprintview( options );
+
+       $fingerprintview.data( 'fingerprintview' ).$label.data( 'labelview' 
)._save
+               = $fingerprintview.data( 'fingerprintview' ).$description.data( 
'descriptionview' )._save
+               = function() {
+                       return $.Deferred().resolve( {
+                               entity: {
+                                       lastrevid: 'i am a revision id'
+                               }
+                       } ).promise();
+               };
+
+       return $fingerprintview;
+};
+
+QUnit.module( 'jquery.wikibase.fingerprintview', QUnit.newMwEnvironment( {
+       teardown: function() {
+               $( '.test_fingerprintview' ).each( function() {
+                       var $fingerprintview = $( this ),
+                               fingerprintview = $fingerprintview.data( 
'fingerprintview' );
+
+                       if( fingerprintview ) {
+                               fingerprintview.destroy();
+                       }
+
+                       $fingerprintview.remove();
+               } );
+       }
+} ) );
+
+QUnit.test( 'Create & destroy', function( assert ) {
+       assert.throws(
+               function() {
+                       createFingerprintview( { value: null } );
+               },
+               'Throwing error when trying to initialize widget without a 
value.'
+       );
+
+       var $fingerprintview = createFingerprintview(),
+               fingerprintview = $fingerprintview.data( 'fingerprintview' );
+
+       assert.ok(
+               fingerprintview !== undefined,
+               'Created widget.'
+       );
+
+       fingerprintview.destroy();
+
+       assert.ok(
+               $fingerprintview.data( 'fingerprintview' ) === undefined,
+               'Destroyed widget.'
+       );
+} );
+
+QUnit.test( 'startEditing() & stopEditing()', 6, function( assert ) {
+       var $fingerprintview = createFingerprintview(),
+               fingerprintview = $fingerprintview.data( 'fingerprintview' );
+
+       $fingerprintview
+       .on( 'fingerprintviewafterstartediting', function( event ) {
+               assert.ok(
+                       true,
+                       'Started edit mode.'
+               );
+       } )
+       .on( 'fingerprintviewafterstopediting', function( event, dropValue ) {
+               assert.ok(
+                       true,
+                       'Stopped edit mode.'
+               );
+       } );
+
+       fingerprintview.startEditing();
+
+       fingerprintview.startEditing(); // should not trigger event
+       fingerprintview.stopEditing( true );
+       fingerprintview.stopEditing( true ); // should not trigger event
+       fingerprintview.stopEditing(); // should not trigger event
+       fingerprintview.startEditing();
+
+       fingerprintview.$label.find( 'input' ).val( '' );
+
+       fingerprintview.stopEditing();
+       fingerprintview.startEditing();
+
+       fingerprintview.$description.find( 'input' ).val( 'changed description' 
);
+
+       fingerprintview.stopEditing();
+} );
+
+QUnit.test( 'isInitialValue()', function( assert ) {
+       var $fingerprintview = createFingerprintview(),
+               fingerprintview = $fingerprintview.data( 'fingerprintview' );
+
+       fingerprintview.startEditing();
+
+       assert.ok(
+               fingerprintview.isInitialValue(),
+               'Verified isInitialValue() returning true.'
+       );
+
+       fingerprintview.$label.find( 'input' ).val( 'changed' );
+
+       assert.ok(
+               !fingerprintview.isInitialValue(),
+               'Verified isInitialValue() returning false after changing 
value.'
+       );
+
+       fingerprintview.$label.find( 'input' ).val( 'test label' );
+
+       assert.ok(
+               fingerprintview.isInitialValue(),
+               'Verified isInitialValue() returning true after resetting to 
initial value.'
+       );
+} );
+
+QUnit.test( 'setError()', function( assert ) {
+       var $fingerprintview = createFingerprintview(),
+               fingerprintview = $fingerprintview.data( 'fingerprintview' );
+
+       $fingerprintview
+       .on( 'fingerprintviewtoggleerror', function( event, error ) {
+               assert.ok(
+                       true,
+                       'Triggered "toggleerror" event.'
+               );
+       } );
+
+       fingerprintview.setError();
+} );
+
+QUnit.test( 'value()', function( assert ) {
+       var $fingerprintview = createFingerprintview(),
+               fingerprintview = $fingerprintview.data( 'fingerprintview' );
+
+       assert.throws(
+               function() {
+                       fingerprintview.value( null );
+               },
+               'Trying to set no value fails.'
+       );
+
+       fingerprintview.value( {
+               language: 'en',
+               label: 'changed label',
+               description: 'test description'
+       } );
+
+       assert.ok(
+               fingerprintview.value().label,
+               'changed label',
+               'Set new label.'
+       );
+
+       assert.equal(
+               fingerprintview.value().language,
+               'en',
+               'Did not change language.'
+       );
+
+       assert.equal(
+               fingerprintview.value().description,
+               'test description',
+               'Did not change description.'
+       );
+
+       fingerprintview.value( {
+               language: 'en',
+               label: 'test label',
+               description: null
+       } );
+
+       assert.equal(
+               fingerprintview.value().label,
+               'test label',
+               'Reset label.'
+       );
+
+       assert.strictEqual(
+               fingerprintview.value().description,
+               null,
+               'Removed description.'
+       );
+
+       assert.throws(
+               function() {
+                       fingerprintview.value( {
+                               language: 'de',
+                               label: 'test label',
+                               description: null
+                       } );
+               },
+               'Trying to change language fails.'
+       );
+} );
+
+}( jQuery, wikibase, QUnit ) );
diff --git a/lib/tests/qunit/jquery.wikibase/resources.php 
b/lib/tests/qunit/jquery.wikibase/resources.php
index 4d3f837..2664054 100644
--- a/lib/tests/qunit/jquery.wikibase/resources.php
+++ b/lib/tests/qunit/jquery.wikibase/resources.php
@@ -72,6 +72,15 @@
                        ),
                ),
 
+               'jquery.wikibase.fingerprintview.tests' => $moduleBase + array(
+                       'scripts' => array(
+                               'jquery.wikibase.fingerprintview.tests.js',
+                       ),
+                       'dependencies' => array(
+                               'jquery.wikibase.fingerprintview',
+                       ),
+               ),
+
                'jquery.wikibase.labelview.tests' => $moduleBase + array(
                        'scripts' => array(
                                'jquery.wikibase.labelview.tests.js',
diff --git a/repo/i18n/en.json b/repo/i18n/en.json
index 955743e..d809faa 100644
--- a/repo/i18n/en.json
+++ b/repo/i18n/en.json
@@ -33,6 +33,7 @@
        "wikibase-alias-edit-placeholder": "enter an alias",
        "wikibase-label-input-help-message": "Enter the label of this entity in 
$1.",
        "wikibase-description-input-help-message": "Enter a short description 
for this entity in $1.",
+       "wikibase-fingerprintview-input-help-message": "Enter the label of this 
entity and a short description in $1.",
        "wikibase-claims": "Claims",
        "wikibase-statements": "Statements",
        "wikibase-attributes": "Attributes",
diff --git a/repo/i18n/qqq.json b/repo/i18n/qqq.json
index d679eaf..59584f3 100644
--- a/repo/i18n/qqq.json
+++ b/repo/i18n/qqq.json
@@ -56,8 +56,9 @@
        "wikibase-sitelink-site-edit-placeholder": "[[File:Screenshot 
WikidataRepo 2012-05-13 E.png|right|0x150px]]\nThis is a generic text used as a 
placeholder while defining the site for a new sitelink. See also Wikidatas 
glossary on [[d:Wikidata:Glossary#sitelink|sitelink]].\n{{Identical|Site}}",
        "wikibase-sitelink-page-edit-placeholder": "[[File:Screenshot 
WikidataRepo 2012-05-13 E.png|right|0x150px]]\nThis is a generic text used as a 
placeholder while defining the page for a possibly new sitelink. See also 
Wikidatas glossary on 
[[d:Wikidata:Glossary#sitelink|sitelink]].\n{{Identical|Page}}",
        "wikibase-alias-edit-placeholder": "This is a generic placeholder 
message used while editing the list of aliases of an item. It is displayed in 
an empty input box which can be used to define a new alias.",
-       "wikibase-label-input-help-message": "[[File:Screenshot WikidataRepo 
2012-05-13 I.png|right|0x150px]]\nBubble help message for entering the label of 
the data set used for a specific item. Takes on additional argument ($1) that 
is the sub site identifier, i.e. \"English\" in nominative singular form. See 
also Wikidatas glossary for 
[[d:Wikidata:Glossary#languageattribute-label|label]] and 
[[d:Wikidata:Glossary#Item|item]].\n\nParameters:\n* $1 - language 
name\n{{Related|Wikibase-input-help-message}}",
-       "wikibase-description-input-help-message": "[[File:Screenshot 
WikidataRepo 2012-05-13 H.png|right|0x150px]]\nBubble help message for entering 
the description of the data set used for a specific item. Takes on additional 
argument that is the sub site identifier, ie. \"English\" in nominative 
singular form. See also Wikidatas glossary for 
[[d:Wikidata:Glossary#languageattribute-description|description]] and 
[[d:Wikidata:Glossary#Item|item]].\n\nParameters:\n* $1 - language 
name\n{{Related|Wikibase-input-help-message}}",
+       "wikibase-label-input-help-message": "[[File:Screenshot WikidataRepo 
2012-05-13 I.png|right|0x150px]]\nBubble help message for entering the label of 
the data set used for a specific item. Takes on additional argument ($1) that 
is the language name, i.e. \"English\" in nominative singular form. See also 
Wikidatas glossary for [[d:Wikidata:Glossary#Label|label]] and 
[[d:Wikidata:Glossary#Item|item]].\n\nParameters:\n* $1 - language 
name\n{{Related|Wikibase-input-help-message}}",
+       "wikibase-description-input-help-message": "[[File:Screenshot 
WikidataRepo 2012-05-13 H.png|right|0x150px]]\nBubble help message for entering 
the description of the data set used for a specific item. Takes on additional 
argument that is the language name, i.e. \"English\" in nominative singular 
form. See also Wikidatas glossary for 
[[d:Wikidata:Glossary#Description|description]] and 
[[d:Wikidata:Glossary#Item|item]].\n\nParameters:\n* $1 - language 
name\n{{Related|Wikibase-input-help-message}}",
+       "wikibase-fingerprintview-input-help-message": "Bubble help message for 
simultaneously editing label and description of the entity in another than the 
user interface language via the \"In other languages\" box. Takes on additional 
argument that is the language name, i.e. \"English\" in nominative singular 
form. See also Wikidatas glossary for 
[[d:Wikidata:Glossary#Language_attributes|language attributes]] and 
[[d:Wikidata:Glossary#Item|item]].\n\nParameters:\n* $1 - language 
name\n{{Related|Wikibase-input-help-message}}",
        "wikibase-claims": "Heading for the list of claims giving specific 
information about the currently viewed entity. See also Wikidata's glossary for 
[[m:d:Wikidata:Glossary#Claim|claim]].",
        "wikibase-statements": "Heading for the list of statements giving 
specific information about the currently viewed item. See also Wikidata's 
glossary for [[m:d:Wikidata:Glossary#Statement|statements]] and 
[[m:d:Wikidata:Glossary#Item|item]].",
        "wikibase-attributes": "Heading for the list of claims defining 
attributes for the currently viewed property. See also Wikidata's glossary for 
[[m:d:Wikidata:Glossary#Claims|claims]] and 
[[m:d:Wikidata:Glossary#Property|property]].\n{{Identical|Attribute}}",
diff --git a/repo/includes/View/TermBoxView.php 
b/repo/includes/View/TermBoxView.php
index 324f588..b817ede 100644
--- a/repo/includes/View/TermBoxView.php
+++ b/repo/includes/View/TermBoxView.php
@@ -72,10 +72,11 @@
 
                $html .= wfTemplate( 'wb-terms-heading', $this->msg( 
'wikibase-terms' ) );
 
-               $rowNumber = 0;
                foreach ( $languageCodes as $languageCode ) {
                        $label = array_key_exists( $languageCode, $labels ) ? 
$labels[$languageCode] : false;
-                       $description = array_key_exists( $languageCode, 
$descriptions ) ? $descriptions[$languageCode] : false;
+                       $description = array_key_exists( $languageCode, 
$descriptions )
+                               ? $descriptions[$languageCode]
+                               : false;
 
                        $editLabelSection = 
$this->sectionEditLinkGenerator->getHtmlForEditSection(
                                'SetLabel',
@@ -90,13 +91,19 @@
                                $editable
                        );
 
-                       $tbody .= wfTemplate( 'wb-term',
+                       $tbody .= wfTemplate( 'wikibase-fingerprintview',
                                $languageCode,
                                htmlspecialchars( Utils::fetchLanguageName( 
$languageCode ) ),
-                               htmlspecialchars( $label !== false ? $label : 
$this->msg( 'wikibase-label-empty' )->text() ),
-                               htmlspecialchars( $description !== false ? 
$description : $this->msg( 'wikibase-description-empty' )->text() ),
-                               $editLabelSection,
-                               $editDescriptionSection,
+                               htmlspecialchars( $label !== false
+                                       ? $label
+                                       : $this->msg( 'wikibase-label-empty' 
)->text()
+                               ),
+                               htmlspecialchars( $description !== false
+                                       ? $description
+                                       : $this->msg( 
'wikibase-description-empty' )->text()
+                               ),
+                               '<td>' . $editLabelSection . '</td>',
+                               '<td>' . $editDescriptionSection . '</td>',
                                $label !== false ? '' : 'wb-value-empty',
                                $description !== false ? '' : 'wb-value-empty',
                                $title->getLocalURL( array( 'setlang' => 
$languageCode ) )
diff --git a/repo/resources/Resources.php b/repo/resources/Resources.php
index e20eb86..bbe3326 100644
--- a/repo/resources/Resources.php
+++ b/repo/resources/Resources.php
@@ -79,16 +79,13 @@
                                'wikibase.initTermBox.js',
                        ),
                        'dependencies' => array(
-                               'jquery.wikibase.edittoolbar',
-                               'jquery.wikibase.toolbar',
-                               'jquery.wikibase.toolbarcontroller',
-                               'jquery.wikibase.toolbareditgroup',
-                               'mediawiki.Title',
+                               'jquery.wikibase.fingerprintview',
                                'wikibase',
                                'wikibase.templates',
                        ),
                        'messages' => array(
                                'wikibase-terms',
+                               'wikibase-fingerprintview-input-help-message',
                        )
                ),
 
diff --git a/repo/resources/wikibase.initTermBox.js 
b/repo/resources/wikibase.initTermBox.js
index 75fed45..9b6ed15 100644
--- a/repo/resources/wikibase.initTermBox.js
+++ b/repo/resources/wikibase.initTermBox.js
@@ -16,7 +16,7 @@
  */
 wb.initTermBox = function( entity, api ) {
        mw.hook( 'wikibase.domready' ).add( function() {
-               var $termBoxRows = $( 'tr.wb-terms-label, 
tr.wb-terms-description' ),
+               var $fingerprintview = $( '.wikibase-fingerprintview' ),
                        userSpecifiedLanguages = mw.config.get( 
'wbUserSpecifiedLanguages' ),
                        hasSpecifiedLanguages = userSpecifiedLanguages && 
userSpecifiedLanguages.length,
                        isUlsDefined = mw.uls !== undefined
@@ -24,104 +24,44 @@
                                && $.uls.data !== undefined;
 
                // Skip if having no extra languages is what the user wants
-               if( !$termBoxRows.length && !hasSpecifiedLanguages && 
isUlsDefined ) {
+               if( !$fingerprintview.length && !hasSpecifiedLanguages && 
isUlsDefined ) {
                        // No term box present; Ask ULS to provide languages 
and generate plain HTML
-                       var languageCodes = mw.uls.getFrequentLanguageList(),
-                               title = new mw.Title(
-                                       mw.config.get( 'wgTitle' ),
-                                       mw.config.get( 'wgNamespaceNumber' )
-                               );
+                       var languageCodes = mw.uls.getFrequentLanguageList();
 
                        if( !languageCodes.length ) {
                                return;
                        }
 
-                       var $sectionHeading = addTermBoxSection();
-                       $sectionHeading.after(
-                               renderTermBox( title, entity, 
languageCodes.slice( 1, 4 ) )
-                       );
+                       var $sectionHeading = addTermBoxSection(),
+                               $table = mw.template( 'wb-terms-table', '' );
 
-                       $termBoxRows = $( 'tr.wb-terms-label, 
tr.wb-terms-description' );
+                       $sectionHeading.after( $table );
+
+                       for( var i = 1; i < languageCodes.length && i < 5; i++ 
) {
+                               var languageCode = languageCodes[i];
+
+                               initFingerprintview(
+                                       $( '<tbody/>' ).appendTo( $table ), 
languageCode, entity, api
+                               );
+                       }
+
+                       return;
                }
 
-               $termBoxRows.each( function() {
-                       var $termsRow = $( this ),
+               $fingerprintview.each( function() {
+                       var $singleFingerprintview = $( this ),
                                languageCode;
 
                        // TODO: Find more sane way to figure out language code.
-                       $.each( $termsRow.attr( 'class' ).split( ' ' ), 
function( i, cssClass ) {
-                               if(
-                                       cssClass.indexOf( 'wb-terms-' ) === 0
-                                       && cssClass.indexOf( 'wb-terms-label' ) 
=== -1
-                                       && cssClass.indexOf( 
'wb-terms-description' ) === -1
-                               ) {
-                                       languageCode =  cssClass.replace( 
/wb-terms-/, '' );
+                       $.each( $singleFingerprintview.attr( 'class' ).split( ' 
' ), function( i, cssClass ) {
+                               if( cssClass.indexOf( 
'wikibase-fingerprintview-' ) === 0 ) {
+                                       languageCode =  cssClass.replace( 
/wikibase-fingerprintview-/, '' );
                                        return false;
                                }
                        } );
 
-                       if( $termsRow.hasClass( 'wb-terms-label' ) ) {
-                               $termsRow.children( 'td' ).eq( 1 ).labelview( {
-                                       value: {
-                                               language: languageCode,
-                                               label: entity.getLabel( 
languageCode )
-                                       },
-                                       helpMessage: mw.msg(
-                                               
'wikibase-label-input-help-message',
-                                               wb.getLanguageNameByCode( 
languageCode )
-                                       ),
-                                       entityId: entity.getId(),
-                                       api: api
-                               } );
-
-                               return true;
-                       }
-
-                       $termsRow.children( 'td' ).first().descriptionview( {
-                               value: {
-                                       language: languageCode,
-                                       description: entity.getDescription( 
languageCode )
-                               },
-                               helpMessage: mw.msg(
-                                       
'wikibase-description-input-help-message',
-                                       wb.getLanguageNameByCode( languageCode )
-                               ),
-                               entityId: entity.getId(),
-                               api: api
-                       } );
-
+                       initFingerprintview( $singleFingerprintview, 
languageCode, entity, api );
                } );
-
-               $( wb )
-               .on( 'startItemPageEditMode', function( event, origin ) {
-                       $termBoxRows.find( ':wikibase-labelview, 
:wikibase-descriptionview' )
-                       .not( origin )
-                       .each( function() {
-                               ( $( this ).data( 'labelview' ) || $( this 
).data( 'descriptionview' ) )
-                                       .disable();
-                               $( this ).data( 'edittoolbar' 
).toolbar.disable();
-                       } );
-               } )
-               .on( 'stopItemPageEditMode', function( event, origin ) {
-                       $termBoxRows.find( ':wikibase-labelview' ).each( 
function() {
-                               var labelview = $( this ).data( 'labelview' );
-
-                               if( labelview.value().label ) {
-                                       $( this ).data( 'edittoolbar' 
).toolbar.enable();
-                               }
-                               labelview.enable();
-                       } );
-
-                       $termBoxRows.find( ':wikibase-descriptionview' ).each( 
function() {
-                               var descriptionview = $( this ).data( 
'descriptionview' );
-
-                               if( descriptionview.value().description ) {
-                                       $( this ).data( 'edittoolbar' 
).toolbar.enable();
-                               }
-                               descriptionview.enable();
-                       } );
-               } );
-
        } );
 };
 
@@ -161,166 +101,26 @@
 }
 
 /**
- * @param {mediaWiki.Title} title
+ * @param {jQuery} $node
+ * @param {string} languageCode
  * @param {wikibase.datamodel.Entity} entity
- * @param {string[]} languageCodes
- * @return {jQuery|undefined}
+ * @param {wikibase.RepoApi} api
+ * @return {jQuery}
  */
-function renderTermBox( title, entity, languageCodes ) {
-       if( languageCodes === undefined ) {
-               return;
-       }
-       var labels = entity.getLabels(),
-               descriptions = entity.getDescriptions(),
-               $tbody = $();
-
-       for( var i = 0; i < languageCodes.length; i++ ) {
-               var languageCode = languageCodes[i];
-
-               $tbody = $tbody.add( mw.template( 'wb-term',
-                       languageCode,
-                       $.uls.data.getAutonym( languageCode ),
-                       labels.hasOwnProperty( languageCode ) ? 
labels[languageCode] : '',
-                       descriptions.hasOwnProperty( languageCode ) ? 
descriptions[languageCode] : '',
-                       '',
-                       '',
-                       '',
-                       '',
-                       title.getUrl( { setlang: languageCode } )
-               ) );
-       }
-
-       return mw.template( 'wb-terms-table', $tbody );
+function initFingerprintview( $node, languageCode, entity, api ) {
+       return $node.fingerprintview( {
+               value: {
+                       language: languageCode,
+                       label: entity.getLabel( languageCode ) || null,
+                       description: entity.getDescription( languageCode ) || 
null
+               },
+               entityId: entity.getId(),
+               api: api,
+               helpMessage: mw.msg(
+                       'wikibase-fingerprintview-input-help-message',
+                       wb.getLanguageNameByCode( languageCode )
+               )
+       } );
 }
-
-// TODO: Merge with native labelview/descriptionview toolbar definiton
-$.wikibase.toolbarcontroller.definition( 'edittoolbar', {
-       id: 'terms-labelview',
-       selector: '.wb-terms-label',
-       events: {
-               labelviewcreate: function( event, toolbarcontroller ) {
-                       var $labelview = $( event.target ),
-                               labelview = $labelview.data( 'labelview' );
-
-                       $labelview.edittoolbar( {
-                               $container: $labelview.next(),
-                               interactionWidgetName: 
$.wikibase.labelview.prototype.widgetName,
-                               enableRemove: false
-                       } );
-
-                       $labelview.on( 'keyup', function( event ) {
-                               if( labelview.option( 'disabled' ) ) {
-                                       return;
-                               }
-                               if( event.keyCode === $.ui.keyCode.ESCAPE ) {
-                                       labelview.stopEditing( true );
-                               } else if( event.keyCode === $.ui.keyCode.ENTER 
) {
-                                       labelview.stopEditing( false );
-                               }
-                       } );
-
-                       if( !labelview.value().label ) {
-                               labelview.startEditing();
-                       }
-               },
-               'labelviewchange labelviewafterstartediting': function( event ) 
{
-                       var $labelview = $( event.target ),
-                               labelview = $labelview.data( 'labelview' ),
-                               toolbar = $labelview.data( 'edittoolbar' 
).toolbar,
-                               $btnSave = toolbar.editGroup.getButton( 'save' 
),
-                               btnSave = $btnSave.data( 'toolbarbutton' ),
-                               enable = labelview.isValid() && 
!labelview.isInitialValue(),
-                               $btnCancel = toolbar.editGroup.getButton( 
'cancel' ),
-                               btnCancel = $btnCancel.data( 'toolbarbutton' ),
-                               currentLabel = labelview.value().label,
-                               disableCancel = !currentLabel && 
labelview.isInitialValue();
-
-                       btnSave[enable ? 'enable' : 'disable']();
-                       btnCancel[disableCancel ? 'disable' : 'enable']();
-               },
-               labelviewafterstopediting: function( event, dropValue ) {
-                       var $labelview = $( event.target ),
-                               labelview = $labelview.data( 'labelview' );
-
-                       if( !labelview.value().label ) {
-                               labelview.startEditing();
-                       }
-               },
-               toolbareditgroupedit: function( event, toolbarcontroller ) {
-                       var $labelview = $( event.target ).closest( 
':wikibase-edittoolbar' ),
-                               labelview = $labelview.data( 'labelview' );
-
-                       if( !labelview ) {
-                               return;
-                       }
-
-                       labelview.focus();
-               }
-       }
-} );
-$.wikibase.toolbarcontroller.definition( 'edittoolbar', {
-       id: 'terms-descriptionview',
-       selector: '.wb-terms-description',
-       events: {
-               descriptionviewcreate: function( event, toolbarcontroller ) {
-                       var $descriptionview = $( event.target ),
-                               descriptionview = $descriptionview.data( 
'descriptionview' );
-
-                       $descriptionview.edittoolbar( {
-                               $container: $descriptionview.next(),
-                               interactionWidgetName: 
$.wikibase.descriptionview.prototype.widgetName,
-                               enableRemove: false
-                       } );
-
-                       $descriptionview.on( 'keyup', function( event ) {
-                               if( descriptionview.option( 'disabled' ) ) {
-                                       return;
-                               }
-                               if( event.keyCode === $.ui.keyCode.ESCAPE ) {
-                                       descriptionview.stopEditing( true );
-                               } else if( event.keyCode === $.ui.keyCode.ENTER 
) {
-                                       descriptionview.stopEditing( false );
-                               }
-                       } );
-
-                       if( !descriptionview.value().description ) {
-                               descriptionview.startEditing();
-                       }
-               },
-               'descriptionviewchange descriptionviewafterstartediting': 
function( event ) {
-                       var $descriptionview = $( event.target ),
-                               descriptionview = $descriptionview.data( 
'descriptionview' ),
-                               toolbar = $descriptionview.data( 'edittoolbar' 
).toolbar,
-                               $btnSave = toolbar.editGroup.getButton( 'save' 
),
-                               btnSave = $btnSave.data( 'toolbarbutton' ),
-                               enable = descriptionview.isValid() && 
!descriptionview.isInitialValue(),
-                               $btnCancel = toolbar.editGroup.getButton( 
'cancel' ),
-                               btnCancel = $btnCancel.data( 'toolbarbutton' ),
-                               currentDescription = 
descriptionview.value().description,
-                               disableCancel = !currentDescription && 
descriptionview.isInitialValue();
-
-                       btnSave[enable ? 'enable' : 'disable']();
-                       btnCancel[disableCancel ? 'disable' : 'enable']();
-               },
-               descriptionviewafterstopediting: function( event, dropValue ) {
-                       var $descriptionview = $( event.target ),
-                               descriptionview = $descriptionview.data( 
'descriptionview' );
-
-                       if( !descriptionview.value().description ) {
-                               descriptionview.startEditing();
-                       }
-               },
-               toolbareditgroupedit: function( event, toolbarcontroller ) {
-                       var $descriptionview = $( event.target ).closest( 
':wikibase-edittoolbar' ),
-                               descriptionview = $descriptionview.data( 
'descriptionview' );
-
-                       if( !descriptionview ) {
-                               return;
-                       }
-
-                       descriptionview.focus();
-               }
-       }
-} );
 
 } )( jQuery, mediaWiki, wikibase );
diff --git a/repo/resources/wikibase.ui.entityViewInit.js 
b/repo/resources/wikibase.ui.entityViewInit.js
index 092549a..dd5bfd3 100644
--- a/repo/resources/wikibase.ui.entityViewInit.js
+++ b/repo/resources/wikibase.ui.entityViewInit.js
@@ -19,7 +19,8 @@
                $( '.wb-editsection:not(td)' ).remove();
 
                // remove all infos about empty values which are displayed in 
non-JS
-               $( '.wb-value-empty' ).empty().removeClass( 'wb-value-empty' );
+               $( '.wb-value-empty' ).not( '.wikibase-fingerprintview td' )
+                       .empty().removeClass( 'wb-value-empty' );
 
                // Since the DOM is altered for the property edit tools to 
initialize properly, the
                // following hook informs about these operations having 
finished.
@@ -181,10 +182,9 @@
                                'claimview',
                                'descriptionview',
                                'labelview',
+                               'fingerprintview',
                                'referenceview',
-                               'sitelinkview',
-                               'terms-labelview',
-                               'terms-descriptionview'
+                               'sitelinkview'
                        ],
                        removetoolbar: ['claim-qualifiers-snak', 
'referenceview-snakview-remove'],
                        movetoolbar: [

-- 
To view, visit https://gerrit.wikimedia.org/r/155533
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: Id0a2457d4083ada7d2a705ca0c255f0e8f744016
Gerrit-PatchSet: 15
Gerrit-Project: mediawiki/extensions/Wikibase
Gerrit-Branch: master
Gerrit-Owner: Henning Snater <henning.sna...@wikimedia.de>
Gerrit-Reviewer: Aude <aude.w...@gmail.com>
Gerrit-Reviewer: Henning Snater <henning.sna...@wikimedia.de>
Gerrit-Reviewer: Siebrand <siebr...@kitano.nl>
Gerrit-Reviewer: Tobias Gritschacher <tobias.gritschac...@wikimedia.de>
Gerrit-Reviewer: WikidataJenkins <wikidata-servi...@wikimedia.de>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to