[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-includes/js/ -> media-grid.js (source)

   1  /******/ (() => { // webpackBootstrap
   2  /******/     var __webpack_modules__ = ({
   3  
   4  /***/ 659:
   5  /***/ ((module) => {
   6  
   7  var l10n = wp.media.view.l10n,
   8      EditAttachmentMetadata;
   9  
  10  /**
  11   * wp.media.controller.EditAttachmentMetadata
  12   *
  13   * A state for editing an attachment's metadata.
  14   *
  15   * @memberOf wp.media.controller
  16   *
  17   * @class
  18   * @augments wp.media.controller.State
  19   * @augments Backbone.Model
  20   */
  21  EditAttachmentMetadata = wp.media.controller.State.extend(/** @lends wp.media.controller.EditAttachmentMetadata.prototype */{
  22      defaults: {
  23          id:      'edit-attachment',
  24          // Title string passed to the frame's title region view.
  25          title:   l10n.attachmentDetails,
  26          // Region mode defaults.
  27          content: 'edit-metadata',
  28          menu:    false,
  29          toolbar: false,
  30          router:  false
  31      }
  32  });
  33  
  34  module.exports = EditAttachmentMetadata;
  35  
  36  
  37  /***/ }),
  38  
  39  /***/ 682:
  40  /***/ ((module) => {
  41  
  42  
  43  var Button = wp.media.view.Button,
  44      l10n = wp.media.view.l10n,
  45      SelectModeToggle;
  46  
  47  /**
  48   * wp.media.view.SelectModeToggleButton
  49   *
  50   * @memberOf wp.media.view
  51   *
  52   * @class
  53   * @augments wp.media.view.Button
  54   * @augments wp.media.View
  55   * @augments wp.Backbone.View
  56   * @augments Backbone.View
  57   */
  58  SelectModeToggle = Button.extend(/** @lends wp.media.view.SelectModeToggle.prototype */{
  59      initialize: function() {
  60          _.defaults( this.options, {
  61              size : ''
  62          } );
  63  
  64          Button.prototype.initialize.apply( this, arguments );
  65          this.controller.on( 'select:activate select:deactivate', this.toggleBulkEditHandler, this );
  66          this.controller.on( 'selection:action:done', this.back, this );
  67      },
  68  
  69      back: function () {
  70          this.controller.deactivateMode( 'select' ).activateMode( 'edit' );
  71      },
  72  
  73      click: function() {
  74          Button.prototype.click.apply( this, arguments );
  75          if ( this.controller.isModeActive( 'select' ) ) {
  76              this.back();
  77          } else {
  78              this.controller.deactivateMode( 'edit' ).activateMode( 'select' );
  79          }
  80      },
  81  
  82      render: function() {
  83          Button.prototype.render.apply( this, arguments );
  84          this.$el.addClass( 'select-mode-toggle-button' );
  85          return this;
  86      },
  87  
  88      toggleBulkEditHandler: function() {
  89          var toolbar = this.controller.content.get().toolbar, children;
  90  
  91          children = toolbar.$( '.media-toolbar-secondary > *, .media-toolbar-primary > *' );
  92  
  93          // @todo The Frame should be doing all of this.
  94          if ( this.controller.isModeActive( 'select' ) ) {
  95              this.model.set( {
  96                  size: 'large',
  97                  text: l10n.cancel
  98              } );
  99              children.not( '.spinner, .media-button' ).hide();
 100              this.$el.show();
 101              toolbar.$el.addClass( 'media-toolbar-mode-select' );
 102              toolbar.$( '.delete-selected-button' ).removeClass( 'hidden' );
 103          } else {
 104              this.model.set( {
 105                  size: '',
 106                  text: l10n.bulkSelect
 107              } );
 108              this.controller.content.get().$el.removeClass( 'fixed' );
 109              toolbar.$el.css( 'width', '' );
 110              toolbar.$el.removeClass( 'media-toolbar-mode-select' );
 111              toolbar.$( '.delete-selected-button' ).addClass( 'hidden' );
 112              children.not( '.media-button' ).show();
 113              this.controller.state().get( 'selection' ).reset();
 114          }
 115      }
 116  });
 117  
 118  module.exports = SelectModeToggle;
 119  
 120  
 121  /***/ }),
 122  
 123  /***/ 1003:
 124  /***/ ((module) => {
 125  
 126  var Frame = wp.media.view.Frame,
 127      MediaFrame = wp.media.view.MediaFrame,
 128  
 129      $ = jQuery,
 130      EditAttachments;
 131  
 132  /**
 133   * wp.media.view.MediaFrame.EditAttachments
 134   *
 135   * A frame for editing the details of a specific media item.
 136   *
 137   * Opens in a modal by default.
 138   *
 139   * Requires an attachment model to be passed in the options hash under `model`.
 140   *
 141   * @memberOf wp.media.view.MediaFrame
 142   *
 143   * @class
 144   * @augments wp.media.view.Frame
 145   * @augments wp.media.View
 146   * @augments wp.Backbone.View
 147   * @augments Backbone.View
 148   * @mixes wp.media.controller.StateMachine
 149   */
 150  EditAttachments = MediaFrame.extend(/** @lends wp.media.view.MediaFrame.EditAttachments.prototype */{
 151  
 152      className: 'edit-attachment-frame',
 153      template:  wp.template( 'edit-attachment-frame' ),
 154      regions:   [ 'title', 'content' ],
 155  
 156      events: {
 157          'click .left':  'previousMediaItem',
 158          'click .right': 'nextMediaItem'
 159      },
 160  
 161      initialize: function() {
 162          Frame.prototype.initialize.apply( this, arguments );
 163  
 164          _.defaults( this.options, {
 165              modal: true,
 166              state: 'edit-attachment'
 167          });
 168  
 169          this.controller = this.options.controller;
 170          this.gridRouter = this.controller.gridRouter;
 171          this.library = this.options.library;
 172  
 173          if ( this.options.model ) {
 174              this.model = this.options.model;
 175          }
 176  
 177          this.bindHandlers();
 178          this.createStates();
 179          this.createModal();
 180  
 181          this.title.mode( 'default' );
 182          this.toggleNav();
 183      },
 184  
 185      bindHandlers: function() {
 186          // Bind default title creation.
 187          this.on( 'title:create:default', this.createTitle, this );
 188  
 189          this.on( 'content:create:edit-metadata', this.editMetadataMode, this );
 190          this.on( 'content:create:edit-image', this.editImageMode, this );
 191          this.on( 'content:render:edit-image', this.editImageModeRender, this );
 192          this.on( 'refresh', this.rerender, this );
 193          this.on( 'close', this.detach );
 194  
 195          this.bindModelHandlers();
 196          this.listenTo( this.gridRouter, 'route:search', this.close, this );
 197      },
 198  
 199      bindModelHandlers: function() {
 200          // Close the modal if the attachment is deleted.
 201          this.listenTo( this.model, 'change:status destroy', this.close, this );
 202      },
 203  
 204      createModal: function() {
 205          // Initialize modal container view.
 206          if ( this.options.modal ) {
 207              this.modal = new wp.media.view.Modal({
 208                  controller:     this,
 209                  title:          this.options.title,
 210                  hasCloseButton: false
 211              });
 212  
 213              this.modal.on( 'open', _.bind( function () {
 214                  $( 'body' ).on( 'keydown.media-modal', _.bind( this.keyEvent, this ) );
 215              }, this ) );
 216  
 217              // Completely destroy the modal DOM element when closing it.
 218              this.modal.on( 'close', _.bind( function() {
 219                  // Remove the keydown event.
 220                  $( 'body' ).off( 'keydown.media-modal' );
 221                  // Move focus back to the original item in the grid if possible.
 222                  $( 'li.attachment[data-id="' + this.model.get( 'id' ) +'"]' ).trigger( 'focus' );
 223                  this.resetRoute();
 224              }, this ) );
 225  
 226              // Set this frame as the modal's content.
 227              this.modal.content( this );
 228              this.modal.open();
 229          }
 230      },
 231  
 232      /**
 233       * Add the default states to the frame.
 234       */
 235      createStates: function() {
 236          this.states.add([
 237              new wp.media.controller.EditAttachmentMetadata({
 238                  model:   this.model,
 239                  library: this.library
 240              })
 241          ]);
 242      },
 243  
 244      /**
 245       * Content region rendering callback for the `edit-metadata` mode.
 246       *
 247       * @param {Object} contentRegion Basic object with a `view` property, which
 248       *                               should be set with the proper region view.
 249       */
 250      editMetadataMode: function( contentRegion ) {
 251          contentRegion.view = new wp.media.view.Attachment.Details.TwoColumn({
 252              controller: this,
 253              model:      this.model
 254          });
 255  
 256          /**
 257           * Attach a subview to display fields added via the
 258           * `attachment_fields_to_edit` filter.
 259           */
 260          contentRegion.view.views.set( '.attachment-compat', new wp.media.view.AttachmentCompat({
 261              controller: this,
 262              model:      this.model
 263          }) );
 264  
 265          // Update browser url when navigating media details, except on load.
 266          if ( this.model && ! this.model.get( 'skipHistory' ) ) {
 267              this.gridRouter.navigate( this.gridRouter.baseUrl( '?item=' + this.model.id ) );
 268          }
 269      },
 270  
 271      /**
 272       * Render the EditImage view into the frame's content region.
 273       *
 274       * @param {Object} contentRegion Basic object with a `view` property, which
 275       *                               should be set with the proper region view.
 276       */
 277      editImageMode: function( contentRegion ) {
 278          var editImageController = new wp.media.controller.EditImage( {
 279              model: this.model,
 280              frame: this
 281          } );
 282          // Noop some methods.
 283          editImageController._toolbar = function() {};
 284          editImageController._router = function() {};
 285          editImageController._menu = function() {};
 286  
 287          contentRegion.view = new wp.media.view.EditImage.Details( {
 288              model: this.model,
 289              frame: this,
 290              controller: editImageController
 291          } );
 292  
 293          this.gridRouter.navigate( this.gridRouter.baseUrl( '?item=' + this.model.id + '&mode=edit' ) );
 294  
 295      },
 296  
 297      editImageModeRender: function( view ) {
 298          view.on( 'ready', view.loadEditor );
 299      },
 300  
 301      toggleNav: function() {
 302          this.$( '.left' ).prop( 'disabled', ! this.hasPrevious() );
 303          this.$( '.right' ).prop( 'disabled', ! this.hasNext() );
 304      },
 305  
 306      /**
 307       * Rerender the view.
 308       */
 309      rerender: function( model ) {
 310          this.stopListening( this.model );
 311  
 312          this.model = model;
 313  
 314          this.bindModelHandlers();
 315  
 316          // Only rerender the `content` region.
 317          if ( this.content.mode() !== 'edit-metadata' ) {
 318              this.content.mode( 'edit-metadata' );
 319          } else {
 320              this.content.render();
 321          }
 322  
 323          this.toggleNav();
 324      },
 325  
 326      /**
 327       * Click handler to switch to the previous media item.
 328       */
 329      previousMediaItem: function() {
 330          if ( ! this.hasPrevious() ) {
 331              return;
 332          }
 333  
 334          this.trigger( 'refresh', this.library.at( this.getCurrentIndex() - 1 ) );
 335          // Move focus to the Previous button. When there are no more items, to the Next button.
 336          this.focusNavButton( this.hasPrevious() ? '.left' : '.right' );
 337      },
 338  
 339      /**
 340       * Click handler to switch to the next media item.
 341       */
 342      nextMediaItem: function() {
 343          if ( ! this.hasNext() ) {
 344              return;
 345          }
 346  
 347          this.trigger( 'refresh', this.library.at( this.getCurrentIndex() + 1 ) );
 348          // Move focus to the Next button. When there are no more items, to the Previous button.
 349          this.focusNavButton( this.hasNext() ? '.right' : '.left' );
 350      },
 351  
 352      /**
 353       * Set focus to the navigation buttons depending on the browsing direction.
 354       *
 355       * @since 5.3.0
 356       *
 357       * @param {string} which A CSS selector to target the button to focus.
 358       */
 359      focusNavButton: function( which ) {
 360          $( which ).trigger( 'focus' );
 361      },
 362  
 363      getCurrentIndex: function() {
 364          return this.library.indexOf( this.model );
 365      },
 366  
 367      hasNext: function() {
 368          return ( this.getCurrentIndex() + 1 ) < this.library.length;
 369      },
 370  
 371      hasPrevious: function() {
 372          return ( this.getCurrentIndex() - 1 ) > -1;
 373      },
 374      /**
 375       * Respond to the keyboard events: right arrow, left arrow, except when
 376       * focus is in a textarea or input field.
 377       */
 378      keyEvent: function( event ) {
 379          if ( ( 'INPUT' === event.target.nodeName || 'TEXTAREA' === event.target.nodeName ) && ! event.target.disabled ) {
 380              return;
 381          }
 382  
 383          // Return if Ctrl + Shift or Shift key pressed
 384          if ( event.shiftKey || ( event.ctrlKey && event.shiftKey ) ) {
 385              return;
 386          }
 387  
 388          // The right arrow key.
 389          if ( 39 === event.keyCode ) {
 390              this.nextMediaItem();
 391          }
 392          // The left arrow key.
 393          if ( 37 === event.keyCode ) {
 394              this.previousMediaItem();
 395          }
 396      },
 397  
 398      resetRoute: function() {
 399          var searchTerm = this.controller.browserView.toolbar.get( 'search' ).$el.val(),
 400              url = '' !== searchTerm ? '?search=' + searchTerm : '';
 401          this.gridRouter.navigate( this.gridRouter.baseUrl( url ), { replace: true } );
 402      }
 403  });
 404  
 405  module.exports = EditAttachments;
 406  
 407  
 408  /***/ }),
 409  
 410  /***/ 1312:
 411  /***/ ((module) => {
 412  
 413  var Details = wp.media.view.Attachment.Details,
 414      TwoColumn;
 415  
 416  /**
 417   * wp.media.view.Attachment.Details.TwoColumn
 418   *
 419   * A similar view to media.view.Attachment.Details
 420   * for use in the Edit Attachment modal.
 421   *
 422   * @memberOf wp.media.view.Attachment.Details
 423   *
 424   * @class
 425   * @augments wp.media.view.Attachment.Details
 426   * @augments wp.media.view.Attachment
 427   * @augments wp.media.View
 428   * @augments wp.Backbone.View
 429   * @augments Backbone.View
 430   */
 431  TwoColumn = Details.extend(/** @lends wp.media.view.Attachment.Details.TwoColumn.prototype */{
 432      template: wp.template( 'attachment-details-two-column' ),
 433  
 434      initialize: function() {
 435          this.controller.on( 'content:activate:edit-details', _.bind( this.editAttachment, this ) );
 436  
 437          Details.prototype.initialize.apply( this, arguments );
 438      },
 439  
 440      editAttachment: function( event ) {
 441          if ( event ) {
 442              event.preventDefault();
 443          }
 444          this.controller.content.mode( 'edit-image' );
 445      },
 446  
 447      /**
 448       * Noop this from parent class, doesn't apply here.
 449       */
 450      toggleSelectionHandler: function() {}
 451  
 452  });
 453  
 454  module.exports = TwoColumn;
 455  
 456  
 457  /***/ }),
 458  
 459  /***/ 2429:
 460  /***/ ((module) => {
 461  
 462  /**
 463   * wp.media.view.MediaFrame.Manage.Router
 464   *
 465   * A router for handling the browser history and application state.
 466   *
 467   * @memberOf wp.media.view.MediaFrame.Manage
 468   *
 469   * @class
 470   * @augments Backbone.Router
 471   */
 472  var Router = Backbone.Router.extend(/** @lends wp.media.view.MediaFrame.Manage.Router.prototype */{
 473      routes: {
 474          'upload.php?item=:slug&mode=edit': 'editItem',
 475          'upload.php?item=:slug':           'showItem',
 476          'upload.php?search=:query':        'search',
 477          'upload.php':                      'reset'
 478      },
 479  
 480      // Map routes against the page URL.
 481      baseUrl: function( url ) {
 482          return 'upload.php' + url;
 483      },
 484  
 485      reset: function() {
 486          var frame = wp.media.frames.edit;
 487  
 488          if ( frame ) {
 489              frame.close();
 490          }
 491      },
 492  
 493      // Respond to the search route by filling the search field and triggering the input event.
 494      search: function( query ) {
 495          jQuery( '#media-search-input' ).val( query ).trigger( 'input' );
 496      },
 497  
 498      // Show the modal with a specific item.
 499      showItem: function( query ) {
 500          var media = wp.media,
 501              frame = media.frames.browse,
 502              library = frame.state().get('library'),
 503              item;
 504  
 505          // Trigger the media frame to open the correct item.
 506          item = library.findWhere( { id: parseInt( query, 10 ) } );
 507  
 508          if ( item ) {
 509              item.set( 'skipHistory', true );
 510              frame.trigger( 'edit:attachment', item );
 511          } else {
 512              item = media.attachment( query );
 513              frame.listenTo( item, 'change', function( model ) {
 514                  frame.stopListening( item );
 515                  frame.trigger( 'edit:attachment', model );
 516              } );
 517              item.fetch();
 518          }
 519      },
 520  
 521      // Show the modal in edit mode with a specific item.
 522      editItem: function( query ) {
 523          this.showItem( query );
 524          wp.media.frames.edit.content.mode( 'edit-details' );
 525      }
 526  });
 527  
 528  module.exports = Router;
 529  
 530  
 531  /***/ }),
 532  
 533  /***/ 5806:
 534  /***/ ((module) => {
 535  
 536  var Button = wp.media.view.Button,
 537      DeleteSelected = wp.media.view.DeleteSelectedButton,
 538      DeleteSelectedPermanently;
 539  
 540  /**
 541   * wp.media.view.DeleteSelectedPermanentlyButton
 542   *
 543   * When MEDIA_TRASH is true, a button that handles bulk Delete Permanently logic
 544   *
 545   * @memberOf wp.media.view
 546   *
 547   * @class
 548   * @augments wp.media.view.DeleteSelectedButton
 549   * @augments wp.media.view.Button
 550   * @augments wp.media.View
 551   * @augments wp.Backbone.View
 552   * @augments Backbone.View
 553   */
 554  DeleteSelectedPermanently = DeleteSelected.extend(/** @lends wp.media.view.DeleteSelectedPermanentlyButton.prototype */{
 555      initialize: function() {
 556          DeleteSelected.prototype.initialize.apply( this, arguments );
 557          this.controller.on( 'select:activate', this.selectActivate, this );
 558          this.controller.on( 'select:deactivate', this.selectDeactivate, this );
 559      },
 560  
 561      filterChange: function( model ) {
 562          this.canShow = ( 'trash' === model.get( 'status' ) );
 563      },
 564  
 565      selectActivate: function() {
 566          this.toggleDisabled();
 567          this.$el.toggleClass( 'hidden', ! this.canShow );
 568      },
 569  
 570      selectDeactivate: function() {
 571          this.toggleDisabled();
 572          this.$el.addClass( 'hidden' );
 573      },
 574  
 575      render: function() {
 576          Button.prototype.render.apply( this, arguments );
 577          this.selectActivate();
 578          return this;
 579      }
 580  });
 581  
 582  module.exports = DeleteSelectedPermanently;
 583  
 584  
 585  /***/ }),
 586  
 587  /***/ 6606:
 588  /***/ ((module) => {
 589  
 590  var Button = wp.media.view.Button,
 591      l10n = wp.media.view.l10n,
 592      DeleteSelected;
 593  
 594  /**
 595   * wp.media.view.DeleteSelectedButton
 596   *
 597   * A button that handles bulk Delete/Trash logic
 598   *
 599   * @memberOf wp.media.view
 600   *
 601   * @class
 602   * @augments wp.media.view.Button
 603   * @augments wp.media.View
 604   * @augments wp.Backbone.View
 605   * @augments Backbone.View
 606   */
 607  DeleteSelected = Button.extend(/** @lends wp.media.view.DeleteSelectedButton.prototype */{
 608      initialize: function() {
 609          Button.prototype.initialize.apply( this, arguments );
 610          if ( this.options.filters ) {
 611              this.options.filters.model.on( 'change', this.filterChange, this );
 612          }
 613          this.controller.on( 'selection:toggle', this.toggleDisabled, this );
 614          this.controller.on( 'select:activate', this.toggleDisabled, this );
 615      },
 616  
 617      filterChange: function( model ) {
 618          if ( 'trash' === model.get( 'status' ) ) {
 619              this.model.set( 'text', l10n.restoreSelected );
 620          } else if ( wp.media.view.settings.mediaTrash ) {
 621              this.model.set( 'text', l10n.trashSelected );
 622          } else {
 623              this.model.set( 'text', l10n.deletePermanently );
 624          }
 625      },
 626  
 627      toggleDisabled: function() {
 628          this.model.set( 'disabled', ! this.controller.state().get( 'selection' ).length );
 629      },
 630  
 631      render: function() {
 632          Button.prototype.render.apply( this, arguments );
 633          if ( this.controller.isModeActive( 'select' ) ) {
 634              this.$el.addClass( 'delete-selected-button' );
 635          } else {
 636              this.$el.addClass( 'delete-selected-button hidden' );
 637          }
 638          this.toggleDisabled();
 639          return this;
 640      }
 641  });
 642  
 643  module.exports = DeleteSelected;
 644  
 645  
 646  /***/ }),
 647  
 648  /***/ 8359:
 649  /***/ ((module) => {
 650  
 651  var MediaFrame = wp.media.view.MediaFrame,
 652      Library = wp.media.controller.Library,
 653  
 654      $ = Backbone.$,
 655      Manage;
 656  
 657  /**
 658   * wp.media.view.MediaFrame.Manage
 659   *
 660   * A generic management frame workflow.
 661   *
 662   * Used in the media grid view.
 663   *
 664   * @memberOf wp.media.view.MediaFrame
 665   *
 666   * @class
 667   * @augments wp.media.view.MediaFrame
 668   * @augments wp.media.view.Frame
 669   * @augments wp.media.View
 670   * @augments wp.Backbone.View
 671   * @augments Backbone.View
 672   * @mixes wp.media.controller.StateMachine
 673   */
 674  Manage = MediaFrame.extend(/** @lends wp.media.view.MediaFrame.Manage.prototype */{
 675      /**
 676       * @constructs
 677       */
 678      initialize: function() {
 679          _.defaults( this.options, {
 680              title:     '',
 681              modal:     false,
 682              selection: [],
 683              library:   {}, // Options hash for the query to the media library.
 684              multiple:  'add',
 685              state:     'library',
 686              uploader:  true,
 687              mode:      [ 'grid', 'edit' ]
 688          });
 689  
 690          this.$body = $( document.body );
 691          this.$window = $( window );
 692          this.$adminBar = $( '#wpadminbar' );
 693          // Store the Add New button for later reuse in wp.media.view.UploaderInline.
 694          this.$uploaderToggler = $( '.page-title-action' )
 695              .attr( 'aria-expanded', 'false' )
 696              .on( 'click', _.bind( this.addNewClickHandler, this ) );
 697  
 698          this.$window.on( 'scroll resize', _.debounce( _.bind( this.fixPosition, this ), 15 ) );
 699  
 700          // Ensure core and media grid view UI is enabled.
 701          this.$el.addClass('wp-core-ui');
 702  
 703          // Force the uploader off if the upload limit has been exceeded or
 704          // if the browser isn't supported.
 705          if ( wp.Uploader.limitExceeded || ! wp.Uploader.browser.supported ) {
 706              this.options.uploader = false;
 707          }
 708  
 709          // Initialize a window-wide uploader.
 710          if ( this.options.uploader ) {
 711              this.uploader = new wp.media.view.UploaderWindow({
 712                  controller: this,
 713                  uploader: {
 714                      dropzone:  document.body,
 715                      container: document.body
 716                  }
 717              }).render();
 718              this.uploader.ready();
 719              $('body').append( this.uploader.el );
 720  
 721              this.options.uploader = false;
 722          }
 723  
 724          this.gridRouter = new wp.media.view.MediaFrame.Manage.Router();
 725  
 726          // Call 'initialize' directly on the parent class.
 727          MediaFrame.prototype.initialize.apply( this, arguments );
 728  
 729          // Append the frame view directly the supplied container.
 730          this.$el.appendTo( this.options.container );
 731  
 732          this.createStates();
 733          this.bindRegionModeHandlers();
 734          this.render();
 735          this.bindSearchHandler();
 736  
 737          wp.media.frames.browse = this;
 738      },
 739  
 740      bindSearchHandler: function() {
 741          var search = this.$( '#media-search-input' ),
 742              searchView = this.browserView.toolbar.get( 'search' ).$el,
 743              listMode = this.$( '.view-list' ),
 744  
 745              input  = _.throttle( function (e) {
 746                  var val = $( e.currentTarget ).val(),
 747                      url = '';
 748  
 749                  if ( val ) {
 750                      url += '?search=' + val;
 751                      this.gridRouter.navigate( this.gridRouter.baseUrl( url ), { replace: true } );
 752                  }
 753              }, 1000 );
 754  
 755          // Update the URL when entering search string (at most once per second).
 756          search.on( 'input', _.bind( input, this ) );
 757  
 758          this.gridRouter
 759              .on( 'route:search', function () {
 760                  var href = window.location.href;
 761                  if ( href.indexOf( 'mode=' ) > -1 ) {
 762                      href = href.replace( /mode=[^&]+/g, 'mode=list' );
 763                  } else {
 764                      href += href.indexOf( '?' ) > -1 ? '&mode=list' : '?mode=list';
 765                  }
 766                  href = href.replace( 'search=', 's=' );
 767                  listMode.prop( 'href', href );
 768              })
 769              .on( 'route:reset', function() {
 770                  searchView.val( '' ).trigger( 'input' );
 771              });
 772      },
 773  
 774      /**
 775       * Create the default states for the frame.
 776       */
 777      createStates: function() {
 778          var options = this.options;
 779  
 780          if ( this.options.states ) {
 781              return;
 782          }
 783  
 784          // Add the default states.
 785          this.states.add([
 786              new Library({
 787                  library:            wp.media.query( options.library ),
 788                  multiple:           options.multiple,
 789                  title:              options.title,
 790                  content:            'browse',
 791                  toolbar:            'select',
 792                  contentUserSetting: false,
 793                  filterable:         'all',
 794                  autoSelect:         false
 795              })
 796          ]);
 797      },
 798  
 799      /**
 800       * Bind region mode activation events to proper handlers.
 801       */
 802      bindRegionModeHandlers: function() {
 803          this.on( 'content:create:browse', this.browseContent, this );
 804  
 805          // Handle a frame-level event for editing an attachment.
 806          this.on( 'edit:attachment', this.openEditAttachmentModal, this );
 807  
 808          this.on( 'select:activate', this.bindKeydown, this );
 809          this.on( 'select:deactivate', this.unbindKeydown, this );
 810      },
 811  
 812      handleKeydown: function( e ) {
 813          if ( 27 === e.which ) {
 814              e.preventDefault();
 815              this.deactivateMode( 'select' ).activateMode( 'edit' );
 816          }
 817      },
 818  
 819      bindKeydown: function() {
 820          this.$body.on( 'keydown.select', _.bind( this.handleKeydown, this ) );
 821      },
 822  
 823      unbindKeydown: function() {
 824          this.$body.off( 'keydown.select' );
 825      },
 826  
 827      fixPosition: function() {
 828          var $browser, $toolbar;
 829          if ( ! this.isModeActive( 'select' ) ) {
 830              return;
 831          }
 832  
 833          $browser = this.$('.attachments-browser');
 834          $toolbar = $browser.find('.media-toolbar');
 835  
 836          // Offset doesn't appear to take top margin into account, hence +16.
 837          if ( ( $browser.offset().top + 16 ) < this.$window.scrollTop() + this.$adminBar.height() ) {
 838              $browser.addClass( 'fixed' );
 839              $toolbar.css('width', $browser.width() + 'px');
 840          } else {
 841              $browser.removeClass( 'fixed' );
 842              $toolbar.css('width', '');
 843          }
 844      },
 845  
 846      /**
 847       * Click handler for the `Add New` button.
 848       */
 849      addNewClickHandler: function( event ) {
 850          event.preventDefault();
 851          this.trigger( 'toggle:upload:attachment' );
 852  
 853          if ( this.uploader ) {
 854              this.uploader.refresh();
 855          }
 856      },
 857  
 858      /**
 859       * Open the Edit Attachment modal.
 860       */
 861      openEditAttachmentModal: function( model ) {
 862          // Create a new EditAttachment frame, passing along the library and the attachment model.
 863          if ( wp.media.frames.edit ) {
 864              wp.media.frames.edit.open().trigger( 'refresh', model );
 865          } else {
 866              wp.media.frames.edit = wp.media( {
 867                  frame:       'edit-attachments',
 868                  controller:  this,
 869                  library:     this.state().get('library'),
 870                  model:       model
 871              } );
 872          }
 873      },
 874  
 875      /**
 876       * Create an attachments browser view within the content region.
 877       *
 878       * @param {Object} contentRegion Basic object with a `view` property, which
 879       *                               should be set with the proper region view.
 880       * @this wp.media.controller.Region
 881       */
 882      browseContent: function( contentRegion ) {
 883          var state = this.state();
 884  
 885          // Browse our library of attachments.
 886          this.browserView = contentRegion.view = new wp.media.view.AttachmentsBrowser({
 887              controller: this,
 888              collection: state.get('library'),
 889              selection:  state.get('selection'),
 890              model:      state,
 891              sortable:   state.get('sortable'),
 892              search:     state.get('searchable'),
 893              filters:    state.get('filterable'),
 894              date:       state.get('date'),
 895              display:    state.get('displaySettings'),
 896              dragInfo:   state.get('dragInfo'),
 897              sidebar:    'errors',
 898  
 899              suggestedWidth:  state.get('suggestedWidth'),
 900              suggestedHeight: state.get('suggestedHeight'),
 901  
 902              AttachmentView: state.get('AttachmentView'),
 903  
 904              scrollElement: document
 905          });
 906          this.browserView.on( 'ready', _.bind( this.bindDeferred, this ) );
 907  
 908          this.errors = wp.Uploader.errors;
 909          this.errors.on( 'add remove reset', this.sidebarVisibility, this );
 910      },
 911  
 912      sidebarVisibility: function() {
 913          this.browserView.$( '.media-sidebar' ).toggle( !! this.errors.length );
 914      },
 915  
 916      bindDeferred: function() {
 917          if ( ! this.browserView.dfd ) {
 918              return;
 919          }
 920          this.browserView.dfd.done( _.bind( this.startHistory, this ) );
 921      },
 922  
 923      startHistory: function() {
 924          // Verify pushState support and activate.
 925          if ( window.history && window.history.pushState ) {
 926              if ( Backbone.History.started ) {
 927                  Backbone.history.stop();
 928              }
 929              Backbone.history.start( {
 930                  root: window._wpMediaGridSettings.adminUrl,
 931                  pushState: true
 932              } );
 933          }
 934      }
 935  });
 936  
 937  module.exports = Manage;
 938  
 939  
 940  /***/ }),
 941  
 942  /***/ 8521:
 943  /***/ ((module) => {
 944  
 945  var View = wp.media.View,
 946      EditImage = wp.media.view.EditImage,
 947      Details;
 948  
 949  /**
 950   * wp.media.view.EditImage.Details
 951   *
 952   * @memberOf wp.media.view.EditImage
 953   *
 954   * @class
 955   * @augments wp.media.view.EditImage
 956   * @augments wp.media.View
 957   * @augments wp.Backbone.View
 958   * @augments Backbone.View
 959   */
 960  Details = EditImage.extend(/** @lends wp.media.view.EditImage.Details.prototype */{
 961      initialize: function( options ) {
 962          this.editor = window.imageEdit;
 963          this.frame = options.frame;
 964          this.controller = options.controller;
 965          View.prototype.initialize.apply( this, arguments );
 966      },
 967  
 968      back: function() {
 969          this.frame.content.mode( 'edit-metadata' );
 970      },
 971  
 972      save: function() {
 973          this.model.fetch().done( _.bind( function() {
 974              this.frame.content.mode( 'edit-metadata' );
 975          }, this ) );
 976      }
 977  });
 978  
 979  module.exports = Details;
 980  
 981  
 982  /***/ })
 983  
 984  /******/     });
 985  /************************************************************************/
 986  /******/     // The module cache
 987  /******/     var __webpack_module_cache__ = {};
 988  /******/     
 989  /******/     // The require function
 990  /******/ 	function __webpack_require__(moduleId) {
 991  /******/         // Check if module is in cache
 992  /******/         var cachedModule = __webpack_module_cache__[moduleId];
 993  /******/         if (cachedModule !== undefined) {
 994  /******/             return cachedModule.exports;
 995  /******/         }
 996  /******/         // Create a new module (and put it into the cache)
 997  /******/         var module = __webpack_module_cache__[moduleId] = {
 998  /******/             // no module.id needed
 999  /******/             // no module.loaded needed
1000  /******/             exports: {}
1001  /******/         };
1002  /******/     
1003  /******/         // Execute the module function
1004  /******/         __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
1005  /******/     
1006  /******/         // Return the exports of the module
1007  /******/         return module.exports;
1008  /******/     }
1009  /******/     
1010  /************************************************************************/
1011  /**
1012   * @output wp-includes/js/media-grid.js
1013   */
1014  
1015  var media = wp.media;
1016  
1017  media.controller.EditAttachmentMetadata = __webpack_require__( 659 );
1018  media.view.MediaFrame.Manage = __webpack_require__( 8359 );
1019  media.view.Attachment.Details.TwoColumn = __webpack_require__( 1312 );
1020  media.view.MediaFrame.Manage.Router = __webpack_require__( 2429 );
1021  media.view.EditImage.Details = __webpack_require__( 8521 );
1022  media.view.MediaFrame.EditAttachments = __webpack_require__( 1003 );
1023  media.view.SelectModeToggleButton = __webpack_require__( 682 );
1024  media.view.DeleteSelectedButton = __webpack_require__( 6606 );
1025  media.view.DeleteSelectedPermanentlyButton = __webpack_require__( 5806 );
1026  
1027  /******/ })()
1028  ;


Generated : Wed Aug 13 08:20:01 2025 Cross-referenced by PHPXref