WordPress.org

Make WordPress Core

Changeset 19971


Ignore:
Timestamp:
02/21/12 19:44:10 (2 years ago)
Author:
koopersmith
Message:

Second pass at infinite scroll for themes, including polling, fixed paging, and fewer ajax calls. props DH-Shredder, helenyhou, garyc40. see #19815.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/wp-admin/js/theme.dev.js

    r19893 r19971  
    4646        }; 
    4747 
    48     return api; 
     48    return api; 
    4949    } 
    5050})(jQuery); 
     
    5555}); 
    5656 
    57 var wpThemes; 
     57var ThemeScroller; 
    5858 
    5959(function($){ 
    60     var inputs = {}, Query; 
     60    ThemeScroller = { 
     61        // Inputs 
     62        nonce: '', 
     63        search: '', 
     64        tab: '', 
     65        type: '', 
     66        nextPage: 2, 
     67        features: {}, 
    6168 
    62     wpThemes = { 
    63         timeToTriggerQuery: 150, 
    64         minQueryAJAXDuration: 200, 
    65         outListBottomThreshold: 200, 
    66         noMoreResults: false, 
    67          
    68         init : function() { 
     69        // Preferences 
     70        scrollPollingDelay: 500, 
     71        failedRetryDelay: 4000, 
     72        outListBottomThreshold: 300, 
     73 
     74        // Flags 
     75        scrolling: false, 
     76        querying: false, 
     77 
     78        init: function() { 
     79            var self = this, 
     80                startPage, 
     81                queryArray = {}, 
     82                queryString = window.location.search; 
     83 
     84            // We're using infinite scrolling, so hide all pagination. 
    6985            $('.pagination-links').hide(); 
    7086 
    71             inputs.nonce = $('#_ajax_fetch_list_nonce').val(); 
    72      
    73             // Parse Query 
    74             inputs.queryString = window.location.search;             
    75             inputs.queryArray = wpThemes.parseQuery( inputs.queryString.substring( 1 ) ); 
     87            // Parse GET query string 
     88            queryArray = this.parseQuery( queryString.substring( 1 ) ); 
    7689 
    77             // Handle Inputs from Query 
    78             inputs.search = inputs.queryArray['s']; 
    79             inputs.features = inputs.queryArray['features']; 
    80             inputs.startPage = parseInt( inputs.queryArray['paged'] );   
    81             inputs.tab = inputs.queryArray['tab']; 
    82             inputs.type = inputs.queryArray['type']; 
     90            // Handle inputs 
     91            this.nonce = $('#_ajax_fetch_list_nonce').val(); 
     92            this.search = queryArray['s']; 
     93            this.features = queryArray['features']; 
     94            this.tab = queryArray['tab']; 
     95            this.type = queryArray['type']; 
    8396 
    84             if ( isNaN( inputs.startPage ) ) 
    85                 inputs.startPage = 2; 
    86             else 
    87                 inputs.startPage++; 
     97            startPage = parseInt( queryArray['paged'], 10 ); 
     98            if ( ! isNaN( startPage ) ) 
     99                this.nextPage = ( startPage + 1 ); 
    88100 
    89             // Cache jQuery objects 
    90             inputs.outList = $('#availablethemes'); 
    91             inputs.waiting = $('div.tablenav.bottom').children( 'img.ajax-loading' ); 
    92             inputs.window = $(window); 
     101            // Cache jQuery selectors 
     102            this.$outList = $('#availablethemes'); 
     103            this.$spinner = $('div.tablenav.bottom').children( 'img.ajax-loading' ); 
     104            this.$window = $(window); 
     105            this.$document = $(document); 
    93106 
    94             // Generate Query 
    95             wpThemes.query = new Query(); 
     107            if ( $('.tablenav-pages').length ) 
     108                this.pollInterval = 
     109                    setInterval( function() {  
     110                        return self.poll(); 
     111                    }, this.scrollPollingDelay ); 
     112        }, 
     113        poll: function() { 
     114            var bottom = this.$document.scrollTop() + this.$window.innerHeight(); 
    96115 
    97             // Start Polling 
    98             inputs.window.scroll( function(){ wpThemes.maybeLoad(); } ); 
    99         }, 
    100         delayedCallback : function( func, delay ) { 
    101             var timeoutTriggered, funcTriggered, funcArgs, funcContext; 
    102  
    103             if ( ! delay ) 
    104                 return func; 
    105  
    106             setTimeout( function() { 
    107                 if ( funcTriggered ) 
    108                     return func.apply( funcContext, funcArgs ); 
    109                 // Otherwise, wait. 
    110                 timeoutTriggered = true; 
    111             }, delay); 
    112  
    113             return function() { 
    114                 if ( timeoutTriggered ) 
    115                     return func.apply( this, arguments ); 
    116                 // Otherwise, wait. 
    117                 funcArgs = arguments; 
    118                 funcContext = this; 
    119                 funcTriggered = true; 
    120             }; 
    121         }, 
    122         ajax: function( callback ) { 
    123             var self = this, 
    124                 response = wpThemes.delayedCallback( function( results, params ) { 
    125                     self.process( results, params ); 
    126                     if ( callback ) 
    127                         callback( results, params ); 
    128                 }, wpThemes.minQueryAJAXDuration ); 
    129  
    130             this.query.ajax( response ); 
    131         }, 
    132         process: function( results, params ) { 
    133             // If no Results, for now, mark as no Matches, and bail. 
    134             // Alternately: inputs.outList.append(wpThemesL10n.noMatchesFound); 
    135             if ( ( results === undefined ) || 
    136                  ( results.rows.indexOf( "no-items" ) != -1 ) ) { 
    137                 this.noMoreResults = true; 
    138             } else { 
    139                 inputs.outList.append( results.rows ); 
    140             } 
    141         }, 
    142         maybeLoad: function() { 
    143             var self = this, 
    144                 el = $(document), 
    145                 bottom = el.scrollTop() + inputs.window.innerHeight(); 
    146                  
    147             if ( this.noMoreResults || 
    148                  !this.query.ready() ||  
    149                  ( bottom < inputs.outList.height() - wpThemes.outListBottomThreshold ) ) 
     116            if ( this.querying || 
     117                ( bottom < this.$outList.height() - this.outListBottomThreshold ) ) 
    150118                return; 
    151119 
    152             setTimeout( function() { 
    153                 var newTop = el.scrollTop(), 
    154                     newBottom = newTop + inputs.window.innerHeight(); 
     120            this.ajax(); 
     121        }, 
     122        process: function( results ) { 
     123            if ( ( results === undefined ) || 
     124                ( results.rows.indexOf( 'no-items' ) != -1 ) ) { 
     125                clearInterval( this.pollInterval ); 
     126                return; 
     127            } 
    155128 
    156                 if ( !self.query.ready() || 
    157                      ( newBottom < inputs.outList.height() - wpThemes.outListBottomThreshold ) ) 
    158                     return; 
     129            var totalPages = parseInt( results.total_pages, 10 ); 
     130            if ( this.nextPage > totalPages ) 
     131                clearInterval( this.pollInterval ); 
    159132 
    160                 inputs.waiting.css( 'visibility', 'visible' ); // Show Spinner 
    161                 self.ajax( function() { inputs.waiting.css( 'visibility', 'hidden' ) } ); // Hide Spinner 
    162                  
    163             }, wpThemes.timeToTriggerQuery ); 
     133            if ( this.nextPage <= ( totalPages + 1 ) ) 
     134                this.$outList.append( results.rows ); 
     135        }, 
     136        ajax: function() { 
     137            var self = this; 
     138            this.querying = true; 
     139 
     140            var query = { 
     141                action: 'fetch-list', 
     142                tab: this.tab, 
     143                paged: this.nextPage, 
     144                s: this.search, 
     145                type: this.type, 
     146                _ajax_fetch_list_nonce: this.nonce, 
     147                'features[]': this.features, 
     148                'list_args': list_args 
     149            }; 
     150 
     151            this.$spinner.css( 'visibility', 'visible' ); 
     152            $.getJSON( ajaxurl, query ) 
     153                .done( function( response ) { 
     154                    self.nextPage++; 
     155                    self.process( response ); 
     156                    self.$spinner.css( 'visibility', 'hidden' ); 
     157                    self.querying = false; 
     158                }) 
     159                .fail( function() { 
     160                    self.$spinner.css( 'visibility', 'hidden' ); 
     161                    self.querying = false; 
     162                    setTimeout( function() { self.ajax(); }, self.failedRetryDelay ) 
     163                }); 
    164164        }, 
    165165        parseQuery: function( query ) { 
    166             var Params = {}; 
    167             if ( ! query ) {return Params;}// return empty object 
    168             var Pairs = query.split(/[;&]/); 
    169             for ( var i = 0; i < Pairs.length; i++ ) { 
    170                 var KeyVal = Pairs[i].split('='); 
    171                 if ( ! KeyVal || KeyVal.length != 2 ) {continue;} 
    172                 var key = unescape( KeyVal[0] ); 
    173                 var val = unescape( KeyVal[1] ); 
    174                 val = val.replace(/\+/g, ' '); 
    175                 key = key.replace(/\[.*\]$/g, ''); 
    176      
    177                 if ( Params[key] === undefined ) { 
    178                     Params[key] = val; 
     166            var params = {}; 
     167            if ( ! query ) 
     168                return params; 
     169 
     170            var pairs = query.split( /[;&]/ ); 
     171            for ( var i = 0; i < pairs.length; i++ ) { 
     172                var keyVal = pairs[i].split( '=' ); 
     173 
     174                if ( ! keyVal || keyVal.length != 2 ) 
     175                    continue; 
     176 
     177                var key = unescape( keyVal[0] ); 
     178                var val = unescape( keyVal[1] ); 
     179                val = val.replace( /\+/g, ' ' ); 
     180                key = key.replace( /\[.*\]$/g, '' ); 
     181 
     182                if ( params[key] === undefined ) { 
     183                    params[key] = val; 
    179184                } else { 
    180                     var oldVal = Params[key]; 
    181                     if ( ! jQuery.isArray( Params[key] ) ) 
    182                         Params[key] = new Array( oldVal, val ); 
     185                    var oldVal = params[key]; 
     186                    if ( ! $.isArray( params[key] ) ) 
     187                        params[key] = new Array( oldVal, val ); 
    183188                    else 
    184                         Params[key].push( val ); 
     189                        params[key].push( val ); 
    185190                } 
    186191            } 
    187             return Params; 
     192            return params; 
    188193        } 
    189194    } 
    190195 
    191     Query = function() { 
    192         this.failedRequest = false; 
    193         this.querying = false; 
    194         this.page = inputs.startPage; 
    195     } 
    196      
    197     $.extend( Query.prototype, { 
    198         ready: function() { 
    199             return !( this.querying || this.failedRequest ); 
    200         }, 
    201         ajax: function( callback ) { 
    202             var self = this, 
    203             query = { 
    204                 action: 'fetch-list', 
    205                 tab: inputs.tab, 
    206                 paged: this.page, 
    207                 s: inputs.search, 
    208                 type: inputs.type, 
    209                 _ajax_fetch_list_nonce: inputs.nonce, 
    210                 'features[]': inputs.features, 
    211                 'list_args': list_args 
    212             }; 
    213  
    214             this.querying = true; 
    215             $.get( ajaxurl, query, function(r) { 
    216                 self.page++; 
    217                 self.querying = false; 
    218                 self.failedRequest = !r; 
    219                 callback( r, query ); 
    220             }, "json" ); 
    221         } 
    222     }); 
    223  
    224     $(document).ready( wpThemes.init ); 
     196    $(document).ready( function( $ ) { ThemeScroller.init(); }); 
    225197 
    226198})(jQuery); 
Note: See TracChangeset for help on using the changeset viewer.