jenkins-bot has submitted this change and it was merged. Change subject: Eliminated global events ......................................................................
Eliminated global events The change removes all global events triggered on the JavaScript "wikibase" object, most prominently "startItemPageEditMode" and "stopItemPageEditMode". Removing the events required consolidating state (disable/enable) handling across the widget hierarchy. This is achieved by applying a "disable" event to TemplatedWidget. Change-Id: Id9ed0ea51064f2ce295cb1b3f1a23cb36a850442 --- M lib/resources/jquery.ui/jquery.ui.TemplatedWidget.js M lib/resources/jquery.wikibase/jquery.wikibase.aliasesview.js M lib/resources/jquery.wikibase/jquery.wikibase.claimgrouplistview.js M lib/resources/jquery.wikibase/jquery.wikibase.claimlistview.js M lib/resources/jquery.wikibase/jquery.wikibase.claimview.js M lib/resources/jquery.wikibase/jquery.wikibase.descriptionview.js M lib/resources/jquery.wikibase/jquery.wikibase.entityview.js M lib/resources/jquery.wikibase/jquery.wikibase.fingerprintgroupview.js M lib/resources/jquery.wikibase/jquery.wikibase.fingerprintlistview.js M lib/resources/jquery.wikibase/jquery.wikibase.fingerprintview.js M lib/resources/jquery.wikibase/jquery.wikibase.labelview.js M lib/resources/jquery.wikibase/jquery.wikibase.listview.js M lib/resources/jquery.wikibase/jquery.wikibase.referenceview.js M lib/resources/jquery.wikibase/jquery.wikibase.sitelinkgrouplistview.js M lib/resources/jquery.wikibase/jquery.wikibase.sitelinkgroupview.js M lib/resources/jquery.wikibase/jquery.wikibase.sitelinklistview.js M lib/resources/jquery.wikibase/jquery.wikibase.sitelinkview.js M lib/resources/jquery.wikibase/jquery.wikibase.snaklistview.js M lib/resources/jquery.wikibase/jquery.wikibase.statementview.js M lib/resources/jquery.wikibase/snakview/snakview.js M lib/resources/jquery.wikibase/toolbar/edittoolbar.js M lib/resources/wikibase.css M lib/resources/wikibase.js M lib/tests/qunit/data/testrunner.js M repo/resources/wikibase.ui.entityViewInit.js 25 files changed, 794 insertions(+), 727 deletions(-) Approvals: Tobias Gritschacher: Looks good to me, approved jenkins-bot: Verified diff --git a/lib/resources/jquery.ui/jquery.ui.TemplatedWidget.js b/lib/resources/jquery.ui/jquery.ui.TemplatedWidget.js index 4b73002..0bf704a 100644 --- a/lib/resources/jquery.ui/jquery.ui.TemplatedWidget.js +++ b/lib/resources/jquery.ui/jquery.ui.TemplatedWidget.js @@ -1,9 +1,8 @@ /** - * * @licence GNU GPL v2+ * @author Daniel Werner < [email protected] > */ -( function( $, util ) { +( function( $ ) { 'use strict'; var PARENT = $.Widget; @@ -43,6 +42,12 @@ * modified on the base prototype. Our workaround for this only worked for one level of * inheritance (doing the copy manually in the prototype's constructor, can't define the * constructor of the new prototype created by jQuery.widget() though). + * + * @event disable + * Triggered whenever the widget is disabled (after disabled state has been set). + * - {jQuery.Event} + * - {boolean} Whether widget has been dis- oder enabled. + * */ $.widget( 'ui.TemplatedWidget', PARENT, { /** @@ -70,6 +75,8 @@ } this._createTemplateShortCuts(); + + PARENT.prototype._create.apply( this ); }, _applyTemplate: function() { @@ -127,8 +134,7 @@ }, /** - * @see jQuery.widget._setOption - * We are using this to disallow changing the 'template' option afterwards + * @see jQuery.Widget._setOption */ _setOption: function( key, value ) { switch( key ) { @@ -137,10 +143,17 @@ case 'templateShortCuts': throw new Error( 'Can not set template related options after initialization' ); } - PARENT.prototype._setOption.call( this, key, value ); + + var response = PARENT.prototype._setOption.apply( this, arguments ); + + if( key === 'disabled' ) { + this._trigger( 'disable', null, [value] ); + } + + return response; } } ); $.TemplatedWidget = $.ui.TemplatedWidget; -}( jQuery, util ) ); +}( jQuery ) ); diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.aliasesview.js b/lib/resources/jquery.wikibase/jquery.wikibase.aliasesview.js index bbe2806..0bd37c5 100644 --- a/lib/resources/jquery.wikibase/jquery.wikibase.aliasesview.js +++ b/lib/resources/jquery.wikibase/jquery.wikibase.aliasesview.js @@ -504,6 +504,25 @@ ] ); } ); }, + aliasesviewdisable: function( event ) { + var $aliasesview = $( event.target ), + aliasesview = $aliasesview.data( 'aliasesview' ), + toolbar = $aliasesview.data( 'edittoolbar' ).toolbar, + $btnSave = toolbar.editGroup.getButton( 'save' ), + btnSave = $btnSave.data( 'toolbarbutton' ), + enable = aliasesview.isValid() && !aliasesview.isInitialValue(), + currentAliases = aliasesview.value().aliases; + + btnSave[enable ? 'enable' : 'disable'](); + + if( aliasesview.option( 'disabled' ) || currentAliases.length ) { + return; + } + + if( !currentAliases ) { + toolbar.disable(); + } + }, toolbareditgroupedit: function( event, toolbarcontroller ) { var $aliasesview = $( event.target ).closest( ':wikibase-edittoolbar' ), aliasesview = $aliasesview.data( 'aliasesview' ); diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.claimgrouplistview.js b/lib/resources/jquery.wikibase/jquery.wikibase.claimgrouplistview.js index eeab832..9f7672c 100644 --- a/lib/resources/jquery.wikibase/jquery.wikibase.claimgrouplistview.js +++ b/lib/resources/jquery.wikibase/jquery.wikibase.claimgrouplistview.js @@ -346,8 +346,20 @@ index++; } } - } + }, + /** + * @see jQuery.ui.TemplatedWidget._setOption + */ + _setOption: function( key, value ) { + var response = PARENT.prototype._setOption.apply( this, arguments ); + + if( key === 'disabled' ) { + this.$listview.data( 'listview' ).option( key, value ); + } + + return response; + } } ); $.wikibase.toolbarcontroller.definition( 'addtoolbar', { @@ -356,7 +368,8 @@ + '-' + $.wikibase.claimgrouplistview.prototype.widgetName, events: { claimgrouplistviewcreate: function( event, toolbarcontroller ) { - var $claimgrouplistview = $( event.target ); + var $claimgrouplistview = $( event.target ), + claimgrouplistview = $claimgrouplistview.data( 'claimgrouplistview' ); $claimgrouplistview.addtoolbar( { addButtonAction: function() { @@ -372,6 +385,20 @@ ); } } ); + + // TODO: Integrate state management into addtoolbar + toolbarcontroller.registerEventHandler( + event.data.toolbar.type, + event.data.toolbar.id, + 'claimgrouplistviewdisable', + function() { + $claimgrouplistview.data( 'addtoolbar' )[ + claimgrouplistview.option( 'disabled' ) + ? 'disable' + : 'enable' + ](); + } + ); } } } ); diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.claimlistview.js b/lib/resources/jquery.wikibase/jquery.wikibase.claimlistview.js index e54e4b4..1af0308 100644 --- a/lib/resources/jquery.wikibase/jquery.wikibase.claimlistview.js +++ b/lib/resources/jquery.wikibase/jquery.wikibase.claimlistview.js @@ -41,12 +41,6 @@ * * @event toggleerror: Triggered when one of the claimlistview's items produces an error. * (1) {jQuery.Event} - * - * @event disable: Triggered whenever the claimlistview gets disabled. - * (1) {jQuery.Event} - * - * @event enable: Triggered whenever the claimlistview gets enabled. - * (1) {jQuery.Event} */ $.widget( 'wikibase.claimlistview', PARENT, { /** @@ -352,6 +346,8 @@ remove: function( claimview ) { var self = this; + claimview.disable(); + this._removeClaimApiCall( claimview.value() ) .done( function( savedClaim, pageInfo ) { // NOTE: we don't update rev store here! If we want uniqueness for Claims, this @@ -382,36 +378,7 @@ }, /** - * Disables the snaklistview. - * @since 0.4 - */ - disable: function() { - var self = this; - $.each( this.listview().items(), function( i, item ) { - var $item = $( item ); - self.listview().listItemAdapter().liInstance( $item ).disable(); - } ); - this._trigger( 'disable' ); - }, - - /** - * Enables the snaklistview. - * @since 0.4 - */ - enable: function() { - var self = this; - $.each( this.listview().items(), function( i, item ) { - var $item = $( item ); - // Item might be about to be removed not being a list item instance. - if ( self.listview().listItemAdapter().liInstance( $item ) ) { - self.listview().listItemAdapter().liInstance( $item ).enable(); - } - } ); - this._trigger( 'enable' ); - }, - - /** - * @see jQuery.widget._setOption + * @see jQuery.ui.TemplatedWidget._setOption */ _setOption: function( key, value ) { // The value should not be set from outside after the initialization because @@ -421,7 +388,14 @@ } else if( key === 'fistClaimIndex' ) { throw new Error( 'firstClaimIndex cannot be set after initialization' ); } - $.Widget.prototype._setOption.call( this, key, value ); + + var response = PARENT.prototype._setOption.apply( this, arguments ); + + if( key === 'disabled' ) { + this.listview().option( key, value ); + } + + return response; } } ); @@ -432,11 +406,12 @@ + '-' + $.wikibase.claimlistview.prototype.widgetName, events: { claimlistviewcreate: function( event, toolbarcontroller ) { - var $claimlistview = $( event.target ); + var $claimlistview = $( event.target ), + claimlistview = $claimlistview.data( 'claimlistview' ); $claimlistview.addtoolbar( { addButtonAction: function() { - $claimlistview.data( 'claimlistview' ).enterNewItem(); + claimlistview.enterNewItem(); // Re-focus "add" button after having added or having cancelled adding a claim: var eventName = 'claimlistviewafterstopediting.addtoolbar'; @@ -454,6 +429,21 @@ ); } } ); + + toolbarcontroller.registerEventHandler( + event.data.toolbar.type, + event.data.toolbar.id, + 'claimlistviewdisable', + function() { + var addtoolbar = $claimlistview.data( 'addtoolbar' ); + if( addtoolbar ) { + addtoolbar[claimlistview.option( 'disabled' ) + ? 'disable' + : 'enable' + ](); + } + } + ); } } } ); @@ -528,6 +518,17 @@ ); } ); + }, + 'claimviewdisable statementviewdisable': function( event ) { + var viewType = event.type.replace( /disable$/, '' ), + $view = $( event.target ), + view = $view.data( viewType ), + toolbar = $view.data( 'edittoolbar' ).toolbar, + $btnSave = toolbar.editGroup.getButton( 'save' ), + btnSave = $btnSave.data( 'toolbarbutton' ), + enable = view.isValid() && !view.isInitialValue(); + + btnSave[enable ? 'enable' : 'disable'](); } } } ); diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.claimview.js b/lib/resources/jquery.wikibase/jquery.wikibase.claimview.js index 1ea65ad..307b14a 100644 --- a/lib/resources/jquery.wikibase/jquery.wikibase.claimview.js +++ b/lib/resources/jquery.wikibase/jquery.wikibase.claimview.js @@ -700,36 +700,6 @@ }, /** - * Disables the Claim view. - * @since 0.4 - */ - disable: function() { - this.$mainSnak.data( 'snakview' ).disable(); - if ( this._qualifiers ) { - var snaklistviews = this._qualifiers.value(); - - for( var i = 0; i < snaklistviews.length; i++ ) { - snaklistviews[i].disable(); - } - } - }, - - /** - * Enables the Claim view. - * @since 0.4 - */ - enable: function() { - this.$mainSnak.data( 'snakview' ).enable(); - if ( this._qualifiers ) { - var snaklistviews = this._qualifiers.value(); - - for( var i = 0; i < snaklistviews.length; i++ ) { - snaklistviews[i].enable(); - } - } - }, - - /** * @see $.widget.destroy */ destroy: function() { @@ -770,14 +740,23 @@ }, /** - * @see jQuery.widget._setOption - * We are using this to disallow changing the value option afterwards + * @see jQuery.Widget._setOption */ _setOption: function( key, value ) { if( key === 'value' ) { throw new Error( 'Can not set value after initialization' ); } - $.Widget.prototype._setOption.apply( this, arguments ); + + var response = PARENT.prototype._setOption.apply( this, arguments ); + + if( key === 'disabled' ) { + this.$mainSnak.data( 'snakview' ).option( key, value ); + if( this._qualifiers ) { + this._qualifiers.option( key, value ); + } + } + + return response; } } ); @@ -847,14 +826,24 @@ event.data.toolbar.type, event.data.toolbar.id, // FIXME: When there are qualifiers, no state change events will be thrown. - 'snaklistviewdisable snaklistviewenable', + 'listviewdisable', function( event ) { var $qualifiers = $( event.target ).closest( '.wb-claim-qualifiers' ), - addToolbar = $qualifiers.data( 'addtoolbar' ); + addToolbar = $qualifiers.data( 'addtoolbar' ), + $parentView = $qualifiers.closest( ':wikibase-statementview' ), + parentView = null; + + if( $parentView.length ) { + parentView = $parentView.data( 'statementview' ); + } else { + $parentView = $qualifiers.closest( ':wikibase-claimview' ); + parentView = $parentView.data( 'claimview' ); + } + // Toolbar might be removed from the DOM already after having stopped edit mode. if( addToolbar ) { var toolbar = addToolbar.toolbar; - toolbar[ ( event.type === 'snaklistviewdisable' ) ? 'disable' : 'enable' ](); + toolbar[parentView.option( 'disabled' ) ? 'disable' : 'enable'](); } } ); @@ -932,19 +921,35 @@ toolbarController.registerEventHandler( event.data.toolbar.type, event.data.toolbar.id, - 'snaklistviewdisable snaklistviewenable', + 'snaklistviewdisable', function( event ) { var $snaklistviewNode = $( event.target ), listview = $snaklistviewNode.data( 'snaklistview' )._listview, lia = listview.listItemAdapter(), - action = ( event.type.indexOf( 'disable' ) !== -1 ) ? 'disable' : 'enable'; + $parentView = $snaklistviewNode.closest( ':wikibase-statementview' ), + parentView = null; - $.each( listview.items(), function( i, item ) { - var $item = $( item ); + if( $parentView.length ) { + parentView = $parentView.data( 'statementview' ); + } else { + $parentView = $snaklistviewNode.closest( ':wikibase-claimview' ); + parentView = $parentView.data( 'claimview' ); + } + + $.each( listview.items(), function( i, node ) { + var $snakview = $( node ), + snakview = lia.liInstance( $snakview ), + removeToolbar = $snakview.data( 'removetoolbar' ); + // Item might be about to be removed not being a list item instance. - if( lia.liInstance( $item ) && $item.data( 'removetoolbar' ) ) { - $item.data( 'removetoolbar' ).toolbar[action](); + if( !snakview || !removeToolbar ) { + return true; } + + $snakview.data( 'removetoolbar' ).toolbar[parentView.option( 'disabled' ) + ? 'disable' + : 'enable' + ](); } ); } ); diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.descriptionview.js b/lib/resources/jquery.wikibase/jquery.wikibase.descriptionview.js index 2c55386..1536387 100644 --- a/lib/resources/jquery.wikibase/jquery.wikibase.descriptionview.js +++ b/lib/resources/jquery.wikibase/jquery.wikibase.descriptionview.js @@ -51,6 +51,11 @@ _isInEditMode: false, /** + * @type {boolean} + */ + _isBeingEdited: false, + + /** * @see jQuery.ui.TemplatedWidget._create * * @throws {Error} if required parameters are not specified properly. @@ -66,7 +71,6 @@ value = this.options.value; this.element - // TODO: Move that code to a sensible place (see jQuery.wikibase.entityview): .on( 'descriptionviewafterstartediting.' + this.widgetName + ' eachchange.' + this.widgetName, @@ -81,28 +85,6 @@ } self.element.removeClass( 'wb-empty' ); - - $( wb ).trigger( 'startItemPageEditMode', [ - self.element, - { - exclusive: false, - wbCopyrightWarningGravity: 'sw' - } - ] ); - } ) - .on( - 'descriptionviewafterstopediting.' + this.widgetName - + ' eachchange.' + this.widgetName, - function( event, dropValue ) { - if( - event.type !== 'eachchange' - || !self.options.value.description && !self.value().description - ) { - $( wb ).trigger( 'stopItemPageEditMode', [ - self.element, - { save: dropValue !== true } - ] ); - } } ); PARENT.prototype._create.call( this ); @@ -134,7 +116,6 @@ */ _draw: function() { if( !this._isInEditMode ) { - this.element.removeClass( 'wb-edit' ); this.$text.text( this.options.value.description || mw.msg( 'wikibase-description-empty' ) ); @@ -157,21 +138,31 @@ $input.val( this.options.value.description ); } - this.element.addClass( 'wb-edit' ); this.$text.empty().append( $input ); }, /** - * Starts the widget's edit mode. + * Switches to editable state. */ - startEditing: function() { + toEditMode: function() { if( this._isInEditMode ) { return; } this._isInEditMode = true; this._draw(); + }, + /** + * Starts the widget's edit mode. + */ + startEditing: function() { + if( this._isBeingEdited ) { + return; + } + this.element.addClass( 'wb-edit' ); + this.toEditMode(); + this._isBeingEdited = true; this._trigger( 'afterstartediting' ); }, @@ -241,11 +232,11 @@ this.options.value = this.value(); } else if( !this.options.value.description ) { this.$text.children( 'input' ).val( '' ); - this._trigger( 'change' ); } this.element[this.options.value.description ? 'removeClass' : 'addClass']( 'wb-empty' ); - + this.element.removeClass( 'wb-edit' ); + this._isBeingEdited = false; this._isInEditMode = false; this._draw(); @@ -399,7 +390,9 @@ } ); if( !descriptionview.value().description ) { - descriptionview.startEditing(); + descriptionview.toEditMode(); + $descriptionview.data( 'edittoolbar' ).toolbar.editGroup.toEditMode(); + $descriptionview.data( 'edittoolbar' ).toolbar.editGroup.disable(); } $descriptionview @@ -408,14 +401,16 @@ var edittoolbar = $( event.target ).data( 'edittoolbar' ); if( descriptionview.value().description ) { edittoolbar.toolbar.editGroup.toNonEditMode(); + edittoolbar.enable(); + edittoolbar.toggleActionMessage( function() { + edittoolbar.toolbar.editGroup.getButton( 'edit' ).focus(); + } ); } else { - descriptionview.startEditing(); + descriptionview.toEditMode(); + edittoolbar.toolbar.editGroup.toEditMode(); + descriptionview.focus(); + $descriptionview.data( 'edittoolbar' ).toolbar.editGroup.disable(); } - - edittoolbar.enable(); - edittoolbar.toggleActionMessage( function() { - edittoolbar.toolbar.editGroup.getButton( 'edit' ).focus(); - } ); } ); }, 'descriptionviewchange descriptionviewafterstartediting descriptionviewafterstopediting': function( event ) { @@ -432,6 +427,33 @@ btnSave[enable ? 'enable' : 'disable'](); btnCancel[disableCancel ? 'disable' : 'enable'](); + + if( event.type === 'descriptionviewchange' ) { + if( !descriptionview.isInitialValue() ) { + descriptionview.startEditing(); + } else if( descriptionview.isInitialValue() && !descriptionview.value().description ) { + descriptionview.cancelEditing(); + } + } + }, + descriptionviewdisable: 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(), + currentDescription = descriptionview.value().description; + + btnSave[enable ? 'enable' : 'disable'](); + + if( descriptionview.option( 'disabled' ) || currentDescription ) { + return; + } + + if( !currentDescription ) { + toolbar.disable(); + } }, toolbareditgroupedit: function( event, toolbarcontroller ) { var $descriptionview = $( event.target ).closest( ':wikibase-edittoolbar' ), diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.entityview.js b/lib/resources/jquery.wikibase/jquery.wikibase.entityview.js index 228f9de..1769bba 100644 --- a/lib/resources/jquery.wikibase/jquery.wikibase.entityview.js +++ b/lib/resources/jquery.wikibase/jquery.wikibase.entityview.js @@ -1,6 +1,5 @@ /** * @licence GNU GPL v2+ - * @author Daniel Werner < [email protected] > * @author H. Snater < [email protected] > */ ( function( wb, $, mw ) { @@ -18,10 +17,19 @@ * @option {wikibase.ValueViewBuilder} valueViewBuilder * @option {wikibase.AbstractedRepoApi} api * @option {string[]} languages + * + * @event afterstartediting + * Triggered after the widget has switched to edit mode. + * - {jQuery.Event} + * + * @event afterstopediting + * Triggered after the widget has left edit mode. + * - {jQuery.Event} + * - {boolean} Whether the pending value has been dropped (editing has been cancelled). */ $.widget( 'wikibase.entityview', PARENT, { /** - * @see jQuery.ui.TemplatedWidget + * @see jQuery.ui.TemplatedWidget.options */ options: { template: 'wikibase-entityview', @@ -61,7 +69,7 @@ $aliases: null, /** - * @type {jQuery} + * @type {jQuery|null} */ $fingerprints: null, @@ -93,7 +101,7 @@ this._initClaims(); this._initSiteLinks(); - this._handleEditModeAffairs(); + this._attachEventHandlers(); }, _initLabel: function() { @@ -268,172 +276,95 @@ } ); }, - /** - * Will make this edit view keeping track over global edit mode and triggers global edit mode - * in case any member of this entity view enters edit mode. - * @since 0.3 - */ - _handleEditModeAffairs: function() { + _attachEventHandlers: function() { var self = this; - /** - * Helper which returns a handler for global edit mode event to disable/enable this entity - * view's toolbars but not the one of the edit widget currently active. - * - * @param {string} action - * @return {function} - */ - var toolbarStatesSetter = function( action ) { - function findToolbars( $range ) { - var $wbToolbars = $range.find( '.wikibase-toolbar' ), - $wbToolbarGroups = $wbToolbars.find( $wbToolbars ); - return $wbToolbars - // Filter out toolbar groups: - .not( $wbToolbarGroups ) - // Re-add "new UI" toolbars: - // TODO Improve selection mechanism as soon as old UI classes have - // converted or get rid of this toolbarStatesSetter. - .add( $wbToolbarGroups.filter( - function() { - var $toolbarNode = $( this.parentNode.parentNode ); - return $toolbarNode.hasClass( 'wb-edittoolbar' ) - || $toolbarNode.hasClass( 'wb-removetoolbar' ) - || $toolbarNode.hasClass( 'wb-addtoolbar' ); - } - ) ); - } + this.element + .on( [ + 'labelviewafterstartediting.' + this.widgetName, + 'descriptionviewafterstartediting.' + this.widgetName, + 'aliasesviewafterstartediting.' + this.widgetName, + 'fingerprintgroupviewafterstartediting.' + this.widgetName, + 'claimviewafterstartediting.' + this.widgetName, + 'statementviewafterstartediting.' + this.widgetName, + 'referenceviewafterstartediting.' + this.widgetName, + 'sitelinkviewafterstartediting.' + this.widgetName + ].join( ' ' ), + function( event ) { + var widgetName = event.type.replace( /afterstartediting/, '' ); - return function( event, origin, options ) { - // TODO: at some point, this should rather disable/enable the widgets for editing, - // there could be other ways for entering edit mode than using the toolbar! + self._disable( $( event.target ).data( widgetName ) ); - // Whether action shall influence sub-toolbars of origin: - // TODO: "exclusive" option/variable restricts arrangement of toolbars. Interaction - // between toolbars should be managed via the toolbar controller. - var originToolbars = null; - if ( options ) { - if ( options.exclusive === false ) { - originToolbars = findToolbars( $( origin ) ); - } else if ( typeof options.exclusive === 'string' ) { - originToolbars = $( origin ).find( options.exclusive ); - } - } - - // find and disable/enable all toolbars in this edit view except,... - findToolbars( self.element ).each( function() { - var $toolbar = $( this ), - toolbar = $toolbar.data( 'toolbar' ); - // ... don't disable toolbar if it has an edit group which is in edit mode - // or if the toolbar is a sub-element of the origin. - if ( - $toolbar.children( '.wikibase-toolbareditgroup-ineditmode' ).length === 0 - && ( !originToolbars || $.inArray( this, originToolbars ) === -1 ) - // Checking if toolbar is defined is done for the purpose of debugging only; - // Toolbar may only be undefined under some weird circumstances, e.g. when - // doing $( 'body' ).empty() for debugging. - && toolbar - ) { - toolbar[ action ](); - } - } ); - }; - }; - - // disable/enable all toolbars when starting/ending an edit mode: - // TODO: Resolve logic - $( wb ) - .on( 'startItemPageEditMode', toolbarStatesSetter( 'disable' ) ) - .on( 'stopItemPageEditMode', toolbarStatesSetter( 'enable' ) ) - .on( 'startItemPageEditMode', function( event, target, options ) { - $( ':wikibase-labelview, :wikibase-descriptionview, :wikibase-aliasesview, :wikibase-fingerprintview' ) - .not( target ) - .find( ':wikibase-toolbar' ) - .each( function() { - $( this ).data( 'toolbar' ).disable(); - } ); - } ) - .on( 'stopItemPageEditMode', function( event, target, options ) { - $( ':wikibase-aliasesview, :wikibase-fingerprintview' ).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' ); - - if( descriptionview.value().description ) { - $descriptionview.find( ':wikibase-toolbar' ).each( function() { - $( this ).data( 'toolbar' ).enable(); - } ); - } - } ); - - $( ':wikibase-sitelinklistview' ).each( function() { - var $sitelinklistview = $( this ), - sitelinklistview = $sitelinklistview.data( 'sitelinklistview' ); - - $sitelinklistview.data( 'addtoolbar' ).toolbar[sitelinklistview.isFull() - ? 'disable' - : 'enable' - ](); - - $sitelinklistview.find( 'tbody :wikibase-toolbar' ).each( function() { - $( this ).data( 'toolbar' ).enable(); - } ); - } ); + self._trigger( 'afterstartediting' ); } ); - // if any of the snaks enters edit mode, trigger global edit mode. This is necessary for - // compatibility with old PropertyEditTool which is still used for label, description etc. - // TODO: this should rather listen to 'valueviewstartediting' once implemented! - $( this.element ) - .on( 'statementviewafterstartediting', function( event ) { - $( wb ).trigger( 'startItemPageEditMode', [ - event.target, - { - exclusive: '.wb-claim-qualifiers .wikibase-toolbar', - wbCopyrightWarningGravity: 'sw' - } - ] ); - } ) - .on( 'referenceviewafterstartediting', function( event ) { - $( wb ).trigger( 'startItemPageEditMode', [ - event.target, - { - exclusive: false, - wbCopyrightWarningGravity: 'sw' - } - ] ); - } ) - .on( 'snakviewstopediting', function( event, dropValue ) { - // snak view got already removed from the DOM on "snakviewafterstopediting" - if ( dropValue ) { - // Return true on dropValue === false as well as dropValue === undefined - $( wb ).trigger( 'stopItemPageEditMode', [ - event.target, - { save: dropValue !== true } - ] ); + this.element + .on( [ + 'labelviewafterstopediting.' + this.widgetName, + 'descriptionviewafterstopediting.' + this.widgetName, + 'aliasesviewafterstopediting.' + this.widgetName, + 'fingerprintgroupviewafterstopediting.' + this.widgetName, + 'claimlistviewafterremove.' + this.widgetName, + 'claimviewafterstopediting.' + this.widgetName, + 'statementviewafterstopediting.' + this.widgetName, + 'statementviewafterremove.' + this.widgetName, + 'referenceviewafterstopediting.' + this.widgetName, + 'sitelinkviewafterstopediting.' + this.widgetName + ].join( ' ' ), + function( event, dropValue ) { + self.enable(); + + self._trigger( 'afterstopediting', null, [dropValue] ); + } ); + }, + + /** + * @see jQuery.ui.TemplatedWidget.disable + * + * @param {jQuery.Widget} [exceptWidget] + */ + _disable: function( exceptWidget ) { + if( exceptWidget ) { + this._setState( 'disable' ); + exceptWidget.enable(); + return; + } + + this.disable(); + }, + + /** + * @see jQuery.ui.TemplatedWidget + */ + _setOption: function( key, value ) { + var response = PARENT.prototype._setOption.apply( this, arguments ); + + if( key === 'disabled' ) { + this._setState( value ? 'disable' : 'enable' ); + } + + return response; + }, + + /** + * @param {string} state + */ + _setState: function( state ) { + this.$label.data( 'labelview' )[state](); + this.$description.data( 'descriptionview' )[state](); + this.$aliases.data( 'aliasesview' )[state](); + if( this.$fingerprints ) { + this.$fingerprints.data( 'fingerprintgroupview' )[state](); + } + this.$claims.data( 'claimgrouplistview' )[state](); + // TODO: Resolve integration of referenceviews + this.$claims.find( '.wb-statement-references' ).each( function() { + var $listview = $( this ).children( ':wikibase-listview' ); + if( $listview.length ) { + $listview.data( 'listview' )[state](); } - } ) - .on( 'statementviewafterstopediting claimlistviewafterremove ' - + 'referenceviewafterstopediting statementviewafterremove', - function( event, dropValue ) { - // Return true on dropValue === false as well as dropValue === undefined - $( wb ).trigger( 'stopItemPageEditMode', [ - event.target, - { save: dropValue !== true } - ] ); - } - ); + } ); + this.$siteLinks.data( 'sitelinkgrouplistview' )[state](); }, /** diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.fingerprintgroupview.js b/lib/resources/jquery.wikibase/jquery.wikibase.fingerprintgroupview.js index 1d0b3d5..100948d 100644 --- a/lib/resources/jquery.wikibase/jquery.wikibase.fingerprintgroupview.js +++ b/lib/resources/jquery.wikibase/jquery.wikibase.fingerprintgroupview.js @@ -94,6 +94,19 @@ entityId: this.options.entityId, api: this.options.api } ); + }, + + /** + * @see jQuery.ui.TemplatedWidget._setOption + */ + _setOption: function( key, value ) { + var response = PARENT.prototype._setOption.apply( this, arguments ); + + if( key === 'disabled' ) { + this.$fingerprintlistview.data( 'fingerprintlistview' ).option( key, value ); + } + + return response; } } ); diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.fingerprintlistview.js b/lib/resources/jquery.wikibase/jquery.wikibase.fingerprintlistview.js index e0f2691..bd33e34 100644 --- a/lib/resources/jquery.wikibase/jquery.wikibase.fingerprintlistview.js +++ b/lib/resources/jquery.wikibase/jquery.wikibase.fingerprintlistview.js @@ -90,6 +90,19 @@ value: self.options.value || null, listItemNodeName: 'TBODY' } ); + }, + + /** + * @see jQuery.ui.TemplatedWidget._setOption + */ + _setOption: function( key, value ) { + var response = PARENT.prototype._setOption.apply( this, arguments ); + + if( key === 'disabled' ) { + this.element.data( 'listview' ).option( key, value ); + } + + return response; } } ); diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.fingerprintview.js b/lib/resources/jquery.wikibase/jquery.wikibase.fingerprintview.js index 9021f61..c3a1be8 100644 --- a/lib/resources/jquery.wikibase/jquery.wikibase.fingerprintview.js +++ b/lib/resources/jquery.wikibase/jquery.wikibase.fingerprintview.js @@ -190,10 +190,13 @@ self.setError( error ); } ) .on( - widgetName + 'create.' + self.widgetName + ' ' - + widgetName + 'afterstartediting.' + self.widgetName + ' ' - + widgetName + 'stopediting.' + self.widgetName + ' ' - + widgetName + 'afterstopediting.' + self.widgetName, + [ + widgetName + 'create.' + self.widgetName, + widgetName + 'afterstartediting.' + self.widgetName, + widgetName + 'stopediting.' + self.widgetName, + widgetName + 'afterstopediting.' + self.widgetName, + widgetName + 'disable.' + self.widgetName + ].join( ' ' ), function( event ) { event.stopPropagation(); } @@ -208,11 +211,6 @@ entityId: self.options.entityId, api: self.options.api } ); - - // Remove events that would trigger startItemPageEditMode/stopItemPageEditMode: - // TODO: Once this widget is managed by entityview, handling those events should be done - // there. - self['$' + widgetName].off( '.' + widgetName ); } ); }, @@ -354,7 +352,16 @@ aliases: value.aliases } ); } - return PARENT.prototype._setOption.call( this, key, value ); + + var response = PARENT.prototype._setOption.apply( this, arguments ); + + if( key === 'disabled' ) { + this.$labelview.data( 'labelview' ).option( key, value ); + this.$descriptionview.data( 'descriptionview' ).option( key, value ); + this.$aliasesview.data( 'aliasesview' ).option( key, value ); + } + + return response; }, /** diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.labelview.js b/lib/resources/jquery.wikibase/jquery.wikibase.labelview.js index 207245f..ab1fe64 100644 --- a/lib/resources/jquery.wikibase/jquery.wikibase.labelview.js +++ b/lib/resources/jquery.wikibase/jquery.wikibase.labelview.js @@ -57,6 +57,11 @@ _isInEditMode: false, /** + * @type {boolean} + */ + _isBeingEdited: false, + + /** * @see jQuery.ui.TemplatedWidget._create * * @throws {Error} if required parameters are not specified properly. @@ -74,7 +79,6 @@ this.element.attr( 'id', 'wb-firstHeading-' + this.options.entityId ); this.element - // TODO: Move that code to a sensible place (see jQuery.wikibase.entityview): .on( 'labelviewafterstartediting.' + this.widgetName + ' eachchange.' + this.widgetName, @@ -89,28 +93,6 @@ } 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 } - ] ); - } } ); PARENT.prototype._create.call( this ); @@ -148,7 +130,6 @@ } if( !this._isInEditMode ) { - this.element.removeClass( 'wb-edit' ); this.$text.text( this.options.value.label || mw.msg( 'wikibase-label-empty' ) ); return; } @@ -169,21 +150,31 @@ $input.val( this.options.value.label ); } - this.element.addClass( 'wb-edit' ); this.$text.empty().append( $input ); }, /** - * Starts the widget's edit mode. + * Switches to editable state. */ - startEditing: function() { + toEditMode: function() { if( this._isInEditMode ) { return; } this._isInEditMode = true; this._draw(); + }, + /** + * Starts the widget's edit mode. + */ + startEditing: function() { + if( this._isBeingEdited ) { + return; + } + this.element.addClass( 'wb-edit' ); + this.toEditMode(); + this._isBeingEdited = true; this._trigger( 'afterstartediting' ); }, @@ -253,11 +244,11 @@ this.options.value = this.value(); } else if( !this.options.value.label ) { this.$text.children( 'input' ).val( '' ); - this._trigger( 'change' ); } this.element[this.options.value.label ? 'removeClass' : 'addClass']( 'wb-empty' ); - + this.element.removeClass( 'wb-edit' ); + this._isBeingEdited = false; this._isInEditMode = false; this._draw(); @@ -411,7 +402,9 @@ } ); if( !labelview.value().label ) { - labelview.startEditing(); + labelview.toEditMode(); + $labelview.data( 'edittoolbar' ).toolbar.editGroup.toEditMode(); + $labelview.data( 'edittoolbar' ).toolbar.editGroup.disable(); } $labelview @@ -420,14 +413,16 @@ var edittoolbar = $( event.target ).data( 'edittoolbar' ); if( labelview.value().label ) { edittoolbar.toolbar.editGroup.toNonEditMode(); + edittoolbar.enable(); + edittoolbar.toggleActionMessage( function() { + edittoolbar.toolbar.editGroup.getButton( 'edit' ).focus(); + } ); } else { - labelview.startEditing(); + labelview.toEditMode(); + edittoolbar.toolbar.editGroup.toEditMode(); + labelview.focus(); + $labelview.data( 'edittoolbar' ).toolbar.editGroup.disable(); } - - edittoolbar.enable(); - edittoolbar.toggleActionMessage( function() { - edittoolbar.toolbar.editGroup.getButton( 'edit' ).focus(); - } ); } ); }, 'labelviewchange labelviewafterstartediting labelviewafterstopediting': function( event ) { @@ -444,6 +439,33 @@ btnSave[enable ? 'enable' : 'disable'](); btnCancel[disableCancel ? 'disable' : 'enable'](); + + if( event.type === 'labelviewchange' ) { + if( !labelview.isInitialValue() ) { + labelview.startEditing(); + } else if( labelview.isInitialValue() && !labelview.value().label ) { + labelview.cancelEditing(); + } + } + }, + labelviewdisable: 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(), + currentLabel = labelview.value().label; + + btnSave[enable ? 'enable' : 'disable'](); + + if( labelview.option( 'disabled' ) || currentLabel ) { + return; + } + + if( !currentLabel ) { + toolbar.disable(); + } }, toolbareditgroupedit: function( event, toolbarcontroller ) { var $labelview = $( event.target ).closest( ':wikibase-edittoolbar' ), diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.listview.js b/lib/resources/jquery.wikibase/jquery.wikibase.listview.js index b292065..1fe9af7 100644 --- a/lib/resources/jquery.wikibase/jquery.wikibase.listview.js +++ b/lib/resources/jquery.wikibase/jquery.wikibase.listview.js @@ -123,10 +123,25 @@ * We are using this to disallow changing the 'listItemAdapter' option afterwards */ _setOption: function( key, value ) { + var self = this; + if( key === 'listItemAdapter' ) { throw new Error( 'Can not change the ListItemAdapter after initialization' ); } - PARENT.prototype._setOption.call( this, key, value ); + + var response = PARENT.prototype._setOption.apply( this, arguments ); + + if( key === 'disabled' ) { + this.items().each( function() { + var liInstance = self._lia.liInstance( $( this ) ); + // Check if instance got destroyed in the meantime: + if( liInstance ) { + liInstance.option( key, value ); + } + } ); + } + + return response; }, /** diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.referenceview.js b/lib/resources/jquery.wikibase/jquery.wikibase.referenceview.js index 709d37e..343fa67 100644 --- a/lib/resources/jquery.wikibase/jquery.wikibase.referenceview.js +++ b/lib/resources/jquery.wikibase/jquery.wikibase.referenceview.js @@ -49,12 +49,6 @@ * @event change: Triggered whenever the referenceview's content is changed. * (1) {jQuery.Event} event * - * @event disable: Triggered whenever the referenceview gets disabled. - * (1) {jQuery.Event} event - * - * @event enable: Triggered whenever the referenceview gets enabled. - * (1) {jQuery.Event} event - * * @event toggleerror: Triggered when an error occurred or is resolved. * (1) {jQuery.Event} event * (2) {wb.RepoApiError|undefined} wb.RepoApiError object if an error occurred, undefined if @@ -591,33 +585,17 @@ }, /** - * Disables the referenceview. - * @since 0.5 - * - * @triggers disable + * @see jQuery.ui.TemplatedWidget._setOption */ - disable: function() { - var $snaklistviews = this._listview.items(); - for( var i = 0; i < $snaklistviews.length; i++ ) { - this.options.listItemAdapter.liInstance( $snaklistviews.eq( i ) ).disable(); - } - this._trigger( 'disable' ); - }, + _setOption: function( key, value ) { + var response = PARENT.prototype._setOption.apply( this, arguments ); - /** - * Enables the referenceview. - * @since 0.5 - * - * @triggers enable - */ - enable: function() { - var $snaklistviews = this._listview.items(); - for( var i = 0; i < $snaklistviews.length; i++ ) { - this.options.listItemAdapter.liInstance( $snaklistviews.eq( i ) ).enable(); + if( key === 'disabled' ) { + this._listview.option( key, value ); } - this._trigger( 'enable' ); + + return response; } - } ); // Register toolbars: @@ -662,23 +640,17 @@ event.data.toolbar.id, 'referenceviewdisable', function( event ) { - $( event.target ).data( 'addtoolbar' ).toolbar.disable(); - } - ); + var referenceview = $( event.target ).data( 'referenceview' ), + addToolbar = $( event.target ).data( 'addtoolbar' ); - toolbarController.registerEventHandler( - event.data.toolbar.type, - event.data.toolbar.id, - 'referenceviewenable', - function( event ) { - var addToolbar = $( event.target ).data( 'addtoolbar' ); - // "add" toolbar might be remove already. if( addToolbar ) { - addToolbar.toolbar.enable(); + addToolbar.toolbar[referenceview.option( 'disabled' ) + ? 'disable' + : 'enable' + ](); } } ); - } } } ); @@ -723,14 +695,20 @@ toolbarController.registerEventHandler( event.data.toolbar.type, event.data.toolbar.id, - 'referenceviewdisable referenceviewenable', + 'referenceviewdisable listviewitemremoved', function( event ) { - var referenceview = $( event.target ).data( 'referenceview' ), - $snaklistviews = referenceview._listview.items(), - lia = referenceview.options.listItemAdapter, - action = ( event.type.indexOf( 'disable' ) !== -1 ) - ? 'disable' - : 'enable'; + var $referenceview = event.type.indexOf( 'referenceview' ) !== -1 + ? $( event.target ) + : $( event.target ).closest( ':wikibase-referenceview' ); + + var referenceview = $referenceview.data( 'referenceview' ); + + if( !referenceview ) { + return; + } + + var $snaklistviews = referenceview._listview.items(), + lia = referenceview.options.listItemAdapter; for( var i = 0; i < $snaklistviews.length; i++ ) { var snaklistview = lia.liInstance( $snaklistviews.eq( i ) ); @@ -740,10 +718,16 @@ var $snakviews = snaklistview._listview.items(); for( var j = 0; j < $snakviews.length; j++ ) { - var removetoolbar = $snakviews.eq( j ).data( 'removetoolbar' ); + var $snakview = $snakviews.eq( j ), + removetoolbar = $snakview.data( 'removetoolbar' ); if( removetoolbar ) { - removetoolbar.toolbar[action](); + removetoolbar.toolbar[ + referenceview.option( 'disabled' ) + || $snakviews.length === 1 && $snaklistviews.length === 1 + ? 'disable' + : 'enable' + ](); } } } diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.sitelinkgrouplistview.js b/lib/resources/jquery.wikibase/jquery.wikibase.sitelinkgrouplistview.js index 3f08dc5..bce5254 100644 --- a/lib/resources/jquery.wikibase/jquery.wikibase.sitelinkgrouplistview.js +++ b/lib/resources/jquery.wikibase/jquery.wikibase.sitelinkgrouplistview.js @@ -97,6 +97,19 @@ } ), value: self.options.value || null } ); + }, + + /** + * @see jQuery.ui.TemplatedWidget._setOption + */ + _setOption: function( key, value ) { + var response = PARENT.prototype._setOption.apply( this, arguments ); + + if( key === 'disabled' ) { + this.$listview.data( 'listview' ).option( key, value ); + } + + return response; } } ); diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.sitelinkgroupview.js b/lib/resources/jquery.wikibase/jquery.wikibase.sitelinkgroupview.js index a354462..afd47aa 100644 --- a/lib/resources/jquery.wikibase/jquery.wikibase.sitelinkgroupview.js +++ b/lib/resources/jquery.wikibase/jquery.wikibase.sitelinkgroupview.js @@ -146,7 +146,7 @@ value = this._checkValue( value ); } - PARENT.prototype._setOption.call( this, key, value ); + var response = PARENT.prototype._setOption.call( this, key, value ); if( key === 'value' ) { this.$sitelinklistview.data( 'sitelinklistview' ) @@ -154,7 +154,11 @@ .value( this.options.value.siteLinks ); this._update(); + } else if( key === 'disabled' ) { + this.$sitelinklistview.data( 'sitelinklistview' ).option( key, value ); } + + return response; }, /** diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.sitelinklistview.js b/lib/resources/jquery.wikibase/jquery.wikibase.sitelinklistview.js index aa941a3..8f88481 100644 --- a/lib/resources/jquery.wikibase/jquery.wikibase.sitelinklistview.js +++ b/lib/resources/jquery.wikibase/jquery.wikibase.sitelinklistview.js @@ -178,22 +178,6 @@ sitelinkview.enable(); } ); } - } ) - // TODO: Move that code to a sensible place (see jQuery.wikibase.entityview): - .on( 'sitelinkviewafterstartediting.' + this.widgetName, function( event ) { - $( wb ).trigger( 'startItemPageEditMode', [ - $( event.target ), - { - exclusive: false, - wbCopyrightWarningGravity: 'sw' - } - ] ); - } ) - .on( 'sitelinkviewafterstopediting.' + this.widgetName, function( event, dropValue ) { - $( wb ).trigger( 'stopItemPageEditMode', [ - $( event.target ), - { save: dropValue !== true } - ] ); } ); }, @@ -254,13 +238,17 @@ * @see jQuery.ui.TemplatedWidget._setOption */ _setOption: function( key, value ) { - PARENT.prototype._setOption.call( this, key, value ); + var response = PARENT.prototype._setOption.apply( this, arguments ); if( key === 'value' ) { this.$listview.data( 'listview' ).value( value ); this._refreshCounter(); this._refreshTableHeader(); + } else if( key === 'disabled' ) { + this.$listview.data( 'listview' ).option( key, value ); } + + return response; }, /** @@ -487,6 +475,21 @@ } } ); + toolbarcontroller.registerEventHandler( + event.data.toolbar.type, + event.data.toolbar.id, + 'sitelinklistviewdisable', + function() { + var disabled = sitelinklistview.option( 'disabled' ); + + if( !disabled && sitelinklistview.isFull() ) { + return; + } + + $sitelinklistview.data( 'addtoolbar' )[disabled ? 'disable' : 'enable'](); + } + ); + if( sitelinklistview.isFull() ) { $sitelinklistview.data( 'addtoolbar' ).toolbar.disable(); } diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.sitelinkview.js b/lib/resources/jquery.wikibase/jquery.wikibase.sitelinkview.js index 1e4de0d..3ff38ba 100644 --- a/lib/resources/jquery.wikibase/jquery.wikibase.sitelinkview.js +++ b/lib/resources/jquery.wikibase/jquery.wikibase.sitelinkview.js @@ -415,10 +415,35 @@ throw new Error( 'Cannot set site link with new site id after initialization' ); } - PARENT.prototype._setOption.apply( this, arguments ); + var response = PARENT.prototype._setOption.apply( this, arguments ); if( key === 'value' ) { this._draw(); + } else if( key === 'disabled' ) { + this._setState( value ? 'disable' : 'enable' ); + } + + return response; + }, + + /** + * @param {string} state + */ + _setState: function( state ) { + if( this._isInEditMode ) { + var $siteInput = this.$siteId.find( 'input' ), + hasSiteId = !!( this.options.value && this.options.value.getSiteId() ); + + if( $siteInput.length ) { + var siteselector = $siteInput.data( 'siteselector' ); + hasSiteId = !!siteselector.getSelectedSite(); + siteselector[state](); + } + + // Do not enable page input if no site is set: + if( state === 'disable' || hasSiteId ) { + this.$link.find( 'input' ).data( 'pagesuggester' )[state](); + } } }, @@ -500,6 +525,16 @@ } ); }, + sitelinkviewdisable: function( event ) { + var $sitelinkview = $( event.target ), + sitelinkview = $sitelinkview.data( 'sitelinkview' ), + toolbar = $sitelinkview.data( 'edittoolbar' ).toolbar, + $btnSave = toolbar.editGroup.getButton( 'save' ), + btnSave = $btnSave.data( 'toolbarbutton' ), + enable = sitelinkview.isValid() && !sitelinkview.isInitialValue(); + + btnSave[enable ? 'enable' : 'disable'](); + }, toolbareditgroupedit: function( event, toolbarcontroller ) { var $sitelinkview = $( event.target ).closest( ':wikibase-edittoolbar' ), sitelinkview = $sitelinkview.data( 'sitelinkview' ); diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.snaklistview.js b/lib/resources/jquery.wikibase/jquery.wikibase.snaklistview.js index 169fe20..b6905bd 100644 --- a/lib/resources/jquery.wikibase/jquery.wikibase.snaklistview.js +++ b/lib/resources/jquery.wikibase/jquery.wikibase.snaklistview.js @@ -442,35 +442,6 @@ }, /** - * Disables the snaklistview. - * @since 0.4 - */ - disable: function() { - var self = this; - $.each( this._listview.items(), function( i, item ) { - var $item = $( item ); - self._lia.liInstance( $item ).disable(); - } ); - this._trigger( 'disable' ); - }, - - /** - * Enables the snaklistview. - * @since 0.4 - */ - enable: function() { - var self = this; - $.each( this._listview.items(), function( i, item ) { - var $item = $( item ); - // Item might be about to be removed not being a list item instance. - if ( self._lia.liInstance( $item ) ) { - self._lia.liInstance( $item ).enable(); - } - } ); - this._trigger( 'enable' ); - }, - - /** * @see jQuery.widget.destroy */ destroy: function() { @@ -479,7 +450,7 @@ }, /** - * @see jQuery.widget._setOption + * @see jQuery.ui.TemplatedWidget._setOption */ _setOption: function( key, value ) { // The value should not be set from outside after the initialization because @@ -487,7 +458,14 @@ if( key === 'value' ) { throw new Error( 'Can not set value after initialization' ); } - $.Widget.prototype._setOption.call( this, key, value ); + + var response = PARENT.prototype._setOption.apply( this, arguments ); + + if( key === 'disabled' ) { + this._listview.option( key, value ); + } + + return response; }, /** diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.statementview.js b/lib/resources/jquery.wikibase/jquery.wikibase.statementview.js index e0d8d7c..0958357 100644 --- a/lib/resources/jquery.wikibase/jquery.wikibase.statementview.js +++ b/lib/resources/jquery.wikibase/jquery.wikibase.statementview.js @@ -459,6 +459,22 @@ }, addButtonLabel: mw.msg( 'wikibase-addreference' ) } ); + + toolbarController.registerEventHandler( + event.data.toolbar.type, + event.data.toolbar.id, + 'listviewdisable', + function( event ) { + if( event.target !== $listview.get( 0 ) ) { + return; + } + $node.data( 'addtoolbar' )[ + listview.option( 'disabled' ) + ? 'disable' + : 'enable' + ](); + } + ); } } } ); diff --git a/lib/resources/jquery.wikibase/snakview/snakview.js b/lib/resources/jquery.wikibase/snakview/snakview.js index 2507b59..7fd6f33 100644 --- a/lib/resources/jquery.wikibase/snakview/snakview.js +++ b/lib/resources/jquery.wikibase/snakview/snakview.js @@ -186,7 +186,7 @@ }, /** - * @see jQuery.widget._setOption + * @see jQuery.ui.TemplatedWidget._setOption */ _setOption: function( key, value ) { if ( key === 'locked' && typeof value === 'boolean' ) { @@ -196,7 +196,22 @@ value[k] = locked; } ); } - PARENT.prototype._setOption.call( this, key, value ); + + var response = PARENT.prototype._setOption.apply( this, arguments ); + + if( key === 'disabled' ) { + this.draw(); + } + + return response; + }, + + /** + * @return {boolean} + */ + isDisabled: function() { + // Function is required by snakview.ViewState. + return this.option( 'disabled' ); }, /** @@ -291,7 +306,7 @@ // attach keyboard input events this.element.on( 'keydown.' + this.widgetName, function( event ) { - if ( self.isDisabled() ) { + if ( self.options.disabled ) { return; } @@ -718,10 +733,6 @@ } ); this.drawSnakTypeSelector(); this.drawVariation(); - - // have native $.Widget functionality add/remove state css classes - // (see jQuery.Widget._setOption) - PARENT.prototype.option.call( this, 'disabled', this.isDisabled() ); }, /** @@ -756,7 +767,7 @@ $propertyDom = this._buildPropertySelector().val( propertyLabel ); // propagate snakview state: - $propertyDom.data( 'entityselector' ).option( 'disabled', this.isDisabled() ); + $propertyDom.data( 'entityselector' ).option( 'disabled', this.options.disabled ); } else { return; } @@ -798,7 +809,7 @@ this.$snakTypeSelector[ ( this._propertyId ? 'show' : 'hide' ) ](); // propagate snakview state: - if ( this.isDisabled() ) { + if ( this.options.disabled ) { selector.disable(); } else { selector.enable(); @@ -890,40 +901,6 @@ */ propertyLabelIsVisible: function() { return this.$property.is( ':visible' ); - }, - - /** - * Marks the Snak view disabled and triggers re-drawing it. - * Since the visual state should be managed completely by the draw method, toggling the css - * classes is done in draw() by issuing a call to $.Widget.option(). - * @see jQuery.Widget.disable - * @since 0.4 - */ - disable: function() { - this.options.disabled = true; - this.draw(); - }, - - /** - * Marks the Snak view enabled and triggers re-drawing the Snak view. - * Since the visual state should be managed completely by the draw method, toggling the css - * classes is done in draw() by issuing a call to $.Widget.option(). - * @see jQuery.Widget.enable - * @since 0.4 - */ - enable: function() { - this.options.disabled = false; - this.draw(); - }, - - /** - * Returns whether the Snak view is disabled. - * @since 0.4 - * - * @return {boolean} - */ - isDisabled: function() { - return this.option( 'disabled' ); } } ); diff --git a/lib/resources/jquery.wikibase/toolbar/edittoolbar.js b/lib/resources/jquery.wikibase/toolbar/edittoolbar.js index 1ad1a64..ac0e243 100644 --- a/lib/resources/jquery.wikibase/toolbar/edittoolbar.js +++ b/lib/resources/jquery.wikibase/toolbar/edittoolbar.js @@ -47,7 +47,6 @@ * @event afterstopediting * Triggered after the toolbar has switched to non-edit mode. * (1) {jQuery.Event} - * (2) {boolean} */ $.widget( 'wikibase.edittoolbar', PARENT, { /** @@ -207,13 +206,12 @@ self.toggleActionMessage( { message: 'wikibase-save-inprogress' } ); } } ) - .on( prefix + 'afterstopediting.' + this.widgetName, function( event, dropValue ) { + .on( prefix + 'afterstopediting.' + this.widgetName, function( event ) { editGroup.toNonEditMode(); self.enable(); self.toggleActionMessage( function() { editGroup.getButton( 'edit' ).focus(); - // TODO: Remove dropValue since it should not be of interest for other components - self._trigger( 'afterstopediting', null, [dropValue] ); + self._trigger( 'afterstopediting' ); } ); } ) .on( prefix + 'afterstartediting ' + prefix + 'change', function( event ) { @@ -229,6 +227,9 @@ editGroup.disableButton( 'save' ); } } ) + .on( prefix + 'disable', function( event, disable ) { + self[disable ? 'disable' : 'enable'](); + } ) .on( prefix + 'toggleerror', function( event, error ) { if ( error && error instanceof wb.RepoApiError ) { var $anchor; diff --git a/lib/resources/wikibase.css b/lib/resources/wikibase.css index 5f66a13..98a191b 100644 --- a/lib/resources/wikibase.css +++ b/lib/resources/wikibase.css @@ -28,11 +28,19 @@ } .wb-entitypage .ui-state-disabled input, +.wb-entitypage input.ui-state-disabled .wb-entitypage .ui-state-disabled textarea { background-color: #F0F0F0; color: #565656; } +/* Overwrite colour for element that are in edit mode although their container element is not */ +.wb-entitypage .ui-state-disabled .wb-edit input:not(.ui-state-disabled), +.wb-entitypage .ui-state-disabled .wb-edit textarea { + background-color: #FFFFFF; + color: inherit; +} + /* Messages displayed while some action is performed (e.g. an API call) */ .wb-actionmsg { font-style: italic; diff --git a/lib/resources/wikibase.js b/lib/resources/wikibase.js index 0aa73c5..78e8a6f 100644 --- a/lib/resources/wikibase.js +++ b/lib/resources/wikibase.js @@ -9,45 +9,6 @@ /** * Global 'Wikibase' extension singleton. * @since 0.1 - * - * TODO: startItemPageEditMode and stopItemPageEditMode should be removed or marked deprecated as - * soon as we can get rid of old wb.ui.PropertyEditTool ui. There should be no global edit - * mode event anymore since with the new jQuery.wikibase widgets all editing related events - * bubble through the DOM anyhow, so everyone can listen to those on any level of a pages DOM. - * - * @event startItemPageEditMode: Triggered when any edit mode on the item page is started - * (1) {jQuery.Event} event - * (2) {wb.ui.PropertyEditTool.EditableValue|jQuery} origin Object which triggered the event. - * If the origin of the event is one of the new (jQuery.wikibase) widgets, then this will - * be the widget's DOM node. - * (3) {Object} options An object with any of the following properties: - * {boolean|string} exclusive Whether action shall influence sub-toolbars of origin. - * {string} wbCopyrightWarningGravity Direction, defaults to "nw". - * - * @event newItemCreated: Triggered after an item has been created and the necessary API request has - * returned. - * (1) {jQuery.Event} event - * (2) {Object} item The new item returned by the API request. | FIXME: this should be an - * 'Item' object! - * - * @event stopItemPageEditMode: Triggered when any edit mode on the item page is stopped. - * (1) {jQuery.Event} event - * (2) {wb.ui.PropertyEditTool.EditableValue|jQuery} origin Object which triggered the event. - * If the origin of the event is one of the new (jQuery.wikibase) widgets, then this will - * be the widget's DOM node. - * (3) {Object} options An object with any of the following properties: - * {boolean} save Whether the change got saved or canceled and dropped. Defaults to true. - * {boolean} wasPending Whether value was a previously not existent/new value that has - * just been added. Defaults to false. - * - * @event restrictEntityPageActions: Triggered when editing is not allowed for the user. - * (see TODO/FIXME in wikibase.ui.entityViewInit - handle edit restrictions) - * (1) {jQuery.Event} event - * - * @event blockEntityPageActions: Triggered when editing is not allowed for the user because he is - * blocked from the page. - * (see TODO/FIXME in wikibase.ui.entityViewInit - handle edit restrictions) - * (1) {jQuery.Event} event */ this.wikibase = this.wb = new ( function Wb( mw, $ ) { 'use strict'; diff --git a/lib/tests/qunit/data/testrunner.js b/lib/tests/qunit/data/testrunner.js index d2e6a3b..24cdf6c 100644 --- a/lib/tests/qunit/data/testrunner.js +++ b/lib/tests/qunit/data/testrunner.js @@ -75,11 +75,6 @@ mw.config.values = $.extend( {}, globalConfig, custom.config ); } - // remove interfering global events - $( wb ).off( 'newItemCreated' ); - $( wb ).off( 'startItemPageEditMode' ); - $( wb ).off( 'stopItemPageEditMode' ); - wb.sites._siteList = null; // empty cache of wikibases site details if( custom.setup !== undefined ) { custom.setup.apply( this, arguments ); diff --git a/repo/resources/wikibase.ui.entityViewInit.js b/repo/resources/wikibase.ui.entityViewInit.js index beba6d3..e66d367 100644 --- a/repo/resources/wikibase.ui.entityViewInit.js +++ b/repo/resources/wikibase.ui.entityViewInit.js @@ -1,13 +1,7 @@ /** - * JavaScript for 'wikibase' extension, initializing some stuff when ready. This is the main - * entry point for initializing edit tools for editing entities on entity pages. - * - * @since 0.1 - * * @licence GNU GPL v2+ + * @author H. Snater < [email protected] > * @author Daniel Werner < daniel.werner at wikimedia.de > - * - * TODO: Refactor this huge single function into smaller pieces of code. */ ( function( $, mw, wb, dataTypes, experts, getFormatterStore, getParserStore ) { @@ -15,147 +9,25 @@ mw.hook( 'wikipage.content' ).add( function() { // Edit sections are re-generated with JS functionality further below: - $( '.wb-editsection' ).parent( 'td' ).not( '.wb-terms td' ).remove(); + $( '.wb-editsection' ).parent( 'td' ).remove(); $( '.wb-editsection:not(td)' ).remove(); - // Since the DOM is altered for the property edit tools to initialize properly, the - // following hook informs about these operations having finished. - // TODO: This hook is not supposed to be permanent. Remove it as soon as no more global DOM - // adjustments are necessary. - mw.hook( 'wikibase.domready' ).fire(); - - registerEditRestrictionHandlers(); + var $entityview = $( '.wikibase-entityview' ); if( mw.config.get( 'wbEntity' ) !== null ) { - var $entityview = $( '.wikibase-entityview' ).first(); - initToolbarController( $entityview ); var entityInitializer = new wb.EntityInitializer( 'wbEntity' ); entityInitializer.getEntity().done( function( entity ) { - createEntityDom( entity, $entityview ); - triggerEditRestrictionHandlers(); + createEntityDom( entity, $entityview.first() ); + evaluateRestrictions(); + + // Remove loading spinner after JavaScript has kicked in: + $entityview.removeClass( 'loading' ); + $( '.wb-entity-spinner' ).remove(); } ); } - - $( wb ).on( 'startItemPageEditMode', function( event, origin, options ) { - // add copyright warning to 'save' button if there is one: - if( mw.config.exists( 'wbCopyright' ) ) { - - var copyRight = mw.config.get( 'wbCopyright' ), - copyRightVersion = copyRight.version, - copyRightMessageHtml = copyRight.messageHtml, - cookieKey = 'wikibase.acknowledgedcopyrightversion', - optionsKey = 'wb-acknowledgedcopyrightversion'; - - if ( $.cookie( cookieKey ) === copyRightVersion || - mw.user.options.get( optionsKey ) === copyRightVersion - ) { - return; - } - - var $message = $( '<span><p>' + copyRightMessageHtml + '</p></span>' ), - edittoolbar = $( origin ).data( 'edittoolbar' ); - - if( !edittoolbar ) { - return; - } - - var $hideMessage = $( '<a/>', { - text: mw.msg( 'wikibase-copyrighttooltip-acknowledge' ) - } ).appendTo( $message ); - - var gravity = ( options && options.wbCopyrightWarningGravity ) || 'nw'; - - // Tooltip gets its own anchor since other elements might have their own tooltip. - // we don't even have to add this new toolbar element to the toolbar, we only use it - // to manage the tooltip which will have the 'save' button as element to point to. - // The 'save' button can still have its own tooltip though. - var $messageAnchor = $( '<span/>' ) - .appendTo( 'body' ) - .toolbarlabel() - .wbtooltip( { - content: $message, - permanent: true, - gravity: gravity, - $anchor: edittoolbar.toolbar.editGroup.getButton( 'save' ) - } ); - - $hideMessage.on( 'click', function( event ) { - event.preventDefault(); - $messageAnchor.data( 'wbtooltip' ).degrade( true ); - if ( mw.user.isAnon() ) { - $.cookie( cookieKey, copyRightVersion, { 'expires': 365 * 3, 'path': '/' } ); - } else { - var api = new mw.Api(); - api.get( { - 'action': 'tokens', - 'type': 'options' - }, function( data ) { - if ( data.tokens && data.tokens.optionstoken ) { - api.post( { - 'action': 'options', - 'token': data.tokens.optionstoken, - 'optionname': optionsKey, - 'optionvalue': copyRightVersion - } ); - } - } ); - } - } ); - - $messageAnchor.data( 'wbtooltip' ).show(); - - // destroy tooltip after edit mode gets closed again: - $( wb ).one( 'stopItemPageEditMode', function( event, origin ) { - if( $messageAnchor.data( 'wbtooltip' ) !== undefined ) { - $messageAnchor.data( 'wbtooltip' ).degrade( true ); - } - } ); - } - } ); - - // Check if the watch link (star in the Vector skin) needs to be updated after an edit - $( wb ).on( 'stopItemPageEditMode', function( event, origin, options ) { - // If save is undefined it should default to true - var canceled = options && options.save === false; - var updateWatchLink = mw.page && mw.page.watch ? mw.page.watch.updateWatchLink : null; - - // Skip if module isn't loaded or user doesn't have "watch by default" enabled anyway - if ( canceled || !updateWatchLink || !mw.user.options.get( 'watchdefault' ) ) { - return; - } - - // All four supported skins are using the same ID, the other selectors - // in mediawiki.page.watch.ajax.js are undocumented and probably legacy stuff - var $link = $( '#ca-watch a' ); - - // Skip if page is already watched and there is no "watch this page" link - // Note: The exposed function fails for empty jQuery collections - if ( $link.length ) { - updateWatchLink( $link, 'watch', 'loading' ); - var api = new mw.Api(); - var pageid = mw.config.get( 'wgArticleId' ); - api.get( { - 'action': 'query', - 'prop': 'info', - 'inprop': 'watched', - 'pageids': pageid - } ).done( function( data ) { - var watched = data.query && data.query.pages[pageid] && - data.query.pages[pageid].watched !== undefined; - updateWatchLink( $link, watched ? 'unwatch' : 'watch' ); - } ).fail( function() { - updateWatchLink( $link, 'watch' ); - } ); - } - } ); - - // remove loading spinner after JavaScript has kicked in - $( '.wikibase-entityview' ).removeClass( 'loading' ); - $( '.wb-entity-spinner' ).remove(); - } ); /** @@ -191,12 +63,25 @@ ] }; - $entityview.toolbarcontroller( toolbarControllerConfig ); + $entityview + .toolbarcontroller( toolbarControllerConfig ) + .on( 'edittoolbarafterstartediting', function( event ) { + var $target = $( event.target ), + gravity = 'sw'; + + if( + $target.data( 'labelview' ) + || $target.data( 'descriptionview' ) + || $target.data( 'aliasesview' ) + ) { + gravity = 'nw'; + } + + showCopyrightTooltip( $entityview, $( event.target ), gravity ); + } ); } /** - * Creates the entity DOM structure. - * * @param {wikibase.datamodel.Entity} entity * @param {jQuery} $entityview */ @@ -205,6 +90,37 @@ var entityStore = new wb.store.EntityStore( abstractedRepoApi ); wb.compileEntityStoreFromMwConfig( entityStore ); + $entityview + .entityview( { + value: entity, + entityStore: entityStore, + valueViewBuilder: new wb.ValueViewBuilder( + experts, + getFormatterStore( abstractedRepoApi, dataTypes ), + getParserStore( abstractedRepoApi ), + mw + ), + api: abstractedRepoApi, + languages: getUserLanguages() + } ) + .on( 'labelviewchange labelviewafterstopediting', 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' ) ) + ); + } ) + .on( 'entityviewafterstartediting', function() { + triggerAnonymousEditWarning( entity.getType() ); + } ) + .on( 'entityviewafterstopediting', function( event, dropValue ) { + updateWatchLink( dropValue ); + } ); + } + + function getUserLanguages() { var userLanguages = mw.config.get( 'wbUserSpecifiedLanguages' ), isUlsDefined = mw.uls !== undefined && $.uls !== undefined @@ -218,82 +134,170 @@ languages.splice( $.inArray( mw.config.get( 'wgUserLanguage' ), userLanguages ), 1 ); } - $entityview - .entityview( { - value: entity, - entityStore: entityStore, - valueViewBuilder: new wb.ValueViewBuilder( - experts, - getFormatterStore( abstractedRepoApi, dataTypes ), - getParserStore( abstractedRepoApi ), - mw - ), - api: abstractedRepoApi, - languages: languages - } ) - .on( 'labelviewchange labelviewafterstopediting', function( event ) { - var $labelview = $( event.target ), - labelview = $labelview.data( 'labelview' ), - label = labelview.value().label; + return languages; + } - $( 'title' ).text( - mw.msg( 'pagetitle', label && label !== '' ? label : mw.config.get( 'wgTitle' ) ) - ); - } ); + /** + * @param {boolean} dropValue + */ + function updateWatchLink( dropValue ) { + var update = mw.page && mw.page.watch ? mw.page.watch.updateWatchLink : null; - $( wb ).on( 'startItemPageEditMode', function( event, origin, options ) { - // Display anonymous user edit warning: - if ( mw.user && mw.user.isAnon() + if( dropValue || !update || !mw.user.options.get( 'watchdefault' ) ) { + return; + } + + // All four supported skins are using the same ID, the other selectors + // in mediawiki.page.watch.ajax.js are undocumented and probably legacy stuff + var $link = $( '#ca-watch a' ); + + // Skip if page is already watched and there is no "watch this page" link + // Note: The exposed function fails for empty jQuery collections + if( $link.length ) { + update( $link, 'watch', 'loading' ); + + var api = new mw.Api(), + pageId = mw.config.get( 'wgArticleId' ); + + api.get( { + action: 'query', + prop: 'info', + inprop: 'watched', + pageids: pageId + } ).done( function( data ) { + var watched = data.query && data.query.pages[pageId] + && data.query.pages[pageId].watched !== undefined; + update( $link, watched ? 'unwatch' : 'watch' ); + } ).fail( function() { + update( $link, 'watch' ); + } ); + } + } + + /** + * @param {string} entityType + */ + function triggerAnonymousEditWarning( entityType ) { + if( + mw.user && mw.user.isAnon() && $.find( '.mw-notification-content' ).length === 0 && !$.cookie( 'wikibase-no-anonymouseditwarning' ) - ) { - mw.notify( - mw.msg( 'wikibase-anonymouseditwarning', - mw.msg( 'wikibase-entity-' + entity.getType() ) - ) - ); + ) { + mw.notify( + mw.msg( 'wikibase-anonymouseditwarning', + mw.msg( 'wikibase-entity-' + entityType ) + ) + ); + } + } + + /** + * @param {jQuery} $entityview + * @param {jQuery} $origin + * @param {string} gravity + */ + function showCopyrightTooltip( $entityview, $origin, gravity ) { + if( !mw.config.exists( 'wbCopyright' ) ) { + return; + } + + gravity = gravity || 'nw'; + + var copyRight = mw.config.get( 'wbCopyright' ), + copyRightVersion = copyRight.version, + copyRightMessageHtml = copyRight.messageHtml, + cookieKey = 'wikibase.acknowledgedcopyrightversion', + optionsKey = 'wb-acknowledgedcopyrightversion'; + + if( + $.cookie( cookieKey ) === copyRightVersion + || mw.user.options.get( optionsKey ) === copyRightVersion + ) { + return; + } + + var $message = $( '<span><p>' + copyRightMessageHtml + '</p></span>' ), + edittoolbar = $origin.data( 'edittoolbar' ); + + if( !edittoolbar ) { + return; + } + + var $hideMessage = $( '<a/>', { + text: mw.msg( 'wikibase-copyrighttooltip-acknowledge' ) + } ).appendTo( $message ); + + // Tooltip gets its own anchor since other elements might have their own tooltip. + // we don't even have to add this new toolbar element to the toolbar, we only use it + // to manage the tooltip which will have the 'save' button as element to point to. + // The 'save' button can still have its own tooltip though. + var $messageAnchor = $( '<span/>' ) + .appendTo( 'body' ) + .toolbarlabel() + .wbtooltip( { + content: $message, + permanent: true, + gravity: gravity, + $anchor: edittoolbar.toolbar.editGroup.getButton( 'save' ) + } ); + + $hideMessage.on( 'click', function( event ) { + event.preventDefault(); + $messageAnchor.data( 'wbtooltip' ).degrade( true ); + if( mw.user.isAnon() ) { + $.cookie( cookieKey, copyRightVersion, { 'expires': 365 * 3, 'path': '/' } ); + } else { + var api = new mw.Api(); + api.postWithToken( 'options', { + 'action': 'options', + 'optionname': optionsKey, + 'optionvalue': copyRightVersion + } ); + } + } ); + + $messageAnchor.data( 'wbtooltip' ).show(); + + // destroy tooltip after edit mode gets closed again: + $entityview + .one( 'entityviewafterstopediting', function( event, origin ) { + if( $messageAnchor.data( 'wbtooltip' ) !== undefined ) { + $messageAnchor.data( 'wbtooltip' ).degrade( true ); } } ); } - function registerEditRestrictionHandlers() { - $( wb ) - .on( 'restrictEntityPageActions blockEntityPageActions', function( event ) { - $( '.wikibase-toolbarbutton' ).each( function( i, node ) { - var toolbarButton = $( node ).data( 'toolbarbutton' ); - - toolbarButton.disable(); - - var messageId = ( event.type === 'blockEntityPageActions' ) - ? 'wikibase-blockeduser-tooltip-message' - : 'wikibase-restrictionedit-tooltip-message'; - - toolbarButton.element.wbtooltip( { - content: mw.message( messageId ).escaped(), - gravity: 'nw' - } ); - } ); - } ); - } - - function triggerEditRestrictionHandlers() { - if ( mw.config.get( 'wbUserIsBlocked' ) ) { - $( wb ).triggerHandler( 'blockEntityPageActions' ); - } else if ( !mw.config.get( 'wbUserCanEdit' ) ) { - $( wb ).triggerHandler( 'restrictEntityPageActions' ); + function evaluateRestrictions() { + if( mw.config.get( 'wbUserIsBlocked' ) ) { + restrict( 'blockeduser' ); + } else if( !mw.config.get( 'wbUserCanEdit' ) ) { + restrict( 'restrictionedit' ); } if( !mw.config.get( 'wbIsEditView' ) ) { - // no need to implement a 'disableEntityPageActions' since hiding all the toolbars directly like this is - // not really worse than hacking the Toolbar prototype to achieve this: - $( '.wikibase-toolbar' ).hide(); + // no need to implement a 'disableEntityPageActions' since hiding all the toolbars + // directly like this is not really worse than hacking the Toolbar prototype to achieve + // this: + $( ':wikibase-toolbar' ).hide(); $( 'body' ).addClass( 'wb-editing-disabled' ); - // make it even harder to edit stuff, e.g. if someone is trying to be smart, using - // firebug to show hidden nodes again to click on them: - $( wb ).triggerHandler( 'restrictEntityPageActions' ); } } + /** + * @param {string} key + */ + function restrict( key ) { + $( ':wikibase-toolbarbutton' ).each( function() { + var toolbarButton = $( this ).data( 'toolbarbutton' ); + toolbarButton.disable(); + + toolbarButton.element.wbtooltip( { + content: mw.message( 'wikibase-' + key + '-tooltip-message' ).escaped(), + gravity: 'nw' + } ); + } ); + } + } )( jQuery, mediaWiki, -- To view, visit https://gerrit.wikimedia.org/r/157794 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: Id9ed0ea51064f2ce295cb1b3f1a23cb36a850442 Gerrit-PatchSet: 10 Gerrit-Project: mediawiki/extensions/Wikibase Gerrit-Branch: master Gerrit-Owner: Henning Snater <[email protected]> Gerrit-Reviewer: Henning Snater <[email protected]> Gerrit-Reviewer: Tobias Gritschacher <[email protected]> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list [email protected] https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
