WordPress.org

Make WordPress Core

Ticket #27055: 27055.18.diff

File 27055.18.diff, 10.0 KB (added by matveb, 5 years ago)

Fix count

  • wp-admin/js/theme.js

     
    213213                collection = _( collection.first( 20 ) );
    214214
    215215                return collection;
     216        },
     217
     218        // Handles requests for more themes
     219        // and caches results
     220        //
     221        // When we are missing a cache object we fire an apiCall()
     222        // which triggers events of `query:success` or `query:fail`
     223        query: function( request ) {
     224                /**
     225                 * @static
     226                 * @type Array
     227                 */
     228                var queries = this.queries,
     229                        self = this,
     230                        query, isPaginated, count;
     231
     232                // Search the query cache for matches.
     233                query = _.find( queries, function( query ) {
     234                        return _.isEqual( query.request, request );
     235                });
     236
     237                // If the request matches the stored currentQuery.request
     238                // it means we have a paginated request.
     239                isPaginated = _.has( request, 'page' );
     240
     241                // Reset the internal api page counter for non paginated queries.
     242                if ( ! isPaginated ) {
     243                        this.currentQuery.page = 1;
     244                }
     245
     246                // Otherwise, send a new API call and add it to the cache.
     247                if ( ! query ) {
     248                        query = this.apiCall( request ).done( function( data ) {
     249                                // Update the collection with the queried data.
     250                                self.reset( data.themes );
     251                                count = data.info.results;
     252
     253                                // Trigger a collection refresh event
     254                                // and a `query:success` event with a `count` argument.
     255                                self.trigger( 'update' );
     256                                self.trigger( 'query:success', count );
     257
     258                                // Store the results and the query request
     259                                queries.push( { themes: data.themes, request: request } );
     260                        }).fail( function() {
     261                                self.trigger( 'query:fail' );
     262                        });
     263                } else {
     264                        // If it's a paginated request we need to fetch more themes...
     265                        if ( isPaginated ) {
     266                                return this.apiCall( request, isPaginated ).done( function( data ) {
     267                                        // Add the new themes to the current collection
     268                                        // @todo update counter
     269                                        self.add( data.themes );
     270                                        self.trigger( 'query:success' );
     271
     272                                }).fail( function() {
     273                                        self.trigger( 'query:fail' );
     274                                });
     275                        }
     276
     277                        // Only trigger an update event since we already have the themes
     278                        // on our cached object
     279                        this.reset( query.themes );
     280                        this.trigger( 'update' );
     281                }
     282        },
     283
     284        // Local cache array for API queries
     285        queries: [],
     286
     287        // Keep track of current query so we can handle pagination
     288        currentQuery: {
     289                page: 1,
     290                request: {}
     291        },
     292
     293        // Send Ajax POST request to api.wordpress.org/themes
     294        apiCall: function( request, paginated ) {
     295                // Store current query request args
     296                // for later use with the event `theme:end`
     297                this.currentQuery.request = request;
     298
     299                // Ajax request to .org API
     300                return $.ajax({
     301                        url: 'https://api.wordpress.org/themes/info/1.1/?action=query_themes',
     302
     303                        // We want JSON data
     304                        dataType: 'json',
     305                        type: 'POST',
     306                        crossDomain: true,
     307
     308                        // Request data
     309                        data: {
     310                                action: 'query_themes',
     311                                request: _.extend({
     312                                        per_page: 72,
     313                                        fields: {
     314                                                description: true,
     315                                                tested: true,
     316                                                requires: true,
     317                                                rating: true,
     318                                                downloaded: true,
     319                                                downloadLink: true,
     320                                                last_updated: true,
     321                                                homepage: true,
     322                                                num_ratings: true
     323                                        }
     324                                }, request)
     325                        },
     326
     327                        beforeSend: function() {
     328                                if ( ! paginated ) {
     329                                        // Spin it
     330                                        $( 'body' ).addClass( 'loading-themes' );
     331                                }
     332                        }
     333                });
    216334        }
    217335});
    218336
     
    571689                        self.render( this );
    572690                });
    573691
     692                // Update theme count to full result set when available.
     693                this.listenTo( self.collection, 'query:success', function( count ) {
     694                        if ( _.isNumber( count ) ) {
     695                                self.count.text( count );
     696                        } else {
     697                                self.count.text( self.collection.length );
     698                        }
     699                });
     700
    574701                this.listenTo( this.parent, 'theme:scroll', function() {
    575702                        self.renderThemes( self.parent.page );
    576703                });
     
    582709                } );
    583710
    584711                // Bind keyboard events.
    585                 $('body').on( 'keyup', function( event ) {
     712                $( 'body' ).on( 'keyup', function( event ) {
    586713                        if ( ! self.overlay ) {
    587714                                return;
    588715                        }
     
    628755
    629756                // Generate the themes
    630757                // Using page instance
    631                 this.renderThemes( this.parent.page );
     758                // While checking the collection has items
     759                if ( this.options.collection.size() > 0 ) {
     760                        this.renderThemes( this.parent.page );
     761                }
    632762
    633763                // Display a live theme count for the collection
    634764                this.count.text( this.collection.length );
     
    642772                self.instance = self.collection.paginate( page );
    643773
    644774                // If we have no more themes bail
    645                 if ( self.instance.length === 0 ) {
     775                if ( self.instance.size() === 0 ) {
     776                        // Fire a no-more-themes event.
     777                        this.parent.trigger( 'theme:end' );
    646778                        return;
    647779                }
    648780
     
    9671099                _.debounce( _.bind( this.doSearch, this ), 300 )( event.target.value );
    9681100        },
    9691101
    970         doSearch: function( value ) {
     1102        doSearch: _.debounce( function( value ) {
    9711103                var request = {},
    9721104                        self = this;
    9731105
     
    9911123                        request.tag = [ value.slice( 4 ) ];
    9921124                }
    9931125
    994                 // Send Ajax POST request to api.wordpress.org/themes
    995                 themes.view.Installer.prototype.apiCall( request ).done( function( data ) {
    996                                 // Update the collection with the queried data
    997                                 self.collection.reset( data.themes );
    998                                 // Trigger a collection refresh event to render the views
    999                                 self.collection.trigger( 'update' );
    1000 
    1001                                 // Un-spin it
    1002                                 $( 'body' ).removeClass( 'loading-themes' );
    1003                                 $( '.theme-browser' ).find( 'div.error' ).remove();
    1004                 }).fail( function() {
    1005                                 $( '.theme-browser' ).find( 'div.error' ).remove();
    1006                                 $( '.theme-browser' ).append( '<div class="error"><p>' + l10n.error + '</p></div>' );
    1007                 });
    1008 
    1009                 return false;
    1010         }
     1126                // Get the themes by sending Ajax POST request to api.wordpress.org/themes
     1127                // or searching the local cache
     1128                this.collection.query( request );
     1129        }, 300 ),
    10111130});
    10121131
    10131132themes.view.Installer = themes.view.Appearance.extend({
     
    10221141                'click [type="checkbox"]': 'addFilter'
    10231142        },
    10241143
    1025         // Send Ajax POST request to api.wordpress.org/themes
    1026         apiCall: function( request ) {
    1027                 return $.ajax({
    1028                         url: 'https://api.wordpress.org/themes/info/1.1/?action=query_themes',
    1029 
    1030                         // We want JSON data
    1031                         dataType: 'json',
    1032                         type: 'POST',
    1033                         crossDomain: true,
    1034 
    1035                         // Request data
    1036                         data: {
    1037                                 action: 'query_themes',
    1038                                 request: _.extend({
    1039                                         per_page: 36,
    1040                                         fields: {
    1041                                                 description: true,
    1042                                                 tested: true,
    1043                                                 requires: true,
    1044                                                 rating: true,
    1045                                                 downloaded: true,
    1046                                                 downloadLink: true,
    1047                                                 last_updated: true,
    1048                                                 homepage: true,
    1049                                                 num_ratings: true
    1050                                         }
    1051                                 }, request)
    1052                         },
    1053 
    1054                         beforeSend: function() {
    1055                                 // Spin it
    1056                                 $( 'body' ).addClass( 'loading-themes' );
    1057                         }
    1058                 });
    1059         },
    1060 
    10611144        // Handles all the rendering of the public theme directory
    10621145        browse: function( section ) {
    10631146                var self = this;
    10641147
    1065                 // @todo Cache the collection after fetching based on the section
    10661148                this.collection = new themes.Collection();
    10671149
    1068                 // Create a new collection with the proper theme data
    1069                 // for each section
    1070                 this.apiCall({ browse: section }).done( function( data ) {
    1071                         // Update the collection with the queried data
    1072                         self.collection.reset( data.themes );
    1073                         // Trigger a collection refresh event to render the views
    1074                         self.collection.trigger( 'update' );
     1150                // Bump `collection.currentQuery.page` and request more themes if we hit the end of the page.
     1151                this.listenTo( this, 'theme:end', function() {
     1152                        self.collection.currentQuery.page++;
     1153                        _.extend( self.collection.currentQuery.request, { page: self.collection.currentQuery.page } );
     1154                        self.collection.query( self.collection.currentQuery.request );
     1155                });
    10751156
    1076                         // Un-spin it
     1157                this.listenTo( this.collection, 'query:success', function() {
    10771158                        $( 'body' ).removeClass( 'loading-themes' );
    10781159                        $( '.theme-browser' ).find( 'div.error' ).remove();
    10791160                });
    10801161
     1162                this.listenTo( this.collection, 'query:fail', function() {
     1163                        $( '.theme-browser' ).find( 'div.error' ).remove();
     1164                        $( '.theme-browser' ).append( '<div class="error"><p>' + l10n.error + '</p></div>' );
     1165                });
     1166
     1167                // Create a new collection with the proper theme data
     1168                // for each section
     1169                this.collection.query( { browse: section } );
     1170
    10811171                if ( this.view ) {
    10821172                        this.view.remove();
    10831173                }
     
    11531243
    11541244                // Construct the filter request
    11551245                // using the default values
    1156 
    1157                 // @todo Cache the collection after fetching based on the filter
    11581246                filter = _.union( filter, this.filtersChecked() );
    11591247                request = { tag: [ filter ] };
    11601248
    1161                 // Send Ajax POST request to api.wordpress.org/themes
    1162                 this.apiCall( request ).done( function( data ) {
    1163                                 // Update the collection with the queried data
    1164                                 self.collection.reset( data.themes );
    1165                                 // Trigger a collection refresh event to render the views
    1166                                 self.collection.trigger( 'update' );
    1167 
    1168                                 // Un-spin it
    1169                                 $( 'body' ).removeClass( 'loading-themes' );
    1170                                 $( '.theme-browser' ).find( 'div.error' ).remove();
    1171                 }).fail( function() {
    1172                                 $( '.theme-browser' ).find( 'div.error' ).remove();
    1173                                 $( '.theme-browser' ).append( '<div class="error"><p>' + l10n.error + '</p></div>' );
    1174                 });
    1175 
    1176                 return false;
     1249                // Get the themes by sending Ajax POST request to api.wordpress.org/themes
     1250                // or searching the local cache
     1251                this.collection.query( request );
    11771252        },
    11781253
    11791254        // Clicking on a checkbox triggers a tag request
     
    11821257                        tags = this.filtersChecked(),
    11831258                        request = { tag: tags };
    11841259
    1185                 // Send Ajax POST request to api.wordpress.org/themes
    1186                 this.apiCall( request ).done( function( data ) {
    1187                                 // Update the collection with the queried data
    1188                                 self.collection.reset( data.themes );
    1189                                 // Trigger a collection refresh event to render the views
    1190                                 self.collection.trigger( 'update' );
    1191 
    1192                                 // Un-spin it
    1193                                 $( 'body' ).removeClass( 'loading-themes' );
    1194                                 $( '.theme-browser' ).find( 'div.error' ).remove();
    1195                 }).fail( function() {
    1196                                 $( '.theme-browser' ).find( 'div.error' ).remove();
    1197                                 $( '.theme-browser' ).append( '<div class="error"><p>' + l10n.error + '</p></div>' );
    1198                 });
     1260                // Get the themes by sending Ajax POST request to api.wordpress.org/themes
     1261                // or searching the local cache
     1262                this.collection.query( request );
    11991263        },
    12001264
    12011265        // Get the checked filters and return an array