WordPress.org

Make WordPress Core

Ticket #24716: 24716.39.diff

File 24716.39.diff, 7.4 KB (added by adamsilverstein, 4 years ago)

better history

  • 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
     
    9191                 * @global wp.Uploader
    9292                 */
    9393                initialize: function() {
     94                        var self = this;
    9495                        _.defaults( this.options, {
    9596                                title:     l10n.mediaLibraryTitle,
    9697                                modal:     false,
     
    140141                        this.createStates();
    141142                        this.bindHandlers();
    142143                        this.render();
     144
     145                        // Set up the Backbone router after a brief delay
     146                        _.delay( function(){
     147                                wp.media.mediarouter = new media.view.Frame.Router( self );
     148                                // Verify pushState support and activate
     149                                if ( window.history && window.history.pushState ) {
     150                                        Backbone.history.start({
     151                                                root: mediaGridSettings.adminUrl,
     152                                                pushState: true
     153                                        });
     154                                }
     155                        }, 250);
     156
     157                        // Update the URL when entering search string (at most once per second)
     158                        $( '#media-search-input' ).on( 'input', _.debounce( function() {
     159                                var $val = $( this ).val();
     160                                wp.media.mediarouter.navigate( wp.media.mediarouter.baseUrl( ( '' == $val ) ? '' : ( '?search=' + $val ) ) );
     161                        }, 1000 ) );
    143162                },
    144163
    145164                createSelection: function() {
     
    218237                 * Open the Edit Attachment modal.
    219238                 */
    220239                editAttachment: function( model ) {
    221                         var library = this.state().get('library');
     240                        var self    = this,
     241                                library = this.state().get('library');
    222242
    223243                        // Create a new EditAttachment frame, passing along the library and the attachment model.
    224                         this.editAttachmentFrame = new media.view.Frame.EditAttachment({
     244                        this.editAttachmentFrame = new media.view.Frame.EditAttachments({
    225245                                library:        library,
    226246                                model:          model
    227247                        });
     
    229249                        // Listen to events on the edit attachment frame for triggering pagination callback handlers.
    230250                        this.listenTo( this.editAttachmentFrame, 'edit:attachment:next', this.editNextAttachment );
    231251                        this.listenTo( this.editAttachmentFrame, 'edit:attachment:previous', this.editPreviousAttachment );
     252                        // Listen to keyboard events on the modal
     253                        $( 'body' ).on( 'keydown.media-modal', function( e ) {
     254                                self.editAttachmentFrame.keyEvent( e );
     255                        } );
    232256                },
    233257
    234258                /**
     
    300324        });
    301325
    302326        /**
     327         * A router for handling the browser history and application state
     328         */
     329        media.view.Frame.Router = Backbone.Router.extend({
     330
     331                mediaFrame: '',
     332
     333                initialize: function( mediaFrame ){
     334                        this.mediaFrame = mediaFrame;
     335                },
     336
     337                routes: {
     338                        'upload.php?item=:slug':    'showitem',
     339                        'upload.php?search=:query': 'search',
     340                        ':default':                 'defaultRoute'
     341                },
     342
     343                // Map routes against the page URL
     344                baseUrl: function( url ) {
     345                        return 'upload.php' + url;
     346                },
     347
     348                // Respond to the search route by filling the search field and trigggering the input event
     349                search: function( query ) {
     350                        // Ensure modal closed, see back button
     351                        this.closeModal();
     352                        $( '#media-search-input' ).val( query ).trigger( 'input' );
     353                },
     354
     355                // Show the modal with a specific item
     356                showitem: function( query ) {
     357                        var library = this.mediaFrame.state().get('library');
     358
     359                        // Remove existing modal if present
     360                        this.closeModal();
     361                        // Trigger the media frame to open the correct item
     362                        this.mediaFrame.trigger( 'edit:attachment', library.findWhere( { id: parseInt( query, 10 ) } ) );
     363                },
     364
     365                // Close the modal if set up
     366                closeModal: function() {
     367                        if ( 'undefined' !== typeof this.mediaFrame.editAttachmentFrame ) {
     368                                this.mediaFrame.editAttachmentFrame.modal.close();
     369                        }
     370                },
     371
     372                // Default route: make sure the modal and search are reset
     373                defaultRoute: function() {
     374                        this.closeModal();
     375                        $( '#media-search-input' ).val( '' ).trigger( 'input' );
     376                }
     377        });
     378
     379        /**
    303380         * A frame for editing the details of a specific media item.
    304381         *
    305382         * Opens in a modal by default.
     
    306383         *
    307384         * Requires an attachment model to be passed in the options hash under `model`.
    308385         */
    309         media.view.Frame.EditAttachment = media.view.Frame.extend({
     386        media.view.Frame.EditAttachments = media.view.Frame.extend({
    310387
    311388                className: 'edit-attachment-frame',
    312389                template: media.template( 'edit-attachment-frame' ),
     
    328405                                state: 'edit-attachment'
    329406                        });
    330407
     408                        this.library = this.options.library;
     409                        if ( this.options.model ) {
     410                                this.model = this.options.model;
     411                        } else {
     412                                this.model = this.library.at( 0 );
     413                        }
     414
    331415                        this.createStates();
    332416
    333417                        this.on( 'content:render:edit-metadata', this.editMetadataContent, this );
     
    334418                        this.on( 'content:render:edit-image', this.editImageContentUgh, this );
    335419
    336420                        // Only need a tab to Edit Image for images.
    337                         if ( this.model.get( 'type' ) === 'image' ) {
     421                        if ( 'undefined' !== typeof this.model && this.model.get( 'type' ) === 'image' ) {
    338422                                this.on( 'router:create', this.createRouter, this );
    339423                                this.on( 'router:render', this.browseRouter, this );
    340424                        }
     
    352436                                // Completely destroy the modal DOM element when closing it.
    353437                                this.modal.close = function() {
    354438                                        self.modal.remove();
     439                                        $( 'body' ).off( 'keydown.media-modal' ); /* remove the keydown event */
    355440                                };
    356441
    357442                                this.modal.content( this );
     
    391476                                model:      this.model
    392477                        });
    393478                        this.content.set( view );
     479                        // Update browser url when navigating media details
     480                        wp.media.mediarouter.navigate( wp.media.mediarouter.baseUrl( '?item=' + this.model.id ) );
    394481                },
    395482
    396483                /**
     
    461548                                return;
    462549                        this.modal.close();
    463550                        this.trigger( 'edit:attachment:next', this.model );
     551                },
     552
     553                getCurrentIndex: function() {
     554                        return this.library.indexOf( this.model );
     555                },
     556
     557                hasNext: function() {
     558                        return ( this.getCurrentIndex() + 1 ) < this.library.length;
     559                },
     560
     561                hasPrevious: function() {
     562                        return ( this.getCurrentIndex() - 1 ) > -1;
     563                },
     564                /**
     565                 * Respond to the keyboard events: right arrow, left arrow, escape.
     566                 */
     567                keyEvent: function( event ) {
     568                        var $target = $( event.target );
     569                        // Pressing the escape key routes back to main url
     570                        if ( event.keyCode === 27 ) {
     571                                this.resetRoute();
     572                                return event;
     573                        }
     574                        //Don't go left/right if we are in a textarea or input field
     575                        if ( $target.is( 'input' ) || $target.is( 'textarea' ) ) {
     576                                return event;
     577                        }
     578                        // The right arrow key
     579                        if ( event.keyCode === 39 ) {
     580                                if ( ! this.hasNext ) { return; }
     581                                _.debounce( this.nextMediaItem(), 250 );
     582                        }
     583                        // The left arrow key
     584                        if ( event.keyCode === 37 ) {
     585                                if ( ! this.hasPrevious ) { return; }
     586                                _.debounce( this.previousMediaItem(), 250 );
     587                        }
     588                },
     589
     590                resetRoute: function() {
     591                        wp.media.mediarouter.navigate( wp.media.mediarouter.baseUrl( '' ) );
     592                        return;
    464593                }
    465594        });
    466595