Henning Snater has uploaded a new change for review. https://gerrit.wikimedia.org/r/177203
Change subject: Split off itemview and propertyview from entityview ...................................................................... Split off itemview and propertyview from entityview - Made entityview abstract - Moved statement handling to itemview and propertyview - Moved site link handling to itemview - itemview and propertyview can be created without any pre-rendered static HTML now Change-Id: Ia417c45af10c881a5edd4d2ef82649492922be05 --- M lib/resources/jquery.wikibase/jquery.wikibase.entityview.js A lib/resources/jquery.wikibase/jquery.wikibase.itemview.js A lib/resources/jquery.wikibase/jquery.wikibase.propertyview.js M lib/resources/jquery.wikibase/resources.php M lib/tests/qunit/jquery.wikibase/jquery.wikibase.entityview.tests.js A lib/tests/qunit/jquery.wikibase/jquery.wikibase.itemview.tests.js A lib/tests/qunit/jquery.wikibase/jquery.wikibase.propertyview.tests.js M lib/tests/qunit/jquery.wikibase/resources.php M repo/resources/Resources.php M repo/resources/templates.php M repo/resources/wikibase.ui.entityViewInit.js 11 files changed, 679 insertions(+), 216 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Wikibase refs/changes/03/177203/1 diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.entityview.js b/lib/resources/jquery.wikibase/jquery.wikibase.entityview.js index b89dc33..9b9e861 100644 --- a/lib/resources/jquery.wikibase/jquery.wikibase.entityview.js +++ b/lib/resources/jquery.wikibase/jquery.wikibase.entityview.js @@ -8,16 +8,22 @@ var PARENT = $.ui.TemplatedWidget; /** - * View for displaying an entire wikibase entity. - * @since 0.3 + * Abstract base view for displaying Wikibase `Entity`s. + * @class jQuery.wikibase.entityview * @extends jQuery.ui.TemplatedWidget + * @abstract + * @since 0.3 + * + * @constructor * * @option {wikibase.entityChangers.EntityChangersFactory} entityChangersFactory - * @option {wikibase.datamodel.Entity} [value] + * @option {wikibase.datamodel.Entity} value * @option {wikibase.store.EntityStore} entityStore * @option {wikibase.ValueViewBuilder} valueViewBuilder * @option {dataTypes.DataTypeStore} dataTypeStore * @option {string[]} languages + * + * @throws {Error} when called. * * @event afterstartediting * Triggered after the widget has switched to edit mode. @@ -76,23 +82,32 @@ $fingerprints: null, /** - * @type {jQuery} + * @see jQuery.ui.TemplatedWidget._create + * + * @throws {Error} when called. */ - $claims: null, + _create: function() { + throw new Error( 'Abstract entityview cannot be created directly' ); + }, /** + * Main initialization actually calling parent's _create(). * @see jQuery.ui.TemplatedWidget._create + * @protected * * @throws {Error} if a required options is missing. */ - _create: function() { + _initEntityview: function() { if( - !this.options.entityStore + !this.options.value + || !this.options.entityStore || !this.options.valueViewBuilder || !this.options.entityChangersFactory ) { throw new Error( 'Required option(s) missing' ); } + + PARENT.prototype._create.call( this ); this.$toc = $( '.toc', this.element ); @@ -101,21 +116,10 @@ this._initAliases(); this._initFingerprints(); - // TODO: Have an itemview and propertyview instead of ugly hack here. - var entityType = this.options.value.getType(); - if( this.element.find( '.wb-claimlistview' ).length > 0 ) { - this._initClaims(); - } - - if( entityType === 'item' ) { - this._initSiteLinks(); - } - this._attachEventHandlers(); }, _initLabel: function() { - // TODO: Allow initializing entitview on empty DOM this.$label = $( '.wb-firstHeading .wikibase-labelview', this.element ).first(); if( !this.$label.length ) { this.$label = $( '<div/>' ); @@ -186,7 +190,7 @@ return; } - this.$fingerprints = $( '.wikibase-fingerprintgroupview' ); + this.$fingerprints = $( '.wikibase-fingerprintgroupview', this.element ); if( !this.$fingerprints.length ) { var $precedingNode = this.$toc; @@ -241,78 +245,6 @@ } ); }, - _initClaims: function() { - this.$claims = $( '.wb-claimgrouplistview', this.element ).first(); - if( this.$claims.length === 0 ) { - this.$claims = $( '<div/>' ).appendTo( this.element ); - } - - this.$claims - .claimgrouplistview( { - value: this.options.value.getStatements(), - dataTypeStore: this.option( 'dataTypeStore' ), - entityType: this.options.value.getType(), - entityStore: this.options.entityStore, - valueViewBuilder: this.options.valueViewBuilder, - entityChangersFactory: this.options.entityChangersFactory - } ) - .claimgrouplabelscroll(); - - // This is here to be sure there is never a duplicate id: - $( '.wb-claimgrouplistview' ) - .prev( '.wb-section-heading' ) - .first() - .attr( 'id', 'claims' ); - }, - - _initSiteLinks: function() { - var self = this; - - this.$siteLinks = $( '.wikibase-sitelinkgrouplistview', this.element ); - - if( this.$siteLinks.length === 0 ) { - // Properties for example don't have sitelinks - return; - } - - // Scrape group and site link order from existing DOM: - var value = []; - this.$siteLinks.find( '.wikibase-sitelinkgroupview' ).each( function() { - var $sitelinkgroupview = $( this ), - $sitelinklistview = $sitelinkgroupview.find( '.wikibase-sitelinklistview' ), - group = $sitelinkgroupview.data( 'wb-sitelinks-group' ), - siteIdsOfGroup = [], - siteLinkSet = self.options.value.getSiteLinks(), - siteLinkIds = siteLinkSet.getKeys(), - siteLinksOfGroup = []; - - $sitelinklistview.find( '.wikibase-sitelinkview' ).each( function() { - siteIdsOfGroup.push( $( this ).data( 'wb-siteid' ) ); - } ); - - for( var i = 0; i < siteIdsOfGroup.length; i++ ) { - for( var j = 0; j < siteLinkIds.length; j++ ) { - if( siteLinkIds[j] === siteIdsOfGroup[i] ) { - siteLinksOfGroup.push( siteLinkSet.getItemByKey( siteLinkIds[j] ) ); - break; - } - } - } - - value.push( { - group: group, - siteLinks: siteLinksOfGroup - } ); - } ); - - this.$siteLinks.sitelinkgrouplistview( { - value: value, - entityId: self.options.value.getId(), - siteLinksChanger: self.options.entityChangersFactory.getSiteLinksChanger(), - entityStore: self.options.entityStore - } ); - }, - _attachEventHandlers: function() { var self = this; @@ -321,11 +253,7 @@ 'labelviewafterstartediting.' + this.widgetName, 'descriptionviewafterstartediting.' + this.widgetName, 'aliasesviewafterstartediting.' + this.widgetName, - 'fingerprintgroupviewafterstartediting.' + this.widgetName, - 'claimviewafterstartediting.' + this.widgetName, - 'statementviewafterstartediting.' + this.widgetName, - 'referenceviewafterstartediting.' + this.widgetName, - 'sitelinkgroupviewafterstartediting.' + this.widgetName + 'fingerprintgroupviewafterstartediting.' + this.widgetName ].join( ' ' ), function( event ) { self._trigger( 'afterstartediting' ); @@ -336,13 +264,7 @@ '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, - 'sitelinkgroupviewafterstopediting.' + this.widgetName + 'fingerprintgroupviewafterstopediting.' + this.widgetName ].join( ' ' ), function( event, dropValue ) { self._trigger( 'afterstopediting', null, [dropValue] ); @@ -371,22 +293,6 @@ this.$aliases.data( 'aliasesview' )[state](); if( this.$fingerprints ) { this.$fingerprints.data( 'fingerprintgroupview' )[state](); - } - - // horrible, horrible hack until we have proper item and property views - if( this.$claims ) { - 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](); - } - } ); - } - - if( this.$siteLinks && this.$siteLinks.length > 0 ) { - this.$siteLinks.data( 'sitelinkgrouplistview' )[state](); } }, @@ -427,4 +333,23 @@ } } ); +/** + * List of entityview types. Every entityview type should add itself to the list in order to be + * matched by $( ':wikibase-entityview' ) pseudo selector. + * @property {string[]} + * @static + */ +$.wikibase.entityview.TYPES = []; + +$.expr[':']['wikibase-entityview'] = $.expr.createPseudo( function( fullName ) { + return function( elem ) { + for( var i = 0; i < $.wikibase.entityview.TYPES.length; i++ ) { + if( !!$.data( elem, $.wikibase.entityview.TYPES[i] ) ) { + return true; + } + } + return false; + }; +} ); + }( wikibase, jQuery, mediaWiki ) ); diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.itemview.js b/lib/resources/jquery.wikibase/jquery.wikibase.itemview.js new file mode 100644 index 0000000..6eb8b13 --- /dev/null +++ b/lib/resources/jquery.wikibase/jquery.wikibase.itemview.js @@ -0,0 +1,228 @@ +( function( $, wb ) { + 'use strict'; + +var PARENT = $.wikibase.entityview; + +/** + * View for displaying a Wikibase `Item`. + * @see wikibase.datamodel.Item + * @class jQuery.wikibase.itemview + * @extends jQuery.wikibase.entityview + * @uses jQuery.wikibase.claimgrouplistview + * @users jQuery.wikibase.claimgrouplabelscroll + * @uses jQuery.wikibase.sitelinkgroupview + * @since 0.5 + * @licence GNU GPL v2+ + * @author H. Snater < mediaw...@snater.com > + * + * @constructor + */ +$.widget( 'wikibase.itemview', PARENT, { + /** + * @see jQuery.Widget.widgetEventPrefix + */ + widgetEventPrefix: $.wikibase.entityview.widgetName, + + /** + * @property {jQuery} + * @protected + * @readonly + */ + $statements: null, + + /** + * @inheritdoc + * @protected + */ + _create: function() { + this._initEntityview(); + this._initStatements(); + this._initSiteLinks(); + }, + + /** + * @protected + */ + _initStatements: function() { + this.$statements = $( '.wb-claimgrouplistview', this.element ).first(); + if( this.$statements.length === 0 ) { + this.$statements = $( '<div/>' ).appendTo( this.element ); + } + + this.$statements + .claimgrouplistview( { + value: this.options.value.getStatements(), + dataTypeStore: this.option( 'dataTypeStore' ), + entityType: this.options.value.getType(), + entityStore: this.options.entityStore, + valueViewBuilder: this.options.valueViewBuilder, + entityChangersFactory: this.options.entityChangersFactory + } ) + .claimgrouplabelscroll(); + + // This is here to be sure there is never a duplicate id: + $( '.wb-claimgrouplistview' ) + .prev( '.wb-section-heading' ) + .first() + .attr( 'id', 'claims' ); + }, + + /** + * @protected + */ + _initSiteLinks: function() { + var self = this, + value = []; + + this.$siteLinks = $( '.wikibase-sitelinkgrouplistview', this.element ); + + if( this.$siteLinks.length ) { + value = scrapeSiteLinks( this.$siteLinks, this.options.value.getSiteLinks() ); + } else { + this.$siteLinks = $( '<div/>' ).appendTo( this.element ); + value = orderSiteLinksByGroup( this.options.value.getSiteLinks() ); + } + + this.$siteLinks.sitelinkgrouplistview( { + value: value, + entityId: self.options.value.getId(), + siteLinksChanger: self.options.entityChangersFactory.getSiteLinksChanger(), + entityStore: self.options.entityStore + } ); + }, + + /** + * @inheritdoc + * @protected + */ + _attachEventHandlers: function() { + PARENT.prototype._attachEventHandlers.call( this ); + + var self = this; + + this.element + .on( [ + 'statementviewafterstartediting.' + this.widgetName, + 'referenceviewafterstartediting.' + this.widgetName, + 'sitelinkgroupviewafterstartediting.' + this.widgetName + ].join( ' ' ), + function( event ) { + self._trigger( 'afterstartediting' ); + } ); + + this.element + .on( [ + 'claimlistviewafterremove.' + this.widgetName, + 'statementviewafterstopediting.' + this.widgetName, + 'statementviewafterremove.' + this.widgetName, + 'referenceviewafterstopediting.' + this.widgetName, + 'sitelinkgroupviewafterstopediting.' + this.widgetName + ].join( ' ' ), + function( event, dropValue ) { + self._trigger( 'afterstopediting', null, [dropValue] ); + } ); + }, + + /** + * @inheritdoc + * @protected + */ + _setState: function( state ) { + PARENT.prototype._setState.call( this, state ); + + this.$statements.data( 'claimgrouplistview' )[state](); + // TODO: Resolve integration of referenceviews + this.$statements.find( '.wb-statement-references' ).each( function() { + var $listview = $( this ).children( ':wikibase-listview' ); + if( $listview.length ) { + $listview.data( 'listview' )[state](); + } + } ); + + this.$siteLinks.data( 'sitelinkgrouplistview' )[state](); + } +} ); + +/** + * Scrapes site links from static HTML in order to be sure the order in the static HTML matches the + * order set on the widget initialized on the HTML structure since that widget is not supposed to + * re-render the HTML for performance reasons. + * @ignore + * + * @param {jQuery} $siteLinks + * @param {wikibase.datamodel.SiteLinkSet} siteLinkSet + * @return {Object} + */ +function scrapeSiteLinks( $siteLinks, siteLinkSet ) { + var value = []; + + $siteLinks.find( '.wikibase-sitelinkgroupview' ).each( function() { + var $sitelinkgroupview = $( this ), + $sitelinklistview = $sitelinkgroupview.find( '.wikibase-sitelinklistview' ), + group = $sitelinkgroupview.data( 'wb-sitelinks-group' ), + siteIdsOfGroup = [], + siteLinkIds = siteLinkSet.getKeys(), + siteLinksOfGroup = []; + + $sitelinklistview.find( '.wikibase-sitelinkview' ).each( function() { + siteIdsOfGroup.push( $( this ).data( 'wb-siteid' ) ); + } ); + + for( var i = 0; i < siteIdsOfGroup.length; i++ ) { + for( var j = 0; j < siteLinkIds.length; j++ ) { + if( siteLinkIds[j] === siteIdsOfGroup[i] ) { + siteLinksOfGroup.push( siteLinkSet.getItemByKey( siteLinkIds[j] ) ); + break; + } + } + } + + value.push( { + group: group, + siteLinks: siteLinksOfGroup + } ); + } ); + + return value; +} + +/** + * Maps site links of a `wikibase.datamodel.SiteLinkSet` to their Wikibase site groups. + * @ignore + * + * @param {wikibase.datamodel.SiteLinkSet} siteLinkSet + * @return {Object} + */ +function orderSiteLinksByGroup( siteLinkSet ) { + var value = []; + + siteLinkSet.each( function( siteId, siteLink ) { + var site = wb.sites.getSite( siteId ), + found = false; + + if( !site ) { + throw new Error( 'Site with id ' + siteId + ' is not registered' ); + } + + for( var i = 0; i < value.length; i++ ) { + if( value[i].group === site.getGroup() ) { + value[i].siteLinks.push( siteLink ); + found = true; + break; + } + } + + if( !found ) { + value.push( { + group: site.getGroup(), + siteLinks: [siteLink] + } ); + } + } ); + + return value; +} + +$.wikibase.entityview.TYPES.push( $.wikibase.itemview.prototype.widgetName ); + +}( jQuery, wikibase ) ); diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.propertyview.js b/lib/resources/jquery.wikibase/jquery.wikibase.propertyview.js new file mode 100644 index 0000000..830d344 --- /dev/null +++ b/lib/resources/jquery.wikibase/jquery.wikibase.propertyview.js @@ -0,0 +1,146 @@ +( function( $, mw ) { + 'use strict'; + +var PARENT = $.wikibase.entityview; + +/** + * View for displaying a Wikibase `Property`. + * @see wikibase.datamodel.Property + * @class jQuery.wikibase.propertyview + * @extends jQuery.wikibase.entityview + * @uses jQuery.wikibase.claimgrouplistview + * @users jQuery.wikibase.claimgrouplabelscroll + * @since 0.5 + * @licence GNU GPL v2+ + * @author H. Snater < mediaw...@snater.com > + * + * @constructor + */ +$.widget( 'wikibase.propertyview', PARENT, { + /** + * @see jQuery.Widget.widgetEventPrefix + */ + widgetEventPrefix: $.wikibase.entityview.widgetName, + + /** + * @property {jQuery} + * @protected + * @readonly + */ + $dataType: null, + + /** + * @property {jQuery} + * @protected + * @readonly + */ + $statements: null, + + /** + * @inheritdoc + * @protected + */ + _create: function() { + this._initEntityview(); + this._initDataType(); + this._initStatements(); + }, + + /** + * @protected + */ + _initDataType: function() { + // TODO: Implement propertyview template to have static HTML rendered by the back-end match + // the HTML rendered here without having to invoke templating mechanism here. + + if( this.$dataType ) { + return; + } + + this.$dataType = $( '.wikibase-propertyview-datatype', this.element ); + + if( !this.$dataType.length ) { + this.$dataType = mw.wbTemplate( 'wikibase-propertyview-datatype', + this.options.value.getDataTypeId() + ).appendTo( this.element ); + } + }, + + /** + * @protected + */ + _initStatements: function() { + this.$statements = $( '.wb-claimgrouplistview', this.element ).first(); + if( this.$statements.length === 0 ) { + this.$statements = $( '<div/>' ).appendTo( this.element ); + } + + this.$statements + .claimgrouplistview( { + value: this.options.value.getStatements(), + dataTypeStore: this.option( 'dataTypeStore' ), + entityType: this.options.value.getType(), + entityStore: this.options.entityStore, + valueViewBuilder: this.options.valueViewBuilder, + entityChangersFactory: this.options.entityChangersFactory + } ) + .claimgrouplabelscroll(); + + // This is here to be sure there is never a duplicate id: + $( '.wb-claimgrouplistview' ) + .prev( '.wb-section-heading' ) + .first() + .attr( 'id', 'claims' ); + }, + + /** + * @inheritdoc + * @protected + */ + _attachEventHandlers: function() { + PARENT.prototype._attachEventHandlers.call( this ); + + var self = this; + + this.element + .on( [ + 'statementviewafterstartediting.' + this.widgetName, + 'referenceviewafterstartediting.' + this.widgetName + ].join( ' ' ), + function( event ) { + self._trigger( 'afterstartediting' ); + } ); + + this.element + .on( [ + 'claimlistviewafterremove.' + this.widgetName, + 'statementviewafterstopediting.' + this.widgetName, + 'statementviewafterremove.' + this.widgetName, + 'referenceviewafterstopediting.' + this.widgetName + ].join( ' ' ), + function( event, dropValue ) { + self._trigger( 'afterstopediting', null, [dropValue] ); + } ); + }, + + /** + * @inheritdoc + * @protected + */ + _setState: function( state ) { + PARENT.prototype._setState.call( this, state ); + + this.$statements.data( 'claimgrouplistview' )[state](); + // TODO: Resolve integration of referenceviews + this.$statements.find( '.wb-statement-references' ).each( function() { + var $listview = $( this ).children( ':wikibase-listview' ); + if( $listview.length ) { + $listview.data( 'listview' )[state](); + } + } ); + } +} ); + +$.wikibase.entityview.TYPES.push( $.wikibase.propertyview.prototype.widgetName ); + +}( jQuery, mediaWiki ) ); diff --git a/lib/resources/jquery.wikibase/resources.php b/lib/resources/jquery.wikibase/resources.php index 6b9fa48..be5fd06 100644 --- a/lib/resources/jquery.wikibase/resources.php +++ b/lib/resources/jquery.wikibase/resources.php @@ -170,14 +170,9 @@ 'dependencies' => array( 'jquery.ui.TemplatedWidget', 'jquery.wikibase.aliasesview', - 'jquery.wikibase.claimgrouplistview', - 'jquery.wikibase.claimlistview', 'jquery.wikibase.descriptionview', 'jquery.wikibase.fingerprintgroupview', 'jquery.wikibase.labelview', - 'jquery.wikibase.toolbarcontroller', - 'jquery.wikibase.sitelinkgrouplistview', - 'jquery.wikibase.statementview', 'wikibase.datamodel.MultiTerm', 'wikibase.datamodel.Term', 'wikibase.getLanguageNameByCode', @@ -243,6 +238,18 @@ ), ), + 'jquery.wikibase.itemview' => $moduleTemplate + array( + 'scripts' => array( + 'jquery.wikibase.itemview.js', + ), + 'dependencies' => array( + 'jquery.wikibase.claimgrouplistview', + 'jquery.wikibase.entityview', + 'jquery.wikibase.sitelinkgrouplistview', + 'wikibase.sites', + ), + ), + 'jquery.wikibase.labelview' => $moduleTemplate + array( 'scripts' => array( 'jquery.wikibase.labelview.js' @@ -290,6 +297,16 @@ ), ), + 'jquery.wikibase.propertyview' => $moduleTemplate + array( + 'scripts' => array( + 'jquery.wikibase.propertyview.js', + ), + 'dependencies' => array( + 'jquery.wikibase.claimgrouplistview', + 'jquery.wikibase.entityview', + ), + ), + 'jquery.wikibase.referenceview' => $moduleTemplate + array( 'scripts' => array( 'jquery.wikibase.referenceview.js', diff --git a/lib/tests/qunit/jquery.wikibase/jquery.wikibase.entityview.tests.js b/lib/tests/qunit/jquery.wikibase/jquery.wikibase.entityview.tests.js index b6c7d2b..021c512 100644 --- a/lib/tests/qunit/jquery.wikibase/jquery.wikibase.entityview.tests.js +++ b/lib/tests/qunit/jquery.wikibase/jquery.wikibase.entityview.tests.js @@ -2,89 +2,27 @@ * @licence GNU GPL v2+ * @author Adrian Lang <adrian.l...@wikimedia.de> */ - ( function( $, wb, QUnit ) { 'use strict'; -/** - * @param {Object} [options] - * @param {jQuery} [$node] - * @return {jQuery} - */ -var createEntityview = function( options, $node ) { - options = $.extend( { - entityStore: 'i am an EntityStore', - entityChangersFactory: { - getAliasesChanger: function() { return 'i am an AliasesChanger'; }, - getDescriptionsChanger: function() { return 'i am a DescriptionsChanger'; }, - getLabelsChanger: function() { return 'i am a LabelsChanger'; } - }, - api: 'i am an Api', - valueViewBuilder: 'i am a valueview builder', - value: new wb.datamodel.Item( 'Q1' ) // FIXME: value is optional according to doc - }, options || {} ); +QUnit.module( 'jquery.wikibase.entityview' ); - $node = $node || $( '<div/>' ).appendTo( 'body' ); - - var $entityview = $node - .addClass( 'test_entityview' ) - .entityview( options ); - - $entityview.data( 'entityview' )._save = function() { - return $.Deferred().resolve( { - entity: { - lastrevid: 'i am a revision id' - } - } ).promise(); - }; - - return $entityview; -}; - -QUnit.module( 'jquery.wikibase.entityview', QUnit.newMwEnvironment( { - teardown: function() { - $( '.test_entityview' ).each( function() { - var $entityview = $( this ), - entityview = $entityview.data( 'entityview' ); - - if( entityview ) { - entityview.destroy(); - } - - $entityview.remove(); - } ); - } -} ) ); - -QUnit.test( 'Create & destroy', function( assert ) { +QUnit.test( 'Direct initialization fails', function( assert ) { assert.throws( function() { - createEntityview( { value: null } ); + $( '<div/>' ).entityview( $.extend( { + entityStore: 'I am an EntityStore', + entityChangersFactory: { + getAliasesChanger: function() { return 'I am an AliasesChanger'; }, + getDescriptionsChanger: function() { return 'I am a DescriptionsChanger'; }, + getLabelsChanger: function() { return 'I am a LabelsChanger'; } + }, + api: 'I am an Api', + valueViewBuilder: 'I am a valueview builder', + value: new wb.datamodel.Property( 'P1', 'someDataType' ) + } ) ); }, - 'Throwing error when trying to initialize widget without a value.' - ); - - var $entityview = createEntityview(), - entityview = $entityview.data( 'entityview' ); - - assert.ok( - entityview instanceof $.wikibase.entityview, - 'Created widget.' - ); - - entityview.destroy(); - - assert.ok( - $entityview.data( 'entityview' ) === undefined, - 'Destroyed widget.' - ); - - $entityview = createEntityview( { languages: [ 'ku' ] } ); - entityview = $entityview.data( 'entityview' ); - - assert.ok( - entityview instanceof $.wikibase.entityview, - 'Created widget with a language.' + 'Throwing error when trying to initialize widget directly.' ); } ); diff --git a/lib/tests/qunit/jquery.wikibase/jquery.wikibase.itemview.tests.js b/lib/tests/qunit/jquery.wikibase/jquery.wikibase.itemview.tests.js new file mode 100644 index 0000000..97f53f7 --- /dev/null +++ b/lib/tests/qunit/jquery.wikibase/jquery.wikibase.itemview.tests.js @@ -0,0 +1,91 @@ +/** + * @licence GNU GPL v2+ + * @author H. Snater < mediaw...@snater.com > + */ +( function( $, wb, QUnit ) { +'use strict'; + +/** + * @param {Object} [options] + * @param {jQuery} [$node] + * @return {jQuery} + */ +var createItemview = function( options, $node ) { + options = $.extend( { + entityStore: 'I am an EntityStore', + entityChangersFactory: { + getAliasesChanger: function() { return 'I am an AliasesChanger'; }, + getDescriptionsChanger: function() { return 'I am a DescriptionsChanger'; }, + getLabelsChanger: function() { return 'I am a LabelsChanger'; }, + getSiteLinksChanger: function() { return 'I am a SiteLinksChanger'; } + }, + api: 'I am an Api', + valueViewBuilder: 'I am a valueview builder', + value: new wb.datamodel.Item( 'Q1' ) + }, options || {} ); + + $node = $node || $( '<div/>' ).appendTo( 'body' ); + + var $itemview = $node + .addClass( 'test_itemview' ) + .itemview( options ); + + $itemview.data( 'itemview' )._save = function() { + return $.Deferred().resolve( { + entity: { + lastrevid: 'i am a revision id' + } + } ).promise(); + }; + + return $itemview; +}; + +QUnit.module( 'jquery.wikibase.itemview', QUnit.newMwEnvironment( { + teardown: function() { + $( '.test_itemview' ).each( function() { + var $itemview = $( this ), + itemview = $itemview.data( 'itemview' ); + + if( itemview ) { + itemview.destroy(); + } + + $itemview.remove(); + } ); + } +} ) ); + +QUnit.test( 'Create & destroy', function( assert ) { + assert.throws( + function() { + createItemview( { value: null } ); + }, + 'Throwing error when trying to initialize widget without a value.' + ); + + var $itemview = createItemview(), + itemview = $itemview.data( 'itemview' ); + + assert.ok( + itemview instanceof $.wikibase.itemview, + 'Created widget.' + ); + + itemview.destroy(); + + assert.ok( + $itemview.data( 'itemview' ) === undefined, + 'Destroyed widget.' + ); + + $itemview = createItemview( { languages: ['ku'] } ); + itemview = $itemview.data( 'itemview' ); + + assert.ok( + itemview instanceof $.wikibase.itemview, + 'Created widget with a language.' + ); +} ); + +}( jQuery, wikibase, QUnit ) ); diff --git a/lib/tests/qunit/jquery.wikibase/jquery.wikibase.propertyview.tests.js b/lib/tests/qunit/jquery.wikibase/jquery.wikibase.propertyview.tests.js new file mode 100644 index 0000000..82db234 --- /dev/null +++ b/lib/tests/qunit/jquery.wikibase/jquery.wikibase.propertyview.tests.js @@ -0,0 +1,90 @@ +/** + * @licence GNU GPL v2+ + * @author H. Snater < mediaw...@snater.com > + */ +( function( $, wb, QUnit ) { +'use strict'; + +/** + * @param {Object} [options] + * @param {jQuery} [$node] + * @return {jQuery} + */ +var createPropertyview = function( options, $node ) { + options = $.extend( { + entityStore: 'I am an EntityStore', + entityChangersFactory: { + getAliasesChanger: function() { return 'I am an AliasesChanger'; }, + getDescriptionsChanger: function() { return 'I am a DescriptionsChanger'; }, + getLabelsChanger: function() { return 'I am a LabelsChanger'; } + }, + api: 'I am an Api', + valueViewBuilder: 'I am a valueview builder', + value: new wb.datamodel.Property( 'P1', 'someDataType' ) + }, options || {} ); + + $node = $node || $( '<div/>' ).appendTo( 'body' ); + + var $propertyview = $node + .addClass( 'test_propertyview' ) + .propertyview( options ); + + $propertyview.data( 'propertyview' )._save = function() { + return $.Deferred().resolve( { + entity: { + lastrevid: 'i am a revision id' + } + } ).promise(); + }; + + return $propertyview; +}; + +QUnit.module( 'jquery.wikibase.propertyview', QUnit.newMwEnvironment( { + teardown: function() { + $( '.test_propertyview' ).each( function() { + var $propertyview = $( this ), + propertyview = $propertyview.data( 'propertyview' ); + + if( propertyview ) { + propertyview.destroy(); + } + + $propertyview.remove(); + } ); + } +} ) ); + +QUnit.test( 'Create & destroy', function( assert ) { + assert.throws( + function() { + createPropertyview( { value: null } ); + }, + 'Throwing error when trying to initialize widget without a value.' + ); + + var $propertyview = createPropertyview(), + propertyview = $propertyview.data( 'propertyview' ); + + assert.ok( + propertyview instanceof $.wikibase.propertyview, + 'Created widget.' + ); + + propertyview.destroy(); + + assert.ok( + $propertyview.data( 'propertyview' ) === undefined, + 'Destroyed widget.' + ); + + $propertyview = createPropertyview( { languages: ['ku'] } ); + propertyview = $propertyview.data( 'propertyview' ); + + assert.ok( + propertyview instanceof $.wikibase.propertyview, + 'Created widget with a language.' + ); +} ); + +}( jQuery, wikibase, QUnit ) ); diff --git a/lib/tests/qunit/jquery.wikibase/resources.php b/lib/tests/qunit/jquery.wikibase/resources.php index 010a63e..38e9bc9 100644 --- a/lib/tests/qunit/jquery.wikibase/resources.php +++ b/lib/tests/qunit/jquery.wikibase/resources.php @@ -85,22 +85,22 @@ ), ), - 'jquery.wikibase.entityview.tests' => $moduleBase + array( - 'scripts' => array( - 'jquery.wikibase.entityview.tests.js', - ), - 'dependencies' => array( - 'jquery.wikibase.entityview', - 'wikibase.datamodel' - ), - ), - 'jquery.wikibase.entityselector.tests' => $moduleBase + array( 'scripts' => array( 'jquery.wikibase.entityselector.tests.js', ), 'dependencies' => array( 'jquery.wikibase.entityselector', + ), + ), + + 'jquery.wikibase.entityview.tests' => $moduleBase + array( + 'scripts' => array( + 'jquery.wikibase.entityview.tests.js', + ), + 'dependencies' => array( + 'jquery.wikibase.entityview', + 'wikibase.datamodel.Property', ), ), @@ -135,6 +135,16 @@ ), ), + 'jquery.wikibase.itemview.tests' => $moduleBase + array( + 'scripts' => array( + 'jquery.wikibase.itemview.tests.js', + ), + 'dependencies' => array( + 'jquery.wikibase.itemview', + 'wikibase.datamodel.Item', + ), + ), + 'jquery.wikibase.labelview.tests' => $moduleBase + array( 'scripts' => array( 'jquery.wikibase.labelview.tests.js', @@ -163,6 +173,16 @@ ), ), + 'jquery.wikibase.propertyview.tests' => $moduleBase + array( + 'scripts' => array( + 'jquery.wikibase.propertyview.tests.js', + ), + 'dependencies' => array( + 'jquery.wikibase.propertyview', + 'wikibase.datamodel.Property', + ), + ), + 'jquery.wikibase.referenceview.tests' => $moduleBase + array( 'scripts' => array( 'jquery.wikibase.referenceview.tests.js', diff --git a/repo/resources/Resources.php b/repo/resources/Resources.php index 9c071f6..19d3ade 100644 --- a/repo/resources/Resources.php +++ b/repo/resources/Resources.php @@ -160,7 +160,8 @@ 'dependencies' => array( 'mediawiki.user', 'mw.config.values.wbRepo', - 'jquery.wikibase.entityview', + 'jquery.wikibase.itemview', + 'jquery.wikibase.propertyview', 'jquery.wikibase.toolbarcontroller', 'jquery.wikibase.wbtooltip', 'jquery.cookie', diff --git a/repo/resources/templates.php b/repo/resources/templates.php index 0b159d3..7ef1fba 100644 --- a/repo/resources/templates.php +++ b/repo/resources/templates.php @@ -294,10 +294,10 @@ <span class="wikibase-badgeselector wikibase-sitelinkview-badges"><!-- [0,*] wb-badge -->$1</span> HTML; - $templates['wb-property-datatype'] = + $templates['wikibase-propertyview-datatype'] = <<<HTML -<div class="wb-datatype"> - <div class="wb-datatype-value">$1</div> +<div class="wikibase-propertyview-datatype"> + <div class="wikibase-propertyview-datatype-value">$1</div> </div> HTML; diff --git a/repo/resources/wikibase.ui.entityViewInit.js b/repo/resources/wikibase.ui.entityViewInit.js index ce73efa..fbf55f0 100644 --- a/repo/resources/wikibase.ui.entityViewInit.js +++ b/repo/resources/wikibase.ui.entityViewInit.js @@ -108,6 +108,8 @@ /** * @param {wikibase.datamodel.Entity} entity * @param {jQuery} $entityview + * + * @throws {Error} if no widget to render the entity exists. */ function createEntityDom( entity, $entityview ) { var repoConfig = mw.config.get( 'wbRepo' ); @@ -121,8 +123,13 @@ entity ); - $entityview - .entityview( { + var view = entity.getType() + 'view'; + + if( !$.wikibase[view] ) { + throw new Error( 'View for entity type ' + entity.getType() + ' does not exist' ); + } + + $entityview[entity.getType() + 'view']( { value: entity, entityChangersFactory: entityChangersFactory, entityStore: entityStore, -- To view, visit https://gerrit.wikimedia.org/r/177203 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ia417c45af10c881a5edd4d2ef82649492922be05 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/Wikibase Gerrit-Branch: master Gerrit-Owner: Henning Snater <henning.sna...@wikimedia.de> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits