[ Index ]

PHP Cross Reference of WordPress

title

Body

[close]

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

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


Generated: Wed Nov 20 01:00:03 2019 Cross-referenced by PHPXref 0.7.1