Ticket #40894: 40894.6.diff
File 40894.6.diff, 530.0 KB (added by , 6 years ago) |
---|
-
.jshintrc
diff --git .jshintrc .jshintrc index 0a082dded5..278eac22c3 100644
21 21 "Backbone": false, 22 22 "jQuery": false, 23 23 "JSON": false, 24 "wp": false 24 "wp": false, 25 "export": false, 26 "module": false, 27 "require": false 25 28 } 26 29 } -
Gruntfile.js
diff --git Gruntfile.js Gruntfile.js index 199f9faa2c..3cf55b2c93 100644
1 1 /* jshint node:true */ 2 var webpackConfig = require( './webpack.config' ); 3 var webpackDevConfig = require( './webpack-dev.config' ); 4 2 5 module.exports = function(grunt) { 3 6 var path = require('path'), 4 7 fs = require( 'fs' ), 5 8 SOURCE_DIR = 'src/', 6 9 BUILD_DIR = 'build/', 7 10 BANNER_TEXT = '/*! This file is auto-generated */', 8 autoprefixer = require('autoprefixer'), 9 mediaConfig = {}, 10 mediaBuilds = ['audiovideo', 'grid', 'models', 'views']; 11 autoprefixer = require( 'autoprefixer' ); 11 12 12 13 // Load tasks. 13 14 require('matchdep').filterDev(['grunt-*', '!grunt-legacy-util']).forEach( grunt.loadNpmTasks ); 14 15 // Load legacy utils 15 16 grunt.util = require('grunt-legacy-util'); 16 17 17 mediaBuilds.forEach( function ( build ) {18 var path = SOURCE_DIR + 'wp-includes/js/media';19 mediaConfig[ build ] = { files : {} };20 mediaConfig[ build ].files[ path + '-' + build + '.js' ] = [ path + '/' + build + '.manifest.js' ];21 } );22 23 18 // Project configuration. 24 19 grunt.initConfig({ 25 20 postcss: { … … module.exports = function(grunt) { 175 170 } 176 171 } 177 172 }, 178 browserify: mediaConfig,179 173 sass: { 180 174 colors: { 181 175 expand: true, … … module.exports = function(grunt) { 336 330 ] 337 331 }, 338 332 media: { 339 options: {340 browserify: true341 },342 333 src: [ 343 334 SOURCE_DIR + 'wp-includes/js/media/**/*.js' 344 335 ] … … module.exports = function(grunt) { 548 539 dest: SOURCE_DIR + 'wp-includes/js/jquery/jquery.masonry.min.js' 549 540 } 550 541 }, 551 542 webpack: { 543 prod: webpackConfig, 544 dev: webpackDevConfig 545 }, 552 546 concat: { 553 547 tinymce: { 554 548 options: { … … module.exports = function(grunt) { 731 725 } 732 726 }, 733 727 config: { 734 files: 'Gruntfile.js' 728 files: [ 729 'Gruntfile.js', 730 'webpack-dev.config.js', 731 'webpack.config.js' 732 ] 735 733 }, 736 734 colors: { 737 735 files: [SOURCE_DIR + 'wp-admin/css/colors/**'], … … module.exports = function(grunt) { 769 767 770 768 // Register tasks. 771 769 770 // Webpack task. 771 grunt.loadNpmTasks( 'grunt-webpack' ); 772 772 773 // RTL task. 773 774 grunt.registerTask('rtl', ['rtlcss:core', 'rtlcss:colors']); 774 775 … … module.exports = function(grunt) { 792 793 grunt.renameTask( 'watch', '_watch' ); 793 794 794 795 grunt.registerTask( 'watch', function() { 795 if ( ! this.args.length || this.args.indexOf( 'browserify' ) > -1 ) { 796 grunt.config( 'browserify.options', { 797 browserifyOptions: { 798 debug: true 799 }, 800 watch: true 801 } ); 796 if ( ! this.args.length || this.args.indexOf( 'webpack' ) > -1 ) { 802 797 803 grunt.task.run( ' browserify' );798 grunt.task.run( 'webpack:dev' ); 804 799 } 805 800 806 801 grunt.task.run( '_' + this.nameArgs ); … … module.exports = function(grunt) { 811 806 ] ); 812 807 813 808 grunt.registerTask( 'precommit:js', [ 814 ' browserify',809 'webpack:prod', 815 810 'jshint:corejs', 816 811 'uglify:masonry', 817 812 'qunit:compiled' … … module.exports = function(grunt) { 879 874 return regex.test( result.stdout ); 880 875 } 881 876 882 if ( [ 'package.json', 'Gruntfile.js' ].some( testPath ) ) {877 if ( [ 'package.json', 'Gruntfile.js', 'webpack.config.js' ].some( testPath ) ) { 883 878 grunt.log.writeln( 'Configuration files modified. Running `prerelease`.' ); 884 879 taskList.push( 'prerelease' ); 885 880 } else { … … module.exports = function(grunt) { 977 972 grunt.event.on('watch', function( action, filepath, target ) { 978 973 var src; 979 974 980 if ( [ 'all', 'rtl', ' browserify' ].indexOf( target ) === -1 ) {975 if ( [ 'all', 'rtl', 'webpack' ].indexOf( target ) === -1 ) { 981 976 return; 982 977 } 983 978 -
package.json
diff --git package.json package.json index 71695dfb77..4e1655c099 100644
15 15 "autoprefixer": "^6.5.1", 16 16 "grunt": "~0.4.5", 17 17 "grunt-banner": "^0.6.0", 18 "grunt-browserify": "~5.0.0",19 18 "grunt-contrib-clean": "~1.0.0", 20 19 "grunt-contrib-compress": "~1.3.0", 21 20 "grunt-contrib-concat": "~1.0.0", … … 36 35 "grunt-rtlcss": "~2.0.1", 37 36 "grunt-sass": "~1.2.1", 38 37 "ink-docstrap": "^1.3.0", 39 "matchdep": "~1.0.0" 38 "grunt-webpack": "^3.0.2", 39 "matchdep": "~1.0.0", 40 "webpack": "^3.5.4", 41 "webpack-dev-server": "^2.7.1" 40 42 } 41 43 } -
deleted file src/wp-content/plugins/hello.php
diff --git src/wp-content/plugins/hello.php src/wp-content/plugins/hello.php deleted file mode 100644 index 2b1e07b59e..0000000000
+ - 1 <?php2 /**3 * @package Hello_Dolly4 * @version 1.65 */6 /*7 Plugin Name: Hello Dolly8 Plugin URI: http://wordpress.org/plugins/hello-dolly/9 Description: This is not just a plugin, it symbolizes the hope and enthusiasm of an entire generation summed up in two words sung most famously by Louis Armstrong: Hello, Dolly. When activated you will randomly see a lyric from <cite>Hello, Dolly</cite> in the upper right of your admin screen on every page.10 Author: Matt Mullenweg11 Version: 1.612 Author URI: http://ma.tt/13 */14 15 function hello_dolly_get_lyric() {16 /** These are the lyrics to Hello Dolly */17 $lyrics = "Hello, Dolly18 Well, hello, Dolly19 It's so nice to have you back where you belong20 You're lookin' swell, Dolly21 I can tell, Dolly22 You're still glowin', you're still crowin'23 You're still goin' strong24 We feel the room swayin'25 While the band's playin'26 One of your old favourite songs from way back when27 So, take her wrap, fellas28 Find her an empty lap, fellas29 Dolly'll never go away again30 Hello, Dolly31 Well, hello, Dolly32 It's so nice to have you back where you belong33 You're lookin' swell, Dolly34 I can tell, Dolly35 You're still glowin', you're still crowin'36 You're still goin' strong37 We feel the room swayin'38 While the band's playin'39 One of your old favourite songs from way back when40 Golly, gee, fellas41 Find her a vacant knee, fellas42 Dolly'll never go away43 Dolly'll never go away44 Dolly'll never go away again";45 46 // Here we split it into lines47 $lyrics = explode( "\n", $lyrics );48 49 // And then randomly choose a line50 return wptexturize( $lyrics[ mt_rand( 0, count( $lyrics ) - 1 ) ] );51 }52 53 // This just echoes the chosen line, we'll position it later54 function hello_dolly() {55 $chosen = hello_dolly_get_lyric();56 echo "<p id='dolly'>$chosen</p>";57 }58 59 // Now we set that function up to execute when the admin_notices action is called60 add_action( 'admin_notices', 'hello_dolly' );61 62 // We need some CSS to position the paragraph63 function dolly_css() {64 // This makes sure that the positioning is also good for right-to-left languages65 $x = is_rtl() ? 'left' : 'right';66 67 echo "68 <style type='text/css'>69 #dolly {70 float: $x;71 padding-$x: 15px;72 padding-top: 5px;73 margin: 0;74 font-size: 11px;75 }76 </style>77 ";78 }79 80 add_action( 'admin_head', 'dolly_css' );81 82 ?> -
deleted file src/wp-content/plugins/index.php
diff --git src/wp-content/plugins/index.php src/wp-content/plugins/index.php deleted file mode 100644 index 62200328fd..0000000000
+ - 1 <?php2 // Silence is golden. -
src/wp-includes/js/media-audiovideo.js
diff --git src/wp-includes/js/media-audiovideo.js src/wp-includes/js/media-audiovideo.js index 0a819747d2..cb2abd57ae 100644
1 (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ 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, { 40 /******/ configurable: false, 41 /******/ enumerable: true, 42 /******/ get: getter 43 /******/ }); 44 /******/ } 45 /******/ }; 46 /******/ 47 /******/ // getDefaultExport function for compatibility with non-harmony modules 48 /******/ __webpack_require__.n = function(module) { 49 /******/ var getter = module && module.__esModule ? 50 /******/ function getDefault() { return module['default']; } : 51 /******/ function getModuleExports() { return module; }; 52 /******/ __webpack_require__.d(getter, 'a', getter); 53 /******/ return getter; 54 /******/ }; 55 /******/ 56 /******/ // Object.prototype.hasOwnProperty.call 57 /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 58 /******/ 59 /******/ // __webpack_public_path__ 60 /******/ __webpack_require__.p = ""; 61 /******/ 62 /******/ // Load entry module and return exports 63 /******/ return __webpack_require__(__webpack_require__.s = 0); 64 /******/ }) 65 /************************************************************************/ 66 /******/ ([ 67 /* 0 */ 68 /***/ (function(module, exports, __webpack_require__) { 69 2 70 var media = wp.media, 3 71 baseSettings = window._wpmejsSettings || {}, 4 72 l10n = window._wpMediaViewsL10n || {}; … … wp.media.video = { 268 336 } 269 337 }; 270 338 271 media.model.PostMedia = require( './models/post-media.js' ); 272 media.controller.AudioDetails = require( './controllers/audio-details.js' ); 273 media.controller.VideoDetails = require( './controllers/video-details.js' ); 274 media.view.MediaFrame.MediaDetails = require( './views/frame/media-details.js' ); 275 media.view.MediaFrame.AudioDetails = require( './views/frame/audio-details.js' ); 276 media.view.MediaFrame.VideoDetails = require( './views/frame/video-details.js' ); 277 media.view.MediaDetails = require( './views/media-details.js' ); 278 media.view.AudioDetails = require( './views/audio-details.js' ); 279 media.view.VideoDetails = require( './views/video-details.js' ); 280 281 },{"./controllers/audio-details.js":2,"./controllers/video-details.js":3,"./models/post-media.js":4,"./views/audio-details.js":5,"./views/frame/audio-details.js":6,"./views/frame/media-details.js":7,"./views/frame/video-details.js":8,"./views/media-details.js":9,"./views/video-details.js":10}],2:[function(require,module,exports){ 282 var State = wp.media.controller.State, 283 l10n = wp.media.view.l10n, 284 AudioDetails; 285 286 /** 287 * wp.media.controller.AudioDetails 288 * 289 * The controller for the Audio Details state 290 * 291 * @memberOf wp.media.controller 292 * 293 * @class 294 * @augments wp.media.controller.State 295 * @augments Backbone.Model 296 */ 297 AudioDetails = State.extend(/** @lends wp.media.controller.AudioDetails.prototype */{ 298 defaults: { 299 id: 'audio-details', 300 toolbar: 'audio-details', 301 title: l10n.audioDetailsTitle, 302 content: 'audio-details', 303 menu: 'audio-details', 304 router: false, 305 priority: 60 306 }, 307 308 initialize: function( options ) { 309 this.media = options.media; 310 State.prototype.initialize.apply( this, arguments ); 311 } 312 }); 313 314 module.exports = AudioDetails; 315 316 },{}],3:[function(require,module,exports){ 317 /** 318 * wp.media.controller.VideoDetails 319 * 320 * The controller for the Video Details state 321 * 322 * @memberOf wp.media.controller 323 * 324 * @class 325 * @augments wp.media.controller.State 326 * @augments Backbone.Model 327 */ 328 var State = wp.media.controller.State, 329 l10n = wp.media.view.l10n, 330 VideoDetails; 331 332 VideoDetails = State.extend(/** @lends wp.media.controller.VideoDetails.prototype */{ 333 defaults: { 334 id: 'video-details', 335 toolbar: 'video-details', 336 title: l10n.videoDetailsTitle, 337 content: 'video-details', 338 menu: 'video-details', 339 router: false, 340 priority: 60 341 }, 339 media.model.PostMedia = __webpack_require__( 1 ); 340 media.controller.AudioDetails = __webpack_require__( 2 ); 341 media.controller.VideoDetails = __webpack_require__( 3 ); 342 media.view.MediaFrame.MediaDetails = __webpack_require__( 4 ); 343 media.view.MediaFrame.AudioDetails = __webpack_require__( 5 ); 344 media.view.MediaFrame.VideoDetails = __webpack_require__( 6 ); 345 media.view.MediaDetails = __webpack_require__( 7 ); 346 media.view.AudioDetails = __webpack_require__( 8 ); 347 media.view.VideoDetails = __webpack_require__( 9 ); 342 348 343 initialize: function( options ) {344 this.media = options.media;345 State.prototype.initialize.apply( this, arguments );346 }347 });348 349 349 module.exports = VideoDetails; 350 /***/ }), 351 /* 1 */ 352 /***/ (function(module, exports) { 350 353 351 },{}],4:[function(require,module,exports){352 354 /** 353 355 * wp.media.model.PostMedia 354 356 * … … var PostMedia = Backbone.Model.extend(/** @lends wp.media.model.PostMedia.protot 392 394 393 395 module.exports = PostMedia; 394 396 395 },{}],5:[function(require,module,exports){ 396 var MediaDetails = wp.media.view.MediaDetails, 397 398 /***/ }), 399 /* 2 */ 400 /***/ (function(module, exports) { 401 402 var State = wp.media.controller.State, 403 l10n = wp.media.view.l10n, 397 404 AudioDetails; 398 405 399 406 /** 400 * wp.media. view.AudioDetails407 * wp.media.controller.AudioDetails 401 408 * 402 * @memberOf wp.media.view 409 * The controller for the Audio Details state 410 * 411 * @memberOf wp.media.controller 403 412 * 404 413 * @class 405 * @augments wp.media.view.MediaDetails 406 * @augments wp.media.view.Settings.AttachmentDisplay 407 * @augments wp.media.view.Settings 408 * @augments wp.media.View 409 * @augments wp.Backbone.View 410 * @augments Backbone.View 414 * @augments wp.media.controller.State 415 * @augments Backbone.Model 411 416 */ 412 AudioDetails = MediaDetails.extend(/** @lends wp.media.view.AudioDetails.prototype */{ 413 className: 'audio-details', 414 template: wp.template('audio-details'), 415 416 setMedia: function() { 417 var audio = this.$('.wp-audio-shortcode'); 418 419 if ( audio.find( 'source' ).length ) { 420 if ( audio.is(':hidden') ) { 421 audio.show(); 422 } 423 this.media = MediaDetails.prepareSrc( audio.get(0) ); 424 } else { 425 audio.hide(); 426 this.media = false; 427 } 417 AudioDetails = State.extend(/** @lends wp.media.controller.AudioDetails.prototype */{ 418 defaults: { 419 id: 'audio-details', 420 toolbar: 'audio-details', 421 title: l10n.audioDetailsTitle, 422 content: 'audio-details', 423 menu: 'audio-details', 424 router: false, 425 priority: 60 426 }, 428 427 429 return this; 428 initialize: function( options ) { 429 this.media = options.media; 430 State.prototype.initialize.apply( this, arguments ); 430 431 } 431 432 }); 432 433 433 434 module.exports = AudioDetails; 434 435 435 },{}],6:[function(require,module,exports){436 var MediaDetails = wp.media.view.MediaFrame.MediaDetails,437 MediaLibrary = wp.media.controller.MediaLibrary,438 436 439 l10n = wp.media.view.l10n, 440 AudioDetails; 437 /***/ }), 438 /* 3 */ 439 /***/ (function(module, exports) { 441 440 442 441 /** 443 * wp.media. view.MediaFrame.AudioDetails442 * wp.media.controller.VideoDetails 444 443 * 445 * @memberOf wp.media.view.MediaFrame 444 * The controller for the Video Details state 445 * 446 * @memberOf wp.media.controller 446 447 * 447 448 * @class 448 * @augments wp.media.view.MediaFrame.MediaDetails 449 * @augments wp.media.view.MediaFrame.Select 450 * @augments wp.media.view.MediaFrame 451 * @augments wp.media.view.Frame 452 * @augments wp.media.View 453 * @augments wp.Backbone.View 454 * @augments Backbone.View 455 * @mixes wp.media.controller.StateMachine 449 * @augments wp.media.controller.State 450 * @augments Backbone.Model 456 451 */ 457 AudioDetails = MediaDetails.extend(/** @lends wp.media.view.MediaFrame.AudioDetails.prototype */{ 452 var State = wp.media.controller.State, 453 l10n = wp.media.view.l10n, 454 VideoDetails; 455 456 VideoDetails = State.extend(/** @lends wp.media.controller.VideoDetails.prototype */{ 458 457 defaults: { 459 id: 'audio', 460 url: '', 461 menu: 'audio-details', 462 content: 'audio-details', 463 toolbar: 'audio-details', 464 type: 'link', 465 title: l10n.audioDetailsTitle, 466 priority: 120 458 id: 'video-details', 459 toolbar: 'video-details', 460 title: l10n.videoDetailsTitle, 461 content: 'video-details', 462 menu: 'video-details', 463 router: false, 464 priority: 60 467 465 }, 468 466 469 467 initialize: function( options ) { 470 options.DetailsView = wp.media.view.AudioDetails; 471 options.cancelText = l10n.audioDetailsCancel; 472 options.addText = l10n.audioAddSourceTitle; 473 474 MediaDetails.prototype.initialize.call( this, options ); 475 }, 476 477 bindHandlers: function() { 478 MediaDetails.prototype.bindHandlers.apply( this, arguments ); 479 480 this.on( 'toolbar:render:replace-audio', this.renderReplaceToolbar, this ); 481 this.on( 'toolbar:render:add-audio-source', this.renderAddSourceToolbar, this ); 482 }, 483 484 createStates: function() { 485 this.states.add([ 486 new wp.media.controller.AudioDetails( { 487 media: this.media 488 } ), 489 490 new MediaLibrary( { 491 type: 'audio', 492 id: 'replace-audio', 493 title: l10n.audioReplaceTitle, 494 toolbar: 'replace-audio', 495 media: this.media, 496 menu: 'audio-details' 497 } ), 498 499 new MediaLibrary( { 500 type: 'audio', 501 id: 'add-audio-source', 502 title: l10n.audioAddSourceTitle, 503 toolbar: 'add-audio-source', 504 media: this.media, 505 menu: false 506 } ) 507 ]); 468 this.media = options.media; 469 State.prototype.initialize.apply( this, arguments ); 508 470 } 509 471 }); 510 472 511 module.exports = AudioDetails; 473 module.exports = VideoDetails; 474 475 476 /***/ }), 477 /* 4 */ 478 /***/ (function(module, exports) { 512 479 513 },{}],7:[function(require,module,exports){514 480 var Select = wp.media.view.MediaFrame.Select, 515 481 l10n = wp.media.view.l10n, 516 482 MediaDetails; … … MediaDetails = Select.extend(/** @lends wp.media.view.MediaFrame.MediaDetails.pr 642 608 643 609 module.exports = MediaDetails; 644 610 645 },{}],8:[function(require,module,exports){ 611 612 /***/ }), 613 /* 5 */ 614 /***/ (function(module, exports) { 615 616 var MediaDetails = wp.media.view.MediaFrame.MediaDetails, 617 MediaLibrary = wp.media.controller.MediaLibrary, 618 619 l10n = wp.media.view.l10n, 620 AudioDetails; 621 622 /** 623 * wp.media.view.MediaFrame.AudioDetails 624 * 625 * @memberOf wp.media.view.MediaFrame 626 * 627 * @class 628 * @augments wp.media.view.MediaFrame.MediaDetails 629 * @augments wp.media.view.MediaFrame.Select 630 * @augments wp.media.view.MediaFrame 631 * @augments wp.media.view.Frame 632 * @augments wp.media.View 633 * @augments wp.Backbone.View 634 * @augments Backbone.View 635 * @mixes wp.media.controller.StateMachine 636 */ 637 AudioDetails = MediaDetails.extend(/** @lends wp.media.view.MediaFrame.AudioDetails.prototype */{ 638 defaults: { 639 id: 'audio', 640 url: '', 641 menu: 'audio-details', 642 content: 'audio-details', 643 toolbar: 'audio-details', 644 type: 'link', 645 title: l10n.audioDetailsTitle, 646 priority: 120 647 }, 648 649 initialize: function( options ) { 650 options.DetailsView = wp.media.view.AudioDetails; 651 options.cancelText = l10n.audioDetailsCancel; 652 options.addText = l10n.audioAddSourceTitle; 653 654 MediaDetails.prototype.initialize.call( this, options ); 655 }, 656 657 bindHandlers: function() { 658 MediaDetails.prototype.bindHandlers.apply( this, arguments ); 659 660 this.on( 'toolbar:render:replace-audio', this.renderReplaceToolbar, this ); 661 this.on( 'toolbar:render:add-audio-source', this.renderAddSourceToolbar, this ); 662 }, 663 664 createStates: function() { 665 this.states.add([ 666 new wp.media.controller.AudioDetails( { 667 media: this.media 668 } ), 669 670 new MediaLibrary( { 671 type: 'audio', 672 id: 'replace-audio', 673 title: l10n.audioReplaceTitle, 674 toolbar: 'replace-audio', 675 media: this.media, 676 menu: 'audio-details' 677 } ), 678 679 new MediaLibrary( { 680 type: 'audio', 681 id: 'add-audio-source', 682 title: l10n.audioAddSourceTitle, 683 toolbar: 'add-audio-source', 684 media: this.media, 685 menu: false 686 } ) 687 ]); 688 } 689 }); 690 691 module.exports = AudioDetails; 692 693 694 /***/ }), 695 /* 6 */ 696 /***/ (function(module, exports) { 697 646 698 var MediaDetails = wp.media.view.MediaFrame.MediaDetails, 647 699 MediaLibrary = wp.media.controller.MediaLibrary, 648 700 l10n = wp.media.view.l10n, … … VideoDetails = MediaDetails.extend(/** @lends wp.media.view.MediaFrame.VideoDeta 779 831 780 832 module.exports = VideoDetails; 781 833 782 },{}],9:[function(require,module,exports){ 834 835 /***/ }), 836 /* 7 */ 837 /***/ (function(module, exports) { 838 783 839 /* global MediaElementPlayer */ 784 840 var AttachmentDisplay = wp.media.view.Settings.AttachmentDisplay, 785 841 $ = jQuery, … … MediaDetails = AttachmentDisplay.extend(/** @lends wp.media.view.MediaDetails.pr 949 1005 950 1006 module.exports = MediaDetails; 951 1007 952 },{}],10:[function(require,module,exports){ 1008 1009 /***/ }), 1010 /* 8 */ 1011 /***/ (function(module, exports) { 1012 1013 var MediaDetails = wp.media.view.MediaDetails, 1014 AudioDetails; 1015 1016 /** 1017 * wp.media.view.AudioDetails 1018 * 1019 * @memberOf wp.media.view 1020 * 1021 * @class 1022 * @augments wp.media.view.MediaDetails 1023 * @augments wp.media.view.Settings.AttachmentDisplay 1024 * @augments wp.media.view.Settings 1025 * @augments wp.media.View 1026 * @augments wp.Backbone.View 1027 * @augments Backbone.View 1028 */ 1029 AudioDetails = MediaDetails.extend(/** @lends wp.media.view.AudioDetails.prototype */{ 1030 className: 'audio-details', 1031 template: wp.template('audio-details'), 1032 1033 setMedia: function() { 1034 var audio = this.$('.wp-audio-shortcode'); 1035 1036 if ( audio.find( 'source' ).length ) { 1037 if ( audio.is(':hidden') ) { 1038 audio.show(); 1039 } 1040 this.media = MediaDetails.prepareSrc( audio.get(0) ); 1041 } else { 1042 audio.hide(); 1043 this.media = false; 1044 } 1045 1046 return this; 1047 } 1048 }); 1049 1050 module.exports = AudioDetails; 1051 1052 1053 /***/ }), 1054 /* 9 */ 1055 /***/ (function(module, exports) { 1056 953 1057 var MediaDetails = wp.media.view.MediaDetails, 954 1058 VideoDetails; 955 1059 … … VideoDetails = MediaDetails.extend(/** @lends wp.media.view.VideoDetails.prototy 994 1098 995 1099 module.exports = VideoDetails; 996 1100 997 },{}]},{},[1]); 1101 1102 /***/ }) 1103 /******/ ]); 1104 No newline at end of file -
src/wp-includes/js/media-grid.js
diff --git src/wp-includes/js/media-grid.js src/wp-includes/js/media-grid.js index 6e35fb52a6..c9babd6d50 100644
1 (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ 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, { 40 /******/ configurable: false, 41 /******/ enumerable: true, 42 /******/ get: getter 43 /******/ }); 44 /******/ } 45 /******/ }; 46 /******/ 47 /******/ // getDefaultExport function for compatibility with non-harmony modules 48 /******/ __webpack_require__.n = function(module) { 49 /******/ var getter = module && module.__esModule ? 50 /******/ function getDefault() { return module['default']; } : 51 /******/ function getModuleExports() { return module; }; 52 /******/ __webpack_require__.d(getter, 'a', getter); 53 /******/ return getter; 54 /******/ }; 55 /******/ 56 /******/ // Object.prototype.hasOwnProperty.call 57 /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 58 /******/ 59 /******/ // __webpack_public_path__ 60 /******/ __webpack_require__.p = ""; 61 /******/ 62 /******/ // Load entry module and return exports 63 /******/ return __webpack_require__(__webpack_require__.s = 10); 64 /******/ }) 65 /************************************************************************/ 66 /******/ ([ 67 /* 0 */, 68 /* 1 */, 69 /* 2 */, 70 /* 3 */, 71 /* 4 */, 72 /* 5 */, 73 /* 6 */, 74 /* 7 */, 75 /* 8 */, 76 /* 9 */, 77 /* 10 */ 78 /***/ (function(module, exports, __webpack_require__) { 79 80 var media = wp.media; 81 82 media.controller.EditAttachmentMetadata = __webpack_require__( 11 ); 83 media.view.MediaFrame.Manage = __webpack_require__( 12 ); 84 media.view.Attachment.Details.TwoColumn = __webpack_require__( 13 ); 85 media.view.MediaFrame.Manage.Router = __webpack_require__( 14 ); 86 media.view.EditImage.Details = __webpack_require__( 15 ); 87 media.view.MediaFrame.EditAttachments = __webpack_require__( 16 ); 88 media.view.SelectModeToggleButton = __webpack_require__( 17 ); 89 media.view.DeleteSelectedButton = __webpack_require__( 18 ); 90 media.view.DeleteSelectedPermanentlyButton = __webpack_require__( 19 ); 91 92 93 /***/ }), 94 /* 11 */ 95 /***/ (function(module, exports) { 96 2 97 var l10n = wp.media.view.l10n, 3 98 EditAttachmentMetadata; 4 99 … … EditAttachmentMetadata = wp.media.controller.State.extend(/** @lends wp.media.co 28 123 29 124 module.exports = EditAttachmentMetadata; 30 125 31 },{}],2:[function(require,module,exports){32 var media = wp.media;33 126 34 media.controller.EditAttachmentMetadata = require( './controllers/edit-attachment-metadata.js' ); 35 media.view.MediaFrame.Manage = require( './views/frame/manage.js' ); 36 media.view.Attachment.Details.TwoColumn = require( './views/attachment/details-two-column.js' ); 37 media.view.MediaFrame.Manage.Router = require( './routers/manage.js' ); 38 media.view.EditImage.Details = require( './views/edit-image-details.js' ); 39 media.view.MediaFrame.EditAttachments = require( './views/frame/edit-attachments.js' ); 40 media.view.SelectModeToggleButton = require( './views/button/select-mode-toggle.js' ); 41 media.view.DeleteSelectedButton = require( './views/button/delete-selected.js' ); 42 media.view.DeleteSelectedPermanentlyButton = require( './views/button/delete-selected-permanently.js' ); 43 44 },{"./controllers/edit-attachment-metadata.js":1,"./routers/manage.js":3,"./views/attachment/details-two-column.js":4,"./views/button/delete-selected-permanently.js":5,"./views/button/delete-selected.js":6,"./views/button/select-mode-toggle.js":7,"./views/edit-image-details.js":8,"./views/frame/edit-attachments.js":9,"./views/frame/manage.js":10}],3:[function(require,module,exports){ 127 /***/ }), 128 /* 12 */ 129 /***/ (function(module, exports) { 130 131 var MediaFrame = wp.media.view.MediaFrame, 132 Library = wp.media.controller.Library, 133 134 $ = Backbone.$, 135 Manage; 136 45 137 /** 46 * wp.media.view.MediaFrame.Manage .Router138 * wp.media.view.MediaFrame.Manage 47 139 * 48 * A router for handling the browser history and application state.140 * A generic management frame workflow. 49 141 * 50 * @memberOf wp.media.view.MediaFrame.Manage 142 * Used in the media grid view. 143 * 144 * @memberOf wp.media.view.MediaFrame 51 145 * 52 146 * @class 53 * @augments Backbone.Router 147 * @augments wp.media.view.MediaFrame 148 * @augments wp.media.view.Frame 149 * @augments wp.media.View 150 * @augments wp.Backbone.View 151 * @augments Backbone.View 152 * @mixes wp.media.controller.StateMachine 54 153 */ 55 var Router = Backbone.Router.extend(/** @lends wp.media.view.MediaFrame.Manage.Router.prototype */{ 56 routes: { 57 'upload.php?item=:slug&mode=edit': 'editItem', 58 'upload.php?item=:slug': 'showItem', 59 'upload.php?search=:query': 'search', 60 'upload.php': 'reset' 61 }, 154 Manage = MediaFrame.extend(/** @lends wp.media.view.MediaFrame.Manage.prototype */{ 155 /** 156 * @constructs 157 */ 158 initialize: function() { 159 _.defaults( this.options, { 160 title: '', 161 modal: false, 162 selection: [], 163 library: {}, // Options hash for the query to the media library. 164 multiple: 'add', 165 state: 'library', 166 uploader: true, 167 mode: [ 'grid', 'edit' ] 168 }); 62 169 63 // Map routes against the page URL 64 baseUrl: function( url ) { 65 return 'upload.php' + url; 66 }, 170 this.$body = $( document.body ); 171 this.$window = $( window ); 172 this.$adminBar = $( '#wpadminbar' ); 173 // Store the Add New button for later reuse in wp.media.view.UploaderInline. 174 this.$uploaderToggler = $( '.page-title-action' ) 175 .attr( 'aria-expanded', 'false' ) 176 .on( 'click', _.bind( this.addNewClickHandler, this ) ); 67 177 68 reset: function() { 69 var frame = wp.media.frames.edit; 178 this.$window.on( 'scroll resize', _.debounce( _.bind( this.fixPosition, this ), 15 ) ); 70 179 71 if ( frame ) { 72 frame.close(); 180 // Ensure core and media grid view UI is enabled. 181 this.$el.addClass('wp-core-ui'); 182 183 // Force the uploader off if the upload limit has been exceeded or 184 // if the browser isn't supported. 185 if ( wp.Uploader.limitExceeded || ! wp.Uploader.browser.supported ) { 186 this.options.uploader = false; 73 187 } 74 },75 188 76 // Respond to the search route by filling the search field and trigggering the input event 77 search: function( query ) { 78 jQuery( '#media-search-input' ).val( query ).trigger( 'input' ); 79 }, 189 // Initialize a window-wide uploader. 190 if ( this.options.uploader ) { 191 this.uploader = new wp.media.view.UploaderWindow({ 192 controller: this, 193 uploader: { 194 dropzone: document.body, 195 container: document.body 196 } 197 }).render(); 198 this.uploader.ready(); 199 $('body').append( this.uploader.el ); 80 200 81 // Show the modal with a specific item 82 showItem: function( query ) { 83 var media = wp.media, 84 frame = media.frames.browse, 85 library = frame.state().get('library'), 86 item; 201 this.options.uploader = false; 202 } 87 203 88 // Trigger the media frame to open the correct item 89 item = library.findWhere( { id: parseInt( query, 10 ) } ); 90 item.set( 'skipHistory', true ); 204 this.gridRouter = new wp.media.view.MediaFrame.Manage.Router(); 91 205 92 if ( item ) { 93 frame.trigger( 'edit:attachment', item ); 94 } else { 95 item = media.attachment( query ); 96 frame.listenTo( item, 'change', function( model ) { 97 frame.stopListening( item ); 98 frame.trigger( 'edit:attachment', model ); 99 } ); 100 item.fetch(); 101 } 102 }, 206 // Call 'initialize' directly on the parent class. 207 MediaFrame.prototype.initialize.apply( this, arguments ); 103 208 104 // Show the modal in edit mode with a specific item. 105 editItem: function( query ) { 106 this.showItem( query ); 107 wp.media.frames.edit.content.mode( 'edit-details' ); 108 } 109 }); 209 // Append the frame view directly the supplied container. 210 this.$el.appendTo( this.options.container ); 110 211 111 module.exports = Router; 212 this.createStates(); 213 this.bindRegionModeHandlers(); 214 this.render(); 215 this.bindSearchHandler(); 112 216 113 },{}],4:[function(require,module,exports){ 114 var Details = wp.media.view.Attachment.Details, 115 TwoColumn; 217 wp.media.frames.browse = this; 218 }, 116 219 117 /** 118 * wp.media.view.Attachment.Details.TwoColumn 119 * 120 * A similar view to media.view.Attachment.Details 121 * for use in the Edit Attachment modal. 122 * 123 * @memberOf wp.media.view.Attachment.Details 124 * 125 * @class 126 * @augments wp.media.view.Attachment.Details 127 * @augments wp.media.view.Attachment 128 * @augments wp.media.View 129 * @augments wp.Backbone.View 130 * @augments Backbone.View 131 */ 132 TwoColumn = Details.extend(/** @lends wp.media.view.Attachment.Details.TowColumn.prototype */{ 133 template: wp.template( 'attachment-details-two-column' ), 220 bindSearchHandler: function() { 221 var search = this.$( '#media-search-input' ), 222 searchView = this.browserView.toolbar.get( 'search' ).$el, 223 listMode = this.$( '.view-list' ), 134 224 135 initialize: function() { 136 this.controller.on( 'content:activate:edit-details', _.bind( this.editAttachment, this ) ); 225 input = _.throttle( function (e) { 226 var val = $( e.currentTarget ).val(), 227 url = ''; 137 228 138 Details.prototype.initialize.apply( this, arguments ); 139 }, 229 if ( val ) { 230 url += '?search=' + val; 231 this.gridRouter.navigate( this.gridRouter.baseUrl( url ), { replace: true } ); 232 } 233 }, 1000 ); 140 234 141 editAttachment: function( event ) { 142 if ( event ) { 143 event.preventDefault(); 144 } 145 this.controller.content.mode( 'edit-image' ); 235 // Update the URL when entering search string (at most once per second) 236 search.on( 'input', _.bind( input, this ) ); 237 238 this.gridRouter 239 .on( 'route:search', function () { 240 var href = window.location.href; 241 if ( href.indexOf( 'mode=' ) > -1 ) { 242 href = href.replace( /mode=[^&]+/g, 'mode=list' ); 243 } else { 244 href += href.indexOf( '?' ) > -1 ? '&mode=list' : '?mode=list'; 245 } 246 href = href.replace( 'search=', 's=' ); 247 listMode.prop( 'href', href ); 248 }) 249 .on( 'route:reset', function() { 250 searchView.val( '' ).trigger( 'input' ); 251 }); 146 252 }, 147 253 148 254 /** 149 * Noop this from parent class, doesn't apply here.255 * Create the default states for the frame. 150 256 */ 151 toggleSelectionHandler: function() {}, 152 153 render: function() { 154 Details.prototype.render.apply( this, arguments ); 257 createStates: function() { 258 var options = this.options; 155 259 156 wp.media.mixin.removeAllPlayers(); 157 this.$( 'audio, video' ).each( function (i, elem) { 158 var el = wp.media.view.MediaDetails.prepareSrc( elem ); 159 new window.MediaElementPlayer( el, wp.media.mixin.mejsSettings ); 160 } ); 161 } 162 }); 260 if ( this.options.states ) { 261 return; 262 } 163 263 164 module.exports = TwoColumn; 264 // Add the default states. 265 this.states.add([ 266 new Library({ 267 library: wp.media.query( options.library ), 268 multiple: options.multiple, 269 title: options.title, 270 content: 'browse', 271 toolbar: 'select', 272 contentUserSetting: false, 273 filterable: 'all', 274 autoSelect: false 275 }) 276 ]); 277 }, 165 278 166 },{}],5:[function(require,module,exports){ 167 var Button = wp.media.view.Button, 168 DeleteSelected = wp.media.view.DeleteSelectedButton, 169 DeleteSelectedPermanently; 279 /** 280 * Bind region mode activation events to proper handlers. 281 */ 282 bindRegionModeHandlers: function() { 283 this.on( 'content:create:browse', this.browseContent, this ); 170 284 171 /** 172 * wp.media.view.DeleteSelectedPermanentlyButton 173 * 174 * When MEDIA_TRASH is true, a button that handles bulk Delete Permanently logic 175 * 176 * @memberOf wp.media.view 177 * 178 * @class 179 * @augments wp.media.view.DeleteSelectedButton 180 * @augments wp.media.view.Button 181 * @augments wp.media.View 182 * @augments wp.Backbone.View 183 * @augments Backbone.View 184 */ 185 DeleteSelectedPermanently = DeleteSelected.extend(/** @lends wp.media.view.DeleteSelectedPermanentlyButton.prototype */{ 186 initialize: function() { 187 DeleteSelected.prototype.initialize.apply( this, arguments ); 188 this.controller.on( 'select:activate', this.selectActivate, this ); 189 this.controller.on( 'select:deactivate', this.selectDeactivate, this ); 190 }, 285 // Handle a frame-level event for editing an attachment. 286 this.on( 'edit:attachment', this.openEditAttachmentModal, this ); 191 287 192 filterChange: function( model ) {193 this. canShow = ( 'trash' === model.get( 'status' ));288 this.on( 'select:activate', this.bindKeydown, this ); 289 this.on( 'select:deactivate', this.unbindKeydown, this ); 194 290 }, 195 291 196 selectActivate: function() { 197 this.toggleDisabled(); 198 this.$el.toggleClass( 'hidden', ! this.canShow ); 292 handleKeydown: function( e ) { 293 if ( 27 === e.which ) { 294 e.preventDefault(); 295 this.deactivateMode( 'select' ).activateMode( 'edit' ); 296 } 199 297 }, 200 298 201 selectDeactivate: function() { 202 this.toggleDisabled(); 203 this.$el.addClass( 'hidden' ); 299 bindKeydown: function() { 300 this.$body.on( 'keydown.select', _.bind( this.handleKeydown, this ) ); 204 301 }, 205 302 206 render: function() { 207 Button.prototype.render.apply( this, arguments ); 208 this.selectActivate(); 209 return this; 210 } 211 }); 303 unbindKeydown: function() { 304 this.$body.off( 'keydown.select' ); 305 }, 212 306 213 module.exports = DeleteSelectedPermanently; 307 fixPosition: function() { 308 var $browser, $toolbar; 309 if ( ! this.isModeActive( 'select' ) ) { 310 return; 311 } 214 312 215 },{}],6:[function(require,module,exports){ 216 var Button = wp.media.view.Button, 217 l10n = wp.media.view.l10n, 218 DeleteSelected; 313 $browser = this.$('.attachments-browser'); 314 $toolbar = $browser.find('.media-toolbar'); 219 315 220 /** 221 * wp.media.view.DeleteSelectedButton 222 * 223 * A button that handles bulk Delete/Trash logic 224 * 225 * @memberOf wp.media.view 226 * 227 * @class 228 * @augments wp.media.view.Button 229 * @augments wp.media.View 230 * @augments wp.Backbone.View 231 * @augments Backbone.View 232 */ 233 DeleteSelected = Button.extend(/** @lends wp.media.view.DeleteSelectedButton.prototype */{ 234 initialize: function() { 235 Button.prototype.initialize.apply( this, arguments ); 236 if ( this.options.filters ) { 237 this.options.filters.model.on( 'change', this.filterChange, this ); 316 // Offset doesn't appear to take top margin into account, hence +16 317 if ( ( $browser.offset().top + 16 ) < this.$window.scrollTop() + this.$adminBar.height() ) { 318 $browser.addClass( 'fixed' ); 319 $toolbar.css('width', $browser.width() + 'px'); 320 } else { 321 $browser.removeClass( 'fixed' ); 322 $toolbar.css('width', ''); 238 323 } 239 this.controller.on( 'selection:toggle', this.toggleDisabled, this );240 324 }, 241 325 242 filterChange: function( model ) { 243 if ( 'trash' === model.get( 'status' ) ) { 244 this.model.set( 'text', l10n.untrashSelected ); 245 } else if ( wp.media.view.settings.mediaTrash ) { 246 this.model.set( 'text', l10n.trashSelected ); 326 /** 327 * Click handler for the `Add New` button. 328 */ 329 addNewClickHandler: function( event ) { 330 event.preventDefault(); 331 this.trigger( 'toggle:upload:attachment' ); 332 333 if ( this.uploader ) { 334 this.uploader.refresh(); 335 } 336 }, 337 338 /** 339 * Open the Edit Attachment modal. 340 */ 341 openEditAttachmentModal: function( model ) { 342 // Create a new EditAttachment frame, passing along the library and the attachment model. 343 if ( wp.media.frames.edit ) { 344 wp.media.frames.edit.open().trigger( 'refresh', model ); 247 345 } else { 248 this.model.set( 'text', l10n.deleteSelected ); 346 wp.media.frames.edit = wp.media( { 347 frame: 'edit-attachments', 348 controller: this, 349 library: this.state().get('library'), 350 model: model 351 } ); 249 352 } 250 353 }, 251 354 252 toggleDisabled: function() { 253 this.model.set( 'disabled', ! this.controller.state().get( 'selection' ).length ); 355 /** 356 * Create an attachments browser view within the content region. 357 * 358 * @param {Object} contentRegion Basic object with a `view` property, which 359 * should be set with the proper region view. 360 * @this wp.media.controller.Region 361 */ 362 browseContent: function( contentRegion ) { 363 var state = this.state(); 364 365 // Browse our library of attachments. 366 this.browserView = contentRegion.view = new wp.media.view.AttachmentsBrowser({ 367 controller: this, 368 collection: state.get('library'), 369 selection: state.get('selection'), 370 model: state, 371 sortable: state.get('sortable'), 372 search: state.get('searchable'), 373 filters: state.get('filterable'), 374 date: state.get('date'), 375 display: state.get('displaySettings'), 376 dragInfo: state.get('dragInfo'), 377 sidebar: 'errors', 378 379 suggestedWidth: state.get('suggestedWidth'), 380 suggestedHeight: state.get('suggestedHeight'), 381 382 AttachmentView: state.get('AttachmentView'), 383 384 scrollElement: document 385 }); 386 this.browserView.on( 'ready', _.bind( this.bindDeferred, this ) ); 387 388 this.errors = wp.Uploader.errors; 389 this.errors.on( 'add remove reset', this.sidebarVisibility, this ); 254 390 }, 255 391 256 render: function() { 257 Button.prototype.render.apply( this, arguments ); 258 if ( this.controller.isModeActive( 'select' ) ) { 259 this.$el.addClass( 'delete-selected-button' ); 260 } else { 261 this.$el.addClass( 'delete-selected-button hidden' ); 392 sidebarVisibility: function() { 393 this.browserView.$( '.media-sidebar' ).toggle( !! this.errors.length ); 394 }, 395 396 bindDeferred: function() { 397 if ( ! this.browserView.dfd ) { 398 return; 399 } 400 this.browserView.dfd.done( _.bind( this.startHistory, this ) ); 401 }, 402 403 startHistory: function() { 404 // Verify pushState support and activate 405 if ( window.history && window.history.pushState ) { 406 if ( Backbone.History.started ) { 407 Backbone.history.stop(); 408 } 409 Backbone.history.start( { 410 root: window._wpMediaGridSettings.adminUrl, 411 pushState: true 412 } ); 262 413 } 263 this.toggleDisabled();264 return this;265 414 } 266 415 }); 267 416 268 module.exports = DeleteSelected;417 module.exports = Manage; 269 418 270 },{}],7:[function(require,module,exports){271 419 272 var Button = wp.media.view.Button, 273 l10n = wp.media.view.l10n, 274 SelectModeToggle; 420 /***/ }), 421 /* 13 */ 422 /***/ (function(module, exports) { 423 424 var Details = wp.media.view.Attachment.Details, 425 TwoColumn; 275 426 276 427 /** 277 * wp.media.view. SelectModeToggleButton428 * wp.media.view.Attachment.Details.TwoColumn 278 429 * 279 * @memberOf wp.media.view 430 * A similar view to media.view.Attachment.Details 431 * for use in the Edit Attachment modal. 432 * 433 * @memberOf wp.media.view.Attachment.Details 280 434 * 281 435 * @class 282 * @augments wp.media.view.Button 436 * @augments wp.media.view.Attachment.Details 437 * @augments wp.media.view.Attachment 283 438 * @augments wp.media.View 284 439 * @augments wp.Backbone.View 285 440 * @augments Backbone.View 286 441 */ 287 SelectModeToggle = Button.extend(/** @lends wp.media.view.SelectModeToggle.prototype */{ 288 initialize: function() { 289 _.defaults( this.options, { 290 size : '' 291 } ); 442 TwoColumn = Details.extend(/** @lends wp.media.view.Attachment.Details.TowColumn.prototype */{ 443 template: wp.template( 'attachment-details-two-column' ), 292 444 293 Button.prototype.initialize.apply( this, arguments ); 294 this.controller.on( 'select:activate select:deactivate', this.toggleBulkEditHandler, this ); 295 this.controller.on( 'selection:action:done', this.back, this ); 296 }, 445 initialize: function() { 446 this.controller.on( 'content:activate:edit-details', _.bind( this.editAttachment, this ) ); 297 447 298 back: function () { 299 this.controller.deactivateMode( 'select' ).activateMode( 'edit' ); 448 Details.prototype.initialize.apply( this, arguments ); 300 449 }, 301 450 302 click: function() { 303 Button.prototype.click.apply( this, arguments ); 304 if ( this.controller.isModeActive( 'select' ) ) { 305 this.back(); 306 } else { 307 this.controller.deactivateMode( 'edit' ).activateMode( 'select' ); 451 editAttachment: function( event ) { 452 if ( event ) { 453 event.preventDefault(); 308 454 } 455 this.controller.content.mode( 'edit-image' ); 309 456 }, 310 457 311 render: function() { 312 Button.prototype.render.apply( this, arguments ); 313 this.$el.addClass( 'select-mode-toggle-button' ); 314 return this; 315 }, 316 317 toggleBulkEditHandler: function() { 318 var toolbar = this.controller.content.get().toolbar, children; 458 /** 459 * Noop this from parent class, doesn't apply here. 460 */ 461 toggleSelectionHandler: function() {}, 319 462 320 children = toolbar.$( '.media-toolbar-secondary > *, .media-toolbar-primary > *' ); 463 render: function() { 464 Details.prototype.render.apply( this, arguments ); 321 465 322 // TODO: the Frame should be doing all of this. 323 if ( this.controller.isModeActive( 'select' ) ) { 324 this.model.set( { 325 size: 'large', 326 text: l10n.cancelSelection 327 } ); 328 children.not( '.spinner, .media-button' ).hide(); 329 this.$el.show(); 330 toolbar.$( '.delete-selected-button' ).removeClass( 'hidden' ); 331 } else { 332 this.model.set( { 333 size: '', 334 text: l10n.bulkSelect 335 } ); 336 this.controller.content.get().$el.removeClass( 'fixed' ); 337 toolbar.$el.css( 'width', '' ); 338 toolbar.$( '.delete-selected-button' ).addClass( 'hidden' ); 339 children.not( '.media-button' ).show(); 340 this.controller.state().get( 'selection' ).reset(); 341 } 466 wp.media.mixin.removeAllPlayers(); 467 this.$( 'audio, video' ).each( function (i, elem) { 468 var el = wp.media.view.MediaDetails.prepareSrc( elem ); 469 new window.MediaElementPlayer( el, wp.media.mixin.mejsSettings ); 470 } ); 342 471 } 343 472 }); 344 473 345 module.exports = SelectModeToggle;474 module.exports = TwoColumn; 346 475 347 },{}],8:[function(require,module,exports){ 348 var View = wp.media.View,349 EditImage = wp.media.view.EditImage, 350 Details; 476 477 /***/ }), 478 /* 14 */ 479 /***/ (function(module, exports) { 351 480 352 481 /** 353 * wp.media.view. EditImage.Details482 * wp.media.view.MediaFrame.Manage.Router 354 483 * 355 * @memberOf wp.media.view.EditImage 484 * A router for handling the browser history and application state. 485 * 486 * @memberOf wp.media.view.MediaFrame.Manage 356 487 * 357 488 * @class 358 * @augments wp.media.view.EditImage 359 * @augments wp.media.View 360 * @augments wp.Backbone.View 361 * @augments Backbone.View 489 * @augments Backbone.Router 362 490 */ 363 Details = EditImage.extend(/** @lends wp.media.view.EditImage.Details.prototype */{ 491 var Router = Backbone.Router.extend(/** @lends wp.media.view.MediaFrame.Manage.Router.prototype */{ 492 routes: { 493 'upload.php?item=:slug&mode=edit': 'editItem', 494 'upload.php?item=:slug': 'showItem', 495 'upload.php?search=:query': 'search', 496 'upload.php': 'reset' 497 }, 498 499 // Map routes against the page URL 500 baseUrl: function( url ) { 501 return 'upload.php' + url; 502 }, 503 504 reset: function() { 505 var frame = wp.media.frames.edit; 506 507 if ( frame ) { 508 frame.close(); 509 } 510 }, 511 512 // Respond to the search route by filling the search field and trigggering the input event 513 search: function( query ) { 514 jQuery( '#media-search-input' ).val( query ).trigger( 'input' ); 515 }, 516 517 // Show the modal with a specific item 518 showItem: function( query ) { 519 var media = wp.media, 520 frame = media.frames.browse, 521 library = frame.state().get('library'), 522 item; 523 524 // Trigger the media frame to open the correct item 525 item = library.findWhere( { id: parseInt( query, 10 ) } ); 526 item.set( 'skipHistory', true ); 527 528 if ( item ) { 529 frame.trigger( 'edit:attachment', item ); 530 } else { 531 item = media.attachment( query ); 532 frame.listenTo( item, 'change', function( model ) { 533 frame.stopListening( item ); 534 frame.trigger( 'edit:attachment', model ); 535 } ); 536 item.fetch(); 537 } 538 }, 539 540 // Show the modal in edit mode with a specific item. 541 editItem: function( query ) { 542 this.showItem( query ); 543 wp.media.frames.edit.content.mode( 'edit-details' ); 544 } 545 }); 546 547 module.exports = Router; 548 549 550 /***/ }), 551 /* 15 */ 552 /***/ (function(module, exports) { 553 554 var View = wp.media.View, 555 EditImage = wp.media.view.EditImage, 556 Details; 557 558 /** 559 * wp.media.view.EditImage.Details 560 * 561 * @memberOf wp.media.view.EditImage 562 * 563 * @class 564 * @augments wp.media.view.EditImage 565 * @augments wp.media.View 566 * @augments wp.Backbone.View 567 * @augments Backbone.View 568 */ 569 Details = EditImage.extend(/** @lends wp.media.view.EditImage.Details.prototype */{ 364 570 initialize: function( options ) { 365 571 this.editor = window.imageEdit; 366 572 this.frame = options.frame; … … Details = EditImage.extend(/** @lends wp.media.view.EditImage.Details.prototype 381 587 382 588 module.exports = Details; 383 589 384 },{}],9:[function(require,module,exports){ 590 591 /***/ }), 592 /* 16 */ 593 /***/ (function(module, exports) { 594 385 595 var Frame = wp.media.view.Frame, 386 596 MediaFrame = wp.media.view.MediaFrame, 387 597 … … EditAttachments = MediaFrame.extend(/** @lends wp.media.view.MediaFrame.EditAtta 643 853 644 854 module.exports = EditAttachments; 645 855 646 },{}],10:[function(require,module,exports){647 var MediaFrame = wp.media.view.MediaFrame,648 Library = wp.media.controller.Library,649 856 650 $ = Backbone.$, 651 Manage; 857 /***/ }), 858 /* 17 */ 859 /***/ (function(module, exports) { 860 861 862 var Button = wp.media.view.Button, 863 l10n = wp.media.view.l10n, 864 SelectModeToggle; 652 865 653 866 /** 654 * wp.media.view.MediaFrame.Manage 655 * 656 * A generic management frame workflow. 657 * 658 * Used in the media grid view. 867 * wp.media.view.SelectModeToggleButton 659 868 * 660 * @memberOf wp.media.view .MediaFrame869 * @memberOf wp.media.view 661 870 * 662 871 * @class 663 * @augments wp.media.view.MediaFrame 664 * @augments wp.media.view.Frame 872 * @augments wp.media.view.Button 665 873 * @augments wp.media.View 666 874 * @augments wp.Backbone.View 667 875 * @augments Backbone.View 668 * @mixes wp.media.controller.StateMachine669 876 */ 670 Manage = MediaFrame.extend(/** @lends wp.media.view.MediaFrame.Manage.prototype */{ 671 /** 672 * @constructs 673 */ 877 SelectModeToggle = Button.extend(/** @lends wp.media.view.SelectModeToggle.prototype */{ 674 878 initialize: function() { 675 879 _.defaults( this.options, { 676 title: '', 677 modal: false, 678 selection: [], 679 library: {}, // Options hash for the query to the media library. 680 multiple: 'add', 681 state: 'library', 682 uploader: true, 683 mode: [ 'grid', 'edit' ] 684 }); 685 686 this.$body = $( document.body ); 687 this.$window = $( window ); 688 this.$adminBar = $( '#wpadminbar' ); 689 // Store the Add New button for later reuse in wp.media.view.UploaderInline. 690 this.$uploaderToggler = $( '.page-title-action' ) 691 .attr( 'aria-expanded', 'false' ) 692 .on( 'click', _.bind( this.addNewClickHandler, this ) ); 693 694 this.$window.on( 'scroll resize', _.debounce( _.bind( this.fixPosition, this ), 15 ) ); 695 696 // Ensure core and media grid view UI is enabled. 697 this.$el.addClass('wp-core-ui'); 880 size : '' 881 } ); 698 882 699 // Force the uploader off if the upload limit has been exceeded or 700 // if the browser isn't supported. 701 if ( wp.Uploader.limitExceeded || ! wp.Uploader.browser.supported ) { 702 this.options.uploader = false; 703 } 883 Button.prototype.initialize.apply( this, arguments ); 884 this.controller.on( 'select:activate select:deactivate', this.toggleBulkEditHandler, this ); 885 this.controller.on( 'selection:action:done', this.back, this ); 886 }, 704 887 705 // Initialize a window-wide uploader. 706 if ( this.options.uploader ) { 707 this.uploader = new wp.media.view.UploaderWindow({ 708 controller: this, 709 uploader: { 710 dropzone: document.body, 711 container: document.body 712 } 713 }).render(); 714 this.uploader.ready(); 715 $('body').append( this.uploader.el ); 888 back: function () { 889 this.controller.deactivateMode( 'select' ).activateMode( 'edit' ); 890 }, 716 891 717 this.options.uploader = false; 892 click: function() { 893 Button.prototype.click.apply( this, arguments ); 894 if ( this.controller.isModeActive( 'select' ) ) { 895 this.back(); 896 } else { 897 this.controller.deactivateMode( 'edit' ).activateMode( 'select' ); 718 898 } 719 720 this.gridRouter = new wp.media.view.MediaFrame.Manage.Router();721 722 // Call 'initialize' directly on the parent class.723 MediaFrame.prototype.initialize.apply( this, arguments );724 725 // Append the frame view directly the supplied container.726 this.$el.appendTo( this.options.container );727 728 this.createStates();729 this.bindRegionModeHandlers();730 this.render();731 this.bindSearchHandler();732 733 wp.media.frames.browse = this;734 899 }, 735 900 736 bindSearchHandler: function() { 737 var search = this.$( '#media-search-input' ), 738 searchView = this.browserView.toolbar.get( 'search' ).$el, 739 listMode = this.$( '.view-list' ), 740 741 input = _.throttle( function (e) { 742 var val = $( e.currentTarget ).val(), 743 url = ''; 744 745 if ( val ) { 746 url += '?search=' + val; 747 this.gridRouter.navigate( this.gridRouter.baseUrl( url ), { replace: true } ); 748 } 749 }, 1000 ); 750 751 // Update the URL when entering search string (at most once per second) 752 search.on( 'input', _.bind( input, this ) ); 753 754 this.gridRouter 755 .on( 'route:search', function () { 756 var href = window.location.href; 757 if ( href.indexOf( 'mode=' ) > -1 ) { 758 href = href.replace( /mode=[^&]+/g, 'mode=list' ); 759 } else { 760 href += href.indexOf( '?' ) > -1 ? '&mode=list' : '?mode=list'; 761 } 762 href = href.replace( 'search=', 's=' ); 763 listMode.prop( 'href', href ); 764 }) 765 .on( 'route:reset', function() { 766 searchView.val( '' ).trigger( 'input' ); 767 }); 901 render: function() { 902 Button.prototype.render.apply( this, arguments ); 903 this.$el.addClass( 'select-mode-toggle-button' ); 904 return this; 768 905 }, 769 906 770 /** 771 * Create the default states for the frame. 772 */ 773 createStates: function() { 774 var options = this.options; 907 toggleBulkEditHandler: function() { 908 var toolbar = this.controller.content.get().toolbar, children; 775 909 776 if ( this.options.states ) { 777 return; 910 children = toolbar.$( '.media-toolbar-secondary > *, .media-toolbar-primary > *' ); 911 912 // TODO: the Frame should be doing all of this. 913 if ( this.controller.isModeActive( 'select' ) ) { 914 this.model.set( { 915 size: 'large', 916 text: l10n.cancelSelection 917 } ); 918 children.not( '.spinner, .media-button' ).hide(); 919 this.$el.show(); 920 toolbar.$( '.delete-selected-button' ).removeClass( 'hidden' ); 921 } else { 922 this.model.set( { 923 size: '', 924 text: l10n.bulkSelect 925 } ); 926 this.controller.content.get().$el.removeClass( 'fixed' ); 927 toolbar.$el.css( 'width', '' ); 928 toolbar.$( '.delete-selected-button' ).addClass( 'hidden' ); 929 children.not( '.media-button' ).show(); 930 this.controller.state().get( 'selection' ).reset(); 778 931 } 932 } 933 }); 779 934 780 // Add the default states. 781 this.states.add([ 782 new Library({ 783 library: wp.media.query( options.library ), 784 multiple: options.multiple, 785 title: options.title, 786 content: 'browse', 787 toolbar: 'select', 788 contentUserSetting: false, 789 filterable: 'all', 790 autoSelect: false 791 }) 792 ]); 793 }, 935 module.exports = SelectModeToggle; 794 936 795 /**796 * Bind region mode activation events to proper handlers.797 */798 bindRegionModeHandlers: function() {799 this.on( 'content:create:browse', this.browseContent, this );800 937 801 // Handle a frame-level event for editing an attachment. 802 this.on( 'edit:attachment', this.openEditAttachmentModal, this ); 938 /***/ }), 939 /* 18 */ 940 /***/ (function(module, exports) { 803 941 804 this.on( 'select:activate', this.bindKeydown, this ); 805 this.on( 'select:deactivate', this.unbindKeydown, this );806 },942 var Button = wp.media.view.Button, 943 l10n = wp.media.view.l10n, 944 DeleteSelected; 807 945 808 handleKeydown: function( e ) { 809 if ( 27 === e.which ) { 810 e.preventDefault(); 811 this.deactivateMode( 'select' ).activateMode( 'edit' ); 946 /** 947 * wp.media.view.DeleteSelectedButton 948 * 949 * A button that handles bulk Delete/Trash logic 950 * 951 * @memberOf wp.media.view 952 * 953 * @class 954 * @augments wp.media.view.Button 955 * @augments wp.media.View 956 * @augments wp.Backbone.View 957 * @augments Backbone.View 958 */ 959 DeleteSelected = Button.extend(/** @lends wp.media.view.DeleteSelectedButton.prototype */{ 960 initialize: function() { 961 Button.prototype.initialize.apply( this, arguments ); 962 if ( this.options.filters ) { 963 this.options.filters.model.on( 'change', this.filterChange, this ); 812 964 } 965 this.controller.on( 'selection:toggle', this.toggleDisabled, this ); 813 966 }, 814 967 815 bindKeydown: function() { 816 this.$body.on( 'keydown.select', _.bind( this.handleKeydown, this ) ); 817 }, 818 819 unbindKeydown: function() { 820 this.$body.off( 'keydown.select' ); 821 }, 822 823 fixPosition: function() { 824 var $browser, $toolbar; 825 if ( ! this.isModeActive( 'select' ) ) { 826 return; 827 } 828 829 $browser = this.$('.attachments-browser'); 830 $toolbar = $browser.find('.media-toolbar'); 831 832 // Offset doesn't appear to take top margin into account, hence +16 833 if ( ( $browser.offset().top + 16 ) < this.$window.scrollTop() + this.$adminBar.height() ) { 834 $browser.addClass( 'fixed' ); 835 $toolbar.css('width', $browser.width() + 'px'); 968 filterChange: function( model ) { 969 if ( 'trash' === model.get( 'status' ) ) { 970 this.model.set( 'text', l10n.untrashSelected ); 971 } else if ( wp.media.view.settings.mediaTrash ) { 972 this.model.set( 'text', l10n.trashSelected ); 836 973 } else { 837 $browser.removeClass( 'fixed' ); 838 $toolbar.css('width', ''); 974 this.model.set( 'text', l10n.deleteSelected ); 839 975 } 840 976 }, 841 977 842 /** 843 * Click handler for the `Add New` button. 844 */ 845 addNewClickHandler: function( event ) { 846 event.preventDefault(); 847 this.trigger( 'toggle:upload:attachment' ); 848 849 if ( this.uploader ) { 850 this.uploader.refresh(); 851 } 978 toggleDisabled: function() { 979 this.model.set( 'disabled', ! this.controller.state().get( 'selection' ).length ); 852 980 }, 853 981 854 /** 855 * Open the Edit Attachment modal. 856 */ 857 openEditAttachmentModal: function( model ) { 858 // Create a new EditAttachment frame, passing along the library and the attachment model. 859 if ( wp.media.frames.edit ) { 860 wp.media.frames.edit.open().trigger( 'refresh', model ); 982 render: function() { 983 Button.prototype.render.apply( this, arguments ); 984 if ( this.controller.isModeActive( 'select' ) ) { 985 this.$el.addClass( 'delete-selected-button' ); 861 986 } else { 862 wp.media.frames.edit = wp.media( { 863 frame: 'edit-attachments', 864 controller: this, 865 library: this.state().get('library'), 866 model: model 867 } ); 987 this.$el.addClass( 'delete-selected-button hidden' ); 868 988 } 869 }, 989 this.toggleDisabled(); 990 return this; 991 } 992 }); 870 993 871 /** 872 * Create an attachments browser view within the content region. 873 * 874 * @param {Object} contentRegion Basic object with a `view` property, which 875 * should be set with the proper region view. 876 * @this wp.media.controller.Region 877 */ 878 browseContent: function( contentRegion ) { 879 var state = this.state(); 994 module.exports = DeleteSelected; 880 995 881 // Browse our library of attachments.882 this.browserView = contentRegion.view = new wp.media.view.AttachmentsBrowser({883 controller: this,884 collection: state.get('library'),885 selection: state.get('selection'),886 model: state,887 sortable: state.get('sortable'),888 search: state.get('searchable'),889 filters: state.get('filterable'),890 date: state.get('date'),891 display: state.get('displaySettings'),892 dragInfo: state.get('dragInfo'),893 sidebar: 'errors',894 996 895 suggestedWidth: state.get('suggestedWidth'), 896 suggestedHeight: state.get('suggestedHeight'), 997 /***/ }), 998 /* 19 */ 999 /***/ (function(module, exports) { 897 1000 898 AttachmentView: state.get('AttachmentView'), 1001 var Button = wp.media.view.Button, 1002 DeleteSelected = wp.media.view.DeleteSelectedButton, 1003 DeleteSelectedPermanently; 899 1004 900 scrollElement: document 901 }); 902 this.browserView.on( 'ready', _.bind( this.bindDeferred, this ) ); 1005 /** 1006 * wp.media.view.DeleteSelectedPermanentlyButton 1007 * 1008 * When MEDIA_TRASH is true, a button that handles bulk Delete Permanently logic 1009 * 1010 * @memberOf wp.media.view 1011 * 1012 * @class 1013 * @augments wp.media.view.DeleteSelectedButton 1014 * @augments wp.media.view.Button 1015 * @augments wp.media.View 1016 * @augments wp.Backbone.View 1017 * @augments Backbone.View 1018 */ 1019 DeleteSelectedPermanently = DeleteSelected.extend(/** @lends wp.media.view.DeleteSelectedPermanentlyButton.prototype */{ 1020 initialize: function() { 1021 DeleteSelected.prototype.initialize.apply( this, arguments ); 1022 this.controller.on( 'select:activate', this.selectActivate, this ); 1023 this.controller.on( 'select:deactivate', this.selectDeactivate, this ); 1024 }, 903 1025 904 this.errors = wp.Uploader.errors;905 this. errors.on( 'add remove reset', this.sidebarVisibility, this);1026 filterChange: function( model ) { 1027 this.canShow = ( 'trash' === model.get( 'status' ) ); 906 1028 }, 907 1029 908 sidebarVisibility: function() { 909 this.browserView.$( '.media-sidebar' ).toggle( !! this.errors.length ); 1030 selectActivate: function() { 1031 this.toggleDisabled(); 1032 this.$el.toggleClass( 'hidden', ! this.canShow ); 910 1033 }, 911 1034 912 bindDeferred: function() { 913 if ( ! this.browserView.dfd ) { 914 return; 915 } 916 this.browserView.dfd.done( _.bind( this.startHistory, this ) ); 1035 selectDeactivate: function() { 1036 this.toggleDisabled(); 1037 this.$el.addClass( 'hidden' ); 917 1038 }, 918 1039 919 startHistory: function() { 920 // Verify pushState support and activate 921 if ( window.history && window.history.pushState ) { 922 if ( Backbone.History.started ) { 923 Backbone.history.stop(); 924 } 925 Backbone.history.start( { 926 root: window._wpMediaGridSettings.adminUrl, 927 pushState: true 928 } ); 929 } 1040 render: function() { 1041 Button.prototype.render.apply( this, arguments ); 1042 this.selectActivate(); 1043 return this; 930 1044 } 931 1045 }); 932 1046 933 module.exports = Manage; 1047 module.exports = DeleteSelectedPermanently; 1048 934 1049 935 },{}]},{},[2]); 1050 /***/ }) 1051 /******/ ]); 1052 No newline at end of file -
src/wp-includes/js/media-models.js
diff --git src/wp-includes/js/media-models.js src/wp-includes/js/media-models.js index caa7fcb590..af64387257 100644
1 (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ 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, { 40 /******/ configurable: false, 41 /******/ enumerable: true, 42 /******/ get: getter 43 /******/ }); 44 /******/ } 45 /******/ }; 46 /******/ 47 /******/ // getDefaultExport function for compatibility with non-harmony modules 48 /******/ __webpack_require__.n = function(module) { 49 /******/ var getter = module && module.__esModule ? 50 /******/ function getDefault() { return module['default']; } : 51 /******/ function getModuleExports() { return module; }; 52 /******/ __webpack_require__.d(getter, 'a', getter); 53 /******/ return getter; 54 /******/ }; 55 /******/ 56 /******/ // Object.prototype.hasOwnProperty.call 57 /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 58 /******/ 59 /******/ // __webpack_public_path__ 60 /******/ __webpack_require__.p = ""; 61 /******/ 62 /******/ // Load entry module and return exports 63 /******/ return __webpack_require__(__webpack_require__.s = 20); 64 /******/ }) 65 /************************************************************************/ 66 /******/ ({ 67 68 /***/ 20: 69 /***/ (function(module, exports, __webpack_require__) { 70 2 71 var $ = jQuery, 3 72 Attachment, Attachments, l10n, media; 4 73 … … l10n = media.model.l10n = window._wpMediaModelsL10n || {}; 65 134 media.model.settings = l10n.settings || {}; 66 135 delete l10n.settings; 67 136 68 Attachment = media.model.Attachment = require( './models/attachment.js');69 Attachments = media.model.Attachments = require( './models/attachments.js');137 Attachment = media.model.Attachment = __webpack_require__( 21 ); 138 Attachments = media.model.Attachments = __webpack_require__( 22 ); 70 139 71 media.model.Query = require( './models/query.js');72 media.model.PostImage = require( './models/post-image.js');73 media.model.Selection = require( './models/selection.js');140 media.model.Query = __webpack_require__( 23 ); 141 media.model.PostImage = __webpack_require__( 24 ); 142 media.model.Selection = __webpack_require__( 25 ); 74 143 75 144 /** 76 145 * ======================================================================== … … $(window).on('unload', function(){ 238 307 window.wp = null; 239 308 }); 240 309 241 },{"./models/attachment.js":2,"./models/attachments.js":3,"./models/post-image.js":4,"./models/query.js":5,"./models/selection.js":6}],2:[function(require,module,exports){ 310 311 /***/ }), 312 313 /***/ 21: 314 /***/ (function(module, exports) { 315 242 316 var $ = Backbone.$, 243 317 Attachment; 244 318 … … Attachment = Backbone.Model.extend(/** @lends wp.media.model.Attachment.prototyp 409 483 410 484 module.exports = Attachment; 411 485 412 },{}],3:[function(require,module,exports){ 486 487 /***/ }), 488 489 /***/ 22: 490 /***/ (function(module, exports) { 491 413 492 /** 414 493 * wp.media.model.Attachments 415 494 * … … var Attachments = Backbone.Collection.extend(/** @lends wp.media.model.Attachmen 954 1033 955 1034 module.exports = Attachments; 956 1035 957 },{}],4:[function(require,module,exports){958 /**959 * wp.media.model.PostImage960 *961 * An instance of an image that's been embedded into a post.962 *963 * Used in the embedded image attachment display settings modal - @see wp.media.view.MediaFrame.ImageDetails.964 *965 * @memberOf wp.media.model966 *967 * @class968 * @augments Backbone.Model969 *970 * @param {int} [attributes] Initial model attributes.971 * @param {int} [attributes.attachment_id] ID of the attachment.972 **/973 var PostImage = Backbone.Model.extend(/** @lends wp.media.model.PostImage.prototype */{974 975 initialize: function( attributes ) {976 var Attachment = wp.media.model.Attachment;977 this.attachment = false;978 1036 979 if ( attributes.attachment_id ) { 980 this.attachment = Attachment.get( attributes.attachment_id ); 981 if ( this.attachment.get( 'url' ) ) { 982 this.dfd = jQuery.Deferred(); 983 this.dfd.resolve(); 984 } else { 985 this.dfd = this.attachment.fetch(); 986 } 987 this.bindAttachmentListeners(); 988 } 1037 /***/ }), 989 1038 990 // keep url in sync with changes to the type of link 991 this.on( 'change:link', this.updateLinkUrl, this ); 992 this.on( 'change:size', this.updateSize, this ); 1039 /***/ 23: 1040 /***/ (function(module, exports) { 993 1041 994 this.setLinkTypeFromUrl();995 this.setAspectRatio();996 997 this.set( 'originalUrl', attributes.url );998 },999 1000 bindAttachmentListeners: function() {1001 this.listenTo( this.attachment, 'sync', this.setLinkTypeFromUrl );1002 this.listenTo( this.attachment, 'sync', this.setAspectRatio );1003 this.listenTo( this.attachment, 'change', this.updateSize );1004 },1005 1006 changeAttachment: function( attachment, props ) {1007 this.stopListening( this.attachment );1008 this.attachment = attachment;1009 this.bindAttachmentListeners();1010 1011 this.set( 'attachment_id', this.attachment.get( 'id' ) );1012 this.set( 'caption', this.attachment.get( 'caption' ) );1013 this.set( 'alt', this.attachment.get( 'alt' ) );1014 this.set( 'size', props.get( 'size' ) );1015 this.set( 'align', props.get( 'align' ) );1016 this.set( 'link', props.get( 'link' ) );1017 this.updateLinkUrl();1018 this.updateSize();1019 },1020 1021 setLinkTypeFromUrl: function() {1022 var linkUrl = this.get( 'linkUrl' ),1023 type;1024 1025 if ( ! linkUrl ) {1026 this.set( 'link', 'none' );1027 return;1028 }1029 1030 // default to custom if there is a linkUrl1031 type = 'custom';1032 1033 if ( this.attachment ) {1034 if ( this.attachment.get( 'url' ) === linkUrl ) {1035 type = 'file';1036 } else if ( this.attachment.get( 'link' ) === linkUrl ) {1037 type = 'post';1038 }1039 } else {1040 if ( this.get( 'url' ) === linkUrl ) {1041 type = 'file';1042 }1043 }1044 1045 this.set( 'link', type );1046 },1047 1048 updateLinkUrl: function() {1049 var link = this.get( 'link' ),1050 url;1051 1052 switch( link ) {1053 case 'file':1054 if ( this.attachment ) {1055 url = this.attachment.get( 'url' );1056 } else {1057 url = this.get( 'url' );1058 }1059 this.set( 'linkUrl', url );1060 break;1061 case 'post':1062 this.set( 'linkUrl', this.attachment.get( 'link' ) );1063 break;1064 case 'none':1065 this.set( 'linkUrl', '' );1066 break;1067 }1068 },1069 1070 updateSize: function() {1071 var size;1072 1073 if ( ! this.attachment ) {1074 return;1075 }1076 1077 if ( this.get( 'size' ) === 'custom' ) {1078 this.set( 'width', this.get( 'customWidth' ) );1079 this.set( 'height', this.get( 'customHeight' ) );1080 this.set( 'url', this.get( 'originalUrl' ) );1081 return;1082 }1083 1084 size = this.attachment.get( 'sizes' )[ this.get( 'size' ) ];1085 1086 if ( ! size ) {1087 return;1088 }1089 1090 this.set( 'url', size.url );1091 this.set( 'width', size.width );1092 this.set( 'height', size.height );1093 },1094 1095 setAspectRatio: function() {1096 var full;1097 1098 if ( this.attachment && this.attachment.get( 'sizes' ) ) {1099 full = this.attachment.get( 'sizes' ).full;1100 1101 if ( full ) {1102 this.set( 'aspectRatio', full.width / full.height );1103 return;1104 }1105 }1106 1107 this.set( 'aspectRatio', this.get( 'customWidth' ) / this.get( 'customHeight' ) );1108 }1109 });1110 1111 module.exports = PostImage;1112 1113 },{}],5:[function(require,module,exports){1114 1042 var Attachments = wp.media.model.Attachments, 1115 1043 Query; 1116 1044 … … Query = Attachments.extend(/** @lends wp.media.model.Query.prototype */{ 1418 1346 1419 1347 module.exports = Query; 1420 1348 1421 },{}],6:[function(require,module,exports){ 1349 1350 /***/ }), 1351 1352 /***/ 24: 1353 /***/ (function(module, exports) { 1354 1355 /** 1356 * wp.media.model.PostImage 1357 * 1358 * An instance of an image that's been embedded into a post. 1359 * 1360 * Used in the embedded image attachment display settings modal - @see wp.media.view.MediaFrame.ImageDetails. 1361 * 1362 * @memberOf wp.media.model 1363 * 1364 * @class 1365 * @augments Backbone.Model 1366 * 1367 * @param {int} [attributes] Initial model attributes. 1368 * @param {int} [attributes.attachment_id] ID of the attachment. 1369 **/ 1370 var PostImage = Backbone.Model.extend(/** @lends wp.media.model.PostImage.prototype */{ 1371 1372 initialize: function( attributes ) { 1373 var Attachment = wp.media.model.Attachment; 1374 this.attachment = false; 1375 1376 if ( attributes.attachment_id ) { 1377 this.attachment = Attachment.get( attributes.attachment_id ); 1378 if ( this.attachment.get( 'url' ) ) { 1379 this.dfd = jQuery.Deferred(); 1380 this.dfd.resolve(); 1381 } else { 1382 this.dfd = this.attachment.fetch(); 1383 } 1384 this.bindAttachmentListeners(); 1385 } 1386 1387 // keep url in sync with changes to the type of link 1388 this.on( 'change:link', this.updateLinkUrl, this ); 1389 this.on( 'change:size', this.updateSize, this ); 1390 1391 this.setLinkTypeFromUrl(); 1392 this.setAspectRatio(); 1393 1394 this.set( 'originalUrl', attributes.url ); 1395 }, 1396 1397 bindAttachmentListeners: function() { 1398 this.listenTo( this.attachment, 'sync', this.setLinkTypeFromUrl ); 1399 this.listenTo( this.attachment, 'sync', this.setAspectRatio ); 1400 this.listenTo( this.attachment, 'change', this.updateSize ); 1401 }, 1402 1403 changeAttachment: function( attachment, props ) { 1404 this.stopListening( this.attachment ); 1405 this.attachment = attachment; 1406 this.bindAttachmentListeners(); 1407 1408 this.set( 'attachment_id', this.attachment.get( 'id' ) ); 1409 this.set( 'caption', this.attachment.get( 'caption' ) ); 1410 this.set( 'alt', this.attachment.get( 'alt' ) ); 1411 this.set( 'size', props.get( 'size' ) ); 1412 this.set( 'align', props.get( 'align' ) ); 1413 this.set( 'link', props.get( 'link' ) ); 1414 this.updateLinkUrl(); 1415 this.updateSize(); 1416 }, 1417 1418 setLinkTypeFromUrl: function() { 1419 var linkUrl = this.get( 'linkUrl' ), 1420 type; 1421 1422 if ( ! linkUrl ) { 1423 this.set( 'link', 'none' ); 1424 return; 1425 } 1426 1427 // default to custom if there is a linkUrl 1428 type = 'custom'; 1429 1430 if ( this.attachment ) { 1431 if ( this.attachment.get( 'url' ) === linkUrl ) { 1432 type = 'file'; 1433 } else if ( this.attachment.get( 'link' ) === linkUrl ) { 1434 type = 'post'; 1435 } 1436 } else { 1437 if ( this.get( 'url' ) === linkUrl ) { 1438 type = 'file'; 1439 } 1440 } 1441 1442 this.set( 'link', type ); 1443 }, 1444 1445 updateLinkUrl: function() { 1446 var link = this.get( 'link' ), 1447 url; 1448 1449 switch( link ) { 1450 case 'file': 1451 if ( this.attachment ) { 1452 url = this.attachment.get( 'url' ); 1453 } else { 1454 url = this.get( 'url' ); 1455 } 1456 this.set( 'linkUrl', url ); 1457 break; 1458 case 'post': 1459 this.set( 'linkUrl', this.attachment.get( 'link' ) ); 1460 break; 1461 case 'none': 1462 this.set( 'linkUrl', '' ); 1463 break; 1464 } 1465 }, 1466 1467 updateSize: function() { 1468 var size; 1469 1470 if ( ! this.attachment ) { 1471 return; 1472 } 1473 1474 if ( this.get( 'size' ) === 'custom' ) { 1475 this.set( 'width', this.get( 'customWidth' ) ); 1476 this.set( 'height', this.get( 'customHeight' ) ); 1477 this.set( 'url', this.get( 'originalUrl' ) ); 1478 return; 1479 } 1480 1481 size = this.attachment.get( 'sizes' )[ this.get( 'size' ) ]; 1482 1483 if ( ! size ) { 1484 return; 1485 } 1486 1487 this.set( 'url', size.url ); 1488 this.set( 'width', size.width ); 1489 this.set( 'height', size.height ); 1490 }, 1491 1492 setAspectRatio: function() { 1493 var full; 1494 1495 if ( this.attachment && this.attachment.get( 'sizes' ) ) { 1496 full = this.attachment.get( 'sizes' ).full; 1497 1498 if ( full ) { 1499 this.set( 'aspectRatio', full.width / full.height ); 1500 return; 1501 } 1502 } 1503 1504 this.set( 'aspectRatio', this.get( 'customWidth' ) / this.get( 'customHeight' ) ); 1505 } 1506 }); 1507 1508 module.exports = PostImage; 1509 1510 1511 /***/ }), 1512 1513 /***/ 25: 1514 /***/ (function(module, exports) { 1515 1422 1516 var Attachments = wp.media.model.Attachments, 1423 1517 Selection; 1424 1518 … … Selection = Attachments.extend(/** @lends wp.media.model.Selection.prototype */{ 1517 1611 1518 1612 module.exports = Selection; 1519 1613 1520 },{}]},{},[1]); 1614 1615 /***/ }) 1616 1617 /******/ }); 1618 No newline at end of file -
src/wp-includes/js/media-views.js
diff --git src/wp-includes/js/media-views.js src/wp-includes/js/media-views.js index 18e6444691..2e462971e2 100644
1 (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ 2 var Selection = wp.media.model.Selection, 3 Library = wp.media.controller.Library, 4 CollectionAdd; 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, { 40 /******/ configurable: false, 41 /******/ enumerable: true, 42 /******/ get: getter 43 /******/ }); 44 /******/ } 45 /******/ }; 46 /******/ 47 /******/ // getDefaultExport function for compatibility with non-harmony modules 48 /******/ __webpack_require__.n = function(module) { 49 /******/ var getter = module && module.__esModule ? 50 /******/ function getDefault() { return module['default']; } : 51 /******/ function getModuleExports() { return module; }; 52 /******/ __webpack_require__.d(getter, 'a', getter); 53 /******/ return getter; 54 /******/ }; 55 /******/ 56 /******/ // Object.prototype.hasOwnProperty.call 57 /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 58 /******/ 59 /******/ // __webpack_public_path__ 60 /******/ __webpack_require__.p = ""; 61 /******/ 62 /******/ // Load entry module and return exports 63 /******/ return __webpack_require__(__webpack_require__.s = 26); 64 /******/ }) 65 /************************************************************************/ 66 /******/ (Array(26).concat([ 67 /* 26 */ 68 /***/ (function(module, exports, __webpack_require__) { 5 69 6 /** 7 * wp.media.controller.CollectionAdd 8 * 9 * A state for adding attachments to a collection (e.g. video playlist). 10 * 11 * @memberOf wp.media.controller 12 * 13 * @class 14 * @augments wp.media.controller.Library 15 * @augments wp.media.controller.State 16 * @augments Backbone.Model 17 * 18 * @param {object} [attributes] The attributes hash passed to the state. 19 * @param {string} [attributes.id=library] Unique identifier. 20 * @param {string} attributes.title Title for the state. Displays in the frame's title region. 21 * @param {boolean} [attributes.multiple=add] Whether multi-select is enabled. @todo 'add' doesn't seem do anything special, and gets used as a boolean. 22 * @param {wp.media.model.Attachments} [attributes.library] The attachments collection to browse. 23 * If one is not supplied, a collection of attachments of the specified type will be created. 24 * @param {boolean|string} [attributes.filterable=uploaded] Whether the library is filterable, and if so what filters should be shown. 25 * Accepts 'all', 'uploaded', or 'unattached'. 26 * @param {string} [attributes.menu=gallery] Initial mode for the menu region. 27 * @param {string} [attributes.content=upload] Initial mode for the content region. 28 * Overridden by persistent user setting if 'contentUserSetting' is true. 29 * @param {string} [attributes.router=browse] Initial mode for the router region. 30 * @param {string} [attributes.toolbar=gallery-add] Initial mode for the toolbar region. 31 * @param {boolean} [attributes.searchable=true] Whether the library is searchable. 32 * @param {boolean} [attributes.sortable=true] Whether the Attachments should be sortable. Depends on the orderby property being set to menuOrder on the attachments collection. 33 * @param {boolean} [attributes.autoSelect=true] Whether an uploaded attachment should be automatically added to the selection. 34 * @param {boolean} [attributes.contentUserSetting=true] Whether the content region's mode should be set and persisted per user. 35 * @param {int} [attributes.priority=100] The priority for the state link in the media menu. 36 * @param {boolean} [attributes.syncSelection=false] Whether the Attachments selection should be persisted from the last state. 37 * Defaults to false because for this state, because the library of the Edit Gallery state is the selection. 38 * @param {string} attributes.type The collection's media type. (e.g. 'video'). 39 * @param {string} attributes.collectionType The collection type. (e.g. 'playlist'). 40 */ 41 CollectionAdd = Library.extend(/** @lends wp.media.controller.CollectionAdd.prototype */{ 42 defaults: _.defaults( { 43 // Selection defaults. @see media.model.Selection 44 multiple: 'add', 45 // Attachments browser defaults. @see media.view.AttachmentsBrowser 46 filterable: 'uploaded', 70 var media = wp.media, 71 $ = jQuery, 72 l10n; 47 73 48 priority: 100, 49 syncSelection: false 50 }, Library.prototype.defaults ), 74 media.isTouchDevice = ( 'ontouchend' in document ); 51 75 52 /** 53 * @since 3.9.0 54 */ 55 initialize: function() { 56 var collectionType = this.get('collectionType'); 76 // Link any localized strings. 77 l10n = media.view.l10n = window._wpMediaViewsL10n || {}; 57 78 58 if ( 'video' === this.get( 'type' ) ) { 59 collectionType = 'video-' + collectionType;60 } 79 // Link any settings. 80 media.view.settings = l10n.settings || {}; 81 delete l10n.settings; 61 82 62 this.set( 'id', collectionType + '-library' ); 63 this.set( 'toolbar', collectionType + '-add' ); 64 this.set( 'menu', collectionType ); 83 // Copy the `post` setting over to the model settings. 84 media.model.settings.post = media.view.settings.post; 65 85 66 // If we haven't been provided a `library`, create a `Selection`. 67 if ( ! this.get('library') ) { 68 this.set( 'library', wp.media.query({ type: this.get('type') }) ); 69 } 70 Library.prototype.initialize.apply( this, arguments ); 71 }, 86 // Check if the browser supports CSS 3.0 transitions 87 $.support.transition = (function(){ 88 var style = document.documentElement.style, 89 transitions = { 90 WebkitTransition: 'webkitTransitionEnd', 91 MozTransition: 'transitionend', 92 OTransition: 'oTransitionEnd otransitionend', 93 transition: 'transitionend' 94 }, transition; 72 95 73 /** 74 * @since 3.9.0 75 */ 76 activate: function() { 77 var library = this.get('library'), 78 editLibrary = this.get('editLibrary'), 79 edit = this.frame.state( this.get('collectionType') + '-edit' ).get('library'); 96 transition = _.find( _.keys( transitions ), function( transition ) { 97 return ! _.isUndefined( style[ transition ] ); 98 }); 80 99 81 if ( editLibrary && editLibrary !== edit ) { 82 library.unobserve( editLibrary ); 100 return transition && { 101 end: transitions[ transition ] 102 }; 103 }()); 104 105 /** 106 * A shared event bus used to provide events into 107 * the media workflows that 3rd-party devs can use to hook 108 * in. 109 */ 110 media.events = _.extend( {}, Backbone.Events ); 111 112 /** 113 * Makes it easier to bind events using transitions. 114 * 115 * @param {string} selector 116 * @param {Number} sensitivity 117 * @returns {Promise} 118 */ 119 media.transition = function( selector, sensitivity ) { 120 var deferred = $.Deferred(); 121 122 sensitivity = sensitivity || 2000; 123 124 if ( $.support.transition ) { 125 if ( ! (selector instanceof $) ) { 126 selector = $( selector ); 83 127 } 84 128 85 // Accepts attachments that exist in the original library and 86 // that do not exist in gallery's library. 87 library.validator = function( attachment ) { 88 return !! this.mirroring.get( attachment.cid ) && ! edit.get( attachment.cid ) && Selection.prototype.validator.apply( this, arguments ); 89 }; 129 // Resolve the deferred when the first element finishes animating. 130 selector.first().one( $.support.transition.end, deferred.resolve ); 90 131 91 // Reset the library to ensure that all attachments are re-added 92 // to the collection. Do so silently, as calling `observe` will 93 // trigger the `reset` event. 94 library.reset( library.mirroring.models, { silent: true }); 95 library.observe( edit ); 96 this.set('editLibrary', edit); 132 // Just in case the event doesn't trigger, fire a callback. 133 _.delay( deferred.resolve, sensitivity ); 97 134 98 Library.prototype.activate.apply( this, arguments ); 135 // Otherwise, execute on the spot. 136 } else { 137 deferred.resolve(); 99 138 } 100 });101 139 102 module.exports = CollectionAdd; 140 return deferred.promise(); 141 }; 103 142 104 },{}],2:[function(require,module,exports){ 105 var Library = wp.media.controller.Library, 106 l10n = wp.media.view.l10n, 107 $ = jQuery, 108 CollectionEdit; 143 media.controller.Region = __webpack_require__( 27 ); 144 media.controller.StateMachine = __webpack_require__( 28 ); 145 media.controller.State = __webpack_require__( 29 ); 146 147 media.selectionSync = __webpack_require__( 30 ); 148 media.controller.Library = __webpack_require__( 31 ); 149 media.controller.ImageDetails = __webpack_require__( 32 ); 150 media.controller.GalleryEdit = __webpack_require__( 33 ); 151 media.controller.GalleryAdd = __webpack_require__( 34 ); 152 media.controller.CollectionEdit = __webpack_require__( 35 ); 153 media.controller.CollectionAdd = __webpack_require__( 36 ); 154 media.controller.FeaturedImage = __webpack_require__( 37 ); 155 media.controller.ReplaceImage = __webpack_require__( 38 ); 156 media.controller.EditImage = __webpack_require__( 39 ); 157 media.controller.MediaLibrary = __webpack_require__( 40 ); 158 media.controller.Embed = __webpack_require__( 41 ); 159 media.controller.Cropper = __webpack_require__( 42 ); 160 media.controller.CustomizeImageCropper = __webpack_require__( 43 ); 161 media.controller.SiteIconCropper = __webpack_require__( 44 ); 162 163 media.View = __webpack_require__( 45 ); 164 media.view.Frame = __webpack_require__( 46 ); 165 media.view.MediaFrame = __webpack_require__( 47 ); 166 media.view.MediaFrame.Select = __webpack_require__( 48 ); 167 media.view.MediaFrame.Post = __webpack_require__( 49 ); 168 media.view.MediaFrame.ImageDetails = __webpack_require__( 50 ); 169 media.view.Modal = __webpack_require__( 51 ); 170 media.view.FocusManager = __webpack_require__( 52 ); 171 media.view.UploaderWindow = __webpack_require__( 53 ); 172 media.view.EditorUploader = __webpack_require__( 54 ); 173 media.view.UploaderInline = __webpack_require__( 55 ); 174 media.view.UploaderStatus = __webpack_require__( 56 ); 175 media.view.UploaderStatusError = __webpack_require__( 57 ); 176 media.view.Toolbar = __webpack_require__( 58 ); 177 media.view.Toolbar.Select = __webpack_require__( 59 ); 178 media.view.Toolbar.Embed = __webpack_require__( 60 ); 179 media.view.Button = __webpack_require__( 61 ); 180 media.view.ButtonGroup = __webpack_require__( 62 ); 181 media.view.PriorityList = __webpack_require__( 63 ); 182 media.view.MenuItem = __webpack_require__( 64 ); 183 media.view.Menu = __webpack_require__( 65 ); 184 media.view.RouterItem = __webpack_require__( 66 ); 185 media.view.Router = __webpack_require__( 67 ); 186 media.view.Sidebar = __webpack_require__( 68 ); 187 media.view.Attachment = __webpack_require__( 69 ); 188 media.view.Attachment.Library = __webpack_require__( 70 ); 189 media.view.Attachment.EditLibrary = __webpack_require__( 71 ); 190 media.view.Attachments = __webpack_require__( 72 ); 191 media.view.Search = __webpack_require__( 73 ); 192 media.view.AttachmentFilters = __webpack_require__( 74 ); 193 media.view.DateFilter = __webpack_require__( 75 ); 194 media.view.AttachmentFilters.Uploaded = __webpack_require__( 76 ); 195 media.view.AttachmentFilters.All = __webpack_require__( 77 ); 196 media.view.AttachmentsBrowser = __webpack_require__( 78 ); 197 media.view.Selection = __webpack_require__( 79 ); 198 media.view.Attachment.Selection = __webpack_require__( 80 ); 199 media.view.Attachments.Selection = __webpack_require__( 81 ); 200 media.view.Attachment.EditSelection = __webpack_require__( 82 ); 201 media.view.Settings = __webpack_require__( 83 ); 202 media.view.Settings.AttachmentDisplay = __webpack_require__( 84 ); 203 media.view.Settings.Gallery = __webpack_require__( 85 ); 204 media.view.Settings.Playlist = __webpack_require__( 86 ); 205 media.view.Attachment.Details = __webpack_require__( 87 ); 206 media.view.AttachmentCompat = __webpack_require__( 88 ); 207 media.view.Iframe = __webpack_require__( 89 ); 208 media.view.Embed = __webpack_require__( 90 ); 209 media.view.Label = __webpack_require__( 91 ); 210 media.view.EmbedUrl = __webpack_require__( 92 ); 211 media.view.EmbedLink = __webpack_require__( 93 ); 212 media.view.EmbedImage = __webpack_require__( 94 ); 213 media.view.ImageDetails = __webpack_require__( 95 ); 214 media.view.Cropper = __webpack_require__( 96 ); 215 media.view.SiteIconCropper = __webpack_require__( 97 ); 216 media.view.SiteIconPreview = __webpack_require__( 98 ); 217 media.view.EditImage = __webpack_require__( 99 ); 218 media.view.Spinner = __webpack_require__( 100 ); 219 220 221 /***/ }), 222 /* 27 */ 223 /***/ (function(module, exports) { 109 224 110 225 /** 111 * wp.media.controller. CollectionEdit226 * wp.media.controller.Region 112 227 * 113 * A state for editing a collection, which is used by audio and video playlists, 114 * and can be used for other collections. 228 * A region is a persistent application layout area. 229 * 230 * A region assumes one mode at any time, and can be switched to another. 231 * 232 * When mode changes, events are triggered on the region's parent view. 233 * The parent view will listen to specific events and fill the region with an 234 * appropriate view depending on mode. For example, a frame listens for the 235 * 'browse' mode t be activated on the 'content' view and then fills the region 236 * with an AttachmentsBrowser view. 115 237 * 116 238 * @memberOf wp.media.controller 117 239 * 118 240 * @class 119 * @augments wp.media.controller.Library120 * @augments wp.media.controller.State121 * @augments Backbone.Model122 241 * 123 * @param {object} [attributes] The attributes hash passed to the state. 124 * @param {string} attributes.title Title for the state. Displays in the media menu and the frame's title region. 125 * @param {wp.media.model.Attachments} [attributes.library] The attachments collection to edit. 126 * If one is not supplied, an empty media.model.Selection collection is created. 127 * @param {boolean} [attributes.multiple=false] Whether multi-select is enabled. 128 * @param {string} [attributes.content=browse] Initial mode for the content region. 129 * @param {string} attributes.menu Initial mode for the menu region. @todo this needs a better explanation. 130 * @param {boolean} [attributes.searchable=false] Whether the library is searchable. 131 * @param {boolean} [attributes.sortable=true] Whether the Attachments should be sortable. Depends on the orderby property being set to menuOrder on the attachments collection. 132 * @param {boolean} [attributes.date=true] Whether to show the date filter in the browser's toolbar. 133 * @param {boolean} [attributes.describe=true] Whether to offer UI to describe the attachments - e.g. captioning images in a gallery. 134 * @param {boolean} [attributes.dragInfo=true] Whether to show instructional text about the attachments being sortable. 135 * @param {boolean} [attributes.dragInfoText] Instructional text about the attachments being sortable. 136 * @param {int} [attributes.idealColumnWidth=170] The ideal column width in pixels for attachments. 137 * @param {boolean} [attributes.editing=false] Whether the gallery is being created, or editing an existing instance. 138 * @param {int} [attributes.priority=60] The priority for the state link in the media menu. 139 * @param {boolean} [attributes.syncSelection=false] Whether the Attachments selection should be persisted from the last state. 140 * Defaults to false for this state, because the library passed in *is* the selection. 141 * @param {view} [attributes.SettingsView] The view to edit the collection instance settings (e.g. Playlist settings with "Show tracklist" checkbox). 142 * @param {view} [attributes.AttachmentView] The single `Attachment` view to be used in the `Attachments`. 143 * If none supplied, defaults to wp.media.view.Attachment.EditLibrary. 144 * @param {string} attributes.type The collection's media type. (e.g. 'video'). 145 * @param {string} attributes.collectionType The collection type. (e.g. 'playlist'). 242 * @param {object} options Options hash for the region. 243 * @param {string} options.id Unique identifier for the region. 244 * @param {Backbone.View} options.view A parent view the region exists within. 245 * @param {string} options.selector jQuery selector for the region within the parent view. 146 246 */ 147 CollectionEdit = Library.extend(/** @lends wp.media.controller.CollectionEdit.prototype */{ 148 defaults: { 149 multiple: false, 150 sortable: true, 151 date: false, 152 searchable: false, 153 content: 'browse', 154 describe: true, 155 dragInfo: true, 156 idealColumnWidth: 170, 157 editing: false, 158 priority: 60, 159 SettingsView: false, 160 syncSelection: false 161 }, 247 var Region = function( options ) { 248 _.extend( this, _.pick( options || {}, 'id', 'view', 'selector' ) ); 249 }; 250 251 // Use Backbone's self-propagating `extend` inheritance method. 252 Region.extend = Backbone.Model.extend; 162 253 254 _.extend( Region.prototype,/** @lends wp.media.controller.Region.prototype */{ 163 255 /** 164 * @since 3.9.0 256 * Activate a mode. 257 * 258 * @since 3.5.0 259 * 260 * @param {string} mode 261 * 262 * @fires Region#activate 263 * @fires Region#deactivate 264 * 265 * @returns {wp.media.controller.Region} Returns itself to allow chaining. 165 266 */ 166 initialize: function() { 167 var collectionType = this.get('collectionType'); 168 169 if ( 'video' === this.get( 'type' ) ) { 170 collectionType = 'video-' + collectionType; 171 } 172 173 this.set( 'id', collectionType + '-edit' ); 174 this.set( 'toolbar', collectionType + '-edit' ); 175 176 // If we haven't been provided a `library`, create a `Selection`. 177 if ( ! this.get('library') ) { 178 this.set( 'library', new wp.media.model.Selection() ); 267 mode: function( mode ) { 268 if ( ! mode ) { 269 return this._mode; 179 270 } 180 // The single `Attachment` view to be used in the `Attachments` view.181 if ( ! this.get('AttachmentView')) {182 this.set( 'AttachmentView', wp.media.view.Attachment.EditLibrary );271 // Bail if we're trying to change to the current mode. 272 if ( mode === this._mode ) { 273 return this; 183 274 } 184 Library.prototype.initialize.apply( this, arguments );185 },186 187 /**188 * @since 3.9.0189 */190 activate: function() {191 var library = this.get('library');192 275 193 // Limit the library to images only. 194 library.props.set( 'type', this.get( 'type' ) ); 195 196 // Watch for uploaded attachments. 197 this.get('library').observe( wp.Uploader.queue ); 276 /** 277 * Region mode deactivation event. 278 * 279 * @event wp.media.controller.Region#deactivate 280 */ 281 this.trigger('deactivate'); 198 282 199 this.frame.on( 'content:render:browse', this.renderSettings, this ); 283 this._mode = mode; 284 this.render( mode ); 200 285 201 Library.prototype.activate.apply( this, arguments ); 286 /** 287 * Region mode activation event. 288 * 289 * @event wp.media.controller.Region#activate 290 */ 291 this.trigger('activate'); 292 return this; 202 293 }, 203 204 294 /** 205 * @since 3.9.0 295 * Render a mode. 296 * 297 * @since 3.5.0 298 * 299 * @param {string} mode 300 * 301 * @fires Region#create 302 * @fires Region#render 303 * 304 * @returns {wp.media.controller.Region} Returns itself to allow chaining 206 305 */ 207 deactivate: function() { 208 // Stop watching for uploaded attachments. 209 this.get('library').unobserve( wp.Uploader.queue ); 306 render: function( mode ) { 307 // If the mode isn't active, activate it. 308 if ( mode && mode !== this._mode ) { 309 return this.mode( mode ); 310 } 210 311 211 this.frame.off( 'content:render:browse', this.renderSettings, this ); 312 var set = { view: null }, 313 view; 212 314 213 Library.prototype.deactivate.apply( this, arguments ); 315 /** 316 * Create region view event. 317 * 318 * Region view creation takes place in an event callback on the frame. 319 * 320 * @event wp.media.controller.Region#create 321 * @type {object} 322 * @property {object} view 323 */ 324 this.trigger( 'create', set ); 325 view = set.view; 326 327 /** 328 * Render region view event. 329 * 330 * Region view creation takes place in an event callback on the frame. 331 * 332 * @event wp.media.controller.Region#render 333 * @type {object} 334 */ 335 this.trigger( 'render', view ); 336 if ( view ) { 337 this.set( view ); 338 } 339 return this; 214 340 }, 215 341 216 342 /** 217 * Render the collection embed settings view in the browser sidebar. 218 * 219 * @todo This is against the pattern elsewhere in media. Typically the frame 220 * is responsible for adding region mode callbacks. Explain. 343 * Get the region's view. 221 344 * 222 * @since 3. 9.0345 * @since 3.5.0 223 346 * 224 * @ param {wp.media.view.attachmentsBrowser} The attachments browser view.347 * @returns {wp.media.View} 225 348 */ 226 renderSettings: function( attachmentsBrowserView ) { 227 var library = this.get('library'), 228 collectionType = this.get('collectionType'), 229 dragInfoText = this.get('dragInfoText'), 230 SettingsView = this.get('SettingsView'), 231 obj = {}; 349 get: function() { 350 return this.view.views.first( this.selector ); 351 }, 232 352 233 if ( ! library || ! attachmentsBrowserView ) { 234 return; 353 /** 354 * Set the region's view as a subview of the frame. 355 * 356 * @since 3.5.0 357 * 358 * @param {Array|Object} views 359 * @param {Object} [options={}] 360 * @returns {wp.Backbone.Subviews} Subviews is returned to allow chaining 361 */ 362 set: function( views, options ) { 363 if ( options ) { 364 options.add = false; 235 365 } 366 return this.view.views.set( this.selector, views, options ); 367 }, 236 368 237 library[ collectionType ] = library[ collectionType ] || new Backbone.Model(); 238 239 obj[ collectionType ] = new SettingsView({ 240 controller: this, 241 model: library[ collectionType ], 242 priority: 40 243 }); 244 245 attachmentsBrowserView.sidebar.set( obj ); 369 /** 370 * Trigger regional view events on the frame. 371 * 372 * @since 3.5.0 373 * 374 * @param {string} event 375 * @returns {undefined|wp.media.controller.Region} Returns itself to allow chaining. 376 */ 377 trigger: function( event ) { 378 var base, args; 246 379 247 if ( dragInfoText ) { 248 attachmentsBrowserView.toolbar.set( 'dragInfo', new wp.media.View({ 249 el: $( '<div class="instructions">' + dragInfoText + '</div>' )[0], 250 priority: -40 251 }) ); 380 if ( ! this._mode ) { 381 return; 252 382 } 253 383 254 // Add the 'Reverse order' button to the toolbar. 255 attachmentsBrowserView.toolbar.set( 'reverse', { 256 text: l10n.reverseOrder, 257 priority: 80, 384 args = _.toArray( arguments ); 385 base = this.id + ':' + event; 258 386 259 click: function() { 260 library.reset( library.toArray().reverse() ); 261 } 262 }); 387 // Trigger `{this.id}:{event}:{this._mode}` event on the frame. 388 args[0] = base + ':' + this._mode; 389 this.view.trigger.apply( this.view, args ); 390 391 // Trigger `{this.id}:{event}` event on the frame. 392 args[0] = base; 393 this.view.trigger.apply( this.view, args ); 394 return this; 263 395 } 264 396 }); 265 397 266 module.exports = CollectionEdit;398 module.exports = Region; 267 399 268 },{}],3:[function(require,module,exports){ 269 var l10n = wp.media.view.l10n, 270 Cropper; 400 401 /***/ }), 402 /* 28 */ 403 /***/ (function(module, exports) { 271 404 272 405 /** 273 * wp.media.controller. Cropper406 * wp.media.controller.StateMachine 274 407 * 275 * A state for cropping an image. 408 * A state machine keeps track of state. It is in one state at a time, 409 * and can change from one state to another. 410 * 411 * States are stored as models in a Backbone collection. 276 412 * 277 413 * @memberOf wp.media.controller 278 414 * 415 * @since 3.5.0 416 * 279 417 * @class 280 * @augments wp.media.controller.State281 418 * @augments Backbone.Model 419 * @mixin 420 * @mixes Backbone.Events 421 * 422 * @param {Array} states 282 423 */ 283 Cropper = wp.media.controller.State.extend(/** @lends wp.media.controller.Cropper.prototype */{ 284 defaults: { 285 id: 'cropper', 286 title: l10n.cropImage, 287 // Region mode defaults. 288 toolbar: 'crop', 289 content: 'crop', 290 router: false, 291 canSkipCrop: false, 292 293 // Default doCrop Ajax arguments to allow the Customizer (for example) to inject state. 294 doCropArgs: {} 295 }, 424 var StateMachine = function( states ) { 425 // @todo This is dead code. The states collection gets created in media.view.Frame._createStates. 426 this.states = new Backbone.Collection( states ); 427 }; 296 428 297 activate: function() { 298 this.frame.on( 'content:create:crop', this.createCropContent, this ); 299 this.frame.on( 'close', this.removeCropper, this ); 300 this.set('selection', new Backbone.Collection(this.frame._selection.single)); 301 }, 429 // Use Backbone's self-propagating `extend` inheritance method. 430 StateMachine.extend = Backbone.Model.extend; 302 431 303 deactivate: function() { 304 this.frame.toolbar.mode('browse'); 305 }, 432 _.extend( StateMachine.prototype, Backbone.Events,/** @lends wp.media.controller.StateMachine.prototype */{ 433 /** 434 * Fetch a state. 435 * 436 * If no `id` is provided, returns the active state. 437 * 438 * Implicitly creates states. 439 * 440 * Ensure that the `states` collection exists so the `StateMachine` 441 * can be used as a mixin. 442 * 443 * @since 3.5.0 444 * 445 * @param {string} id 446 * @returns {wp.media.controller.State} Returns a State model 447 * from the StateMachine collection 448 */ 449 state: function( id ) { 450 this.states = this.states || new Backbone.Collection(); 306 451 307 createCropContent: function() { 308 this.cropperView = new wp.media.view.Cropper({ 309 controller: this, 310 attachment: this.get('selection').first() 311 }); 312 this.cropperView.on('image-loaded', this.createCropToolbar, this); 313 this.frame.content.set(this.cropperView); 452 // Default to the active state. 453 id = id || this._state; 314 454 455 if ( id && ! this.states.get( id ) ) { 456 this.states.add({ id: id }); 457 } 458 return this.states.get( id ); 315 459 }, 316 removeCropper: function() {317 this.imgSelect.cancelSelection();318 this.imgSelect.setOptions({remove: true});319 this.imgSelect.update();320 this.cropperView.remove();321 },322 createCropToolbar: function() {323 var canSkipCrop, toolbarOptions;324 460 325 canSkipCrop = this.get('canSkipCrop') || false; 461 /** 462 * Sets the active state. 463 * 464 * Bail if we're trying to select the current state, if we haven't 465 * created the `states` collection, or are trying to select a state 466 * that does not exist. 467 * 468 * @since 3.5.0 469 * 470 * @param {string} id 471 * 472 * @fires wp.media.controller.State#deactivate 473 * @fires wp.media.controller.State#activate 474 * 475 * @returns {wp.media.controller.StateMachine} Returns itself to allow chaining 476 */ 477 setState: function( id ) { 478 var previous = this.state(); 326 479 327 toolbarOptions = { 328 controller: this.frame, 329 items: { 330 insert: { 331 style: 'primary', 332 text: l10n.cropImage, 333 priority: 80, 334 requires: { library: false, selection: false }, 335 336 click: function() { 337 var controller = this.controller, 338 selection; 339 340 selection = controller.state().get('selection').first(); 341 selection.set({cropDetails: controller.state().imgSelect.getSelection()}); 342 343 this.$el.text(l10n.cropping); 344 this.$el.attr('disabled', true); 345 346 controller.state().doCrop( selection ).done( function( croppedImage ) { 347 controller.trigger('cropped', croppedImage ); 348 controller.close(); 349 }).fail( function() { 350 controller.trigger('content:error:crop'); 351 }); 352 } 353 } 354 } 355 }; 480 if ( ( previous && id === previous.id ) || ! this.states || ! this.states.get( id ) ) { 481 return this; 482 } 356 483 357 if ( canSkipCrop ) { 358 _.extend( toolbarOptions.items, { 359 skip: { 360 style: 'secondary', 361 text: l10n.skipCropping, 362 priority: 70, 363 requires: { library: false, selection: false }, 364 click: function() { 365 var selection = this.controller.state().get('selection').first(); 366 this.controller.state().cropperView.remove(); 367 this.controller.trigger('skippedcrop', selection); 368 this.controller.close(); 369 } 370 } 371 }); 484 if ( previous ) { 485 previous.trigger('deactivate'); 486 this._lastState = previous.id; 372 487 } 373 488 374 this.frame.toolbar.set( new wp.media.view.Toolbar(toolbarOptions) ); 489 this._state = id; 490 this.state().trigger('activate'); 491 492 return this; 375 493 }, 376 494 377 doCrop: function( attachment ) { 378 return wp.ajax.post( 'custom-header-crop', _.extend( 379 {}, 380 this.defaults.doCropArgs, 381 { 382 nonce: attachment.get( 'nonces' ).edit, 383 id: attachment.get( 'id' ), 384 cropDetails: attachment.get( 'cropDetails' ) 385 } 386 ) ); 495 /** 496 * Returns the previous active state. 497 * 498 * Call the `state()` method with no parameters to retrieve the current 499 * active state. 500 * 501 * @since 3.5.0 502 * 503 * @returns {wp.media.controller.State} Returns a State model 504 * from the StateMachine collection 505 */ 506 lastState: function() { 507 if ( this._lastState ) { 508 return this.state( this._lastState ); 509 } 387 510 } 388 511 }); 389 512 390 module.exports = Cropper; 391 392 },{}],4:[function(require,module,exports){ 393 var Controller = wp.media.controller, 394 CustomizeImageCropper; 395 396 /** 397 * wp.media.controller.CustomizeImageCropper 398 * 399 * @memberOf wp.media.controller 400 * 401 * A state for cropping an image. 402 * 403 * @class 404 * @augments wp.media.controller.Cropper 405 * @augments wp.media.controller.State 406 * @augments Backbone.Model 407 */ 408 CustomizeImageCropper = Controller.Cropper.extend(/** @lends wp.media.controller.CustomizeImageCropper.prototype */{ 409 doCrop: function( attachment ) { 410 var cropDetails = attachment.get( 'cropDetails' ), 411 control = this.get( 'control' ), 412 ratio = cropDetails.width / cropDetails.height; 413 414 // Use crop measurements when flexible in both directions. 415 if ( control.params.flex_width && control.params.flex_height ) { 416 cropDetails.dst_width = cropDetails.width; 417 cropDetails.dst_height = cropDetails.height; 418 419 // Constrain flexible side based on image ratio and size of the fixed side. 420 } else { 421 cropDetails.dst_width = control.params.flex_width ? control.params.height * ratio : control.params.width; 422 cropDetails.dst_height = control.params.flex_height ? control.params.width / ratio : control.params.height; 423 } 424 425 return wp.ajax.post( 'crop-image', { 426 wp_customize: 'on', 427 nonce: attachment.get( 'nonces' ).edit, 428 id: attachment.get( 'id' ), 429 context: control.id, 430 cropDetails: cropDetails 431 } ); 432 } 513 // Map all event binding and triggering on a StateMachine to its `states` collection. 514 _.each([ 'on', 'off', 'trigger' ], function( method ) { 515 /** 516 * @function on 517 * @memberOf wp.media.controller.StateMachine 518 * @instance 519 * @returns {wp.media.controller.StateMachine} Returns itself to allow chaining. 520 */ 521 /** 522 * @function off 523 * @memberOf wp.media.controller.StateMachine 524 * @instance 525 * @returns {wp.media.controller.StateMachine} Returns itself to allow chaining. 526 */ 527 /** 528 * @function trigger 529 * @memberOf wp.media.controller.StateMachine 530 * @instance 531 * @returns {wp.media.controller.StateMachine} Returns itself to allow chaining. 532 */ 533 StateMachine.prototype[ method ] = function() { 534 // Ensure that the `states` collection exists so the `StateMachine` 535 // can be used as a mixin. 536 this.states = this.states || new Backbone.Collection(); 537 // Forward the method to the `states` collection. 538 this.states[ method ].apply( this.states, arguments ); 539 return this; 540 }; 433 541 }); 434 542 435 module.exports = CustomizeImageCropper;543 module.exports = StateMachine; 436 544 437 },{}],5:[function(require,module,exports){ 438 var l10n = wp.media.view.l10n, 439 EditImage; 545 546 /***/ }), 547 /* 29 */ 548 /***/ (function(module, exports) { 440 549 441 550 /** 442 * wp.media.controller. EditImage551 * wp.media.controller.State 443 552 * 444 * A state for editing (cropping, etc.) an image. 553 * A state is a step in a workflow that when set will trigger the controllers 554 * for the regions to be updated as specified in the frame. 555 * 556 * A state has an event-driven lifecycle: 557 * 558 * 'ready' triggers when a state is added to a state machine's collection. 559 * 'activate' triggers when a state is activated by a state machine. 560 * 'deactivate' triggers when a state is deactivated by a state machine. 561 * 'reset' is not triggered automatically. It should be invoked by the 562 * proper controller to reset the state to its default. 445 563 * 446 564 * @memberOf wp.media.controller 447 565 * 448 566 * @class 449 * @augments wp.media.controller.State450 567 * @augments Backbone.Model 451 *452 * @param {object} attributes The attributes hash passed to the state.453 * @param {wp.media.model.Attachment} attributes.model The attachment.454 * @param {string} [attributes.id=edit-image] Unique identifier.455 * @param {string} [attributes.title=Edit Image] Title for the state. Displays in the media menu and the frame's title region.456 * @param {string} [attributes.content=edit-image] Initial mode for the content region.457 * @param {string} [attributes.toolbar=edit-image] Initial mode for the toolbar region.458 * @param {string} [attributes.menu=false] Initial mode for the menu region.459 * @param {string} [attributes.url] Unused. @todo Consider removal.460 568 */ 461 EditImage = wp.media.controller.State.extend(/** @lends wp.media.controller.EditImage.prototype */{ 462 defaults: { 463 id: 'edit-image', 464 title: l10n.editImage, 465 menu: false, 466 toolbar: 'edit-image', 467 content: 'edit-image', 468 url: '' 569 var State = Backbone.Model.extend(/** @lends wp.media.controller.State.prototype */{ 570 /** 571 * Constructor. 572 * 573 * @since 3.5.0 574 */ 575 constructor: function() { 576 this.on( 'activate', this._preActivate, this ); 577 this.on( 'activate', this.activate, this ); 578 this.on( 'activate', this._postActivate, this ); 579 this.on( 'deactivate', this._deactivate, this ); 580 this.on( 'deactivate', this.deactivate, this ); 581 this.on( 'reset', this.reset, this ); 582 this.on( 'ready', this._ready, this ); 583 this.on( 'ready', this.ready, this ); 584 /** 585 * Call parent constructor with passed arguments 586 */ 587 Backbone.Model.apply( this, arguments ); 588 this.on( 'change:menu', this._updateMenu, this ); 469 589 }, 590 /** 591 * Ready event callback. 592 * 593 * @abstract 594 * @since 3.5.0 595 */ 596 ready: function() {}, 470 597 471 598 /** 472 * @since 3.9.0 599 * Activate event callback. 600 * 601 * @abstract 602 * @since 3.5.0 473 603 */ 474 activate: function() { 475 this.frame.on( 'toolbar:render:edit-image', _.bind( this.toolbar, this ) ); 476 }, 604 activate: function() {}, 477 605 478 606 /** 479 * @since 3.9.0 607 * Deactivate event callback. 608 * 609 * @abstract 610 * @since 3.5.0 480 611 */ 481 deactivate: function() { 482 this.frame.off( 'toolbar:render:edit-image' ); 483 }, 612 deactivate: function() {}, 484 613 485 614 /** 486 * @since 3.9.0 615 * Reset event callback. 616 * 617 * @abstract 618 * @since 3.5.0 487 619 */ 488 toolbar: function() { 489 var frame = this.frame, 490 lastState = frame.lastState(), 491 previous = lastState && lastState.id; 620 reset: function() {}, 492 621 493 frame.toolbar.set( new wp.media.view.Toolbar({ 494 controller: frame, 495 items: { 496 back: { 497 style: 'primary', 498 text: l10n.back, 499 priority: 20, 500 click: function() { 501 if ( previous ) { 502 frame.setState( previous ); 503 } else { 504 frame.close(); 505 } 506 } 507 } 508 } 509 }) ); 510 } 511 }); 622 /** 623 * @access private 624 * @since 3.5.0 625 */ 626 _ready: function() { 627 this._updateMenu(); 628 }, 512 629 513 module.exports = EditImage; 630 /** 631 * @access private 632 * @since 3.5.0 633 */ 634 _preActivate: function() { 635 this.active = true; 636 }, 514 637 515 },{}],6:[function(require,module,exports){ 516 var l10n = wp.media.view.l10n, 517 $ = Backbone.$, 518 Embed; 638 /** 639 * @access private 640 * @since 3.5.0 641 */ 642 _postActivate: function() { 643 this.on( 'change:menu', this._menu, this ); 644 this.on( 'change:titleMode', this._title, this ); 645 this.on( 'change:content', this._content, this ); 646 this.on( 'change:toolbar', this._toolbar, this ); 519 647 520 /** 521 * wp.media.controller.Embed 522 * 523 * A state for embedding media from a URL. 524 * 525 * @memberOf wp.media.controller 526 * 527 * @class 528 * @augments wp.media.controller.State 529 * @augments Backbone.Model 530 * 531 * @param {object} attributes The attributes hash passed to the state. 532 * @param {string} [attributes.id=embed] Unique identifier. 533 * @param {string} [attributes.title=Insert From URL] Title for the state. Displays in the media menu and the frame's title region. 534 * @param {string} [attributes.content=embed] Initial mode for the content region. 535 * @param {string} [attributes.menu=default] Initial mode for the menu region. 536 * @param {string} [attributes.toolbar=main-embed] Initial mode for the toolbar region. 537 * @param {string} [attributes.menu=false] Initial mode for the menu region. 538 * @param {int} [attributes.priority=120] The priority for the state link in the media menu. 539 * @param {string} [attributes.type=link] The type of embed. Currently only link is supported. 540 * @param {string} [attributes.url] The embed URL. 541 * @param {object} [attributes.metadata={}] Properties of the embed, which will override attributes.url if set. 542 */ 543 Embed = wp.media.controller.State.extend(/** @lends wp.media.controller.Embed.prototype */{ 544 defaults: { 545 id: 'embed', 546 title: l10n.insertFromUrlTitle, 547 content: 'embed', 548 menu: 'default', 549 toolbar: 'main-embed', 550 priority: 120, 551 type: 'link', 552 url: '', 553 metadata: {} 648 this.frame.on( 'title:render:default', this._renderTitle, this ); 649 650 this._title(); 651 this._menu(); 652 this._toolbar(); 653 this._content(); 654 this._router(); 554 655 }, 555 656 556 // The amount of time used when debouncing the scan. 557 sensitivity: 400, 657 /** 658 * @access private 659 * @since 3.5.0 660 */ 661 _deactivate: function() { 662 this.active = false; 558 663 559 initialize: function(options) { 560 this.metadata = options.metadata; 561 this.debouncedScan = _.debounce( _.bind( this.scan, this ), this.sensitivity ); 562 this.props = new Backbone.Model( this.metadata || { url: '' }); 563 this.props.on( 'change:url', this.debouncedScan, this ); 564 this.props.on( 'change:url', this.refresh, this ); 565 this.on( 'scan', this.scanImage, this ); 664 this.frame.off( 'title:render:default', this._renderTitle, this ); 665 666 this.off( 'change:menu', this._menu, this ); 667 this.off( 'change:titleMode', this._title, this ); 668 this.off( 'change:content', this._content, this ); 669 this.off( 'change:toolbar', this._toolbar, this ); 566 670 }, 567 671 568 672 /** 569 * Trigger a scan of the embedded URL's content for metadata required to embed. 570 * 571 * @fires wp.media.controller.Embed#scan 673 * @access private 674 * @since 3.5.0 572 675 */ 573 scan: function() { 574 var scanners, 575 embed = this, 576 attributes = { 577 type: 'link', 578 scanners: [] 579 }; 676 _title: function() { 677 this.frame.title.render( this.get('titleMode') || 'default' ); 678 }, 580 679 581 // Scan is triggered with the list of `attributes` to set on the 582 // state, useful for the 'type' attribute and 'scanners' attribute, 583 // an array of promise objects for asynchronous scan operations. 584 if ( this.props.get('url') ) { 585 this.trigger( 'scan', attributes ); 586 } 680 /** 681 * @access private 682 * @since 3.5.0 683 */ 684 _renderTitle: function( view ) { 685 view.$el.text( this.get('title') || '' ); 686 }, 587 687 588 if ( attributes.scanners.length ) { 589 scanners = attributes.scanners = $.when.apply( $, attributes.scanners ); 590 scanners.always( function() { 591 if ( embed.get('scanners') === scanners ) { 592 embed.set( 'loading', false ); 593 } 594 }); 595 } else { 596 attributes.scanners = null; 688 /** 689 * @access private 690 * @since 3.5.0 691 */ 692 _router: function() { 693 var router = this.frame.router, 694 mode = this.get('router'), 695 view; 696 697 this.frame.$el.toggleClass( 'hide-router', ! mode ); 698 if ( ! mode ) { 699 return; 597 700 } 598 701 599 attributes.loading = !! attributes.scanners; 600 this.set( attributes ); 702 this.frame.router.render( mode ); 703 704 view = router.get(); 705 if ( view && view.select ) { 706 view.select( this.frame.content.mode() ); 707 } 601 708 }, 709 602 710 /** 603 * Try scanning the embed as an image to discover its dimensions. 604 * 605 * @param {Object} attributes 711 * @access private 712 * @since 3.5.0 606 713 */ 607 scanImage: function( attributes ) { 608 var frame = this.frame, 609 state = this, 610 url = this.props.get('url'), 611 image = new Image(), 612 deferred = $.Deferred(); 714 _menu: function() { 715 var menu = this.frame.menu, 716 mode = this.get('menu'), 717 view; 613 718 614 attributes.scanners.push( deferred.promise() ); 719 this.frame.$el.toggleClass( 'hide-menu', ! mode ); 720 if ( ! mode ) { 721 return; 722 } 615 723 616 // Try to load the image and find its width/height. 617 image.onload = function() { 618 deferred.resolve(); 724 menu.mode( mode ); 619 725 620 if ( state !== frame.state() || url !== state.props.get('url') ) { 621 return; 622 } 726 view = menu.get(); 727 if ( view && view.select ) { 728 view.select( this.id ); 729 } 730 }, 623 731 624 state.set({ 625 type: 'image' 626 }); 732 /** 733 * @access private 734 * @since 3.5.0 735 */ 736 _updateMenu: function() { 737 var previous = this.previous('menu'), 738 menu = this.get('menu'); 627 739 628 state.props.set({ 629 width: image.width, 630 height: image.height 631 }); 632 }; 740 if ( previous ) { 741 this.frame.off( 'menu:render:' + previous, this._renderMenu, this ); 742 } 633 743 634 image.onerror = deferred.reject; 635 image.src = url; 744 if ( menu ) { 745 this.frame.on( 'menu:render:' + menu, this._renderMenu, this ); 746 } 636 747 }, 637 748 638 refresh: function() { 639 this.frame.toolbar.get().refresh(); 640 }, 749 /** 750 * Create a view in the media menu for the state. 751 * 752 * @access private 753 * @since 3.5.0 754 * 755 * @param {media.view.Menu} view The menu view. 756 */ 757 _renderMenu: function( view ) { 758 var menuItem = this.get('menuItem'), 759 title = this.get('title'), 760 priority = this.get('priority'); 641 761 642 reset: function() {643 this.props.clear().set({ url: '' });762 if ( ! menuItem && title ) { 763 menuItem = { text: title }; 644 764 645 if ( this.active ) { 646 this.refresh(); 765 if ( priority ) { 766 menuItem.priority = priority; 767 } 768 } 769 770 if ( ! menuItem ) { 771 return; 647 772 } 773 774 view.set( this.id, menuItem ); 648 775 } 649 776 }); 650 777 651 module.exports = Embed; 778 _.each(['toolbar','content'], function( region ) { 779 /** 780 * @access private 781 */ 782 State.prototype[ '_' + region ] = function() { 783 var mode = this.get( region ); 784 if ( mode ) { 785 this.frame[ region ].render( mode ); 786 } 787 }; 788 }); 789 790 module.exports = State; 652 791 653 },{}],7:[function(require,module,exports){ 654 var Attachment = wp.media.model.Attachment, 655 Library = wp.media.controller.Library, 656 l10n = wp.media.view.l10n, 657 FeaturedImage; 792 793 /***/ }), 794 /* 30 */ 795 /***/ (function(module, exports) { 658 796 659 797 /** 660 * wp.media. controller.FeaturedImage798 * wp.media.selectionSync 661 799 * 662 * A state for selecting a featured image for a post.800 * Sync an attachments selection in a state with another state. 663 801 * 664 * @memberOf wp.media.controller 802 * Allows for selecting multiple images in the Add Media workflow, and then 803 * switching to the Insert Gallery workflow while preserving the attachments selection. 665 804 * 666 * @class 667 * @augments wp.media.controller.Library 668 * @augments wp.media.controller.State 669 * @augments Backbone.Model 805 * @memberOf wp.media 670 806 * 671 * @param {object} [attributes] The attributes hash passed to the state. 672 * @param {string} [attributes.id=featured-image] Unique identifier. 673 * @param {string} [attributes.title=Set Featured Image] Title for the state. Displays in the media menu and the frame's title region. 674 * @param {wp.media.model.Attachments} [attributes.library] The attachments collection to browse. 675 * If one is not supplied, a collection of all images will be created. 676 * @param {boolean} [attributes.multiple=false] Whether multi-select is enabled. 677 * @param {string} [attributes.content=upload] Initial mode for the content region. 678 * Overridden by persistent user setting if 'contentUserSetting' is true. 679 * @param {string} [attributes.menu=default] Initial mode for the menu region. 680 * @param {string} [attributes.router=browse] Initial mode for the router region. 681 * @param {string} [attributes.toolbar=featured-image] Initial mode for the toolbar region. 682 * @param {int} [attributes.priority=60] The priority for the state link in the media menu. 683 * @param {boolean} [attributes.searchable=true] Whether the library is searchable. 684 * @param {boolean|string} [attributes.filterable=false] Whether the library is filterable, and if so what filters should be shown. 685 * Accepts 'all', 'uploaded', or 'unattached'. 686 * @param {boolean} [attributes.sortable=true] Whether the Attachments should be sortable. Depends on the orderby property being set to menuOrder on the attachments collection. 687 * @param {boolean} [attributes.autoSelect=true] Whether an uploaded attachment should be automatically added to the selection. 688 * @param {boolean} [attributes.describe=false] Whether to offer UI to describe attachments - e.g. captioning images in a gallery. 689 * @param {boolean} [attributes.contentUserSetting=true] Whether the content region's mode should be set and persisted per user. 690 * @param {boolean} [attributes.syncSelection=true] Whether the Attachments selection should be persisted from the last state. 807 * @mixin 691 808 */ 692 FeaturedImage = Library.extend(/** @lends wp.media.controller.FeaturedImage.prototype */{ 693 defaults: _.defaults({ 694 id: 'featured-image', 695 title: l10n.setFeaturedImageTitle, 696 multiple: false, 697 filterable: 'uploaded', 698 toolbar: 'featured-image', 699 priority: 60, 700 syncSelection: true 701 }, Library.prototype.defaults ), 702 809 var selectionSync = { 703 810 /** 704 811 * @since 3.5.0 705 812 */ 706 initialize: function() { 707 var library, comparator; 813 syncSelection: function() { 814 var selection = this.get('selection'), 815 manager = this.frame._selection; 708 816 709 // If we haven't been provided a `library`, create a `Selection`. 710 if ( ! this.get('library') ) { 711 this.set( 'library', wp.media.query({ type: 'image' }) ); 817 if ( ! this.get('syncSelection') || ! manager || ! selection ) { 818 return; 712 819 } 713 820 714 Library.prototype.initialize.apply( this, arguments ); 715 716 library = this.get('library'); 717 comparator = library.comparator; 718 719 // Overload the library's comparator to push items that are not in 720 // the mirrored query to the front of the aggregate collection. 721 library.comparator = function( a, b ) { 722 var aInQuery = !! this.mirroring.get( a.cid ), 723 bInQuery = !! this.mirroring.get( b.cid ); 724 725 if ( ! aInQuery && bInQuery ) { 726 return -1; 727 } else if ( aInQuery && ! bInQuery ) { 728 return 1; 729 } else { 730 return comparator.apply( this, arguments ); 731 } 732 }; 733 734 // Add all items in the selection to the library, so any featured 735 // images that are not initially loaded still appear. 736 library.observe( this.get('selection') ); 737 }, 738 739 /** 740 * @since 3.5.0 741 */ 742 activate: function() { 743 this.updateSelection(); 744 this.frame.on( 'open', this.updateSelection, this ); 745 746 Library.prototype.activate.apply( this, arguments ); 747 }, 748 749 /** 750 * @since 3.5.0 751 */ 752 deactivate: function() { 753 this.frame.off( 'open', this.updateSelection, this ); 821 // If the selection supports multiple items, validate the stored 822 // attachments based on the new selection's conditions. Record 823 // the attachments that are not included; we'll maintain a 824 // reference to those. Other attachments are considered in flux. 825 if ( selection.multiple ) { 826 selection.reset( [], { silent: true }); 827 selection.validateAll( manager.attachments ); 828 manager.difference = _.difference( manager.attachments.models, selection.models ); 829 } 754 830 755 Library.prototype.deactivate.apply( this, arguments ); 831 // Sync the selection's single item with the master. 832 selection.single( manager.single ); 756 833 }, 757 834 758 835 /** 836 * Record the currently active attachments, which is a combination 837 * of the selection's attachments and the set of selected 838 * attachments that this specific selection considered invalid. 839 * Reset the difference and record the single attachment. 840 * 759 841 * @since 3.5.0 760 842 */ 761 updateSelection: function() {843 recordSelection: function() { 762 844 var selection = this.get('selection'), 763 id = wp.media.view.settings.post.featuredImageId, 764 attachment; 845 manager = this.frame._selection; 765 846 766 if ( '' !== id && -1 !== id ) { 767 attachment = Attachment.get( id ); 768 attachment.fetch(); 847 if ( ! this.get('syncSelection') || ! manager || ! selection ) { 848 return; 769 849 } 770 850 771 selection.reset( attachment ? [ attachment ] : [] ); 851 if ( selection.multiple ) { 852 manager.attachments.reset( selection.toArray().concat( manager.difference ) ); 853 manager.difference = []; 854 } else { 855 manager.attachments.add( selection.toArray() ); 856 } 857 858 manager.single = selection._single; 772 859 } 773 } );860 }; 774 861 775 module.exports = FeaturedImage;862 module.exports = selectionSync; 776 863 777 },{}],8:[function(require,module,exports){ 778 var Selection = wp.media.model.Selection, 779 Library = wp.media.controller.Library, 780 l10n = wp.media.view.l10n, 781 GalleryAdd; 864 865 /***/ }), 866 /* 31 */ 867 /***/ (function(module, exports) { 868 869 var l10n = wp.media.view.l10n, 870 getUserSetting = window.getUserSetting, 871 setUserSetting = window.setUserSetting, 872 Library; 782 873 783 874 /** 784 * wp.media.controller. GalleryAdd875 * wp.media.controller.Library 785 876 * 786 * A state for selecting more images to add to a gallery.877 * A state for choosing an attachment or group of attachments from the media library. 787 878 * 788 879 * @memberOf wp.media.controller 789 880 * 790 881 * @class 791 * @augments wp.media.controller.Library792 882 * @augments wp.media.controller.State 793 883 * @augments Backbone.Model 884 * @mixes media.selectionSync 794 885 * 795 * @param {object} [attributes] The attributes hash passed to the state. 796 * @param {string} [attributes.id=gallery-library] Unique identifier. 797 * @param {string} [attributes.title=Add to Gallery] Title for the state. Displays in the frame's title region. 798 * @param {boolean} [attributes.multiple=add] Whether multi-select is enabled. @todo 'add' doesn't seem do anything special, and gets used as a boolean. 799 * @param {wp.media.model.Attachments} [attributes.library] The attachments collection to browse. 800 * If one is not supplied, a collection of all images will be created. 801 * @param {boolean|string} [attributes.filterable=uploaded] Whether the library is filterable, and if so what filters should be shown. 802 * Accepts 'all', 'uploaded', or 'unattached'. 803 * @param {string} [attributes.menu=gallery] Initial mode for the menu region. 804 * @param {string} [attributes.content=upload] Initial mode for the content region. 805 * Overridden by persistent user setting if 'contentUserSetting' is true. 806 * @param {string} [attributes.router=browse] Initial mode for the router region. 807 * @param {string} [attributes.toolbar=gallery-add] Initial mode for the toolbar region. 808 * @param {boolean} [attributes.searchable=true] Whether the library is searchable. 809 * @param {boolean} [attributes.sortable=true] Whether the Attachments should be sortable. Depends on the orderby property being set to menuOrder on the attachments collection. 810 * @param {boolean} [attributes.autoSelect=true] Whether an uploaded attachment should be automatically added to the selection. 811 * @param {boolean} [attributes.contentUserSetting=true] Whether the content region's mode should be set and persisted per user. 812 * @param {int} [attributes.priority=100] The priority for the state link in the media menu. 813 * @param {boolean} [attributes.syncSelection=false] Whether the Attachments selection should be persisted from the last state. 814 * Defaults to false because for this state, because the library of the Edit Gallery state is the selection. 886 * @param {object} [attributes] The attributes hash passed to the state. 887 * @param {string} [attributes.id=library] Unique identifier. 888 * @param {string} [attributes.title=Media library] Title for the state. Displays in the media menu and the frame's title region. 889 * @param {wp.media.model.Attachments} [attributes.library] The attachments collection to browse. 890 * If one is not supplied, a collection of all attachments will be created. 891 * @param {wp.media.model.Selection|object} [attributes.selection] A collection to contain attachment selections within the state. 892 * If the 'selection' attribute is a plain JS object, 893 * a Selection will be created using its values as the selection instance's `props` model. 894 * Otherwise, it will copy the library's `props` model. 895 * @param {boolean} [attributes.multiple=false] Whether multi-select is enabled. 896 * @param {string} [attributes.content=upload] Initial mode for the content region. 897 * Overridden by persistent user setting if 'contentUserSetting' is true. 898 * @param {string} [attributes.menu=default] Initial mode for the menu region. 899 * @param {string} [attributes.router=browse] Initial mode for the router region. 900 * @param {string} [attributes.toolbar=select] Initial mode for the toolbar region. 901 * @param {boolean} [attributes.searchable=true] Whether the library is searchable. 902 * @param {boolean|string} [attributes.filterable=false] Whether the library is filterable, and if so what filters should be shown. 903 * Accepts 'all', 'uploaded', or 'unattached'. 904 * @param {boolean} [attributes.sortable=true] Whether the Attachments should be sortable. Depends on the orderby property being set to menuOrder on the attachments collection. 905 * @param {boolean} [attributes.autoSelect=true] Whether an uploaded attachment should be automatically added to the selection. 906 * @param {boolean} [attributes.describe=false] Whether to offer UI to describe attachments - e.g. captioning images in a gallery. 907 * @param {boolean} [attributes.contentUserSetting=true] Whether the content region's mode should be set and persisted per user. 908 * @param {boolean} [attributes.syncSelection=true] Whether the Attachments selection should be persisted from the last state. 815 909 */ 816 GalleryAdd = Library.extend(/** @lends wp.media.controller.GalleryAdd.prototype */{ 817 defaults: _.defaults({ 818 id: 'gallery-library', 819 title: l10n.addToGalleryTitle, 820 multiple: 'add', 821 filterable: 'uploaded', 822 menu: 'gallery', 823 toolbar: 'gallery-add', 824 priority: 100, 825 syncSelection: false 826 }, Library.prototype.defaults ), 910 Library = wp.media.controller.State.extend(/** @lends wp.media.controller.Library.prototype */{ 911 defaults: { 912 id: 'library', 913 title: l10n.mediaLibraryTitle, 914 multiple: false, 915 content: 'upload', 916 menu: 'default', 917 router: 'browse', 918 toolbar: 'select', 919 searchable: true, 920 filterable: false, 921 sortable: true, 922 autoSelect: true, 923 describe: false, 924 contentUserSetting: true, 925 syncSelection: true 926 }, 827 927 828 928 /** 929 * If a library isn't provided, query all media items. 930 * If a selection instance isn't provided, create one. 931 * 829 932 * @since 3.5.0 830 933 */ 831 934 initialize: function() { 832 // If a library wasn't supplied, create a library of images. 935 var selection = this.get('selection'), 936 props; 937 833 938 if ( ! this.get('library') ) { 834 this.set( 'library', wp.media.query( { type: 'image' }) );939 this.set( 'library', wp.media.query() ); 835 940 } 836 941 837 Library.prototype.initialize.apply( this, arguments ); 942 if ( ! ( selection instanceof wp.media.model.Selection ) ) { 943 props = selection; 944 945 if ( ! props ) { 946 props = this.get('library').props.toJSON(); 947 props = _.omit( props, 'orderby', 'query' ); 948 } 949 950 this.set( 'selection', new wp.media.model.Selection( null, { 951 multiple: this.get('multiple'), 952 props: props 953 }) ); 954 } 955 956 this.resetDisplays(); 838 957 }, 839 958 840 959 /** 841 960 * @since 3.5.0 842 961 */ 843 962 activate: function() { 844 var library = this.get('library'), 845 edit = this.frame.state('gallery-edit').get('library'); 963 this.syncSelection(); 846 964 847 if ( this.editLibrary && this.editLibrary !== edit ) { 848 library.unobserve( this.editLibrary ); 849 } 965 wp.Uploader.queue.on( 'add', this.uploading, this ); 850 966 851 // Accepts attachments that exist in the original library and 852 // that do not exist in gallery's library. 853 library.validator = function( attachment ) { 854 return !! this.mirroring.get( attachment.cid ) && ! edit.get( attachment.cid ) && Selection.prototype.validator.apply( this, arguments ); 855 }; 967 this.get('selection').on( 'add remove reset', this.refreshContent, this ); 856 968 857 // Reset the library to ensure that all attachments are re-added 858 // to the collection. Do so silently, as calling `observe` will 859 // trigger the `reset` event. 860 library.reset( library.mirroring.models, { silent: true }); 861 library.observe( edit ); 862 this.editLibrary = edit; 969 if ( this.get( 'router' ) && this.get('contentUserSetting') ) { 970 this.frame.on( 'content:activate', this.saveContentMode, this ); 971 this.set( 'content', getUserSetting( 'libraryContent', this.get('content') ) ); 972 } 973 }, 863 974 864 Library.prototype.activate.apply( this, arguments ); 865 } 866 }); 975 /** 976 * @since 3.5.0 977 */ 978 deactivate: function() { 979 this.recordSelection(); 867 980 868 module.exports = GalleryAdd;981 this.frame.off( 'content:activate', this.saveContentMode, this ); 869 982 870 },{}],9:[function(require,module,exports){ 871 var Library = wp.media.controller.Library, 872 l10n = wp.media.view.l10n, 873 GalleryEdit; 983 // Unbind all event handlers that use this state as the context 984 // from the selection. 985 this.get('selection').off( null, null, this ); 874 986 875 /** 876 * wp.media.controller.GalleryEdit 877 * 878 * A state for editing a gallery's images and settings. 879 * 880 * @memberOf wp.media.controller 881 * 882 * @class 883 * @augments wp.media.controller.Library 884 * @augments wp.media.controller.State 885 * @augments Backbone.Model 886 * 887 * @param {object} [attributes] The attributes hash passed to the state. 888 * @param {string} [attributes.id=gallery-edit] Unique identifier. 889 * @param {string} [attributes.title=Edit Gallery] Title for the state. Displays in the frame's title region. 890 * @param {wp.media.model.Attachments} [attributes.library] The collection of attachments in the gallery. 891 * If one is not supplied, an empty media.model.Selection collection is created. 892 * @param {boolean} [attributes.multiple=false] Whether multi-select is enabled. 893 * @param {boolean} [attributes.searchable=false] Whether the library is searchable. 894 * @param {boolean} [attributes.sortable=true] Whether the Attachments should be sortable. Depends on the orderby property being set to menuOrder on the attachments collection. 895 * @param {boolean} [attributes.date=true] Whether to show the date filter in the browser's toolbar. 896 * @param {string|false} [attributes.content=browse] Initial mode for the content region. 897 * @param {string|false} [attributes.toolbar=image-details] Initial mode for the toolbar region. 898 * @param {boolean} [attributes.describe=true] Whether to offer UI to describe attachments - e.g. captioning images in a gallery. 899 * @param {boolean} [attributes.displaySettings=true] Whether to show the attachment display settings interface. 900 * @param {boolean} [attributes.dragInfo=true] Whether to show instructional text about the attachments being sortable. 901 * @param {int} [attributes.idealColumnWidth=170] The ideal column width in pixels for attachments. 902 * @param {boolean} [attributes.editing=false] Whether the gallery is being created, or editing an existing instance. 903 * @param {int} [attributes.priority=60] The priority for the state link in the media menu. 904 * @param {boolean} [attributes.syncSelection=false] Whether the Attachments selection should be persisted from the last state. 905 * Defaults to false for this state, because the library passed in *is* the selection. 906 * @param {view} [attributes.AttachmentView] The single `Attachment` view to be used in the `Attachments`. 907 * If none supplied, defaults to wp.media.view.Attachment.EditLibrary. 908 */ 909 GalleryEdit = Library.extend(/** @lends wp.media.controller.GalleryEdit.prototype */{ 910 defaults: { 911 id: 'gallery-edit', 912 title: l10n.editGalleryTitle, 913 multiple: false, 914 searchable: false, 915 sortable: true, 916 date: false, 917 display: false, 918 content: 'browse', 919 toolbar: 'gallery-edit', 920 describe: true, 921 displaySettings: true, 922 dragInfo: true, 923 idealColumnWidth: 170, 924 editing: false, 925 priority: 60, 926 syncSelection: false 987 wp.Uploader.queue.off( null, null, this ); 927 988 }, 928 989 929 990 /** 991 * Reset the library to its initial state. 992 * 930 993 * @since 3.5.0 931 994 */ 932 initialize: function() { 933 // If we haven't been provided a `library`, create a `Selection`. 934 if ( ! this.get('library') ) { 935 this.set( 'library', new wp.media.model.Selection() ); 995 reset: function() { 996 this.get('selection').reset(); 997 this.resetDisplays(); 998 this.refreshContent(); 999 }, 1000 1001 /** 1002 * Reset the attachment display settings defaults to the site options. 1003 * 1004 * If site options don't define them, fall back to a persistent user setting. 1005 * 1006 * @since 3.5.0 1007 */ 1008 resetDisplays: function() { 1009 var defaultProps = wp.media.view.settings.defaultProps; 1010 this._displays = []; 1011 this._defaultDisplaySettings = { 1012 align: getUserSetting( 'align', defaultProps.align ) || 'none', 1013 size: getUserSetting( 'imgsize', defaultProps.size ) || 'medium', 1014 link: getUserSetting( 'urlbutton', defaultProps.link ) || 'none' 1015 }; 1016 }, 1017 1018 /** 1019 * Create a model to represent display settings (alignment, etc.) for an attachment. 1020 * 1021 * @since 3.5.0 1022 * 1023 * @param {wp.media.model.Attachment} attachment 1024 * @returns {Backbone.Model} 1025 */ 1026 display: function( attachment ) { 1027 var displays = this._displays; 1028 1029 if ( ! displays[ attachment.cid ] ) { 1030 displays[ attachment.cid ] = new Backbone.Model( this.defaultDisplaySettings( attachment ) ); 936 1031 } 1032 return displays[ attachment.cid ]; 1033 }, 937 1034 938 // The single `Attachment` view to be used in the `Attachments` view. 939 if ( ! this.get('AttachmentView') ) { 940 this.set( 'AttachmentView', wp.media.view.Attachment.EditLibrary ); 1035 /** 1036 * Given an attachment, create attachment display settings properties. 1037 * 1038 * @since 3.6.0 1039 * 1040 * @param {wp.media.model.Attachment} attachment 1041 * @returns {Object} 1042 */ 1043 defaultDisplaySettings: function( attachment ) { 1044 var settings = _.clone( this._defaultDisplaySettings ); 1045 1046 if ( settings.canEmbed = this.canEmbed( attachment ) ) { 1047 settings.link = 'embed'; 1048 } else if ( ! this.isImageAttachment( attachment ) && settings.link === 'none' ) { 1049 settings.link = 'file'; 941 1050 } 942 1051 943 Library.prototype.initialize.apply( this, arguments );1052 return settings; 944 1053 }, 945 1054 946 1055 /** 947 * @since 3.5.0 1056 * Whether an attachment is image. 1057 * 1058 * @since 4.4.1 1059 * 1060 * @param {wp.media.model.Attachment} attachment 1061 * @returns {Boolean} 948 1062 */ 949 activate: function() { 950 var library = this.get('library'); 1063 isImageAttachment: function( attachment ) { 1064 // If uploading, we know the filename but not the mime type. 1065 if ( attachment.get('uploading') ) { 1066 return /\.(jpe?g|png|gif)$/i.test( attachment.get('filename') ); 1067 } 951 1068 952 // Limit the library to images only.953 library.props.set( 'type', 'image' );1069 return attachment.get('type') === 'image'; 1070 }, 954 1071 955 // Watch for uploaded attachments. 956 this.get('library').observe( wp.Uploader.queue ); 1072 /** 1073 * Whether an attachment can be embedded (audio or video). 1074 * 1075 * @since 3.6.0 1076 * 1077 * @param {wp.media.model.Attachment} attachment 1078 * @returns {Boolean} 1079 */ 1080 canEmbed: function( attachment ) { 1081 // If uploading, we know the filename but not the mime type. 1082 if ( ! attachment.get('uploading') ) { 1083 var type = attachment.get('type'); 1084 if ( type !== 'audio' && type !== 'video' ) { 1085 return false; 1086 } 1087 } 957 1088 958 this.frame.on( 'content:render:browse', this.gallerySettings, this ); 1089 return _.contains( wp.media.view.settings.embedExts, attachment.get('filename').split('.').pop() ); 1090 }, 959 1091 960 Library.prototype.activate.apply( this, arguments ); 1092 1093 /** 1094 * If the state is active, no items are selected, and the current 1095 * content mode is not an option in the state's router (provided 1096 * the state has a router), reset the content mode to the default. 1097 * 1098 * @since 3.5.0 1099 */ 1100 refreshContent: function() { 1101 var selection = this.get('selection'), 1102 frame = this.frame, 1103 router = frame.router.get(), 1104 mode = frame.content.mode(); 1105 1106 if ( this.active && ! selection.length && router && ! router.get( mode ) ) { 1107 this.frame.content.render( this.get('content') ); 1108 } 961 1109 }, 962 1110 963 1111 /** 1112 * Callback handler when an attachment is uploaded. 1113 * 1114 * Switch to the Media Library if uploaded from the 'Upload Files' tab. 1115 * 1116 * Adds any uploading attachments to the selection. 1117 * 1118 * If the state only supports one attachment to be selected and multiple 1119 * attachments are uploaded, the last attachment in the upload queue will 1120 * be selected. 1121 * 964 1122 * @since 3.5.0 1123 * 1124 * @param {wp.media.model.Attachment} attachment 965 1125 */ 966 deactivate: function() { 967 // Stop watching for uploaded attachments. 968 this.get('library').unobserve( wp.Uploader.queue ); 1126 uploading: function( attachment ) { 1127 var content = this.frame.content; 969 1128 970 this.frame.off( 'content:render:browse', this.gallerySettings, this ); 1129 if ( 'upload' === content.mode() ) { 1130 this.frame.content.mode('browse'); 1131 } 971 1132 972 Library.prototype.deactivate.apply( this, arguments ); 1133 if ( this.get( 'autoSelect' ) ) { 1134 this.get('selection').add( attachment ); 1135 this.frame.trigger( 'library:selection:add' ); 1136 } 973 1137 }, 974 1138 975 1139 /** 976 * @since 3.5.01140 * Persist the mode of the content region as a user setting. 977 1141 * 978 * @ param browser1142 * @since 3.5.0 979 1143 */ 980 gallerySettings: function( browser) {981 if ( ! this.get('displaySettings') ) {1144 saveContentMode: function() { 1145 if ( 'browse' !== this.get('router') ) { 982 1146 return; 983 1147 } 984 1148 985 var library = this.get('library'); 1149 var mode = this.frame.content.mode(), 1150 view = this.frame.router.get(); 986 1151 987 if ( ! library || ! browser) {988 return;1152 if ( view && view.get( mode ) ) { 1153 setUserSetting( 'libraryContent', mode ); 989 1154 } 1155 } 1156 }); 990 1157 991 library.gallery = library.gallery || new Backbone.Model(); 1158 // Make selectionSync available on any Media Library state. 1159 _.extend( Library.prototype, wp.media.selectionSync ); 992 1160 993 browser.sidebar.set({ 994 gallery: new wp.media.view.Settings.Gallery({ 995 controller: this, 996 model: library.gallery, 997 priority: 40 998 }) 999 }); 1161 module.exports = Library; 1000 1162 1001 browser.toolbar.set( 'reverse', {1002 text: l10n.reverseOrder,1003 priority: 80,1004 1005 click: function() {1006 library.reset( library.toArray().reverse() );1007 }1008 });1009 }1010 });1011 1163 1012 module.exports = GalleryEdit; 1164 /***/ }), 1165 /* 32 */ 1166 /***/ (function(module, exports) { 1013 1167 1014 },{}],10:[function(require,module,exports){1015 1168 var State = wp.media.controller.State, 1016 1169 Library = wp.media.controller.Library, 1017 1170 l10n = wp.media.view.l10n, … … ImageDetails = State.extend(/** @lends wp.media.controller.ImageDetails.prototyp 1075 1228 1076 1229 module.exports = ImageDetails; 1077 1230 1078 },{}],11:[function(require,module,exports){ 1079 var l10n = wp.media.view.l10n, 1080 getUserSetting = window.getUserSetting, 1081 setUserSetting = window.setUserSetting, 1082 Library; 1231 1232 /***/ }), 1233 /* 33 */ 1234 /***/ (function(module, exports) { 1235 1236 var Library = wp.media.controller.Library, 1237 l10n = wp.media.view.l10n, 1238 GalleryEdit; 1083 1239 1084 1240 /** 1085 * wp.media.controller. Library1241 * wp.media.controller.GalleryEdit 1086 1242 * 1087 * A state for choosing an attachment or group of attachments from the media library.1243 * A state for editing a gallery's images and settings. 1088 1244 * 1089 1245 * @memberOf wp.media.controller 1090 1246 * 1091 1247 * @class 1248 * @augments wp.media.controller.Library 1092 1249 * @augments wp.media.controller.State 1093 1250 * @augments Backbone.Model 1094 * @mixes media.selectionSync1095 1251 * 1096 * @param {object} [attributes] The attributes hash passed to the state. 1097 * @param {string} [attributes.id=library] Unique identifier. 1098 * @param {string} [attributes.title=Media library] Title for the state. Displays in the media menu and the frame's title region. 1099 * @param {wp.media.model.Attachments} [attributes.library] The attachments collection to browse. 1100 * If one is not supplied, a collection of all attachments will be created. 1101 * @param {wp.media.model.Selection|object} [attributes.selection] A collection to contain attachment selections within the state. 1102 * If the 'selection' attribute is a plain JS object, 1103 * a Selection will be created using its values as the selection instance's `props` model. 1104 * Otherwise, it will copy the library's `props` model. 1105 * @param {boolean} [attributes.multiple=false] Whether multi-select is enabled. 1106 * @param {string} [attributes.content=upload] Initial mode for the content region. 1107 * Overridden by persistent user setting if 'contentUserSetting' is true. 1108 * @param {string} [attributes.menu=default] Initial mode for the menu region. 1109 * @param {string} [attributes.router=browse] Initial mode for the router region. 1110 * @param {string} [attributes.toolbar=select] Initial mode for the toolbar region. 1111 * @param {boolean} [attributes.searchable=true] Whether the library is searchable. 1112 * @param {boolean|string} [attributes.filterable=false] Whether the library is filterable, and if so what filters should be shown. 1113 * Accepts 'all', 'uploaded', or 'unattached'. 1114 * @param {boolean} [attributes.sortable=true] Whether the Attachments should be sortable. Depends on the orderby property being set to menuOrder on the attachments collection. 1115 * @param {boolean} [attributes.autoSelect=true] Whether an uploaded attachment should be automatically added to the selection. 1116 * @param {boolean} [attributes.describe=false] Whether to offer UI to describe attachments - e.g. captioning images in a gallery. 1117 * @param {boolean} [attributes.contentUserSetting=true] Whether the content region's mode should be set and persisted per user. 1118 * @param {boolean} [attributes.syncSelection=true] Whether the Attachments selection should be persisted from the last state. 1252 * @param {object} [attributes] The attributes hash passed to the state. 1253 * @param {string} [attributes.id=gallery-edit] Unique identifier. 1254 * @param {string} [attributes.title=Edit Gallery] Title for the state. Displays in the frame's title region. 1255 * @param {wp.media.model.Attachments} [attributes.library] The collection of attachments in the gallery. 1256 * If one is not supplied, an empty media.model.Selection collection is created. 1257 * @param {boolean} [attributes.multiple=false] Whether multi-select is enabled. 1258 * @param {boolean} [attributes.searchable=false] Whether the library is searchable. 1259 * @param {boolean} [attributes.sortable=true] Whether the Attachments should be sortable. Depends on the orderby property being set to menuOrder on the attachments collection. 1260 * @param {boolean} [attributes.date=true] Whether to show the date filter in the browser's toolbar. 1261 * @param {string|false} [attributes.content=browse] Initial mode for the content region. 1262 * @param {string|false} [attributes.toolbar=image-details] Initial mode for the toolbar region. 1263 * @param {boolean} [attributes.describe=true] Whether to offer UI to describe attachments - e.g. captioning images in a gallery. 1264 * @param {boolean} [attributes.displaySettings=true] Whether to show the attachment display settings interface. 1265 * @param {boolean} [attributes.dragInfo=true] Whether to show instructional text about the attachments being sortable. 1266 * @param {int} [attributes.idealColumnWidth=170] The ideal column width in pixels for attachments. 1267 * @param {boolean} [attributes.editing=false] Whether the gallery is being created, or editing an existing instance. 1268 * @param {int} [attributes.priority=60] The priority for the state link in the media menu. 1269 * @param {boolean} [attributes.syncSelection=false] Whether the Attachments selection should be persisted from the last state. 1270 * Defaults to false for this state, because the library passed in *is* the selection. 1271 * @param {view} [attributes.AttachmentView] The single `Attachment` view to be used in the `Attachments`. 1272 * If none supplied, defaults to wp.media.view.Attachment.EditLibrary. 1119 1273 */ 1120 Library = wp.media.controller.State.extend(/** @lends wp.media.controller.Library.prototype */{1274 GalleryEdit = Library.extend(/** @lends wp.media.controller.GalleryEdit.prototype */{ 1121 1275 defaults: { 1122 id: 'library', 1123 title: l10n.mediaLibraryTitle, 1124 multiple: false, 1125 content: 'upload', 1126 menu: 'default', 1127 router: 'browse', 1128 toolbar: 'select', 1129 searchable: true, 1130 filterable: false, 1131 sortable: true, 1132 autoSelect: true, 1133 describe: false, 1134 contentUserSetting: true, 1135 syncSelection: true 1276 id: 'gallery-edit', 1277 title: l10n.editGalleryTitle, 1278 multiple: false, 1279 searchable: false, 1280 sortable: true, 1281 date: false, 1282 display: false, 1283 content: 'browse', 1284 toolbar: 'gallery-edit', 1285 describe: true, 1286 displaySettings: true, 1287 dragInfo: true, 1288 idealColumnWidth: 170, 1289 editing: false, 1290 priority: 60, 1291 syncSelection: false 1136 1292 }, 1137 1293 1138 1294 /** 1139 * If a library isn't provided, query all media items.1140 * If a selection instance isn't provided, create one.1141 *1142 1295 * @since 3.5.0 1143 1296 */ 1144 1297 initialize: function() { 1145 var selection = this.get('selection'), 1146 props; 1147 1298 // If we haven't been provided a `library`, create a `Selection`. 1148 1299 if ( ! this.get('library') ) { 1149 this.set( 'library', wp.media.query() );1300 this.set( 'library', new wp.media.model.Selection() ); 1150 1301 } 1151 1302 1152 if ( ! ( selection instanceof wp.media.model.Selection ) ) { 1153 props = selection; 1154 1155 if ( ! props ) { 1156 props = this.get('library').props.toJSON(); 1157 props = _.omit( props, 'orderby', 'query' ); 1158 } 1159 1160 this.set( 'selection', new wp.media.model.Selection( null, { 1161 multiple: this.get('multiple'), 1162 props: props 1163 }) ); 1303 // The single `Attachment` view to be used in the `Attachments` view. 1304 if ( ! this.get('AttachmentView') ) { 1305 this.set( 'AttachmentView', wp.media.view.Attachment.EditLibrary ); 1164 1306 } 1165 1307 1166 this.resetDisplays();1308 Library.prototype.initialize.apply( this, arguments ); 1167 1309 }, 1168 1310 1169 1311 /** 1170 1312 * @since 3.5.0 1171 1313 */ 1172 1314 activate: function() { 1173 this.syncSelection();1315 var library = this.get('library'); 1174 1316 1175 wp.Uploader.queue.on( 'add', this.uploading, this ); 1317 // Limit the library to images only. 1318 library.props.set( 'type', 'image' ); 1176 1319 1177 this.get('selection').on( 'add remove reset', this.refreshContent, this ); 1320 // Watch for uploaded attachments. 1321 this.get('library').observe( wp.Uploader.queue ); 1178 1322 1179 if ( this.get( 'router' ) && this.get('contentUserSetting') ) { 1180 this.frame.on( 'content:activate', this.saveContentMode, this ); 1181 this.set( 'content', getUserSetting( 'libraryContent', this.get('content') ) ); 1182 } 1323 this.frame.on( 'content:render:browse', this.gallerySettings, this ); 1324 1325 Library.prototype.activate.apply( this, arguments ); 1183 1326 }, 1184 1327 1185 1328 /** 1186 1329 * @since 3.5.0 1187 1330 */ 1188 1331 deactivate: function() { 1189 this.recordSelection(); 1190 1191 this.frame.off( 'content:activate', this.saveContentMode, this ); 1332 // Stop watching for uploaded attachments. 1333 this.get('library').unobserve( wp.Uploader.queue ); 1192 1334 1193 // Unbind all event handlers that use this state as the context 1194 // from the selection. 1195 this.get('selection').off( null, null, this ); 1335 this.frame.off( 'content:render:browse', this.gallerySettings, this ); 1196 1336 1197 wp.Uploader.queue.off( null, null, this );1337 Library.prototype.deactivate.apply( this, arguments ); 1198 1338 }, 1199 1339 1200 1340 /** 1201 * Reset the library to its initial state.1202 *1203 1341 * @since 3.5.0 1204 */1205 reset: function() {1206 this.get('selection').reset();1207 this.resetDisplays();1208 this.refreshContent();1209 },1210 1211 /**1212 * Reset the attachment display settings defaults to the site options.1213 *1214 * If site options don't define them, fall back to a persistent user setting.1215 1342 * 1216 * @ since 3.5.01343 * @param browser 1217 1344 */ 1218 resetDisplays: function() { 1219 var defaultProps = wp.media.view.settings.defaultProps; 1220 this._displays = []; 1221 this._defaultDisplaySettings = { 1222 align: getUserSetting( 'align', defaultProps.align ) || 'none', 1223 size: getUserSetting( 'imgsize', defaultProps.size ) || 'medium', 1224 link: getUserSetting( 'urlbutton', defaultProps.link ) || 'none' 1225 }; 1226 }, 1345 gallerySettings: function( browser ) { 1346 if ( ! this.get('displaySettings') ) { 1347 return; 1348 } 1227 1349 1228 /** 1229 * Create a model to represent display settings (alignment, etc.) for an attachment. 1230 * 1231 * @since 3.5.0 1232 * 1233 * @param {wp.media.model.Attachment} attachment 1234 * @returns {Backbone.Model} 1235 */ 1236 display: function( attachment ) { 1237 var displays = this._displays; 1350 var library = this.get('library'); 1238 1351 1239 if ( ! displays[ attachment.cid ]) {1240 displays[ attachment.cid ] = new Backbone.Model( this.defaultDisplaySettings( attachment ) );1352 if ( ! library || ! browser ) { 1353 return; 1241 1354 } 1242 return displays[ attachment.cid ];1243 },1244 1355 1245 /** 1246 * Given an attachment, create attachment display settings properties. 1247 * 1248 * @since 3.6.0 1249 * 1250 * @param {wp.media.model.Attachment} attachment 1251 * @returns {Object} 1252 */ 1253 defaultDisplaySettings: function( attachment ) { 1254 var settings = _.clone( this._defaultDisplaySettings ); 1356 library.gallery = library.gallery || new Backbone.Model(); 1255 1357 1256 if ( settings.canEmbed = this.canEmbed( attachment ) ) { 1257 settings.link = 'embed'; 1258 } else if ( ! this.isImageAttachment( attachment ) && settings.link === 'none' ) { 1259 settings.link = 'file'; 1260 } 1358 browser.sidebar.set({ 1359 gallery: new wp.media.view.Settings.Gallery({ 1360 controller: this, 1361 model: library.gallery, 1362 priority: 40 1363 }) 1364 }); 1261 1365 1262 return settings; 1263 }, 1366 browser.toolbar.set( 'reverse', { 1367 text: l10n.reverseOrder, 1368 priority: 80, 1264 1369 1265 /** 1266 * Whether an attachment is image. 1267 * 1268 * @since 4.4.1 1269 * 1270 * @param {wp.media.model.Attachment} attachment 1271 * @returns {Boolean} 1272 */ 1273 isImageAttachment: function( attachment ) { 1274 // If uploading, we know the filename but not the mime type. 1275 if ( attachment.get('uploading') ) { 1276 return /\.(jpe?g|png|gif)$/i.test( attachment.get('filename') ); 1277 } 1370 click: function() { 1371 library.reset( library.toArray().reverse() ); 1372 } 1373 }); 1374 } 1375 }); 1278 1376 1279 return attachment.get('type') === 'image'; 1280 }, 1377 module.exports = GalleryEdit; 1281 1378 1282 /**1283 * Whether an attachment can be embedded (audio or video).1284 *1285 * @since 3.6.01286 *1287 * @param {wp.media.model.Attachment} attachment1288 * @returns {Boolean}1289 */1290 canEmbed: function( attachment ) {1291 // If uploading, we know the filename but not the mime type.1292 if ( ! attachment.get('uploading') ) {1293 var type = attachment.get('type');1294 if ( type !== 'audio' && type !== 'video' ) {1295 return false;1296 }1297 }1298 1299 return _.contains( wp.media.view.settings.embedExts, attachment.get('filename').split('.').pop() );1300 },1301 1379 1380 /***/ }), 1381 /* 34 */ 1382 /***/ (function(module, exports) { 1302 1383 1303 /** 1304 * If the state is active, no items are selected, and the current 1305 * content mode is not an option in the state's router (provided 1306 * the state has a router), reset the content mode to the default. 1307 * 1308 * @since 3.5.0 1309 */ 1310 refreshContent: function() { 1311 var selection = this.get('selection'), 1312 frame = this.frame, 1313 router = frame.router.get(), 1314 mode = frame.content.mode(); 1384 var Selection = wp.media.model.Selection, 1385 Library = wp.media.controller.Library, 1386 l10n = wp.media.view.l10n, 1387 GalleryAdd; 1315 1388 1316 if ( this.active && ! selection.length && router && ! router.get( mode ) ) { 1317 this.frame.content.render( this.get('content') ); 1318 } 1319 }, 1389 /** 1390 * wp.media.controller.GalleryAdd 1391 * 1392 * A state for selecting more images to add to a gallery. 1393 * 1394 * @memberOf wp.media.controller 1395 * 1396 * @class 1397 * @augments wp.media.controller.Library 1398 * @augments wp.media.controller.State 1399 * @augments Backbone.Model 1400 * 1401 * @param {object} [attributes] The attributes hash passed to the state. 1402 * @param {string} [attributes.id=gallery-library] Unique identifier. 1403 * @param {string} [attributes.title=Add to Gallery] Title for the state. Displays in the frame's title region. 1404 * @param {boolean} [attributes.multiple=add] Whether multi-select is enabled. @todo 'add' doesn't seem do anything special, and gets used as a boolean. 1405 * @param {wp.media.model.Attachments} [attributes.library] The attachments collection to browse. 1406 * If one is not supplied, a collection of all images will be created. 1407 * @param {boolean|string} [attributes.filterable=uploaded] Whether the library is filterable, and if so what filters should be shown. 1408 * Accepts 'all', 'uploaded', or 'unattached'. 1409 * @param {string} [attributes.menu=gallery] Initial mode for the menu region. 1410 * @param {string} [attributes.content=upload] Initial mode for the content region. 1411 * Overridden by persistent user setting if 'contentUserSetting' is true. 1412 * @param {string} [attributes.router=browse] Initial mode for the router region. 1413 * @param {string} [attributes.toolbar=gallery-add] Initial mode for the toolbar region. 1414 * @param {boolean} [attributes.searchable=true] Whether the library is searchable. 1415 * @param {boolean} [attributes.sortable=true] Whether the Attachments should be sortable. Depends on the orderby property being set to menuOrder on the attachments collection. 1416 * @param {boolean} [attributes.autoSelect=true] Whether an uploaded attachment should be automatically added to the selection. 1417 * @param {boolean} [attributes.contentUserSetting=true] Whether the content region's mode should be set and persisted per user. 1418 * @param {int} [attributes.priority=100] The priority for the state link in the media menu. 1419 * @param {boolean} [attributes.syncSelection=false] Whether the Attachments selection should be persisted from the last state. 1420 * Defaults to false because for this state, because the library of the Edit Gallery state is the selection. 1421 */ 1422 GalleryAdd = Library.extend(/** @lends wp.media.controller.GalleryAdd.prototype */{ 1423 defaults: _.defaults({ 1424 id: 'gallery-library', 1425 title: l10n.addToGalleryTitle, 1426 multiple: 'add', 1427 filterable: 'uploaded', 1428 menu: 'gallery', 1429 toolbar: 'gallery-add', 1430 priority: 100, 1431 syncSelection: false 1432 }, Library.prototype.defaults ), 1320 1433 1321 1434 /** 1322 * Callback handler when an attachment is uploaded.1323 *1324 * Switch to the Media Library if uploaded from the 'Upload Files' tab.1325 *1326 * Adds any uploading attachments to the selection.1327 *1328 * If the state only supports one attachment to be selected and multiple1329 * attachments are uploaded, the last attachment in the upload queue will1330 * be selected.1331 *1332 1435 * @since 3.5.0 1333 *1334 * @param {wp.media.model.Attachment} attachment1335 1436 */ 1336 uploading: function( attachment ) { 1337 var content = this.frame.content; 1338 1339 if ( 'upload' === content.mode() ) { 1340 this.frame.content.mode('browse'); 1437 initialize: function() { 1438 // If a library wasn't supplied, create a library of images. 1439 if ( ! this.get('library') ) { 1440 this.set( 'library', wp.media.query({ type: 'image' }) ); 1341 1441 } 1342 1442 1343 if ( this.get( 'autoSelect' ) ) { 1344 this.get('selection').add( attachment ); 1345 this.frame.trigger( 'library:selection:add' ); 1346 } 1443 Library.prototype.initialize.apply( this, arguments ); 1347 1444 }, 1348 1445 1349 1446 /** 1350 * Persist the mode of the content region as a user setting.1351 *1352 1447 * @since 3.5.0 1353 1448 */ 1354 saveContentMode: function() { 1355 if ( 'browse' !== this.get('router') ) { 1356 return; 1449 activate: function() { 1450 var library = this.get('library'), 1451 edit = this.frame.state('gallery-edit').get('library'); 1452 1453 if ( this.editLibrary && this.editLibrary !== edit ) { 1454 library.unobserve( this.editLibrary ); 1357 1455 } 1358 1456 1359 var mode = this.frame.content.mode(), 1360 view = this.frame.router.get(); 1457 // Accepts attachments that exist in the original library and 1458 // that do not exist in gallery's library. 1459 library.validator = function( attachment ) { 1460 return !! this.mirroring.get( attachment.cid ) && ! edit.get( attachment.cid ) && Selection.prototype.validator.apply( this, arguments ); 1461 }; 1361 1462 1362 if ( view && view.get( mode ) ) { 1363 setUserSetting( 'libraryContent', mode ); 1364 } 1463 // Reset the library to ensure that all attachments are re-added 1464 // to the collection. Do so silently, as calling `observe` will 1465 // trigger the `reset` event. 1466 library.reset( library.mirroring.models, { silent: true }); 1467 library.observe( edit ); 1468 this.editLibrary = edit; 1469 1470 Library.prototype.activate.apply( this, arguments ); 1365 1471 } 1366 1472 }); 1367 1473 1368 // Make selectionSync available on any Media Library state. 1369 _.extend( Library.prototype, wp.media.selectionSync ); 1474 module.exports = GalleryAdd; 1370 1475 1371 module.exports = Library;1372 1476 1373 },{}],12:[function(require,module,exports){ 1477 /***/ }), 1478 /* 35 */ 1479 /***/ (function(module, exports) { 1480 1481 var Library = wp.media.controller.Library, 1482 l10n = wp.media.view.l10n, 1483 $ = jQuery, 1484 CollectionEdit; 1485 1374 1486 /** 1375 * wp.media.controller.MediaLibrary 1487 * wp.media.controller.CollectionEdit 1488 * 1489 * A state for editing a collection, which is used by audio and video playlists, 1490 * and can be used for other collections. 1376 1491 * 1377 1492 * @memberOf wp.media.controller 1378 1493 * … … module.exports = Library; 1380 1495 * @augments wp.media.controller.Library 1381 1496 * @augments wp.media.controller.State 1382 1497 * @augments Backbone.Model 1498 * 1499 * @param {object} [attributes] The attributes hash passed to the state. 1500 * @param {string} attributes.title Title for the state. Displays in the media menu and the frame's title region. 1501 * @param {wp.media.model.Attachments} [attributes.library] The attachments collection to edit. 1502 * If one is not supplied, an empty media.model.Selection collection is created. 1503 * @param {boolean} [attributes.multiple=false] Whether multi-select is enabled. 1504 * @param {string} [attributes.content=browse] Initial mode for the content region. 1505 * @param {string} attributes.menu Initial mode for the menu region. @todo this needs a better explanation. 1506 * @param {boolean} [attributes.searchable=false] Whether the library is searchable. 1507 * @param {boolean} [attributes.sortable=true] Whether the Attachments should be sortable. Depends on the orderby property being set to menuOrder on the attachments collection. 1508 * @param {boolean} [attributes.date=true] Whether to show the date filter in the browser's toolbar. 1509 * @param {boolean} [attributes.describe=true] Whether to offer UI to describe the attachments - e.g. captioning images in a gallery. 1510 * @param {boolean} [attributes.dragInfo=true] Whether to show instructional text about the attachments being sortable. 1511 * @param {boolean} [attributes.dragInfoText] Instructional text about the attachments being sortable. 1512 * @param {int} [attributes.idealColumnWidth=170] The ideal column width in pixels for attachments. 1513 * @param {boolean} [attributes.editing=false] Whether the gallery is being created, or editing an existing instance. 1514 * @param {int} [attributes.priority=60] The priority for the state link in the media menu. 1515 * @param {boolean} [attributes.syncSelection=false] Whether the Attachments selection should be persisted from the last state. 1516 * Defaults to false for this state, because the library passed in *is* the selection. 1517 * @param {view} [attributes.SettingsView] The view to edit the collection instance settings (e.g. Playlist settings with "Show tracklist" checkbox). 1518 * @param {view} [attributes.AttachmentView] The single `Attachment` view to be used in the `Attachments`. 1519 * If none supplied, defaults to wp.media.view.Attachment.EditLibrary. 1520 * @param {string} attributes.type The collection's media type. (e.g. 'video'). 1521 * @param {string} attributes.collectionType The collection type. (e.g. 'playlist'). 1383 1522 */ 1384 var Library = wp.media.controller.Library, 1385 MediaLibrary; 1386 1387 MediaLibrary = Library.extend(/** @lends wp.media.controller.MediaLibrary.prototype */{ 1388 defaults: _.defaults({ 1389 // Attachments browser defaults. @see media.view.AttachmentsBrowser 1390 filterable: 'uploaded', 1391 1392 displaySettings: false, 1393 priority: 80, 1394 syncSelection: false 1395 }, Library.prototype.defaults ), 1523 CollectionEdit = Library.extend(/** @lends wp.media.controller.CollectionEdit.prototype */{ 1524 defaults: { 1525 multiple: false, 1526 sortable: true, 1527 date: false, 1528 searchable: false, 1529 content: 'browse', 1530 describe: true, 1531 dragInfo: true, 1532 idealColumnWidth: 170, 1533 editing: false, 1534