2 * MediaWiki Widgets - CategoryCapsuleItemWidget class.
4 * @copyright 2011-2015 MediaWiki Widgets Team and others; see AUTHORS.txt
5 * @license The MIT License (MIT); see LICENSE.txt
10 * @class mw.widgets.PageExistenceCache
12 * @param {mw.Api} [api]
14 function PageExistenceCache( api ) {
15 this.api = api || new mw.Api();
16 this.processExistenceCheckQueueDebounced = OO.ui.debounce( this.processExistenceCheckQueue );
17 this.currentRequest = null;
18 this.existenceCache = {};
19 this.existenceCheckQueue = {};
23 * Check for existence of pages in the queue.
27 PageExistenceCache.prototype.processExistenceCheckQueue = function () {
29 if ( this.currentRequest ) {
30 // Don't fire off a million requests at the same time
31 this.currentRequest.always( function () {
32 this.currentRequest = null;
33 this.processExistenceCheckQueueDebounced();
37 queue = this.existenceCheckQueue;
38 this.existenceCheckQueue = {};
39 titles = Object.keys( queue ).filter( function ( title ) {
40 if ( this.existenceCache.hasOwnProperty( title ) ) {
41 queue[ title ].resolve( this.existenceCache[ title ] );
43 return !this.existenceCache.hasOwnProperty( title );
45 if ( !titles.length ) {
48 this.currentRequest = this.api.get( {
52 } ).done( function ( response ) {
53 var index, curr, title;
54 for ( index in response.query.pages ) {
55 curr = response.query.pages[ index ];
56 title = new ForeignTitle( curr.title ).getPrefixedText();
57 this.existenceCache[ title ] = curr.missing === undefined;
58 queue[ title ].resolve( this.existenceCache[ title ] );
64 * Register a request to check whether a page exists.
67 * @param {mw.Title} title
68 * @return {jQuery.Promise} Promise resolved with true if the page exists or false otherwise
70 PageExistenceCache.prototype.checkPageExistence = function ( title ) {
71 var key = title.getPrefixedText();
72 if ( !this.existenceCheckQueue[ key ] ) {
73 this.existenceCheckQueue[ key ] = $.Deferred();
75 this.processExistenceCheckQueueDebounced();
76 return this.existenceCheckQueue[ key ].promise();
80 * @class mw.widgets.ForeignTitle
87 function ForeignTitle() {
88 ForeignTitle.parent.apply( this, arguments );
90 OO.inheritClass( ForeignTitle, mw.Title );
91 ForeignTitle.prototype.getNamespacePrefix = function () {
92 // We only need to handle categories here...
93 return 'Category:'; // HACK
97 * @class mw.widgets.CategoryCapsuleItemWidget
99 * Category selector capsule item widget. Extends OO.ui.CapsuleItemWidget with the ability to link
100 * to the given page, and to show its existence status (i.e., whether it is a redlink).
103 * @extends OO.ui.CapsuleItemWidget
106 * @param {Object} config Configuration options
107 * @cfg {mw.Title} title Page title to use (required)
108 * @cfg {string} [apiUrl] API URL, if not the current wiki's API
110 mw.widgets.CategoryCapsuleItemWidget = function MWWCategoryCapsuleItemWidget( config ) {
111 // Parent constructor
112 mw.widgets.CategoryCapsuleItemWidget.parent.call( this, $.extend( {
113 data: config.title.getMainText(),
114 label: config.title.getMainText()
118 this.title = config.title;
119 this.apiUrl = config.apiUrl || '';
120 this.$link = $( '<a>' )
122 .attr( 'target', '_blank' )
123 .on( 'click', function ( e ) {
124 // CapsuleMultiSelectWidget really wants to prevent you from clicking the link, don't let it
129 this.setMissing( false );
130 this.$label.replaceWith( this.$link );
131 this.setLabelElement( this.$link );
134 if ( !this.constructor.static.pageExistenceCaches[ this.apiUrl ] ) {
135 this.constructor.static.pageExistenceCaches[ this.apiUrl ] =
136 new PageExistenceCache( new mw.ForeignApi( this.apiUrl ) );
138 this.constructor.static.pageExistenceCaches[ this.apiUrl ]
139 .checkPageExistence( new ForeignTitle( this.title.getPrefixedText() ) )
140 .done( function ( exists ) {
141 this.setMissing( !exists );
148 OO.inheritClass( mw.widgets.CategoryCapsuleItemWidget, OO.ui.CapsuleItemWidget );
150 /* Static Properties */
154 * Map of API URLs to PageExistenceCache objects.
160 mw.widgets.CategoryCapsuleItemWidget.static.pageExistenceCaches = {
161 '': new PageExistenceCache()
168 * Update label link href and CSS classes to reflect page existence status.
171 * @param {boolean} missing Whether the page is missing (does not exist)
173 mw.widgets.CategoryCapsuleItemWidget.prototype.setMissing = function ( missing ) {
175 title = new ForeignTitle( this.title.getPrefixedText() ), // HACK
176 prefix = this.apiUrl.replace( '/w/api.php', '' ); // HACK
178 this.missing = missing;
182 .attr( 'href', prefix + title.getUrl() )
183 .attr( 'title', title.getPrefixedText() )
184 .removeClass( 'new' );
187 .attr( 'href', prefix + title.getUrl( { action: 'edit', redlink: 1 } ) )
188 .attr( 'title', mw.msg( 'red-link-title', title.getPrefixedText() ) )
193 }( jQuery, mediaWiki ) );