WordPress.org

Make WordPress Core

Ticket #24716: 24716.31.diff

File 24716.31.diff, 8.9 KB (added by adamsilverstein, 3 years ago)

improved search routing

  • src/wp-admin/upload.php

     
    2424        wp_enqueue_media(); 
    2525        wp_enqueue_script( 'media-grid' ); 
    2626        wp_enqueue_script( 'media' ); 
     27        wp_localize_script( 'media-grid', 'mediaGridSettings', array( 'adminUrl' => parse_url( self_admin_url(), PHP_URL_PATH )  ) ); 
    2728 
    2829        require_once( ABSPATH . 'wp-admin/admin-header.php' ); 
    2930        include( ABSPATH . 'wp-admin/admin-footer.php' ); 
  • src/wp-includes/js/media-grid.js

     
    1 /* global _wpMediaViewsL10n, setUserSetting, deleteUserSetting, MediaElementPlayer */ 
     1/* global _wpMediaViewsL10n, setUserSetting, deleteUserSetting, MediaElementPlayer, mediaGridSettings*/ 
    22(function($, _, Backbone, wp) { 
    33        var media = wp.media, l10n; 
    44 
     
    120120                 * @global wp.Uploader 
    121121                 */ 
    122122                initialize: function() { 
     123                        var self = this; 
    123124                        _.defaults( this.options, { 
    124125                                title:     l10n.mediaLibraryTitle, 
    125126                                modal:     false, 
     
    168169                        this.createStates(); 
    169170                        this.bindHandlers(); 
    170171                        this.render(); 
     172 
     173                        // Set up the Backbone router after a brief delay 
     174                        _.delay( function(){ 
     175                                wp.media.mediarouter = new media.view.Frame.Router( self ); 
     176                                // Verify pushState support and activate 
     177                                if ( window.history && window.history.pushState ) { 
     178                                        Backbone.history.start({ 
     179                                                root: mediaGridSettings.adminUrl, 
     180                                                pushState: true 
     181                                        }); 
     182                                } 
     183                        }, 150); 
     184 
     185                        // Update the URL when entering search string (at most once per second) 
     186                        $( '#media-search-input' ).on( 'input', _.debounce( function() { 
     187                                var $val = $( this ).val(); 
     188                                wp.media.mediarouter.navigate( wp.media.mediarouter.baseUrl( ( '' == $val ) ? '' : ( '?search=' + $val ) ) ); 
     189                        }, 1000 ) ); 
    171190                }, 
    172191 
    173192                createSelection: function() { 
     
    213232 
    214233                        // Handle a frame-level event for editing an attachment. 
    215234                        this.on( 'edit:attachment', this.editAttachment, this ); 
    216                         this.on( 'edit:attachment:next', this.editNextAttachment, this ); 
    217                         this.on( 'edit:attachment:previous', this.editPreviousAttachment, this ); 
    218235                }, 
    219236 
    220                 editPreviousAttachment: function( currentModel ) { 
    221                         var library = this.state().get('library'), 
    222                                 currentModelIndex = library.indexOf( currentModel ); 
    223                         this.trigger( 'edit:attachment', library.at( currentModelIndex - 1 ) ); 
    224                 }, 
    225  
    226                 editNextAttachment: function( currentModel ) { 
    227                         var library = this.state().get('library'), 
    228                                 currentModelIndex = library.indexOf( currentModel ); 
    229                         this.trigger( 'edit:attachment', library.at( currentModelIndex + 1 ) ); 
    230                 }, 
    231  
    232237                /** 
    233238                 * Open the Edit Attachment modal. 
    234239                 */ 
    235240                editAttachment: function( model ) { 
    236                         var library = this.state().get('library'), hasPrevious, hasNext; 
    237                         if ( library.indexOf( model ) > 0 ) { 
    238                                 hasPrevious = true; 
    239                         } 
    240                         else { 
    241                                 hasPrevious = false; 
    242                         } 
    243                         if ( library.indexOf( model ) < library.length - 1 ) { 
    244                                 hasNext = true; 
    245                         } 
    246                         else { 
    247                                 hasNext = false; 
    248                         } 
    249  
    250                         new media.view.Frame.EditAttachment({ 
    251                                 hasPrevious:    hasPrevious, 
    252                                 hasNext:        hasNext, 
    253                                 model:          model, 
    254                                 gridController: this 
     241                        var self = this; 
     242                        // Create a new EditAttachment frame, passing along the library. 
     243                        this.editAttachmentFrame = new media.view.Frame.EditAttachments({ 
     244                                library: this.state().get('library'), 
     245                                model: model 
    255246                        }); 
     247                        $( 'body' ).on( 'keydown.media-modal', function( e ) { 
     248                                self.editAttachmentFrame.keyEvent( e ); 
     249                                } ); 
    256250                }, 
    257251 
    258252                /** 
     
    324318        }); 
    325319 
    326320        /** 
     321         * A router for handling the browser history and application state 
     322         */ 
     323        media.view.Frame.Router = Backbone.Router.extend({ 
     324 
     325                mediaFrame: '', 
     326 
     327                initialize: function( mediaFrame ){ 
     328                        this.mediaFrame = mediaFrame; 
     329                }, 
     330 
     331                routes: { 
     332                        'upload.php?item=:slug':    'showitem', 
     333                        'upload.php?search=:query': 'search', 
     334                        ':default':                 'defaultRoute' 
     335                }, 
     336 
     337                // Map routes against the page URL 
     338                baseUrl: function( url ) { 
     339                        return 'upload.php' + url; 
     340                }, 
     341 
     342                // Respond to the search route by filling the search field and trigggering the input event 
     343                search: function( query ) { 
     344                        // Ensure modal closed, see back button 
     345                        this.closeModal(); 
     346                        $( '#media-search-input' ).val( query ).trigger( 'input' ); 
     347                }, 
     348 
     349                // Show the modal with a specific item 
     350                showitem: function( query ) { 
     351                        var library = this.mediaFrame.state().get('library'); 
     352 
     353                        // Remove existing modal if present 
     354                        this.closeModal(); 
     355                        // Trigger the media frame to open the correct item 
     356                        this.mediaFrame.trigger( 'edit:attachment', library.findWhere( { id: parseInt( query, 10 ) } ) ); 
     357                }, 
     358 
     359                // Close the modal if set up 
     360                closeModal: function() { 
     361                        if ( 'undefined' !== typeof this.mediaFrame.editAttachmentFrame ) { 
     362                                this.mediaFrame.editAttachmentFrame.modal.close(); 
     363                        } 
     364                }, 
     365 
     366                // Default route: make sure the modal and search are reset 
     367                defaultRoute: function() { 
     368                        this.closeModal(); 
     369                        $( '#media-search-input' ).val( '' ).trigger( 'input' ); 
     370                } 
     371        }); 
     372 
     373        /** 
    327374         * A frame for editing the details of a specific media item. 
    328375         * 
    329376         * Opens in a modal by default. 
     
    330377         * 
    331378         * Requires an attachment model to be passed in the options hash under `model`. 
    332379         */ 
    333         media.view.Frame.EditAttachment = media.view.Frame.extend({ 
     380        media.view.Frame.EditAttachments = media.view.Frame.extend({ 
    334381 
    335382                className: 'edit-attachment-frame', 
    336383                template: media.template( 'edit-attachment-frame' ), 
     
    352399                                state: 'edit-attachment' 
    353400                        }); 
    354401 
     402                        this.library = this.options.library; 
     403                        if ( this.options.model ) { 
     404                                this.model = this.options.model; 
     405                        } else { 
     406                                this.model = this.library.at( 0 ); 
     407                        } 
     408 
    355409                        this.createStates(); 
    356410 
    357411                        this.on( 'content:render:edit-metadata', this.editMetadataContent, this ); 
     
    358412                        this.on( 'content:render:edit-image', this.editImageContentUgh, this ); 
    359413 
    360414                        // Only need a tab to Edit Image for images. 
    361                         if ( this.model.get( 'type' ) === 'image' ) { 
     415                        if ( 'undefined' !== typeof this.model && this.model.get( 'type' ) === 'image' ) { 
    362416                                this.on( 'router:create', this.createRouter, this ); 
    363417                                this.on( 'router:render', this.browseRouter, this ); 
    364418                        } 
     
    373427                                // Completely destroy the modal DOM element when closing it. 
    374428                                this.modal.close = function() { 
    375429                                        self.modal.remove(); 
     430                                        $( 'body' ).off( 'keydown.media-modal' ); /* remove the keydown event */ 
     431                                        // Reset the browser URL 
     432                                        self.resetRoute(); 
    376433                                }; 
    377434 
    378435                                this.modal.content( this ); 
     
    412469                                model:      this.model 
    413470                        }); 
    414471                        this.content.set( view ); 
     472                        // Update browser url when navigating media details 
     473                        wp.media.mediarouter.navigate( wp.media.mediarouter.baseUrl( '?item=' + this.model.id ) ); 
    415474                }, 
    416475 
    417476                /** 
     
    464523                        }); 
    465524                }, 
    466525 
     526                getCurrentIndex: function() { 
     527                        return this.library.indexOf( this.model ); 
     528                }, 
     529 
     530                hasNext: function() { 
     531                        return ( this.getCurrentIndex() + 1 ) < this.library.length; 
     532                }, 
     533 
     534                hasPrevious: function() { 
     535                        return ( this.getCurrentIndex() - 1 ) > -1; 
     536                }, 
     537 
    467538                /** 
    468539                 * Click handler to switch to the previous media item. 
    469540                 */ 
    470541                previousMediaItem: function() { 
    471                         if ( ! this.options.hasPrevious ) 
     542                        if ( ! this.hasPrevious() ) { 
    472543                                return; 
    473                         this.modal.close(); 
    474                         this.options.gridController.trigger( 'edit:attachment:previous', this.model ); 
     544                        } 
     545                        this.model = this.library.at( this.getCurrentIndex() - 1 ); 
     546                        this.editMetadataContent(); 
    475547                }, 
    476548 
    477549                /** 
     
    478550                 * Click handler to switch to the next media item. 
    479551                 */ 
    480552                nextMediaItem: function() { 
    481                         if ( ! this.options.hasNext ) 
     553                        if ( ! this.hasNext() ) { 
    482554                                return; 
    483                         this.modal.close(); 
    484                         this.options.gridController.trigger( 'edit:attachment:next', this.model ); 
     555                        } 
     556                        this.model = this.library.at( this.getCurrentIndex() + 1 ); 
     557                        this.editMetadataContent(); 
     558                }, 
     559                /** 
     560                 * Respond to the keyboard events: right arrow, left arrow, escape. 
     561                 */ 
     562                keyEvent: function( event ) { 
     563                        var $target = $( event.target ); 
     564 
     565                        // Pressing the escape key routes back to main url 
     566                        if ( event.keyCode === 27 ) { 
     567                                this.resetRoute(); 
     568                                return event; 
     569                        } 
     570 
     571                        //Don't go left/right if we are in a textarea or input field 
     572                        if ( $target.is( 'input' ) || $target.is( 'textarea' ) ) { 
     573                                return event; 
     574                        } 
     575 
     576                        // The right arrow key 
     577                        if ( event.keyCode === 39 ) { 
     578                                if ( ! this.hasNext ) { return; } 
     579                                _.debounce( this.nextMediaItem(), 250 ); 
     580                        } 
     581 
     582                        // The left arrow key 
     583                        if ( event.keyCode === 37 ) { 
     584                                if ( ! this.hasPrevious ) { return; } 
     585                                _.debounce( this.previousMediaItem(), 250 ); 
     586                        } 
     587                }, 
     588 
     589                resetRoute: function() { 
     590                        wp.media.mediarouter.navigate( wp.media.mediarouter.baseUrl( '' ) ); 
     591                        return; 
    485592                } 
    486  
    487593        }); 
    488594 
    489595        media.view.GridFieldOptions = media.View.extend({