mw.widgets.CategorySelector: Add client-side caching
[lhc/web/wiklou.git] / resources / src / mediawiki.widgets / mw.widgets.CategorySelector.js
index 45f52b7..267eebb 100644 (file)
         * Category selector widget. Displays an OO.ui.CapsuleMultiselectWidget
         * and autocompletes with available categories.
         *
-        *     var selector = new mw.widgets.CategorySelector( {
-        *       searchTypes: [
-        *         mw.widgets.CategorySelector.SearchType.OpenSearch,
-        *         mw.widgets.CategorySelector.SearchType.InternalSearch
-        *       ]
-        *     } );
+        *     mw.loader.using( 'mediawiki.widgets.CategorySelector', function () {
+        *       var selector = new mw.widgets.CategorySelector( {
+        *         searchTypes: [
+        *           mw.widgets.CategorySelector.SearchType.OpenSearch,
+        *           mw.widgets.CategorySelector.SearchType.InternalSearch
+        *         ]
+        *       } );
         *
-        *     $( '#content' ).append( selector.$element );
+        *       $( 'body' ).append( selector.$element );
         *
-        *     selector.setSearchTypes( [ mw.widgets.CategorySelector.SearchType.SubCategories ] );
+        *       selector.setSearchTypes( [ mw.widgets.CategorySelector.SearchType.SubCategories ] );
+        *     } );
         *
         * @class mw.widgets.CategorySelector
         * @uses mw.Api
@@ -63,6 +65,7 @@
 
                // Initialize
                this.api = config.api || new mw.Api();
+               this.searchCache = {};
        }
 
        /* Setup */
         * @inheritdoc
         */
        CSP.createItemWidget = function ( data ) {
+               var title = mw.Title.makeTitle( NS_CATEGORY, data );
+               if ( !title ) {
+                       return null;
+               }
                return new mw.widgets.CategoryCapsuleItemWidget( {
                        apiUrl: this.api.apiUrl || undefined,
-                       title: mw.Title.makeTitle( NS_CATEGORY, data )
+                       title: title
                } );
        };
 
        CSP.getItemFromData = function ( data ) {
                // This is a bit of a hack... We have to canonicalize the data in the same way that
                // #createItemWidget and CategoryCapsuleItemWidget will do, otherwise we won't find duplicates.
-               data = mw.Title.makeTitle( NS_CATEGORY, data ).getMainText();
-               return OO.ui.mixin.GroupElement.prototype.getItemFromData.call( this, data );
+               var title = mw.Title.makeTitle( NS_CATEGORY, data );
+               if ( !title ) {
+                       return null;
+               }
+               return OO.ui.mixin.GroupElement.prototype.getItemFromData.call( this, title.getMainText() );
        };
 
        /**
         * @return {jQuery.Promise} Resolves with an array of categories
         */
        CSP.searchCategories = function ( input, searchType ) {
-               var deferred = $.Deferred();
+               var deferred = $.Deferred(),
+                       cacheKey = input + searchType.toString();
+
+               // Check cache
+               if ( this.searchCache[ cacheKey ] !== undefined ) {
+                       return this.searchCache[ cacheKey ];
+               }
 
                switch ( searchType ) {
                        case CategorySelector.SearchType.OpenSearch:
                                        var categories = [];
 
                                        $.each( res.query.pages, function ( index, page ) {
-                                               if ( !page.missing ) {
-                                                       if ( $.isArray( page.categories ) ) {
-                                                               categories.push.apply( categories, page.categories.map( function ( category ) {
-                                                                       return category.title;
-                                                               } ) );
-                                                       }
+                                               if ( !page.missing && $.isArray( page.categories ) ) {
+                                                       categories.push.apply( categories, page.categories.map( function ( category ) {
+                                                               return category.title;
+                                                       } ) );
                                                }
                                        } );
 
                                throw new Error( 'Unknown searchType' );
                }
 
+               // Cache the result
+               this.searchCache[ cacheKey ] = deferred.promise();
+
                return deferred.promise();
        };