Henning Snater has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/154394

Change subject: Implemented jQuery.wikibase.labelview
......................................................................

Implemented jQuery.wikibase.labelview

jQuery.wikibase.labelview replaces EditableLabel and LabelEditTool. 
PropertyEditTool and
corresponding components have become obsolete by this change set and are 
removed in a
subsequent change set.

Change-Id: Id36ab9c2dd0a3acb0c19e34c3ce8c8b2e7b954bb
---
M lib/WikibaseLib.hooks.php
M lib/resources/Resources.php
M lib/resources/jquery.wikibase/jquery.wikibase.descriptionview.js
A lib/resources/jquery.wikibase/jquery.wikibase.labelview.js
A lib/resources/jquery.wikibase/themes/default/jquery.wikibase.labelview.css
M lib/resources/templates.php
M lib/resources/wikibase.css
D lib/resources/wikibase.ui.LabelEditTool.js
D lib/resources/wikibase.ui.PropertyEditTool.EditableLabel.js
M lib/resources/wikibase.ui.PropertyEditTool.css
A lib/tests/qunit/jquery.wikibase/jquery.wikibase.labelview.tests.js
D lib/tests/qunit/wikibase.ui.LabelEditTool.tests.js
D lib/tests/qunit/wikibase.ui.PropertyEditTool.EditableLabel.tests.js
M repo/includes/EntityView.php
M repo/resources/Resources.php
M repo/resources/wikibase.ui.entityViewInit.js
M repo/resources/wikibase.ui.initTermBox.js
17 files changed, 961 insertions(+), 555 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Wikibase 
refs/changes/94/154394/6

diff --git a/lib/WikibaseLib.hooks.php b/lib/WikibaseLib.hooks.php
index f7c859a..e19c1d7 100644
--- a/lib/WikibaseLib.hooks.php
+++ b/lib/WikibaseLib.hooks.php
@@ -83,9 +83,7 @@
                                
'tests/qunit/wikibase.RepoApi/wikibase.RepoApi.tests.js',
                                
'tests/qunit/wikibase.RepoApi/wikibase.RepoApiError.tests.js',
 
-                               
'tests/qunit/wikibase.ui.LabelEditTool.tests.js',
                                
'tests/qunit/wikibase.ui.PropertyEditTool.tests.js',
-                               
'tests/qunit/wikibase.ui.PropertyEditTool.EditableLabel.tests.js',
                                
'tests/qunit/wikibase.ui.PropertyEditTool.EditableValue.tests.js',
                                
'tests/qunit/wikibase.ui.PropertyEditTool.EditableValue.Interface.tests.js',
 
@@ -170,6 +168,15 @@
                        ),
                );
 
+               $testModules['qunit']['jquery.wikibase.labelview.tests'] = 
$moduleBase + array(
+                       'scripts' => array(
+                               
'tests/qunit/jquery.wikibase/jquery.wikibase.labelview.tests.js',
+                       ),
+                       'dependencies' => array(
+                               'jquery.wikibase.labelview',
+                       ),
+               );
+
                $testModules['qunit']['jquery.wikibase.listview.tests'] = 
$moduleBase + array(
                        'scripts' => array(
                                
'tests/qunit/jquery.wikibase/jquery.wikibase.listview.tests.js',
diff --git a/lib/resources/Resources.php b/lib/resources/Resources.php
index dc36178..0ec5dc9 100644
--- a/lib/resources/Resources.php
+++ b/lib/resources/Resources.php
@@ -299,8 +299,6 @@
                                'wikibase.ui.PropertyEditTool.js',
                                'wikibase.ui.PropertyEditTool.EditableValue.js',
                                
'wikibase.ui.PropertyEditTool.EditableValue.Interface.js',
-                               'wikibase.ui.PropertyEditTool.EditableLabel.js',
-                               'wikibase.ui.LabelEditTool.js',
                        ),
                        'styles' => array(
                                'wikibase.ui.PropertyEditTool.css'
@@ -502,6 +500,23 @@
                        ),
                ),
 
+               'jquery.wikibase.labelview' => $moduleTemplate + array(
+                       'scripts' => array(
+                               'jquery.wikibase/jquery.wikibase.labelview.js'
+                       ),
+                       'styles' => array(
+                               
'jquery.wikibase/themes/default/jquery.wikibase.labelview.css',
+                       ),
+                       'dependencies' => array(
+                               'jquery',
+                               'jquery.ui.TemplatedWidget',
+                               'jquery.wikibase.edittoolbar',
+                               'jquery.wikibase.toolbarcontroller',
+                               'wikibase',
+                               'wikibase.RepoApiError',
+                       ),
+               ),
+
                'jquery.wikibase.sitelinkgroupview' => $moduleTemplate + array(
                        'scripts' => array(
                                
'jquery.wikibase/jquery.wikibase.sitelinkgroupview.js'
diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.descriptionview.js 
b/lib/resources/jquery.wikibase/jquery.wikibase.descriptionview.js
index 0f548ad..d5c41a9 100644
--- a/lib/resources/jquery.wikibase/jquery.wikibase.descriptionview.js
+++ b/lib/resources/jquery.wikibase/jquery.wikibase.descriptionview.js
@@ -98,7 +98,7 @@
                } )
                .on(
                        'descriptionviewafterstopediting.' + this.widgetName
-                               + ' eachchange.' + this.widgetName,
+                       + ' eachchange.' + this.widgetName,
                function( event, dropValue ) {
                        if(
                                event.type !== 'eachchange'
diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.labelview.js 
b/lib/resources/jquery.wikibase/jquery.wikibase.labelview.js
new file mode 100644
index 0000000..c6abab9
--- /dev/null
+++ b/lib/resources/jquery.wikibase/jquery.wikibase.labelview.js
@@ -0,0 +1,460 @@
+/**
+ * @licence GNU GPL v2+
+ * @author H. Snater < mediaw...@snater.com >
+ */
+( function( $, mw, wb ) {
+       'use strict';
+
+       var PARENT = $.ui.TemplatedWidget;
+
+/**
+ * Manages a label.
+ * @since 0.5
+ * @extends jQuery.ui.TemplatedWidget
+ *
+ * @option {Object|null} value
+ *         Object representing the widget's value.
+ *         Structure: { language: <{string}>, label: <{string|null}> }
+ *
+ * @option {string} [helpMessage]
+ *         Default: mw.msg( 'wikibase-label-input-help-message' )
+ *
+ * @options {string} entityId
+ *
+ * @option {wikibase.RepoApi} api
+ *
+ * @option {wikibase.store.EntityStore} entityStore
+ *
+ * @option {boolean} [showEntityId]
+ *         Default: false
+ */
+$.widget( 'wikibase.labelview', PARENT, {
+       /**
+        * @see jQuery.ui.TemplatedWidget.options
+        */
+       options: {
+               template: 'wikibase-labelview',
+               templateParams: [
+                       '', // additional class
+                       '', // text
+                       '', // entity id
+                       '' // toolbar
+               ],
+               templateShortCuts: {
+                       '$text': '.wikibase-labelview-text',
+                       '$entityId': '.wikibase-labelview-entityid'
+               },
+               value: null,
+               helpMessage: mw.msg( 'wikibase-label-input-help-message' ),
+               entityId: null,
+               api: null,
+               showEntityId: false
+       },
+
+       /**
+        * @type {boolean}
+        */
+       _isInEditMode: false,
+
+       /**
+        * @see jQuery.ui.TemplatedWidget._create
+        *
+        * @throws {Error} if required parameters are not specified properly.
+        */
+       _create: function() {
+               if( !this.options.entityId || !this.options.api ) {
+                       throw new Error( 'Required parameter(s) missing' );
+               }
+
+               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):
+               .on(
+                       'labelviewafterstartediting.' + this.widgetName
+                       + ' eachchange.' + this.widgetName,
+               function( event ) {
+                       if( !self.value().label ) {
+                               // Since the widget shall not be in view mode 
when there is no value, triggering
+                               // the event without a proper value is only 
done when creating the widget. Disabling
+                               // other edit buttons shall be avoided.
+                               // TODO: Move logic to a sensible place.
+                               self.element.addClass( 'wb-empty' );
+                               return;
+                       }
+
+                       self.element.removeClass( 'wb-empty' );
+
+                       $( wb ).trigger( 'startItemPageEditMode', [
+                               self.element,
+                               {
+                                       exclusive: false,
+                                       wbCopyrightWarningGravity: 'sw'
+                               }
+                       ] );
+               } )
+               .on(
+                       'labelviewafterstopediting.' + this.widgetName
+                       + ' eachchange.' + this.widgetName,
+               function( event, dropValue ) {
+                       if(
+                               event.type !== 'eachchange'
+                               || !self.options.value.label && 
!self.value().label
+                       ) {
+                               $( wb ).trigger( 'stopItemPageEditMode', [
+                                       self.element,
+                                       { save: dropValue !== true }
+                               ] );
+                       }
+               } );
+       },
+
+       /**
+        * @see jQuery.ui.TemplatedWidget.destroy
+        */
+       destroy: function() {
+               if( this._isInEditMode ) {
+                       var self = this;
+
+                       this.element.one( this.widgetEventPrefix + 
'afterstopediting', function( event ) {
+                               PARENT.prototype.destroy.call( self );
+                       } );
+
+                       this.cancelEditing();
+               } else {
+                       PARENT.prototype.destroy.call( this );
+               }
+       },
+
+       /**
+        * Main draw routine.
+        */
+       _draw: function() {
+               if( !this._isInEditMode ) {
+                       this.element.removeClass( 'wb-edit' );
+                       this.$text.text( this.options.value.label );
+                       if( this.options.showEntityId ) {
+                               this.$entityId.text( mw.msg( 'parentheses', 
this.options.entityId ) );
+                       }
+                       return;
+               }
+
+               // TODO: Inject correct placeholder via options
+               var self = this,
+                       languageName = wb.getLanguageNameByCode( 
this.options.value.language ),
+                       placeholder = mw.msg( 'wikibase-label-edit-placeholder' 
);
+
+               if( languageName ) {
+                       placeholder = mw.msg(
+                               
'wikibase-label-edit-placeholder-language-aware',
+                               languageName
+                       );
+               }
+
+               var $input = $( '<input/>' )
+               .attr( 'placeholder', placeholder )
+               .on( 'eachchange.' + this.widgetName, function( event ) {
+                       self._trigger( 'change' );
+               } );
+
+               if( this.options.value.label ) {
+                       $input.val( this.options.value.label );
+               }
+
+               this.element.addClass( 'wb-edit' );
+               this.$text.empty().append( $input );
+
+               this.$entityId.empty();
+       },
+
+       /**
+        * Starts the widget's edit mode.
+        */
+       startEditing: function() {
+               if( this._isInEditMode ) {
+                       return;
+               }
+
+               this._isInEditMode = true;
+               this._draw();
+
+               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;
+               }
+
+               if( dropValue ) {
+                       this._afterStopEditing( dropValue );
+                       return;
+               }
+
+               this.disable();
+
+               this._trigger( 'stopediting', null, [dropValue] );
+
+               // TODO: Performing API interaction should be managed in parent 
component (probably
+               // entityview)
+               this._save()
+               .done( function( response ) {
+                       wb.getRevisionStore().setLabelRevision( 
response.entity.lastrevid );
+                       self.enable();
+                       self._afterStopEditing( dropValue );
+               } )
+               .fail( function( errorCode, details ) {
+                       // TODO: API should return an Error object
+                       var error = wb.RepoApiError.newFromApiResponse( 
errorCode, details, 'save' );
+                       self.setError( error );
+                       self.enable();
+               } );
+       },
+
+       /**
+        * @return {jQuery.Promise}
+        */
+       _save: function() {
+               return this.options.api.setLabel(
+                       this.options.entityId,
+                       wb.getRevisionStore().getLabelRevision(),
+                       this.value().label || '',
+                       this.options.value.language
+               );
+       },
+
+       /**
+        * Cancels the widget's edit mode.
+        */
+       cancelEditing: function() {
+               this.stopEditing( true );
+       },
+
+       /**
+        * Callback tearing down edit mode.
+        *
+        * @param {boolean} dropValue
+        */
+       _afterStopEditing: function( dropValue ) {
+               if( !dropValue ) {
+                       this.options.value = this.value();
+               } else if( !this.options.value.label ) {
+                       this.$text.children( 'input' ).val( '' );
+                       this._trigger( 'change' );
+               }
+
+               this._isInEditMode = false;
+               this._draw();
+
+               this._trigger( 'afterstopediting', null, [dropValue] );
+       },
+
+       /**
+        * @return {boolean}
+        */
+       isValid: function() {
+               // Function is required by edittoolbar definition.
+               return true;
+       },
+
+       /**
+        * @return {boolean}
+        */
+       isInitialValue: function() {
+               var initialValue = this.options.value,
+                       currentValue = this.value();
+
+               return currentValue.language === initialValue.language
+                       && currentValue.label === initialValue.label;
+       },
+
+       /**
+        * Toggles 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' );
+               }
+       },
+
+       /**
+        * @see jQuery.ui.TemplatedWidget._setOption
+        */
+       _setOption: function( key, value ) {
+               if( key === 'value' ) {
+                       value = this._checkValue( value );
+               }
+               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;
+               }
+
+               return value;
+       },
+
+       /**
+        * Gets/Sets the widget's value.
+        *
+        * @param {Object} [value]
+        * @return {Object|undefined}
+        */
+       value: function( value ) {
+               if( value !== undefined ) {
+                       this.option( 'value', value );
+                       return;
+               }
+
+               if( !this._isInEditMode ) {
+                       return this.option( 'value' );
+               }
+
+               var text = $.trim( this.$text.children( 'input' ).val() );
+
+               return {
+                       language: this.options.value.language,
+                       label: text !== '' ? text : null
+               };
+       },
+
+       /**
+        * Puts Keyboard focus on the widget.
+        */
+       focus: function() {
+               if( this._isInEditMode ) {
+                       this.$text.children( 'input' ).focus();
+               }
+       },
+
+       /**
+        * @see jQuery.ui.TemplatedWidget.disable
+        */
+       disable: function() {
+               if( this._isInEditMode ) {
+                       this.$text.children( 'input' ).prop( 'disabled', true );
+               }
+
+               return PARENT.prototype.disable.call( this );
+       },
+
+       /**
+        * @see jQuery.ui.TemplatedWidget.enable
+        */
+       enable: function() {
+               if( this._isInEditMode ) {
+                       this.$text.children( 'input' ).prop( 'disabled', false 
);
+               }
+
+               return PARENT.prototype.enable.call( this );
+       }
+
+} );
+
+$.wikibase.toolbarcontroller.definition( 'edittoolbar', {
+       id: 'labelview',
+       events: {
+               labelviewcreate: function( event, toolbarcontroller ) {
+                       var $labelview = $( event.target ),
+                               labelview = $labelview.data( 'labelview' );
+
+                       $labelview.edittoolbar( {
+                               $container: $labelview.find( 
'.wikibase-labelview-container' ),
+                               interactionWidgetName: 
$.wikibase.labelview.prototype.widgetName,
+                               enableRemove: false
+                       } );
+
+                       $labelview.on( 'keyup', function( event ) {
+                               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();
+                       }
+
+                       $labelview
+                       .off( 'labelviewafterstopediting.edittoolbar' )
+                       .on( 'labelviewafterstopediting', function( event ) {
+                               var edittoolbar = $( event.target ).data( 
'edittoolbar' );
+                               if( labelview.value().label ) {
+                                       
edittoolbar.toolbar.editGroup.toNonEditMode();
+                               } else {
+                                       labelview.startEditing();
+                               }
+
+                               edittoolbar.enable();
+                               edittoolbar.toggleActionMessage( function() {
+                                       
edittoolbar.toolbar.editGroup.getButton( 'edit' ).focus();
+                               } );
+                       } );
+               },
+               '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']();
+               },
+               toolbareditgroupedit: function( event, toolbarcontroller ) {
+                       var $labelview = $( event.target ).closest( 
':wikibase-edittoolbar' ),
+                               labelview = $labelview.data( 'labelview' );
+
+                       if( !labelview ) {
+                               return;
+                       }
+
+                       labelview.focus();
+               }
+       }
+} );
+
+}( jQuery, mediaWiki, wikibase ) );
diff --git 
a/lib/resources/jquery.wikibase/themes/default/jquery.wikibase.labelview.css 
b/lib/resources/jquery.wikibase/themes/default/jquery.wikibase.labelview.css
new file mode 100644
index 0000000..2a65104
--- /dev/null
+++ b/lib/resources/jquery.wikibase/themes/default/jquery.wikibase.labelview.css
@@ -0,0 +1,118 @@
+/**
+ * @licence GNU GPL v2+
+ * @author H. Snater < mediaw...@snater.com >
+ */
+/* TODO: Re-evaluate all styles and clean-up */
+.wikibase-labelview {
+       float: left;
+       position: relative;
+       width: 100%;
+}
+
+.wb-firstHeading .wikibase-labelview-container.wb-edit 
.wikibase-labelview-container {
+       background-color: #D6F3FF;
+}
+.wb-firstHeading .wikibase-labelview-container.wb-empty 
.wikibase-labelview-container {
+       background-color: inherit;
+}
+
+.wb-firstHeading .wikibase-labelview-container {
+       margin: .3em .3em .13em 0;
+       padding-right: 19em;
+}
+
+.wb-firstHeading .wikibase-labelview .wikibase-labelview-container {
+       margin-left: 10px;
+       word-wrap: break-word;
+}
+
+.wb-firstHeading .wikibase-labelview.wb-edit .wikibase-labelview-container {
+       margin-left: 7px;
+}
+
+.wb-firstHeading .wikibase-labelview-text {
+       font-size: 188%;
+       line-height: 1.2;
+}
+
+.wikibase-labelview .wikibase-labelview-entityid {
+       color: #A1A1A1;
+}
+
+#content .wb-firstHeading {
+       font-size: 100%; /* required since Gerrit 
Ic5ba836364d04b2c3814777b69b5f47fce25292a */
+}
+
+.wb-firstHeading {
+       border-bottom: 0;
+       margin-bottom: 0; /* FIXME: Should be removed if the Typography refresh 
is stable */
+       padding-top: 0; /* FIXME: Should be removed if the Typography refresh 
is stable */
+       clear: both; /* so success bar after new item created won't float 
heading */
+}
+
+.wb-firstHeading span {
+       line-height: 100%;
+}
+
+.wikibase-labelview .wikibase-labelview-entityid {
+       /* In RTL UI, if the last word of the label is LTR,
+        * the supplement will get jumbled without isolation */
+       unicode-bidi: -moz-isolate;
+       unicode-bidi: -webkit-isolate;
+       unicode-bidi: isolate;
+}
+
+.wb-firstHeading .wb-editsection {
+       /* this nodes font size will affect the toolbar padding which is 
specified in em; therefore, the
+       font size should be the same as on every other toolbar container node */
+       font-size: 100%;
+}
+
+/* vertical positioning */
+/* the following lines are used to vertically position the toolbar on the 
baseline of the heading
+(label) which has a bigger font size */
+.wb-firstHeading .wb-editsection {
+       /* FIXME: Should use the LESS variable @content-font-family */
+       font-family: sans-serif;
+       line-height: 188%;
+       top: .3em; /* even out margin of label container in view mode */
+}
+.wb-firstHeading .wikibase-toolbar {
+       font-size: 100%;
+       line-height: 1.2; /* adjust to height of value */
+       padding-top: 1px; /* even out border of input box */
+}
+
+.wb-firstHeading .wikibase-toolbar .wikibase-toolbareditgroup {
+       font-size: 53%;
+       margin-bottom: 2px;
+}
+.wb-firstHeading .wikibase-toolbar .wikibase-toolbar, /* inner group (buttons) 
*/
+.wb-firstHeading .wikibase-toolbar .wikibase-toolbarlabel /* tooltip */ {
+       font-size: 100%;
+       margin-bottom: 0; /* even out border of label container in view mode */
+}
+
+.wikibase-labelview input {
+       width: 100%;
+       font-family: inherit;
+       font-size: inherit;
+       height: 1.2em;
+}
+
+/* The wait message displayed when saving the label has to be customized due 
to diverging font
+sizes and line heights within the heading */
+.wikibase-labelview .wb-actionmsg {
+       display: inline-block;
+       font-size: 188%;
+       line-height: 1.2;
+       padding-top: 1px;
+       margin: 0;
+}
+.wikibase-labelview .wb-actionmsg span {
+       font-size: 53%;
+}
+
+.wb-firstHeading .wb-editsection > .wikibase-toolbar {
+       font-size: 188%;
+}
diff --git a/lib/resources/templates.php b/lib/resources/templates.php
index 813b00c..305552f 100644
--- a/lib/resources/templates.php
+++ b/lib/resources/templates.php
@@ -159,14 +159,27 @@
 </div>
 HTML;
 
-       $templates['wb-label'] =
+       $templates['wikibase-h1'] =
 // add an h1 for displaying the entity's label; the actual firstHeading is 
being hidden by
 // css since the original MediaWiki DOM does not represent a Wikidata entity's 
structure
 // where the combination of label and description is the unique "title" of an 
entity which
 // should not be semantically disconnected by having elements in between, like 
siteSub,
 // contentSub and jump-to-nav
 <<<HTML
-<h1 id="wb-firstHeading-$1" class="wb-firstHeading wb-value-row">$2</h1>
+<h1 id="wb-firstHeading-$1" class="wb-firstHeading">
+       <!-- wikibase-labelview -->$2
+</h1>
+HTML;
+
+       $templates['wikibase-labelview'] =
+<<<HTML
+<div class="wikibase-labelview $1">
+       <div class="wikibase-labelview-container">
+               <span class="wikibase-labelview-text">$2</span>
+               <span class="wikibase-labelview-entityid">$3</span>
+               <!-- wikibase-toolbar -->$4
+       </div>
+</div>
 HTML;
 
        $templates['wikibase-descriptionview'] =
diff --git a/lib/resources/wikibase.css b/lib/resources/wikibase.css
index a6c905b..8367da0 100644
--- a/lib/resources/wikibase.css
+++ b/lib/resources/wikibase.css
@@ -160,88 +160,6 @@
 /********** /BASIC LAYOUT **********/
 
 
-/********** LABEL & DESCRIPTION **********/
-
-.wb-ui-labeledittool .wb-value-container {
-       padding-right: 19em; /* width of toolbar + white space border */
-}
-
-/********** LABEL **********/
-
-#content .wb-firstHeading {
-       font-size: 100%; /* required since Gerrit 
Ic5ba836364d04b2c3814777b69b5f47fce25292a */
-}
-
-.wb-firstHeading {
-       border-bottom: 0;
-       margin-bottom: 0; /* FIXME: Should be removed if the Typography refresh 
is stable */
-       padding-top: 0; /* FIXME: Should be removed if the Typography refresh 
is stable */
-       clear: both; /* so success bar after new item created won't float 
heading */
-}
-
-.wb-firstHeading span {
-       line-height: 100%;
-}
-
-/* the label edit tool styles have to be further customized due to the 
differing font sizes of the
-label and its toolbar */
-
-/* preventing layout jittering toggling between view and edit mode */
-.wb-firstHeading .wb-value {
-       font-size: 188%;
-       line-height: 1.2; /* adjust line height to input box height in edit 
mode */
-       padding: 1px 0; /* even out border of input box in edit mode */
-}
-
-.wb-firstHeading .wb-value-supplement {
-       line-height: 188%;
-       /* In RTL UI, if the last word of the label is LTR,
-        * the supplement will get jumbled without isolation */
-       unicode-bidi: -moz-isolate;
-       unicode-bidi: -webkit-isolate;
-       unicode-bidi: isolate;
-}
-
-.wb-firstHeading .wb-value-container {
-       display: block;
-       margin: .3em .3em .13em 10px; /* h1 natively has 0.17em bottom padding 
to avoid clipping */
-}
-
-.wb-firstHeading .wb-editsection {
-       /* this nodes font size will affect the toolbar padding which is 
specified in em; therefore, the
-       font size should be the same as on every other toolbar container node */
-       font-size: 100%;
-}
-
-/* vertical positioning */
-/* the following lines are used to vertically position the toolbar on the 
baseline of the heading
-(label) which has a bigger font size */
-.wb-firstHeading .wb-editsection {
-       /* FIXME: Should use the LESS variable @content-font-family */
-       font-family: sans-serif;
-       line-height: 188%;
-       top: .3em; /* even out margin of label container in view mode */
-}
-.wb-firstHeading .wikibase-toolbar {
-       font-size: 188%;
-       line-height: 1.2; /* adjust to height of value */
-       padding-top: 1px; /* even out border of input box */
-}
-.wb-firstHeading .wikibase-toolbar .wikibase-toolbareditgroup {
-       font-size: 53%;
-       margin-bottom: 2px;
-}
-.wb-firstHeading .wikibase-toolbar .wikibase-toolbar, /* inner group (buttons) 
*/
-.wb-firstHeading .wikibase-toolbar .wikibase-toolbarlabel /* tooltip */ {
-       font-size: 100%;
-       margin-bottom: 0; /* even out border of label container in view mode */
-}
-
-/********** /LABEL **********/
-
-/********** /LABEL & DESCRIPTION **********/
-
-
 /********** TERMS **********/
 
 .wb-terms .wb-value {
@@ -332,6 +250,7 @@
        padding-right: 0;
 }
 
+.wb-terms .wikibase-labelview,
 .wb-terms .wikibase-descriptionview {
        display: block;
        float: none;
@@ -340,6 +259,7 @@
        width: auto;
 }
 
+.wb-terms .wikibase-labelview.wb-edit,
 .wb-terms .wikibase-descriptionview.wb-edit {
        padding: 9px 8px 9px 7px;
 }
diff --git a/lib/resources/wikibase.ui.LabelEditTool.js 
b/lib/resources/wikibase.ui.LabelEditTool.js
deleted file mode 100644
index 97a7aba..0000000
--- a/lib/resources/wikibase.ui.LabelEditTool.js
+++ /dev/null
@@ -1,60 +0,0 @@
-/**
- * @licence GNU GPL v2+
- * @author Daniel Werner < daniel.werner at wikimedia.de >
- */
-( function( mw, wb, util, $ ) {
-'use strict';
-var PARENT = wb.ui.PropertyEditTool;
-
-/**
- * Module for 'Wikibase' extensions user interface functionality for editing 
the heading representing an items label.
- * @constructor
- * @see wb.ui.PropertyEditTool
- * @since 0.1
- */
-wb.ui.LabelEditTool = util.inherit( PARENT, {
-       /**
-        * @see wb.ui.SECONDARY_UI_CLASSES
-        */
-       SECONDARY_UI_CLASSES: PARENT.prototype.SECONDARY_UI_CLASSES + ' 
wb-ui-labeledittool',
-
-       /**
-        * @see wb.ui.PropertyEditTool._getValueElems()
-        */
-       _getValueElems: function() {
-               return this._subject.children( 'h1.wb-firstHeading span' );
-       },
-
-       /**
-        * @see wb.ui.PropertyEditTool._init()
-        */
-       _init: function( subject, options ) {
-               // setting default options
-               options = $.extend( {}, PARENT.prototype._options, {
-                       /**
-                        * @see 
wikibase.ui.PropertyEditTool.allowsMultipleValues
-                        */
-                       allowsMultipleValues: false
-               }, options );
-               PARENT.prototype._init.call( this, subject, options );
-       },
-
-       /**
-        * @see wb.ui.PropertyEditTool.getPropertyName()
-        *
-        * @return string 'label'
-        */
-       getPropertyName: function() {
-               return 'label';
-       },
-
-       /**
-        * @see wb.ui.PropertyEditTool.getEditableValuePrototype
-        */
-       getEditableValuePrototype: function() {
-               return PARENT.EditableLabel;
-       }
-
-} );
-
-} )( mediaWiki, wikibase, util, jQuery );
diff --git a/lib/resources/wikibase.ui.PropertyEditTool.EditableLabel.js 
b/lib/resources/wikibase.ui.PropertyEditTool.EditableLabel.js
deleted file mode 100644
index 886c3cc..0000000
--- a/lib/resources/wikibase.ui.PropertyEditTool.EditableLabel.js
+++ /dev/null
@@ -1,115 +0,0 @@
-/**
- * @licence GNU GPL v2+
- * @author Daniel Werner
- * @author Tobias Gritschacher
- */
-( function( mw, wb, util, $ ) {
-'use strict';
-
-var PARENT = wb.ui.PropertyEditTool.EditableValue;
-
-/**
- * Serves the input interface for the label of an item, extends EditableValue.
- * @constructor
- * @extends wb.ui.PropertyEditTool.EditableValue
- * @since 0.1
- */
-var SELF = wb.ui.PropertyEditTool.EditableLabel = util.inherit( PARENT, {
-       /**
-        * @see wikibase.ui.PropertyEditTool.EditableValue.API_VALUE_KEY
-        */
-       API_VALUE_KEY: 'labels',
-
-       /**
-        * @see wb.ui.PropertyEditTool.EditableValue._options
-        */
-       _options: $.extend( {}, PARENT.prototype._options, {
-               inputHelpMessageKey: 'wikibase-label-input-help-message'
-       } ),
-
-       /**
-        * see wb.ui.PropertyEditTool.EditableValue.startEditing
-        */
-       startEditing: function() {
-               var self = this;
-               return PARENT.prototype.startEditing.call( this ).done( 
function() {
-                       if( !self._interfaces[0].isEmpty() ) {
-                               self._subject.children( '.wb-value-supplement' 
).hide();
-                       }
-               }) ;
-       },
-
-       /**
-        * @see wb.ui.PropertyEditTool.EditableValue.stopEditing
-        */
-       stopEditing: function( save ) {
-               var self = this;
-               return PARENT.prototype.stopEditing.call( this, save ).done( 
function() {
-                       self._subject.children( '.wb-value-supplement' ).show();
-               } );
-       },
-
-       /**
-        * @see 
wikibase.ui.PropertyEditTool.EditableValue._setRevisionIdFromApiResponse
-        */
-       _setRevisionIdFromApiResponse: function( response ) {
-               wb.getRevisionStore().setLabelRevision( response.lastrevid );
-               return true;
-       },
-
-       /**
-        * Calling the corresponding method in the wikibase.RepoApi
-        *
-        * @return {jQuery.Promise}
-        */
-       queryApi: function() {
-               return this._api.setLabel(
-                       mw.config.get( 'wbEntityId' ),
-                       wb.getRevisionStore().getLabelRevision(),
-                       this.getValue().toString(),
-                       this.getValueLanguageContext()
-               );
-       }
-} );
-
-/**
- * @see wb.ui.PropertyEditTool.EditableValue.newFromDom
- */
-SELF.newFromDom = function( subject, options, toolbar ) {
-       var ev = wb.ui.PropertyEditTool.EditableValue,
-               $subject = $( subject ),
-               $interfaceParent = $subject.find( '.wb-value' ).first(),
-               languageName, placeHolderMsg, simpleInterface;
-
-       options = options || {};
-       options.valueLanguageContext =
-               options.valueLanguageContext || 
ev.getValueLanguageContextFromDom( $interfaceParent );
-
-       languageName = wb.getLanguageNameByCode( options.valueLanguageContext );
-
-       if ( languageName ) {
-               placeHolderMsg = mw.msg(
-                       'wikibase-label-edit-placeholder-language-aware',
-                       languageName
-               );
-       } else {
-               placeHolderMsg = mw.msg( 'wikibase-label-edit-placeholder' );
-       }
-
-       simpleInterface = new ev.Interface( $interfaceParent, {
-               'inputPlaceholder': placeHolderMsg,
-               'autoExpand': false
-       } );
-
-       // TODO: get rid of this
-       simpleInterface.normalize = function( value ) {
-               value = ev.Interface.prototype.normalize.call( this, value );
-               // make sure we don't ever allow two+ sequential spaces in an 
item's label:
-               value = value.replace( /\s+/g, ' ' );
-               return value;
-       };
-
-       return new SELF( $subject, options, simpleInterface, toolbar );
-};
-
-}( mediaWiki, wikibase, util, jQuery ) );
diff --git a/lib/resources/wikibase.ui.PropertyEditTool.css 
b/lib/resources/wikibase.ui.PropertyEditTool.css
index d335f53..8a447f0 100644
--- a/lib/resources/wikibase.ui.PropertyEditTool.css
+++ b/lib/resources/wikibase.ui.PropertyEditTool.css
@@ -41,43 +41,6 @@
 /********** /BASIC LAYOUT **********/
 
 
-/***** LABEL *****/
-
-.wb-ui-labeledittool .wb-ui-propertyedittool-editablevalue-ineditmode 
.wb-value {
-       padding: 0; /* even out border of input box in edit mode */
-}
-
-.wb-ui-labeledittool .wb-ui-propertyedittool-editablevalue-ineditmode {
-       margin-left: 7px; /* h1 natively has 0.17em bottom padding to avoid 
clipping */
-}
-
-.wb-ui-labeledittool .wb-ui-propertyedittool-editablevalue-ineditmode 
.wb-ui-propertyedittool-editablevalue-toolbarparent {
-       top: .3em;
-}
-
-.wb-ui-labeledittool input {
-       width: 100%;
-       font-family: inherit;
-       font-size: inherit;
-       height: 1.2em;
-}
-
-/* The wait message displayed when saving the label has to be customized due 
to differging font
-sizes and line heights within the heading */
-.wb-ui-labeledittool .wb-ui-propertyedittool-editablevalue-waitmsg {
-       display: inline-block;
-       font-size: 188%;
-       line-height: 1.2;
-       padding-top: 1px;
-       margin: 0;
-}
-.wb-ui-labeledittool .wb-ui-propertyedittool-editablevalue-waitmsg span {
-       font-size: 53%;
-}
-
-/***** /LABEL *****/
-
-
 /********** TAGADATA **********/
 
 ul.tagadata {
diff --git a/lib/tests/qunit/jquery.wikibase/jquery.wikibase.labelview.tests.js 
b/lib/tests/qunit/jquery.wikibase/jquery.wikibase.labelview.tests.js
new file mode 100644
index 0000000..d731969
--- /dev/null
+++ b/lib/tests/qunit/jquery.wikibase/jquery.wikibase.labelview.tests.js
@@ -0,0 +1,191 @@
+/**
+ * @licence GNU GPL v2+
+ * @author H. Snater < mediaw...@snater.com >
+ */
+
+( function( $, jQuery, QUnit ) {
+'use strict';
+
+/**
+ * @param {Object} [options]
+ * @param {jQuery} [$node]
+ * @return {jQuery}
+ */
+var createLabelview = function( options, $node ) {
+       options = $.extend( {
+               entityId: 'i am an entity id',
+               api: 'i am an api',
+               value: {
+                       language: 'en',
+                       label: 'test label'
+               }
+       }, options || {} );
+
+       $node = $node || $( '<div/>' ).appendTo( 'body' );
+
+       var $labelview = $node
+               .addClass( 'test_labelview' )
+               .labelview( options );
+
+       $labelview.data( 'labelview' )._save = function() {
+               return $.Deferred().resolve( {
+                       entity: {
+                               lastrevid: 'i am a revision id'
+                       }
+               } ).promise();
+       };
+
+       return $labelview;
+};
+
+QUnit.module( 'jquery.wikibase.labelview', QUnit.newMwEnvironment( {
+       teardown: function() {
+               $( '.test_labelview' ).each( function() {
+                       var $labelview = $( this ),
+                               labelview = $labelview.data( 'labelview' );
+
+                       if( labelview ) {
+                               labelview.destroy();
+                       }
+
+                       $labelview.remove();
+               } );
+       }
+} ) );
+
+QUnit.test( 'Create & destroy', function( assert ) {
+       assert.throws(
+               function() {
+                       createLabelview( { value: null } );
+               },
+               'Throwing error when trying to initialize widget without a 
value.'
+       );
+
+       var $labelview = createLabelview(),
+               labelview = $labelview.data( 'labelview' );
+
+       assert.ok(
+               labelview !== 'undefined',
+               'Created widget.'
+       );
+
+       labelview.destroy();
+
+       assert.ok(
+               $labelview.data( 'labelview' ) === undefined,
+               'Destroyed widget.'
+       );
+} );
+
+QUnit.test( 'startEditing() & stopEditing()', 5, function( assert ) {
+       var $labelview = createLabelview(),
+               labelview = $labelview.data( 'labelview' );
+
+       $labelview
+       .on( 'labelviewafterstartediting', function( event ) {
+               assert.ok(
+                       true,
+                       'Started edit mode.'
+               );
+       } )
+       .on( 'labelviewafterstopediting', function( event, dropValue ) {
+               assert.ok(
+                       true,
+                       'Stopped edit mode.'
+               );
+       } );
+
+       labelview.startEditing();
+
+       assert.ok(
+               labelview.$text.find( 'input' ).length === 1,
+               'Generated input element.'
+       );
+
+       labelview.startEditing(); // should not trigger event
+       labelview.stopEditing( true );
+       labelview.stopEditing( true ); // should not trigger event
+       labelview.stopEditing(); // should not trigger event
+       labelview.startEditing();
+
+       labelview.$text.find( 'input' ).val( '' );
+
+       labelview.stopEditing();
+} );
+
+QUnit.test( 'isInitialValue()', function( assert ) {
+       var $labelview = createLabelview(),
+               labelview = $labelview.data( 'labelview' );
+
+       labelview.startEditing();
+
+       assert.ok(
+               labelview.isInitialValue(),
+               'Verified isInitialValue() returning true.'
+       );
+
+       labelview.$text.find( 'input' ).val( 'changed' );
+
+       assert.ok(
+               !labelview.isInitialValue(),
+               'Verified isInitialValue() returning false after changing 
value.'
+       );
+
+       labelview.$text.find( 'input' ).val( 'test label' );
+
+       assert.ok(
+               labelview.isInitialValue(),
+               'Verified isInitialValue() returning true after resetting to 
initial value.'
+       );
+} );
+
+QUnit.test( 'setError()', function( assert ) {
+       var $labelview = createLabelview(),
+               labelview = $labelview.data( 'labelview' );
+
+       $labelview
+       .on( 'labelviewtoggleerror', function( event, error ) {
+               assert.ok(
+                       true,
+                       'Triggered "toggleerror" event.'
+               );
+       } );
+
+       labelview.setError();
+} );
+
+QUnit.test( 'value()', function( assert ) {
+       var $labelview = createLabelview(),
+               labelview = $labelview.data( 'labelview' );
+
+       assert.throws(
+               function() {
+                       labelview.value( null );
+               },
+               'Trying to set no value fails.'
+       );
+
+       labelview.value( {
+               language: 'de',
+               label: 'changed label'
+       } );
+
+       assert.ok(
+               labelview.value().language === 'de'
+                       && labelview.value().label === 'changed label',
+               'Set new value.'
+       );
+
+       labelview.value( {
+               language: 'en',
+               label: null
+       } );
+
+       assert.ok(
+               labelview.value().language === 'en'
+                       && labelview.value().label === null,
+               'Set another value.'
+       );
+} );
+
+}( jQuery, wikibase, QUnit ) );
diff --git a/lib/tests/qunit/wikibase.ui.LabelEditTool.tests.js 
b/lib/tests/qunit/wikibase.ui.LabelEditTool.tests.js
deleted file mode 100644
index 5d08347..0000000
--- a/lib/tests/qunit/wikibase.ui.LabelEditTool.tests.js
+++ /dev/null
@@ -1,73 +0,0 @@
-/**
- * QUnit tests heading edit tool
- * @see https://www.mediawiki.org/wiki/Extension:Wikibase
- *
- * @since 0.1
- *
- * @licence GNU GPL v2+
- * @author H. Snater <mediaw...@snater.com>
- */
-
-( function( mw, wb, $, QUnit, undefined ) {
-       'use strict';
-
-       QUnit.module( 'wikibase.ui.LabelEditTool', QUnit.newWbEnvironment( {
-               setup: function() {
-                       this.h1 = $( '<h1/>', { 'class': 'wb-firstHeading' } );
-                       this.span = $( '<span/>' ).append( $( '<span/>', {
-                               'class': 'wb-value',
-                               text: 'Text'
-                       } ) ).appendTo( this.h1 );
-                       this.subject = new wb.ui.LabelEditTool( this.h1, { api: 
{} } );
-               },
-               teardown: function() {}
-       } ) );
-
-       QUnit.test( 'basic check', function( assert ) {
-
-               assert.ok(
-                       this.subject instanceof wb.ui.LabelEditTool,
-                       'instantiated HeadingEditTool'
-               );
-
-               assert.equal(
-                       this.subject._getValueElems()[0],
-                       this.span[0],
-                       'checked getting value element'
-               );
-
-               assert.equal(
-                       this.subject.getPropertyName(),
-                       'label',
-                       'property name is label'
-               );
-
-               assert.equal(
-                       this.subject.getEditableValuePrototype(),
-                       wb.ui.PropertyEditTool.EditableLabel,
-                       'retrieved prototype'
-               );
-
-               assert.equal(
-                       this.subject.getOption( 'allowsMultipleValues' ),
-                       false,
-                       'does not allow multiple values'
-               );
-
-               this.subject.destroy();
-
-               assert.equal(
-                       this.h1.children().length + 
this.h1.children().first().children().length,
-                       1,
-                       'cleaned DOM'
-               );
-
-               assert.equal(
-                       this.h1.children()[0],
-                       this.span[0],
-                       'span child remains'
-               );
-
-       } );
-
-}( mediaWiki, wikibase, jQuery, QUnit ) );
diff --git 
a/lib/tests/qunit/wikibase.ui.PropertyEditTool.EditableLabel.tests.js 
b/lib/tests/qunit/wikibase.ui.PropertyEditTool.EditableLabel.tests.js
deleted file mode 100644
index 55ce8b4..0000000
--- a/lib/tests/qunit/wikibase.ui.PropertyEditTool.EditableLabel.tests.js
+++ /dev/null
@@ -1,101 +0,0 @@
-/**
- * QUnit tests for editable label component
- * @see https://www.mediawiki.org/wiki/Extension:Wikibase
- *
- * @since 0.1
- *
- * @licence GNU GPL v2+
- * @author H. Snater <mediaw...@snater.com>
- * @author Marius Hoch < h...@online.de >
- */
-
-( function( mw, wb, $, QUnit, undefined ) {
-       'use strict';
-
-       function setup( options ) {
-               options = $.extend( { api: {} }, options || {} );
-
-               var $node = $( '<div><div class="wb-value"/></div>' );
-               $( '<div/>', { id: 'parent' } ).append( $node );
-
-               var propertyEditTool = new wb.ui.PropertyEditTool( $node ),
-                       subject = 
wb.ui.PropertyEditTool.EditableLabel.newFromDom( $node, options ),
-                       toolbar = propertyEditTool._buildSingleValueToolbar();
-
-               subject.setToolbar( toolbar );
-
-               return subject;
-       }
-
-       QUnit.module( 'wikibase.ui.PropertyEditTool.EditableLabel', 
QUnit.newWbEnvironment( {
-               setup: function() {
-                       this.subject = setup();
-               },
-               teardown: function() {}
-       } ) );
-
-       QUnit.test( 'basic', function( assert ) {
-
-               assert.ok(
-                       this.subject instanceof 
wb.ui.PropertyEditTool.EditableLabel,
-                       'instantiated editable label'
-               );
-
-               assert.equal(
-                       this.subject._interfaces.length,
-                       1,
-                       'initialized single interface'
-               );
-
-               assert.ok(
-                       this.subject.getInputHelpMessage() !== '',
-                       'help message not empty'
-               );
-
-               this.subject.destroy();
-
-               assert.equal(
-                       this.subject._toolbar,
-                       null,
-                       'destroyed toolbar'
-               );
-
-               assert.equal(
-                       this.subject._instances,
-                       null,
-                       'destroyed instances'
-               );
-
-       } );
-
-       QUnit.test( 'placeholder', function( assert ) {
-               var oldGetLanguageNameByCode = wb.getLanguageNameByCode;
-
-               wb.getLanguageNameByCode = function( code ) {
-                       if ( code === 'de' ) {
-                               return 'Deutsch';
-                       } else {
-                               return '';
-                       }
-               };
-
-               var withLanguage = setup( { valueLanguageContext: 'de' } ),
-                       withoutLanguage = setup( { valueLanguageContext: 'ru' } 
);
-
-               assert.equal(
-                       withLanguage._interfaces[0]._options.inputPlaceholder,
-                       mw.msg(
-                               
'wikibase-label-edit-placeholder-language-aware',
-                               'Deutsch'
-                       )
-               );
-
-               assert.equal(
-                       
withoutLanguage._interfaces[0]._options.inputPlaceholder,
-                       mw.msg( 'wikibase-label-edit-placeholder' )
-               );
-
-               wb.getLanguageNameByCode = oldGetLanguageNameByCode;
-       } );
-
-}( mediaWiki, wikibase, jQuery, QUnit ) );
diff --git a/repo/includes/EntityView.php b/repo/includes/EntityView.php
index 8ea7402..700f5df 100644
--- a/repo/includes/EntityView.php
+++ b/repo/includes/EntityView.php
@@ -401,22 +401,17 @@
                $label = $entity->getLabel( $languageCode );
                $entityId = $entity->getId();
                $idString = 'new';
-               $supplement = '';
 
-               if ( $entityId !== null ) {
-                       $idString = $entityId->getSerialization();
-                       $supplement .= wfTemplate( 
'wb-property-value-supplement', wfMessage( 'parentheses', $idString ) );
-                       if ( $editable ) {
-                               $supplement .= $this->getHtmlForEditSection( 
'SetLabel', array( $idString, $languageCode ) );
-                       }
-               }
-
-               $html = wfTemplate( 'wb-label',
+               $html = wfTemplate( 'wikibase-h1',
                        $idString,
-                       wfTemplate( 'wb-property',
+                       wfTemplate( 'wikibase-labelview',
                                $label === false ? 'wb-value-empty' : '',
-                               htmlspecialchars( $label === false ? wfMessage( 
'wikibase-label-empty' )->text() : $label ),
-                               $supplement
+                               htmlspecialchars( $label === false
+                                       ? wfMessage( 'wikibase-label-empty' 
)->text()
+                                       : $label
+                               ),
+                               wfMessage( 'parentheses', 
$entityId->getSerialization() )->text(),
+                               $this->getHtmlForEditSection( 'SetLabel', 
array( $idString, $languageCode ) )
                        )
                );
 
diff --git a/repo/resources/Resources.php b/repo/resources/Resources.php
index 5fe5b10..d09d6a3 100644
--- a/repo/resources/Resources.php
+++ b/repo/resources/Resources.php
@@ -30,6 +30,7 @@
                                'jquery.wikibase.aliasesview',
                                'jquery.wikibase.descriptionview',
                                'jquery.wikibase.entityview',
+                               'jquery.wikibase.labelview',
                                'jquery.wikibase.toolbarcontroller',
                                'jquery.wikibase.wbtooltip',
                                'jquery.cookie',
diff --git a/repo/resources/wikibase.ui.entityViewInit.js 
b/repo/resources/wikibase.ui.entityViewInit.js
index 81dec62..1a1a2b2 100644
--- a/repo/resources/wikibase.ui.entityViewInit.js
+++ b/repo/resources/wikibase.ui.entityViewInit.js
@@ -30,29 +30,6 @@
 
                var repoApi = new wb.RepoApi();
 
-               // add an edit tool for the main label. This will be integrated 
into the heading nicely:
-               var $firstHeading = $( '.wb-firstHeading' );
-               if ( $firstHeading.length ) { // Special pages do not have a 
custom wb heading
-                       var labelEditTool = new wb.ui.LabelEditTool( 
$firstHeading[0], { api: repoApi } ),
-                               editableLabel = labelEditTool.getValues( true 
)[0], // [0] will always be set
-                               fn = function( event, origin ) {
-                                       // Limit the global 
stopItemPageEditMode event to that element
-                                       if ( event.type !== 
'stopItemPageEditMode' || origin === editableLabel ) {
-                                               var title = 
editableLabel.isEmpty()
-                                                       ? mw.config.get( 
'wgTitle' )
-                                                       : 
editableLabel.getValue()[0];
-
-                                               // update 'title' tag
-                                               $( 'title' ).text( mw.msg( 
'pagetitle', title ) );
-                                       }
-                               };
-
-                       editableLabel.getSubject().on( 'eachchange', fn );
-                       // Can't use afterStopEditing because it does not fire 
on cancel
-                       // but this is needed to reset the title
-                       $( wb ).on( 'stopItemPageEditMode', fn );
-               }
-
                registerEditRestrictionHandlers();
 
                if( mw.config.get( 'wbEntity' ) !== null ) {
@@ -242,6 +219,36 @@
                wb.compileEntityStoreFromMwConfig( entityStore );
 
                // TODO: Integrate into entityview
+               $( '.wikibase-labelview' )
+               .toolbarcontroller( {
+                       edittoolbar: ['labelview']
+               } )
+               .labelview( {
+                       value: {
+                               language: mw.config.get( 'wgUserLanguage' ),
+                               label: $( '.wikibase-labelview' ).hasClass( 
'wb-empty' )
+                                       ? null
+                                       // FIXME: entity object should not 
contain fallback strings
+                                       : entity.getLabel( mw.config.get( 
'wgUserLanguage' ) )
+                       },
+                       helpMessage: mw.msg(
+                               'wikibase-description-input-help-message',
+                               wb.getLanguageNameByCode( mw.config.get( 
'wgUserLanguage' ) )
+                       ),
+                       entityId: entity.getId(),
+                       api: repoApi,
+                       showEntityId: true
+               } )
+               .on( 'labelviewchange', function( event ) {
+                       var $labelview = $( event.target ),
+                               labelview = $labelview.data( 'labelview' ),
+                               label = labelview.value().label;
+
+                       $( 'title' ).text(
+                               mw.msg( 'pagetitle', label && label !== '' ? 
label : mw.config.get( 'wgTitle' ) )
+                       );
+               } );
+
                $( '.wikibase-descriptionview' )
                .toolbarcontroller( {
                        edittoolbar: ['descriptionview']
@@ -317,7 +324,8 @@
                // it to a sensible place.
                $( wb )
                .on( 'startItemPageEditMode', function( event, target, options 
) {
-                       $( ':wikibase-descriptionview, :wikibase-aliasesview, 
:wikibase-sitelinklistview' )
+                       $( ':wikibase-labelview, :wikibase-descriptionview, 
:wikibase-aliasesview, '
+                               + ':wikibase-sitelinklistview' )
                        .not( target )
                        .find( ':wikibase-toolbar' )
                        .each( function() {
@@ -328,6 +336,16 @@
                        $( ':wikibase-aliasesview' ).find( ':wikibase-toolbar' 
).each( function() {
                                $( this ).data( 'toolbar' ).enable();
                        } );
+                       $( ':wikibase-labelview' ).each( function() {
+                               var $labelview = $( this ),
+                                       labelview = $labelview.data( 
'labelview' );
+
+                               if( labelview.value().label ) {
+                                       $labelview.find( ':wikibase-toolbar' 
).each( function() {
+                                               $( this ).data( 'toolbar' 
).enable();
+                                       } );
+                               }
+                       } );
                        $( ':wikibase-descriptionview' ).each( function() {
                                var $descriptionview = $( this ),
                                        descriptionview = 
$descriptionview.data( 'descriptionview' );
diff --git a/repo/resources/wikibase.ui.initTermBox.js 
b/repo/resources/wikibase.ui.initTermBox.js
index 57438e3..25db8d6 100644
--- a/repo/resources/wikibase.ui.initTermBox.js
+++ b/repo/resources/wikibase.ui.initTermBox.js
@@ -16,8 +16,7 @@
  */
 wb.ui.initTermBox = function( entity, api ) {
        mw.hook( 'wikibase.domready' ).add( function() {
-               var termsValueTools = [],
-                       $termBoxRows = $( 'tr.wb-terms-label, 
tr.wb-terms-description' ),
+               var $termBoxRows = $( 'tr.wb-terms-label, 
tr.wb-terms-description' ),
                        userSpecifiedLanguages = mw.config.get( 
'wbUserSpecifiedLanguages' ),
                        hasSpecifiedLanguages = userSpecifiedLanguages && 
userSpecifiedLanguages.length,
                        isUlsDefined = mw.uls !== undefined
@@ -25,7 +24,7 @@
                                && $.uls.data !== undefined;
 
                $( '.wb-terms' ).toolbarcontroller( {
-                       edittoolbar: ['terms-descriptionview']
+                       edittoolbar: ['terms-labelview', 
'terms-descriptionview']
                } );
 
                // Skip if having no extra languages is what the user wants
@@ -50,39 +49,37 @@
                }
 
                $termBoxRows.each( function() {
-                       var $termsRow = $( this );
-
-                       if( $termsRow.hasClass( 'wb-terms-label' ) ) {
-                               var editTool = 
wb.ui.PropertyEditTool.EditableLabel,
-                                       $toolbar = mw.template( 
'wikibase-toolbar', '', '' ).toolbar(),
-                                       toolbar = $toolbar.data( 'toolbar' ),
-                                       $editGroup = mw.template( 
'wikibase-toolbareditgroup', '', '' )
-                                               .toolbareditgroup();
-
-                               toolbar.addElement( $editGroup );
-
-                               // TODO: EditableLabel should not assume that 
this is set
-                               toolbar.$editGroup = $editGroup;
-
-                               termsValueTools.push( editTool.newFromDom( 
$termsRow, {
-                                       api: api
-                               }, toolbar ) );
-
-                               return true;
-                       }
-
-                       var languageCode;
+                       var $termsRow = $( 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-/, '' );
                                        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: {
@@ -101,29 +98,25 @@
 
                $( wb )
                .on( 'startItemPageEditMode', function( event, origin ) {
-                       // Disable language terms table's editable value or 
mark it as the active one if it
-                       // is the one being edited by the user and therefore 
the origin of the event
-                       $.each( termsValueTools, function( i, termValueTool ) {
-                               if(
-                                       !( origin instanceof 
wb.ui.PropertyEditTool.EditableValue )
-                                       || origin.getSubject() !== 
termValueTool.getSubject()
-                               ) {
-                                       termValueTool.disable();
-                               } else if( origin && origin.getSubject() === 
termValueTool.getSubject() ) {
-                                       $( 'table.wb-terms' ).addClass( 
'wb-edit' );
-                               }
-                       } );
-
-                       $termBoxRows.find( ':wikibase-descriptionview' )
+                       $termBoxRows.find( ':wikibase-labelview, 
:wikibase-descriptionview' )
                        .not( origin )
                        .each( function() {
                                $( this ).data( 'edittoolbar' 
).toolbar.disable();
                        } );
                } )
                .on( 'stopItemPageEditMode', function( event, origin ) {
-                       $( 'table.wb-terms' ).removeClass( 'wb-edit' );
-                       $.each( termsValueTools, function( i, termValueTool ) {
-                               termValueTool.enable();
+                       $termBoxRows.find( ':wikibase-labelview' ).each( 
function() {
+                               var labelview = $( this ).data( 'labelview' );
+
+                               if( labelview.value().label ) {
+                                       var toolbar = $( this ).data( 
'edittoolbar' ).toolbar,
+                                               btnEdit = 
toolbar.editGroup.getButton( 'edit' ).data( 'toolbarbutton' );
+
+                                       $( this ).data( 'edittoolbar' 
).toolbar.enable();
+
+                                       // FIXME: Get rid of StatableObject 
making things complicated
+                                       btnEdit.setState( btnEdit.STATE.ENABLED 
);
+                               }
                        } );
 
                        $termBoxRows.find( ':wikibase-descriptionview' ).each( 
function() {
@@ -212,7 +205,68 @@
        return mw.template( 'wb-terms-table', $tbody );
 }
 
-// TODO: Merge with native descriptionview toolbar definiton
+// 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( 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',

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: Id36ab9c2dd0a3acb0c19e34c3ce8c8b2e7b954bb
Gerrit-PatchSet: 6
Gerrit-Project: mediawiki/extensions/Wikibase
Gerrit-Branch: master
Gerrit-Owner: Henning Snater <henning.sna...@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