mw.widgets.CategorySelector: Link to category page and display existence status
[lhc/web/wiklou.git] / resources / src / mediawiki.widgets / mw.widgets.CategoryCapsuleItemWidget.js
1 /*!
2 * MediaWiki Widgets - CategoryCapsuleItemWidget class.
3 *
4 * @copyright 2011-2015 MediaWiki Widgets Team and others; see AUTHORS.txt
5 * @license The MIT License (MIT); see LICENSE.txt
6 */
7 ( function ( $, mw ) {
8
9 /**
10 * @class mw.widgets.CategoryCapsuleItemWidget
11 */
12
13 var processExistenceCheckQueueDebounced,
14 api = new mw.Api(),
15 currentRequest = null,
16 existenceCache = {},
17 existenceCheckQueue = {};
18
19 // The existence checking code really could be refactored into a separate class.
20
21 /**
22 * @private
23 */
24 function processExistenceCheckQueue() {
25 var queue, titles;
26 if ( currentRequest ) {
27 // Don't fire off a million requests at the same time
28 currentRequest.always( function () {
29 currentRequest = null;
30 processExistenceCheckQueueDebounced();
31 } );
32 return;
33 }
34 queue = existenceCheckQueue;
35 existenceCheckQueue = {};
36 titles = Object.keys( queue ).filter( function ( title ) {
37 if ( existenceCache.hasOwnProperty( title ) ) {
38 queue[ title ].resolve( existenceCache[ title ] );
39 }
40 return !existenceCache.hasOwnProperty( title );
41 } );
42 if ( !titles.length ) {
43 return;
44 }
45 currentRequest = api.get( {
46 action: 'query',
47 prop: [ 'info' ],
48 titles: titles
49 } ).done( function ( response ) {
50 var index, curr, title;
51 for ( index in response.query.pages ) {
52 curr = response.query.pages[ index ];
53 title = mw.Title.newFromText( curr.title ).getPrefixedText();
54 existenceCache[ title ] = curr.missing === undefined;
55 queue[ title ].resolve( existenceCache[ title ] );
56 }
57 } );
58 }
59
60 processExistenceCheckQueueDebounced = OO.ui.debounce( processExistenceCheckQueue );
61
62 /**
63 * Register a request to check whether a page exists.
64 *
65 * @private
66 * @param {mw.Title} title
67 * @return {jQuery.Promise} Promise resolved with true if the page exists or false otherwise
68 */
69 function checkPageExistence( title ) {
70 var key = title.getPrefixedText();
71 if ( !existenceCheckQueue[ key ] ) {
72 existenceCheckQueue[ key ] = $.Deferred();
73 }
74 processExistenceCheckQueueDebounced();
75 return existenceCheckQueue[ key ].promise();
76 }
77
78 /**
79 * Category selector capsule item widget. Extends OO.ui.CapsuleItemWidget with the ability to link
80 * to the given page, and to show its existence status (i.e., whether it is a redlink).
81 *
82 * @uses mw.Api
83 * @extends OO.ui.CapsuleItemWidget
84 *
85 * @constructor
86 * @param {Object} config Configuration options
87 * @cfg {mw.Title} title Page title to use (required)
88 */
89 mw.widgets.CategoryCapsuleItemWidget = function MWWCategoryCapsuleItemWidget( config ) {
90 // Parent constructor
91 mw.widgets.CategoryCapsuleItemWidget.parent.call( this, $.extend( {
92 data: config.title.getMainText(),
93 label: config.title.getMainText()
94 }, config ) );
95
96 // Properties
97 this.title = config.title;
98 this.$link = $( '<a>' )
99 .text( this.label )
100 .attr( 'target', '_blank' )
101 .on( 'click', function ( e ) {
102 // CapsuleMultiSelectWidget really wants to prevent you from clicking the link, don't let it
103 e.stopPropagation();
104 } );
105
106 // Initialize
107 this.setMissing( false );
108 this.$label.replaceWith( this.$link );
109 this.setLabelElement( this.$link );
110 checkPageExistence( this.title ).done( function ( exists ) {
111 this.setMissing( !exists );
112 }.bind( this ) );
113 };
114
115 /* Setup */
116
117 OO.inheritClass( mw.widgets.CategoryCapsuleItemWidget, OO.ui.CapsuleItemWidget );
118
119 /* Methods */
120
121 /**
122 * Update label link href and CSS classes to reflect page existence status.
123 *
124 * @private
125 * @param {boolean} missing Whether the page is missing (does not exist)
126 */
127 mw.widgets.CategoryCapsuleItemWidget.prototype.setMissing = function ( missing ) {
128 if ( !missing ) {
129 this.$link
130 .attr( 'href', this.title.getUrl() )
131 .removeClass( 'new' );
132 } else {
133 this.$link
134 .attr( 'href', this.title.getUrl( { action: 'edit', redlink: 1 } ) )
135 .addClass( 'new' );
136 }
137 };
138
139 }( jQuery, mediaWiki ) );