Merge "Drop zh-tw message "saveprefs""
[lhc/web/wiklou.git] / resources / src / mediawiki.widgets / mw.widgets.CategorySelector.js
1 /*!
2 * MediaWiki Widgets - CategorySelector 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 * Category selector widget. Displays an OO.ui.CapsuleMultiSelectWidget
11 * and autocompletes with available categories.
12 *
13 * @class
14 * @uses mw.Api
15 * @extends OO.ui.CapsuleMultiSelectWidget
16 *
17 * @constructor
18 * @param {Object} [config] Configuration options
19 * @cfg {number} [limit=10] Maximum number of results to load
20 */
21 mw.widgets.CategorySelector = function ( config ) {
22 // Config initialization
23 config = $.extend( { limit: 10 }, config );
24 this.limit = config.limit;
25
26 // Parent constructor
27 mw.widgets.CategorySelector.parent.call( this, config );
28
29 // Event handler to call the autocomplete methods
30 this.$input.on( 'change input cut paste', OO.ui.debounce( this.updateMenuItems.bind( this ), 100 ) );
31 };
32
33 /* Setup */
34
35 OO.inheritClass( mw.widgets.CategorySelector, OO.ui.CapsuleMultiSelectWidget );
36
37 /* Methods */
38
39 /**
40 * Gets new items based on the input by calling
41 * {@link #getNewMenuItems getNewItems} and updates the menu
42 * after removing duplicates based on the data value.
43 *
44 * @private
45 * @method
46 */
47 mw.widgets.CategorySelector.prototype.updateMenuItems = function () {
48 this.getNewMenuItems( this.$input.val() ).then( function ( items ) {
49 var existingItems, filteredItems,
50 menu = this.getMenu();
51
52 // Array of strings of the data of OO.ui.MenuOptionsWidgets
53 existingItems = menu.getItems().map( function ( item ) {
54 return item.data;
55 } );
56
57 // Remove if items' data already exists
58 filteredItems = items.filter( function ( item ) {
59 return existingItems.indexOf( item ) === -1;
60 } );
61
62 // Map to an array of OO.ui.MenuOptionWidgets
63 filteredItems = filteredItems.map( function ( item ) {
64 return new OO.ui.MenuOptionWidget( {
65 data: item,
66 label: item
67 } );
68 } );
69
70 menu.addItems( filteredItems ).updateItemVisibility();
71 }.bind( this ) );
72 };
73
74 /**
75 * Searches for categories based on the input.
76 *
77 * @private
78 * @method
79 * @param {string} input The input used to prefix search categories
80 * @return {jQuery.Promise} Resolves with an array of categories
81 */
82 mw.widgets.CategorySelector.prototype.getNewMenuItems = function ( input ) {
83 var deferred = new $.Deferred(),
84 catNsId = mw.config.get( 'wgNamespaceIds' ).category,
85 api = new mw.Api();
86
87 api.get( {
88 action: 'opensearch',
89 namespace: catNsId,
90 limit: this.limit,
91 search: input
92 } ).done( function ( res ) {
93 var categoryNames = res[ 1 ].map( function ( name ) {
94 return mw.Title.newFromText( name, catNsId ).getMainText();
95 } );
96
97 deferred.resolve( categoryNames );
98 } );
99
100 return deferred.promise();
101 };
102 }( jQuery, mediaWiki ) );