From 5db34748e65de330f187a309b77cf57836f711ec Mon Sep 17 00:00:00 2001 From: desrosj Date: Thu, 13 Dec 2018 17:27:38 +0000 Subject: [PATCH] Script loader: Adjust JS packages registration. Adjusts the packages registration after [43723]: Combine the different registration functions into one `wp_default_packages` function. To reach this goal move the prefix logic into a function so it can be called from different locations. Use a static variable there to prevent duplicate inclusion of `version.php`. Call this function from the `wp_default_scripts` action by registering it as a default filter. Combine some of the logic in `_WP_Editors::print_tinymce_scripts` into `wp_register_tinymce_scripts`. The logic to force an uncompressed TinyMCE script file stays in `_WP_Editors::force_uncompressed_tinymce` because that logic is very specific to the classic editor. The script handle `wp-tinymce` is now a dependency of the editor script handle. In combination with the previous item, this makes the classic editor work. Adjust the syntax of the script paths to be more consistent with other WordPress code. Always use "production" mode for the media files to prevent people from inadvertently committing development files. Props pento, omarreiss, atimmer. Merges [43738] into trunk. Fixes #45065. Built from https://develop.svn.wordpress.org/trunk@44115 git-svn-id: http://core.svn.wordpress.org/trunk@43945 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- wp-includes/class-wp-editor.php | 62 +- wp-includes/default-filters.php | 2 + wp-includes/js/media-audiovideo.js | 1159 ++- wp-includes/js/media-audiovideo.min.js | 2 +- wp-includes/js/media-grid.js | 1106 ++- wp-includes/js/media-grid.min.js | 2 +- wp-includes/js/media-models.js | 1631 +++- wp-includes/js/media-models.min.js | 3 +- wp-includes/js/media-views.js | 10259 +++++++++++++++++++++-- wp-includes/js/media-views.min.js | 13 +- wp-includes/script-loader.php | 114 +- wp-includes/version.php | 2 +- 12 files changed, 13151 insertions(+), 1204 deletions(-) diff --git a/wp-includes/class-wp-editor.php b/wp-includes/class-wp-editor.php index 1846214e3c..47d82ecacb 100644 --- a/wp-includes/class-wp-editor.php +++ b/wp-includes/class-wp-editor.php @@ -317,9 +317,11 @@ final class _WP_Editors { if ( empty( self::$first_init ) ) { if ( is_admin() ) { add_action( 'admin_print_footer_scripts', array( __CLASS__, 'editor_js' ), 50 ); + add_action( 'admin_print_footer_scripts', array( __CLASS__, 'force_uncompressed_tinymce' ), 1 ); add_action( 'admin_print_footer_scripts', array( __CLASS__, 'enqueue_scripts' ), 1 ); } else { add_action( 'wp_print_footer_scripts', array( __CLASS__, 'editor_js' ), 50 ); + add_action( 'wp_print_footer_scripts', array( __CLASS__, 'force_uncompressed_tinymce' ), 1 ); add_action( 'wp_print_footer_scripts', array( __CLASS__, 'enqueue_scripts' ), 1 ); } } @@ -755,6 +757,9 @@ final class _WP_Editors { } /** + * + * @static + * * @param bool $default_scripts Optional. Whether default scripts should be enqueued. Default false. */ public static function enqueue_scripts( $default_scripts = false ) { @@ -819,8 +824,10 @@ final class _WP_Editors { wp_enqueue_style( 'editor-buttons' ); if ( is_admin() ) { + add_action( 'admin_print_footer_scripts', array( __CLASS__, 'force_uncompressed_tinymce' ), 1 ); add_action( 'admin_print_footer_scripts', array( __CLASS__, 'print_default_editor_scripts' ), 45 ); } else { + add_action( 'wp_print_footer_scripts', array( __CLASS__, 'force_uncompressed_tinymce' ), 1 ); add_action( 'wp_print_footer_scripts', array( __CLASS__, 'print_default_editor_scripts' ), 45 ); } } @@ -1387,6 +1394,32 @@ final class _WP_Editors { "tinymce.ScriptLoader.markDone( '$baseurl/langs/$mce_locale.js' );\n"; } + /** + * Force uncompressed TinyMCE when a custom theme has been defined. + * + * The compressed TinyMCE file cannot deal with custom themes, so this makes + * sure that we use the uncompressed TinyMCE file if a theme is defined. + * Even if we are on a production environment. + */ + public static function force_uncompressed_tinymce() { + $has_custom_theme = false; + foreach ( self::$mce_settings as $init ) { + if ( ! empty( $init['theme_url'] ) ) { + $has_custom_theme = true; + break; + } + } + + if ( ! $has_custom_theme ) { + return; + } + + $wp_scripts = wp_scripts(); + + $wp_scripts->remove( 'wp-tinymce' ); + wp_register_tinymce_scripts( $wp_scripts, true ); + } + /** * Print (output) the main TinyMCE scripts. * @@ -1397,7 +1430,7 @@ final class _WP_Editors { * @global bool $compress_scripts */ public static function print_tinymce_scripts() { - global $tinymce_version, $concatenate_scripts, $compress_scripts; + global $concatenate_scripts; if ( self::$tinymce_scripts_printed ) { return; @@ -1408,33 +1441,6 @@ final class _WP_Editors { if ( ! isset( $concatenate_scripts ) ) { script_concat_settings(); } - - $suffix = SCRIPT_DEBUG ? '' : '.min'; - $version = 'ver=' . $tinymce_version; - $baseurl = self::get_baseurl(); - - $has_custom_theme = false; - foreach ( self::$mce_settings as $init ) { - if ( ! empty( $init['theme_url'] ) ) { - $has_custom_theme = true; - break; - } - } - - $compressed = $compress_scripts && $concatenate_scripts && isset( $_SERVER['HTTP_ACCEPT_ENCODING'] ) - && false !== stripos( $_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip' ) && ! $has_custom_theme; - - // Load tinymce.js when running from /src, else load wp-tinymce.js.gz (production) or tinymce.min.js (SCRIPT_DEBUG) - $mce_suffix = false !== strpos( get_bloginfo( 'version' ), '-src' ) ? '' : '.min'; - - if ( $compressed ) { - echo "\n"; - } else { - echo "\n"; - echo "\n"; - } - - echo "\n"; } /** diff --git a/wp-includes/default-filters.php b/wp-includes/default-filters.php index 9989957b14..c36ba799cf 100644 --- a/wp-includes/default-filters.php +++ b/wp-includes/default-filters.php @@ -502,6 +502,8 @@ add_action( 'set_current_user', 'kses_init' ); // Script Loader add_action( 'wp_default_scripts', 'wp_default_scripts' ); +add_action( 'wp_default_scripts', 'wp_default_packages' ); + add_action( 'wp_enqueue_scripts', 'wp_localize_jquery_ui_datepicker', 1000 ); add_action( 'admin_enqueue_scripts', 'wp_localize_jquery_ui_datepicker', 1000 ); add_action( 'admin_print_scripts-index.php', 'wp_localize_community_events' ); diff --git a/wp-includes/js/media-audiovideo.js b/wp-includes/js/media-audiovideo.js index b53479fe5a..ee5d7f92de 100644 --- a/wp-includes/js/media-audiovideo.js +++ b/wp-includes/js/media-audiovideo.js @@ -84,127 +84,1054 @@ /******/ return __webpack_require__(__webpack_require__.s = 0); /******/ }) /************************************************************************/ -/******/ ({ - -/***/ "./src/js/_enqueues/wp/media/audiovideo.js": -/*!*************************************************!*\ - !*** ./src/js/_enqueues/wp/media/audiovideo.js ***! - \*************************************************/ -/*! no static exports found */ +/******/ ([ +/* 0 */ /***/ (function(module, exports, __webpack_require__) { -eval("/**\n * @output wp-includes/js/media-audiovideo.js\n */\n\nvar media = wp.media,\n\tbaseSettings = window._wpmejsSettings || {},\n\tl10n = window._wpMediaViewsL10n || {};\n\n/**\n *\n * Defines the wp.media.mixin object.\n *\n * @mixin\n *\n * @since 4.2.0\n */\nwp.media.mixin = {\n\tmejsSettings: baseSettings,\n\n\t/**\n\t * Pauses and removes all players.\n\t *\n\t * @since 4.2.0\n\t *\n\t * @return {void}\n\t */\n\tremoveAllPlayers: function() {\n\t\tvar p;\n\n\t\tif ( window.mejs && window.mejs.players ) {\n\t\t\tfor ( p in window.mejs.players ) {\n\t\t\t\twindow.mejs.players[p].pause();\n\t\t\t\tthis.removePlayer( window.mejs.players[p] );\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Removes the player.\n\t *\n\t * Override the MediaElement method for removing a player.\n\t * MediaElement tries to pull the audio/video tag out of\n\t * its container and re-add it to the DOM.\n\t *\n\t * @since 4.2.0\n\t *\n\t * @return {void}\n\t */\n\tremovePlayer: function(t) {\n\t\tvar featureIndex, feature;\n\n\t\tif ( ! t.options ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// invoke features cleanup\n\t\tfor ( featureIndex in t.options.features ) {\n\t\t\tfeature = t.options.features[featureIndex];\n\t\t\tif ( t['clean' + feature] ) {\n\t\t\t\ttry {\n\t\t\t\t\tt['clean' + feature](t);\n\t\t\t\t} catch (e) {}\n\t\t\t}\n\t\t}\n\n\t\tif ( ! t.isDynamic ) {\n\t\t\tt.node.remove();\n\t\t}\n\n\t\tif ( 'html5' !== t.media.rendererName ) {\n\t\t\tt.media.remove();\n\t\t}\n\n\t\tdelete window.mejs.players[t.id];\n\n\t\tt.container.remove();\n\t\tt.globalUnbind('resize', t.globalResizeCallback);\n\t\tt.globalUnbind('keydown', t.globalKeydownCallback);\n\t\tt.globalUnbind('click', t.globalClickCallback);\n\t\tdelete t.media.player;\n\t},\n\n\t/**\n\t *\n\t * Removes and resets all players.\n\t *\n\t * Allows any class that has set 'player' to a MediaElementPlayer\n\t * instance to remove the player when listening to events.\n\t *\n\t * Examples: modal closes, shortcode properties are removed, etc.\n\t *\n\t * @since 4.2.0\n\t */\n\tunsetPlayers : function() {\n\t\tif ( this.players && this.players.length ) {\n\t\t\t_.each( this.players, function (player) {\n\t\t\t\tplayer.pause();\n\t\t\t\twp.media.mixin.removePlayer( player );\n\t\t\t} );\n\t\t\tthis.players = [];\n\t\t}\n\t}\n};\n\n/**\n * Shortcode modeling for playlists.\n *\n * @since 4.2.0\n */\nwp.media.playlist = new wp.media.collection({\n\ttag: 'playlist',\n\teditTitle : l10n.editPlaylistTitle,\n\tdefaults : {\n\t\tid: wp.media.view.settings.post.id,\n\t\tstyle: 'light',\n\t\ttracklist: true,\n\t\ttracknumbers: true,\n\t\timages: true,\n\t\tartists: true,\n\t\ttype: 'audio'\n\t}\n});\n\n/**\n * Shortcode modeling for audio.\n *\n * `edit()` prepares the shortcode for the media modal.\n * `shortcode()` builds the new shortcode after an update.\n *\n * @namespace\n *\n * @since 4.2.0\n */\nwp.media.audio = {\n\tcoerce : wp.media.coerce,\n\n\tdefaults : {\n\t\tid : wp.media.view.settings.post.id,\n\t\tsrc : '',\n\t\tloop : false,\n\t\tautoplay : false,\n\t\tpreload : 'none',\n\t\twidth : 400\n\t},\n\n\t/**\n\t * Instantiates a new media object with the next matching shortcode.\n\t *\n\t * @since 4.2.0\n\t *\n\t * @param {string} data The text to apply the shortcode on.\n\t * @returns {wp.media} The media object.\n\t */\n\tedit : function( data ) {\n\t\tvar frame, shortcode = wp.shortcode.next( 'audio', data ).shortcode;\n\n\t\tframe = wp.media({\n\t\t\tframe: 'audio',\n\t\t\tstate: 'audio-details',\n\t\t\tmetadata: _.defaults( shortcode.attrs.named, this.defaults )\n\t\t});\n\n\t\treturn frame;\n\t},\n\n\t/**\n\t * Generates an audio shortcode.\n\t *\n\t * @since 4.2.0\n\t *\n\t * @param {Array} model Array with attributes for the shortcode.\n\t * @returns {wp.shortcode} The audio shortcode object.\n\t */\n\tshortcode : function( model ) {\n\t\tvar content;\n\n\t\t_.each( this.defaults, function( value, key ) {\n\t\t\tmodel[ key ] = this.coerce( model, key );\n\n\t\t\tif ( value === model[ key ] ) {\n\t\t\t\tdelete model[ key ];\n\t\t\t}\n\t\t}, this );\n\n\t\tcontent = model.content;\n\t\tdelete model.content;\n\n\t\treturn new wp.shortcode({\n\t\t\ttag: 'audio',\n\t\t\tattrs: model,\n\t\t\tcontent: content\n\t\t});\n\t}\n};\n\n/**\n * Shortcode modeling for video.\n *\n * `edit()` prepares the shortcode for the media modal.\n * `shortcode()` builds the new shortcode after update.\n *\n * @since 4.2.0\n *\n * @namespace\n */\nwp.media.video = {\n\tcoerce : wp.media.coerce,\n\n\tdefaults : {\n\t\tid : wp.media.view.settings.post.id,\n\t\tsrc : '',\n\t\tposter : '',\n\t\tloop : false,\n\t\tautoplay : false,\n\t\tpreload : 'metadata',\n\t\tcontent : '',\n\t\twidth : 640,\n\t\theight : 360\n\t},\n\n\t/**\n\t * Instantiates a new media object with the next matching shortcode.\n\t *\n\t * @since 4.2.0\n\t *\n\t * @param {string} data The text to apply the shortcode on.\n\t * @returns {wp.media} The media object.\n\t */\n\tedit : function( data ) {\n\t\tvar frame,\n\t\t\tshortcode = wp.shortcode.next( 'video', data ).shortcode,\n\t\t\tattrs;\n\n\t\tattrs = shortcode.attrs.named;\n\t\tattrs.content = shortcode.content;\n\n\t\tframe = wp.media({\n\t\t\tframe: 'video',\n\t\t\tstate: 'video-details',\n\t\t\tmetadata: _.defaults( attrs, this.defaults )\n\t\t});\n\n\t\treturn frame;\n\t},\n\n\t/**\n\t * Generates an video shortcode.\n\t *\n\t * @since 4.2.0\n\t *\n\t * @param {Array} model Array with attributes for the shortcode.\n\t * @returns {wp.shortcode} The video shortcode object.\n\t */\n\tshortcode : function( model ) {\n\t\tvar content;\n\n\t\t_.each( this.defaults, function( value, key ) {\n\t\t\tmodel[ key ] = this.coerce( model, key );\n\n\t\t\tif ( value === model[ key ] ) {\n\t\t\t\tdelete model[ key ];\n\t\t\t}\n\t\t}, this );\n\n\t\tcontent = model.content;\n\t\tdelete model.content;\n\n\t\treturn new wp.shortcode({\n\t\t\ttag: 'video',\n\t\t\tattrs: model,\n\t\t\tcontent: content\n\t\t});\n\t}\n};\n\nmedia.model.PostMedia = __webpack_require__( /*! ../../../media/models/post-media.js */ \"./src/js/media/models/post-media.js\" );\nmedia.controller.AudioDetails = __webpack_require__( /*! ../../../media/controllers/audio-details.js */ \"./src/js/media/controllers/audio-details.js\" );\nmedia.controller.VideoDetails = __webpack_require__( /*! ../../../media/controllers/video-details.js */ \"./src/js/media/controllers/video-details.js\" );\nmedia.view.MediaFrame.MediaDetails = __webpack_require__( /*! ../../../media/views/frame/media-details.js */ \"./src/js/media/views/frame/media-details.js\" );\nmedia.view.MediaFrame.AudioDetails = __webpack_require__( /*! ../../../media/views/frame/audio-details.js */ \"./src/js/media/views/frame/audio-details.js\" );\nmedia.view.MediaFrame.VideoDetails = __webpack_require__( /*! ../../../media/views/frame/video-details.js */ \"./src/js/media/views/frame/video-details.js\" );\nmedia.view.MediaDetails = __webpack_require__( /*! ../../../media/views/media-details.js */ \"./src/js/media/views/media-details.js\" );\nmedia.view.AudioDetails = __webpack_require__( /*! ../../../media/views/audio-details.js */ \"./src/js/media/views/audio-details.js\" );\nmedia.view.VideoDetails = __webpack_require__( /*! ../../../media/views/video-details.js */ \"./src/js/media/views/video-details.js\" );\n\n\n//# sourceURL=webpack:///./src/js/_enqueues/wp/media/audiovideo.js?"); +module.exports = __webpack_require__(1); + /***/ }), - -/***/ "./src/js/media/controllers/audio-details.js": -/*!***************************************************!*\ - !*** ./src/js/media/controllers/audio-details.js ***! - \***************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("var State = wp.media.controller.State,\n\tl10n = wp.media.view.l10n,\n\tAudioDetails;\n\n/**\n * wp.media.controller.AudioDetails\n *\n * The controller for the Audio Details state\n *\n * @memberOf wp.media.controller\n *\n * @class\n * @augments wp.media.controller.State\n * @augments Backbone.Model\n */\nAudioDetails = State.extend(/** @lends wp.media.controller.AudioDetails.prototype */{\n\tdefaults: {\n\t\tid: 'audio-details',\n\t\ttoolbar: 'audio-details',\n\t\ttitle: l10n.audioDetailsTitle,\n\t\tcontent: 'audio-details',\n\t\tmenu: 'audio-details',\n\t\trouter: false,\n\t\tpriority: 60\n\t},\n\n\tinitialize: function( options ) {\n\t\tthis.media = options.media;\n\t\tState.prototype.initialize.apply( this, arguments );\n\t}\n});\n\nmodule.exports = AudioDetails;\n\n\n//# sourceURL=webpack:///./src/js/media/controllers/audio-details.js?"); - -/***/ }), - -/***/ "./src/js/media/controllers/video-details.js": -/*!***************************************************!*\ - !*** ./src/js/media/controllers/video-details.js ***! - \***************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("/**\n * wp.media.controller.VideoDetails\n *\n * The controller for the Video Details state\n *\n * @memberOf wp.media.controller\n *\n * @class\n * @augments wp.media.controller.State\n * @augments Backbone.Model\n */\nvar State = wp.media.controller.State,\n\tl10n = wp.media.view.l10n,\n\tVideoDetails;\n\nVideoDetails = State.extend(/** @lends wp.media.controller.VideoDetails.prototype */{\n\tdefaults: {\n\t\tid: 'video-details',\n\t\ttoolbar: 'video-details',\n\t\ttitle: l10n.videoDetailsTitle,\n\t\tcontent: 'video-details',\n\t\tmenu: 'video-details',\n\t\trouter: false,\n\t\tpriority: 60\n\t},\n\n\tinitialize: function( options ) {\n\t\tthis.media = options.media;\n\t\tState.prototype.initialize.apply( this, arguments );\n\t}\n});\n\nmodule.exports = VideoDetails;\n\n\n//# sourceURL=webpack:///./src/js/media/controllers/video-details.js?"); - -/***/ }), - -/***/ "./src/js/media/models/post-media.js": -/*!*******************************************!*\ - !*** ./src/js/media/models/post-media.js ***! - \*******************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("/**\n * wp.media.model.PostMedia\n *\n * Shared model class for audio and video. Updates the model after\n * \"Add Audio|Video Source\" and \"Replace Audio|Video\" states return\n *\n * @memberOf wp.media.model\n *\n * @class\n * @augments Backbone.Model\n */\nvar PostMedia = Backbone.Model.extend(/** @lends wp.media.model.PostMedia.prototype */{\n\tinitialize: function() {\n\t\tthis.attachment = false;\n\t},\n\n\tsetSource: function( attachment ) {\n\t\tthis.attachment = attachment;\n\t\tthis.extension = attachment.get( 'filename' ).split('.').pop();\n\n\t\tif ( this.get( 'src' ) && this.extension === this.get( 'src' ).split('.').pop() ) {\n\t\t\tthis.unset( 'src' );\n\t\t}\n\n\t\tif ( _.contains( wp.media.view.settings.embedExts, this.extension ) ) {\n\t\t\tthis.set( this.extension, this.attachment.get( 'url' ) );\n\t\t} else {\n\t\t\tthis.unset( this.extension );\n\t\t}\n\t},\n\n\tchangeAttachment: function( attachment ) {\n\t\tthis.setSource( attachment );\n\n\t\tthis.unset( 'src' );\n\t\t_.each( _.without( wp.media.view.settings.embedExts, this.extension ), function( ext ) {\n\t\t\tthis.unset( ext );\n\t\t}, this );\n\t}\n});\n\nmodule.exports = PostMedia;\n\n\n//# sourceURL=webpack:///./src/js/media/models/post-media.js?"); - -/***/ }), - -/***/ "./src/js/media/views/audio-details.js": -/*!*********************************************!*\ - !*** ./src/js/media/views/audio-details.js ***! - \*********************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("var MediaDetails = wp.media.view.MediaDetails,\n\tAudioDetails;\n\n/**\n * wp.media.view.AudioDetails\n *\n * @memberOf wp.media.view\n *\n * @class\n * @augments wp.media.view.MediaDetails\n * @augments wp.media.view.Settings.AttachmentDisplay\n * @augments wp.media.view.Settings\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n */\nAudioDetails = MediaDetails.extend(/** @lends wp.media.view.AudioDetails.prototype */{\n\tclassName: 'audio-details',\n\ttemplate: wp.template('audio-details'),\n\n\tsetMedia: function() {\n\t\tvar audio = this.$('.wp-audio-shortcode');\n\n\t\tif ( audio.find( 'source' ).length ) {\n\t\t\tif ( audio.is(':hidden') ) {\n\t\t\t\taudio.show();\n\t\t\t}\n\t\t\tthis.media = MediaDetails.prepareSrc( audio.get(0) );\n\t\t} else {\n\t\t\taudio.hide();\n\t\t\tthis.media = false;\n\t\t}\n\n\t\treturn this;\n\t}\n});\n\nmodule.exports = AudioDetails;\n\n\n//# sourceURL=webpack:///./src/js/media/views/audio-details.js?"); - -/***/ }), - -/***/ "./src/js/media/views/frame/audio-details.js": -/*!***************************************************!*\ - !*** ./src/js/media/views/frame/audio-details.js ***! - \***************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("var MediaDetails = wp.media.view.MediaFrame.MediaDetails,\n\tMediaLibrary = wp.media.controller.MediaLibrary,\n\n\tl10n = wp.media.view.l10n,\n\tAudioDetails;\n\n/**\n * wp.media.view.MediaFrame.AudioDetails\n *\n * @memberOf wp.media.view.MediaFrame\n *\n * @class\n * @augments wp.media.view.MediaFrame.MediaDetails\n * @augments wp.media.view.MediaFrame.Select\n * @augments wp.media.view.MediaFrame\n * @augments wp.media.view.Frame\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n * @mixes wp.media.controller.StateMachine\n */\nAudioDetails = MediaDetails.extend(/** @lends wp.media.view.MediaFrame.AudioDetails.prototype */{\n\tdefaults: {\n\t\tid: 'audio',\n\t\turl: '',\n\t\tmenu: 'audio-details',\n\t\tcontent: 'audio-details',\n\t\ttoolbar: 'audio-details',\n\t\ttype: 'link',\n\t\ttitle: l10n.audioDetailsTitle,\n\t\tpriority: 120\n\t},\n\n\tinitialize: function( options ) {\n\t\toptions.DetailsView = wp.media.view.AudioDetails;\n\t\toptions.cancelText = l10n.audioDetailsCancel;\n\t\toptions.addText = l10n.audioAddSourceTitle;\n\n\t\tMediaDetails.prototype.initialize.call( this, options );\n\t},\n\n\tbindHandlers: function() {\n\t\tMediaDetails.prototype.bindHandlers.apply( this, arguments );\n\n\t\tthis.on( 'toolbar:render:replace-audio', this.renderReplaceToolbar, this );\n\t\tthis.on( 'toolbar:render:add-audio-source', this.renderAddSourceToolbar, this );\n\t},\n\n\tcreateStates: function() {\n\t\tthis.states.add([\n\t\t\tnew wp.media.controller.AudioDetails( {\n\t\t\t\tmedia: this.media\n\t\t\t} ),\n\n\t\t\tnew MediaLibrary( {\n\t\t\t\ttype: 'audio',\n\t\t\t\tid: 'replace-audio',\n\t\t\t\ttitle: l10n.audioReplaceTitle,\n\t\t\t\ttoolbar: 'replace-audio',\n\t\t\t\tmedia: this.media,\n\t\t\t\tmenu: 'audio-details'\n\t\t\t} ),\n\n\t\t\tnew MediaLibrary( {\n\t\t\t\ttype: 'audio',\n\t\t\t\tid: 'add-audio-source',\n\t\t\t\ttitle: l10n.audioAddSourceTitle,\n\t\t\t\ttoolbar: 'add-audio-source',\n\t\t\t\tmedia: this.media,\n\t\t\t\tmenu: false\n\t\t\t} )\n\t\t]);\n\t}\n});\n\nmodule.exports = AudioDetails;\n\n\n//# sourceURL=webpack:///./src/js/media/views/frame/audio-details.js?"); - -/***/ }), - -/***/ "./src/js/media/views/frame/media-details.js": -/*!***************************************************!*\ - !*** ./src/js/media/views/frame/media-details.js ***! - \***************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("var Select = wp.media.view.MediaFrame.Select,\n\tl10n = wp.media.view.l10n,\n\tMediaDetails;\n\n/**\n * wp.media.view.MediaFrame.MediaDetails\n *\n * @memberOf wp.media.view.MediaFrame\n *\n * @class\n * @augments wp.media.view.MediaFrame.Select\n * @augments wp.media.view.MediaFrame\n * @augments wp.media.view.Frame\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n * @mixes wp.media.controller.StateMachine\n */\nMediaDetails = Select.extend(/** @lends wp.media.view.MediaFrame.MediaDetails.prototype */{\n\tdefaults: {\n\t\tid: 'media',\n\t\turl: '',\n\t\tmenu: 'media-details',\n\t\tcontent: 'media-details',\n\t\ttoolbar: 'media-details',\n\t\ttype: 'link',\n\t\tpriority: 120\n\t},\n\n\tinitialize: function( options ) {\n\t\tthis.DetailsView = options.DetailsView;\n\t\tthis.cancelText = options.cancelText;\n\t\tthis.addText = options.addText;\n\n\t\tthis.media = new wp.media.model.PostMedia( options.metadata );\n\t\tthis.options.selection = new wp.media.model.Selection( this.media.attachment, { multiple: false } );\n\t\tSelect.prototype.initialize.apply( this, arguments );\n\t},\n\n\tbindHandlers: function() {\n\t\tvar menu = this.defaults.menu;\n\n\t\tSelect.prototype.bindHandlers.apply( this, arguments );\n\n\t\tthis.on( 'menu:create:' + menu, this.createMenu, this );\n\t\tthis.on( 'content:render:' + menu, this.renderDetailsContent, this );\n\t\tthis.on( 'menu:render:' + menu, this.renderMenu, this );\n\t\tthis.on( 'toolbar:render:' + menu, this.renderDetailsToolbar, this );\n\t},\n\n\trenderDetailsContent: function() {\n\t\tvar view = new this.DetailsView({\n\t\t\tcontroller: this,\n\t\t\tmodel: this.state().media,\n\t\t\tattachment: this.state().media.attachment\n\t\t}).render();\n\n\t\tthis.content.set( view );\n\t},\n\n\trenderMenu: function( view ) {\n\t\tvar lastState = this.lastState(),\n\t\t\tprevious = lastState && lastState.id,\n\t\t\tframe = this;\n\n\t\tview.set({\n\t\t\tcancel: {\n\t\t\t\ttext: this.cancelText,\n\t\t\t\tpriority: 20,\n\t\t\t\tclick: function() {\n\t\t\t\t\tif ( previous ) {\n\t\t\t\t\t\tframe.setState( previous );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tframe.close();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\tseparateCancel: new wp.media.View({\n\t\t\t\tclassName: 'separator',\n\t\t\t\tpriority: 40\n\t\t\t})\n\t\t});\n\n\t},\n\n\tsetPrimaryButton: function(text, handler) {\n\t\tthis.toolbar.set( new wp.media.view.Toolbar({\n\t\t\tcontroller: this,\n\t\t\titems: {\n\t\t\t\tbutton: {\n\t\t\t\t\tstyle: 'primary',\n\t\t\t\t\ttext: text,\n\t\t\t\t\tpriority: 80,\n\t\t\t\t\tclick: function() {\n\t\t\t\t\t\tvar controller = this.controller;\n\t\t\t\t\t\thandler.call( this, controller, controller.state() );\n\t\t\t\t\t\t// Restore and reset the default state.\n\t\t\t\t\t\tcontroller.setState( controller.options.state );\n\t\t\t\t\t\tcontroller.reset();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}) );\n\t},\n\n\trenderDetailsToolbar: function() {\n\t\tthis.setPrimaryButton( l10n.update, function( controller, state ) {\n\t\t\tcontroller.close();\n\t\t\tstate.trigger( 'update', controller.media.toJSON() );\n\t\t} );\n\t},\n\n\trenderReplaceToolbar: function() {\n\t\tthis.setPrimaryButton( l10n.replace, function( controller, state ) {\n\t\t\tvar attachment = state.get( 'selection' ).single();\n\t\t\tcontroller.media.changeAttachment( attachment );\n\t\t\tstate.trigger( 'replace', controller.media.toJSON() );\n\t\t} );\n\t},\n\n\trenderAddSourceToolbar: function() {\n\t\tthis.setPrimaryButton( this.addText, function( controller, state ) {\n\t\t\tvar attachment = state.get( 'selection' ).single();\n\t\t\tcontroller.media.setSource( attachment );\n\t\t\tstate.trigger( 'add-source', controller.media.toJSON() );\n\t\t} );\n\t}\n});\n\nmodule.exports = MediaDetails;\n\n\n//# sourceURL=webpack:///./src/js/media/views/frame/media-details.js?"); - -/***/ }), - -/***/ "./src/js/media/views/frame/video-details.js": -/*!***************************************************!*\ - !*** ./src/js/media/views/frame/video-details.js ***! - \***************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("var MediaDetails = wp.media.view.MediaFrame.MediaDetails,\n\tMediaLibrary = wp.media.controller.MediaLibrary,\n\tl10n = wp.media.view.l10n,\n\tVideoDetails;\n\n/**\n * wp.media.view.MediaFrame.VideoDetails\n *\n * @memberOf wp.media.view.MediaFrame\n *\n * @class\n * @augments wp.media.view.MediaFrame.MediaDetails\n * @augments wp.media.view.MediaFrame.Select\n * @augments wp.media.view.MediaFrame\n * @augments wp.media.view.Frame\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n * @mixes wp.media.controller.StateMachine\n */\nVideoDetails = MediaDetails.extend(/** @lends wp.media.view.MediaFrame.VideoDetails.prototype */{\n\tdefaults: {\n\t\tid: 'video',\n\t\turl: '',\n\t\tmenu: 'video-details',\n\t\tcontent: 'video-details',\n\t\ttoolbar: 'video-details',\n\t\ttype: 'link',\n\t\ttitle: l10n.videoDetailsTitle,\n\t\tpriority: 120\n\t},\n\n\tinitialize: function( options ) {\n\t\toptions.DetailsView = wp.media.view.VideoDetails;\n\t\toptions.cancelText = l10n.videoDetailsCancel;\n\t\toptions.addText = l10n.videoAddSourceTitle;\n\n\t\tMediaDetails.prototype.initialize.call( this, options );\n\t},\n\n\tbindHandlers: function() {\n\t\tMediaDetails.prototype.bindHandlers.apply( this, arguments );\n\n\t\tthis.on( 'toolbar:render:replace-video', this.renderReplaceToolbar, this );\n\t\tthis.on( 'toolbar:render:add-video-source', this.renderAddSourceToolbar, this );\n\t\tthis.on( 'toolbar:render:select-poster-image', this.renderSelectPosterImageToolbar, this );\n\t\tthis.on( 'toolbar:render:add-track', this.renderAddTrackToolbar, this );\n\t},\n\n\tcreateStates: function() {\n\t\tthis.states.add([\n\t\t\tnew wp.media.controller.VideoDetails({\n\t\t\t\tmedia: this.media\n\t\t\t}),\n\n\t\t\tnew MediaLibrary( {\n\t\t\t\ttype: 'video',\n\t\t\t\tid: 'replace-video',\n\t\t\t\ttitle: l10n.videoReplaceTitle,\n\t\t\t\ttoolbar: 'replace-video',\n\t\t\t\tmedia: this.media,\n\t\t\t\tmenu: 'video-details'\n\t\t\t} ),\n\n\t\t\tnew MediaLibrary( {\n\t\t\t\ttype: 'video',\n\t\t\t\tid: 'add-video-source',\n\t\t\t\ttitle: l10n.videoAddSourceTitle,\n\t\t\t\ttoolbar: 'add-video-source',\n\t\t\t\tmedia: this.media,\n\t\t\t\tmenu: false\n\t\t\t} ),\n\n\t\t\tnew MediaLibrary( {\n\t\t\t\ttype: 'image',\n\t\t\t\tid: 'select-poster-image',\n\t\t\t\ttitle: l10n.videoSelectPosterImageTitle,\n\t\t\t\ttoolbar: 'select-poster-image',\n\t\t\t\tmedia: this.media,\n\t\t\t\tmenu: 'video-details'\n\t\t\t} ),\n\n\t\t\tnew MediaLibrary( {\n\t\t\t\ttype: 'text',\n\t\t\t\tid: 'add-track',\n\t\t\t\ttitle: l10n.videoAddTrackTitle,\n\t\t\t\ttoolbar: 'add-track',\n\t\t\t\tmedia: this.media,\n\t\t\t\tmenu: 'video-details'\n\t\t\t} )\n\t\t]);\n\t},\n\n\trenderSelectPosterImageToolbar: function() {\n\t\tthis.setPrimaryButton( l10n.videoSelectPosterImageTitle, function( controller, state ) {\n\t\t\tvar urls = [], attachment = state.get( 'selection' ).single();\n\n\t\t\tcontroller.media.set( 'poster', attachment.get( 'url' ) );\n\t\t\tstate.trigger( 'set-poster-image', controller.media.toJSON() );\n\n\t\t\t_.each( wp.media.view.settings.embedExts, function (ext) {\n\t\t\t\tif ( controller.media.get( ext ) ) {\n\t\t\t\t\turls.push( controller.media.get( ext ) );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\twp.ajax.send( 'set-attachment-thumbnail', {\n\t\t\t\tdata : {\n\t\t\t\t\turls: urls,\n\t\t\t\t\tthumbnail_id: attachment.get( 'id' )\n\t\t\t\t}\n\t\t\t} );\n\t\t} );\n\t},\n\n\trenderAddTrackToolbar: function() {\n\t\tthis.setPrimaryButton( l10n.videoAddTrackTitle, function( controller, state ) {\n\t\t\tvar attachment = state.get( 'selection' ).single(),\n\t\t\t\tcontent = controller.media.get( 'content' );\n\n\t\t\tif ( -1 === content.indexOf( attachment.get( 'url' ) ) ) {\n\t\t\t\tcontent += [\n\t\t\t\t\t''\n\t\t\t\t].join('');\n\n\t\t\t\tcontroller.media.set( 'content', content );\n\t\t\t}\n\t\t\tstate.trigger( 'add-track', controller.media.toJSON() );\n\t\t} );\n\t}\n});\n\nmodule.exports = VideoDetails;\n\n\n//# sourceURL=webpack:///./src/js/media/views/frame/video-details.js?"); - -/***/ }), - -/***/ "./src/js/media/views/media-details.js": -/*!*********************************************!*\ - !*** ./src/js/media/views/media-details.js ***! - \*********************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("/* global MediaElementPlayer */\nvar AttachmentDisplay = wp.media.view.Settings.AttachmentDisplay,\n\t$ = jQuery,\n\tMediaDetails;\n\n/**\n * wp.media.view.MediaDetails\n *\n * @memberOf wp.media.view\n *\n * @class\n * @augments wp.media.view.Settings.AttachmentDisplay\n * @augments wp.media.view.Settings\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n */\nMediaDetails = AttachmentDisplay.extend(/** @lends wp.media.view.MediaDetails.prototype */{\n\tinitialize: function() {\n\t\t_.bindAll(this, 'success');\n\t\tthis.players = [];\n\t\tthis.listenTo( this.controller, 'close', wp.media.mixin.unsetPlayers );\n\t\tthis.on( 'ready', this.setPlayer );\n\t\tthis.on( 'media:setting:remove', wp.media.mixin.unsetPlayers, this );\n\t\tthis.on( 'media:setting:remove', this.render );\n\t\tthis.on( 'media:setting:remove', this.setPlayer );\n\n\t\tAttachmentDisplay.prototype.initialize.apply( this, arguments );\n\t},\n\n\tevents: function(){\n\t\treturn _.extend( {\n\t\t\t'click .remove-setting' : 'removeSetting',\n\t\t\t'change .content-track' : 'setTracks',\n\t\t\t'click .remove-track' : 'setTracks',\n\t\t\t'click .add-media-source' : 'addSource'\n\t\t}, AttachmentDisplay.prototype.events );\n\t},\n\n\tprepare: function() {\n\t\treturn _.defaults({\n\t\t\tmodel: this.model.toJSON()\n\t\t}, this.options );\n\t},\n\n\t/**\n\t * Remove a setting's UI when the model unsets it\n\t *\n\t * @fires wp.media.view.MediaDetails#media:setting:remove\n\t *\n\t * @param {Event} e\n\t */\n\tremoveSetting : function(e) {\n\t\tvar wrap = $( e.currentTarget ).parent(), setting;\n\t\tsetting = wrap.find( 'input' ).data( 'setting' );\n\n\t\tif ( setting ) {\n\t\t\tthis.model.unset( setting );\n\t\t\tthis.trigger( 'media:setting:remove', this );\n\t\t}\n\n\t\twrap.remove();\n\t},\n\n\t/**\n\t *\n\t * @fires wp.media.view.MediaDetails#media:setting:remove\n\t */\n\tsetTracks : function() {\n\t\tvar tracks = '';\n\n\t\t_.each( this.$('.content-track'), function(track) {\n\t\t\ttracks += $( track ).val();\n\t\t} );\n\n\t\tthis.model.set( 'content', tracks );\n\t\tthis.trigger( 'media:setting:remove', this );\n\t},\n\n\taddSource : function( e ) {\n\t\tthis.controller.lastMime = $( e.currentTarget ).data( 'mime' );\n\t\tthis.controller.setState( 'add-' + this.controller.defaults.id + '-source' );\n\t},\n\n\tloadPlayer: function () {\n\t\tthis.players.push( new MediaElementPlayer( this.media, this.settings ) );\n\t\tthis.scriptXhr = false;\n\t},\n\n\tsetPlayer : function() {\n\t\tvar src;\n\n\t\tif ( this.players.length || ! this.media || this.scriptXhr ) {\n\t\t\treturn;\n\t\t}\n\n\t\tsrc = this.model.get( 'src' );\n\n\t\tif ( src && src.indexOf( 'vimeo' ) > -1 && ! ( 'Vimeo' in window ) ) {\n\t\t\tthis.scriptXhr = $.getScript( 'https://player.vimeo.com/api/player.js', _.bind( this.loadPlayer, this ) );\n\t\t} else {\n\t\t\tthis.loadPlayer();\n\t\t}\n\t},\n\n\t/**\n\t * @abstract\n\t */\n\tsetMedia : function() {\n\t\treturn this;\n\t},\n\n\tsuccess : function(mejs) {\n\t\tvar autoplay = mejs.attributes.autoplay && 'false' !== mejs.attributes.autoplay;\n\n\t\tif ( 'flash' === mejs.pluginType && autoplay ) {\n\t\t\tmejs.addEventListener( 'canplay', function() {\n\t\t\t\tmejs.play();\n\t\t\t}, false );\n\t\t}\n\n\t\tthis.mejs = mejs;\n\t},\n\n\t/**\n\t * @returns {media.view.MediaDetails} Returns itself to allow chaining\n\t */\n\trender: function() {\n\t\tAttachmentDisplay.prototype.render.apply( this, arguments );\n\n\t\tsetTimeout( _.bind( function() {\n\t\t\tthis.resetFocus();\n\t\t}, this ), 10 );\n\n\t\tthis.settings = _.defaults( {\n\t\t\tsuccess : this.success\n\t\t}, wp.media.mixin.mejsSettings );\n\n\t\treturn this.setMedia();\n\t},\n\n\tresetFocus: function() {\n\t\tthis.$( '.embed-media-settings' ).scrollTop( 0 );\n\t}\n},/** @lends wp.media.view.MediaDetails */{\n\tinstances : 0,\n\t/**\n\t * When multiple players in the DOM contain the same src, things get weird.\n\t *\n\t * @param {HTMLElement} elem\n\t * @returns {HTMLElement}\n\t */\n\tprepareSrc : function( elem ) {\n\t\tvar i = MediaDetails.instances++;\n\t\t_.each( $( elem ).find( 'source' ), function( source ) {\n\t\t\tsource.src = [\n\t\t\t\tsource.src,\n\t\t\t\tsource.src.indexOf('?') > -1 ? '&' : '?',\n\t\t\t\t'_=',\n\t\t\t\ti\n\t\t\t].join('');\n\t\t} );\n\n\t\treturn elem;\n\t}\n});\n\nmodule.exports = MediaDetails;\n\n\n//# sourceURL=webpack:///./src/js/media/views/media-details.js?"); - -/***/ }), - -/***/ "./src/js/media/views/video-details.js": -/*!*********************************************!*\ - !*** ./src/js/media/views/video-details.js ***! - \*********************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("var MediaDetails = wp.media.view.MediaDetails,\n\tVideoDetails;\n\n/**\n * wp.media.view.VideoDetails\n *\n * @memberOf wp.media.view\n *\n * @class\n * @augments wp.media.view.MediaDetails\n * @augments wp.media.view.Settings.AttachmentDisplay\n * @augments wp.media.view.Settings\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n */\nVideoDetails = MediaDetails.extend(/** @lends wp.media.view.VideoDetails.prototype */{\n\tclassName: 'video-details',\n\ttemplate: wp.template('video-details'),\n\n\tsetMedia: function() {\n\t\tvar video = this.$('.wp-video-shortcode');\n\n\t\tif ( video.find( 'source' ).length ) {\n\t\t\tif ( video.is(':hidden') ) {\n\t\t\t\tvideo.show();\n\t\t\t}\n\n\t\t\tif ( ! video.hasClass( 'youtube-video' ) && ! video.hasClass( 'vimeo-video' ) ) {\n\t\t\t\tthis.media = MediaDetails.prepareSrc( video.get(0) );\n\t\t\t} else {\n\t\t\t\tthis.media = video.get(0);\n\t\t\t}\n\t\t} else {\n\t\t\tvideo.hide();\n\t\t\tthis.media = false;\n\t\t}\n\n\t\treturn this;\n\t}\n});\n\nmodule.exports = VideoDetails;\n\n\n//# sourceURL=webpack:///./src/js/media/views/video-details.js?"); - -/***/ }), - -/***/ 0: -/*!*******************************************************!*\ - !*** multi ./src/js/_enqueues/wp/media/audiovideo.js ***! - \*******************************************************/ -/*! no static exports found */ +/* 1 */ /***/ (function(module, exports, __webpack_require__) { -eval("module.exports = __webpack_require__(/*! ./src/js/_enqueues/wp/media/audiovideo.js */\"./src/js/_enqueues/wp/media/audiovideo.js\");\n\n\n//# sourceURL=webpack:///multi_./src/js/_enqueues/wp/media/audiovideo.js?"); +/** + * @output wp-includes/js/media-audiovideo.js + */ + +var media = wp.media, + baseSettings = window._wpmejsSettings || {}, + l10n = window._wpMediaViewsL10n || {}; + +/** + * + * Defines the wp.media.mixin object. + * + * @mixin + * + * @since 4.2.0 + */ +wp.media.mixin = { + mejsSettings: baseSettings, + + /** + * Pauses and removes all players. + * + * @since 4.2.0 + * + * @return {void} + */ + removeAllPlayers: function() { + var p; + + if ( window.mejs && window.mejs.players ) { + for ( p in window.mejs.players ) { + window.mejs.players[p].pause(); + this.removePlayer( window.mejs.players[p] ); + } + } + }, + + /** + * Removes the player. + * + * Override the MediaElement method for removing a player. + * MediaElement tries to pull the audio/video tag out of + * its container and re-add it to the DOM. + * + * @since 4.2.0 + * + * @return {void} + */ + removePlayer: function(t) { + var featureIndex, feature; + + if ( ! t.options ) { + return; + } + + // invoke features cleanup + for ( featureIndex in t.options.features ) { + feature = t.options.features[featureIndex]; + if ( t['clean' + feature] ) { + try { + t['clean' + feature](t); + } catch (e) {} + } + } + + if ( ! t.isDynamic ) { + t.node.remove(); + } + + if ( 'html5' !== t.media.rendererName ) { + t.media.remove(); + } + + delete window.mejs.players[t.id]; + + t.container.remove(); + t.globalUnbind('resize', t.globalResizeCallback); + t.globalUnbind('keydown', t.globalKeydownCallback); + t.globalUnbind('click', t.globalClickCallback); + delete t.media.player; + }, + + /** + * + * Removes and resets all players. + * + * Allows any class that has set 'player' to a MediaElementPlayer + * instance to remove the player when listening to events. + * + * Examples: modal closes, shortcode properties are removed, etc. + * + * @since 4.2.0 + */ + unsetPlayers : function() { + if ( this.players && this.players.length ) { + _.each( this.players, function (player) { + player.pause(); + wp.media.mixin.removePlayer( player ); + } ); + this.players = []; + } + } +}; + +/** + * Shortcode modeling for playlists. + * + * @since 4.2.0 + */ +wp.media.playlist = new wp.media.collection({ + tag: 'playlist', + editTitle : l10n.editPlaylistTitle, + defaults : { + id: wp.media.view.settings.post.id, + style: 'light', + tracklist: true, + tracknumbers: true, + images: true, + artists: true, + type: 'audio' + } +}); + +/** + * Shortcode modeling for audio. + * + * `edit()` prepares the shortcode for the media modal. + * `shortcode()` builds the new shortcode after an update. + * + * @namespace + * + * @since 4.2.0 + */ +wp.media.audio = { + coerce : wp.media.coerce, + + defaults : { + id : wp.media.view.settings.post.id, + src : '', + loop : false, + autoplay : false, + preload : 'none', + width : 400 + }, + + /** + * Instantiates a new media object with the next matching shortcode. + * + * @since 4.2.0 + * + * @param {string} data The text to apply the shortcode on. + * @returns {wp.media} The media object. + */ + edit : function( data ) { + var frame, shortcode = wp.shortcode.next( 'audio', data ).shortcode; + + frame = wp.media({ + frame: 'audio', + state: 'audio-details', + metadata: _.defaults( shortcode.attrs.named, this.defaults ) + }); + + return frame; + }, + + /** + * Generates an audio shortcode. + * + * @since 4.2.0 + * + * @param {Array} model Array with attributes for the shortcode. + * @returns {wp.shortcode} The audio shortcode object. + */ + shortcode : function( model ) { + var content; + + _.each( this.defaults, function( value, key ) { + model[ key ] = this.coerce( model, key ); + + if ( value === model[ key ] ) { + delete model[ key ]; + } + }, this ); + + content = model.content; + delete model.content; + + return new wp.shortcode({ + tag: 'audio', + attrs: model, + content: content + }); + } +}; + +/** + * Shortcode modeling for video. + * + * `edit()` prepares the shortcode for the media modal. + * `shortcode()` builds the new shortcode after update. + * + * @since 4.2.0 + * + * @namespace + */ +wp.media.video = { + coerce : wp.media.coerce, + + defaults : { + id : wp.media.view.settings.post.id, + src : '', + poster : '', + loop : false, + autoplay : false, + preload : 'metadata', + content : '', + width : 640, + height : 360 + }, + + /** + * Instantiates a new media object with the next matching shortcode. + * + * @since 4.2.0 + * + * @param {string} data The text to apply the shortcode on. + * @returns {wp.media} The media object. + */ + edit : function( data ) { + var frame, + shortcode = wp.shortcode.next( 'video', data ).shortcode, + attrs; + + attrs = shortcode.attrs.named; + attrs.content = shortcode.content; + + frame = wp.media({ + frame: 'video', + state: 'video-details', + metadata: _.defaults( attrs, this.defaults ) + }); + + return frame; + }, + + /** + * Generates an video shortcode. + * + * @since 4.2.0 + * + * @param {Array} model Array with attributes for the shortcode. + * @returns {wp.shortcode} The video shortcode object. + */ + shortcode : function( model ) { + var content; + + _.each( this.defaults, function( value, key ) { + model[ key ] = this.coerce( model, key ); + + if ( value === model[ key ] ) { + delete model[ key ]; + } + }, this ); + + content = model.content; + delete model.content; + + return new wp.shortcode({ + tag: 'video', + attrs: model, + content: content + }); + } +}; + +media.model.PostMedia = __webpack_require__( 2 ); +media.controller.AudioDetails = __webpack_require__( 3 ); +media.controller.VideoDetails = __webpack_require__( 4 ); +media.view.MediaFrame.MediaDetails = __webpack_require__( 5 ); +media.view.MediaFrame.AudioDetails = __webpack_require__( 6 ); +media.view.MediaFrame.VideoDetails = __webpack_require__( 7 ); +media.view.MediaDetails = __webpack_require__( 8 ); +media.view.AudioDetails = __webpack_require__( 9 ); +media.view.VideoDetails = __webpack_require__( 10 ); + + +/***/ }), +/* 2 */ +/***/ (function(module, exports) { + +/** + * wp.media.model.PostMedia + * + * Shared model class for audio and video. Updates the model after + * "Add Audio|Video Source" and "Replace Audio|Video" states return + * + * @memberOf wp.media.model + * + * @class + * @augments Backbone.Model + */ +var PostMedia = Backbone.Model.extend(/** @lends wp.media.model.PostMedia.prototype */{ + initialize: function() { + this.attachment = false; + }, + + setSource: function( attachment ) { + this.attachment = attachment; + this.extension = attachment.get( 'filename' ).split('.').pop(); + + if ( this.get( 'src' ) && this.extension === this.get( 'src' ).split('.').pop() ) { + this.unset( 'src' ); + } + + if ( _.contains( wp.media.view.settings.embedExts, this.extension ) ) { + this.set( this.extension, this.attachment.get( 'url' ) ); + } else { + this.unset( this.extension ); + } + }, + + changeAttachment: function( attachment ) { + this.setSource( attachment ); + + this.unset( 'src' ); + _.each( _.without( wp.media.view.settings.embedExts, this.extension ), function( ext ) { + this.unset( ext ); + }, this ); + } +}); + +module.exports = PostMedia; + + +/***/ }), +/* 3 */ +/***/ (function(module, exports) { + +var State = wp.media.controller.State, + l10n = wp.media.view.l10n, + AudioDetails; + +/** + * wp.media.controller.AudioDetails + * + * The controller for the Audio Details state + * + * @memberOf wp.media.controller + * + * @class + * @augments wp.media.controller.State + * @augments Backbone.Model + */ +AudioDetails = State.extend(/** @lends wp.media.controller.AudioDetails.prototype */{ + defaults: { + id: 'audio-details', + toolbar: 'audio-details', + title: l10n.audioDetailsTitle, + content: 'audio-details', + menu: 'audio-details', + router: false, + priority: 60 + }, + + initialize: function( options ) { + this.media = options.media; + State.prototype.initialize.apply( this, arguments ); + } +}); + +module.exports = AudioDetails; + + +/***/ }), +/* 4 */ +/***/ (function(module, exports) { + +/** + * wp.media.controller.VideoDetails + * + * The controller for the Video Details state + * + * @memberOf wp.media.controller + * + * @class + * @augments wp.media.controller.State + * @augments Backbone.Model + */ +var State = wp.media.controller.State, + l10n = wp.media.view.l10n, + VideoDetails; + +VideoDetails = State.extend(/** @lends wp.media.controller.VideoDetails.prototype */{ + defaults: { + id: 'video-details', + toolbar: 'video-details', + title: l10n.videoDetailsTitle, + content: 'video-details', + menu: 'video-details', + router: false, + priority: 60 + }, + + initialize: function( options ) { + this.media = options.media; + State.prototype.initialize.apply( this, arguments ); + } +}); + +module.exports = VideoDetails; + + +/***/ }), +/* 5 */ +/***/ (function(module, exports) { + +var Select = wp.media.view.MediaFrame.Select, + l10n = wp.media.view.l10n, + MediaDetails; + +/** + * wp.media.view.MediaFrame.MediaDetails + * + * @memberOf wp.media.view.MediaFrame + * + * @class + * @augments wp.media.view.MediaFrame.Select + * @augments wp.media.view.MediaFrame + * @augments wp.media.view.Frame + * @augments wp.media.View + * @augments wp.Backbone.View + * @augments Backbone.View + * @mixes wp.media.controller.StateMachine + */ +MediaDetails = Select.extend(/** @lends wp.media.view.MediaFrame.MediaDetails.prototype */{ + defaults: { + id: 'media', + url: '', + menu: 'media-details', + content: 'media-details', + toolbar: 'media-details', + type: 'link', + priority: 120 + }, + + initialize: function( options ) { + this.DetailsView = options.DetailsView; + this.cancelText = options.cancelText; + this.addText = options.addText; + + this.media = new wp.media.model.PostMedia( options.metadata ); + this.options.selection = new wp.media.model.Selection( this.media.attachment, { multiple: false } ); + Select.prototype.initialize.apply( this, arguments ); + }, + + bindHandlers: function() { + var menu = this.defaults.menu; + + Select.prototype.bindHandlers.apply( this, arguments ); + + this.on( 'menu:create:' + menu, this.createMenu, this ); + this.on( 'content:render:' + menu, this.renderDetailsContent, this ); + this.on( 'menu:render:' + menu, this.renderMenu, this ); + this.on( 'toolbar:render:' + menu, this.renderDetailsToolbar, this ); + }, + + renderDetailsContent: function() { + var view = new this.DetailsView({ + controller: this, + model: this.state().media, + attachment: this.state().media.attachment + }).render(); + + this.content.set( view ); + }, + + renderMenu: function( view ) { + var lastState = this.lastState(), + previous = lastState && lastState.id, + frame = this; + + view.set({ + cancel: { + text: this.cancelText, + priority: 20, + click: function() { + if ( previous ) { + frame.setState( previous ); + } else { + frame.close(); + } + } + }, + separateCancel: new wp.media.View({ + className: 'separator', + priority: 40 + }) + }); + + }, + + setPrimaryButton: function(text, handler) { + this.toolbar.set( new wp.media.view.Toolbar({ + controller: this, + items: { + button: { + style: 'primary', + text: text, + priority: 80, + click: function() { + var controller = this.controller; + handler.call( this, controller, controller.state() ); + // Restore and reset the default state. + controller.setState( controller.options.state ); + controller.reset(); + } + } + } + }) ); + }, + + renderDetailsToolbar: function() { + this.setPrimaryButton( l10n.update, function( controller, state ) { + controller.close(); + state.trigger( 'update', controller.media.toJSON() ); + } ); + }, + + renderReplaceToolbar: function() { + this.setPrimaryButton( l10n.replace, function( controller, state ) { + var attachment = state.get( 'selection' ).single(); + controller.media.changeAttachment( attachment ); + state.trigger( 'replace', controller.media.toJSON() ); + } ); + }, + + renderAddSourceToolbar: function() { + this.setPrimaryButton( this.addText, function( controller, state ) { + var attachment = state.get( 'selection' ).single(); + controller.media.setSource( attachment ); + state.trigger( 'add-source', controller.media.toJSON() ); + } ); + } +}); + +module.exports = MediaDetails; + + +/***/ }), +/* 6 */ +/***/ (function(module, exports) { + +var MediaDetails = wp.media.view.MediaFrame.MediaDetails, + MediaLibrary = wp.media.controller.MediaLibrary, + + l10n = wp.media.view.l10n, + AudioDetails; + +/** + * wp.media.view.MediaFrame.AudioDetails + * + * @memberOf wp.media.view.MediaFrame + * + * @class + * @augments wp.media.view.MediaFrame.MediaDetails + * @augments wp.media.view.MediaFrame.Select + * @augments wp.media.view.MediaFrame + * @augments wp.media.view.Frame + * @augments wp.media.View + * @augments wp.Backbone.View + * @augments Backbone.View + * @mixes wp.media.controller.StateMachine + */ +AudioDetails = MediaDetails.extend(/** @lends wp.media.view.MediaFrame.AudioDetails.prototype */{ + defaults: { + id: 'audio', + url: '', + menu: 'audio-details', + content: 'audio-details', + toolbar: 'audio-details', + type: 'link', + title: l10n.audioDetailsTitle, + priority: 120 + }, + + initialize: function( options ) { + options.DetailsView = wp.media.view.AudioDetails; + options.cancelText = l10n.audioDetailsCancel; + options.addText = l10n.audioAddSourceTitle; + + MediaDetails.prototype.initialize.call( this, options ); + }, + + bindHandlers: function() { + MediaDetails.prototype.bindHandlers.apply( this, arguments ); + + this.on( 'toolbar:render:replace-audio', this.renderReplaceToolbar, this ); + this.on( 'toolbar:render:add-audio-source', this.renderAddSourceToolbar, this ); + }, + + createStates: function() { + this.states.add([ + new wp.media.controller.AudioDetails( { + media: this.media + } ), + + new MediaLibrary( { + type: 'audio', + id: 'replace-audio', + title: l10n.audioReplaceTitle, + toolbar: 'replace-audio', + media: this.media, + menu: 'audio-details' + } ), + + new MediaLibrary( { + type: 'audio', + id: 'add-audio-source', + title: l10n.audioAddSourceTitle, + toolbar: 'add-audio-source', + media: this.media, + menu: false + } ) + ]); + } +}); + +module.exports = AudioDetails; + + +/***/ }), +/* 7 */ +/***/ (function(module, exports) { + +var MediaDetails = wp.media.view.MediaFrame.MediaDetails, + MediaLibrary = wp.media.controller.MediaLibrary, + l10n = wp.media.view.l10n, + VideoDetails; + +/** + * wp.media.view.MediaFrame.VideoDetails + * + * @memberOf wp.media.view.MediaFrame + * + * @class + * @augments wp.media.view.MediaFrame.MediaDetails + * @augments wp.media.view.MediaFrame.Select + * @augments wp.media.view.MediaFrame + * @augments wp.media.view.Frame + * @augments wp.media.View + * @augments wp.Backbone.View + * @augments Backbone.View + * @mixes wp.media.controller.StateMachine + */ +VideoDetails = MediaDetails.extend(/** @lends wp.media.view.MediaFrame.VideoDetails.prototype */{ + defaults: { + id: 'video', + url: '', + menu: 'video-details', + content: 'video-details', + toolbar: 'video-details', + type: 'link', + title: l10n.videoDetailsTitle, + priority: 120 + }, + + initialize: function( options ) { + options.DetailsView = wp.media.view.VideoDetails; + options.cancelText = l10n.videoDetailsCancel; + options.addText = l10n.videoAddSourceTitle; + + MediaDetails.prototype.initialize.call( this, options ); + }, + + bindHandlers: function() { + MediaDetails.prototype.bindHandlers.apply( this, arguments ); + + this.on( 'toolbar:render:replace-video', this.renderReplaceToolbar, this ); + this.on( 'toolbar:render:add-video-source', this.renderAddSourceToolbar, this ); + this.on( 'toolbar:render:select-poster-image', this.renderSelectPosterImageToolbar, this ); + this.on( 'toolbar:render:add-track', this.renderAddTrackToolbar, this ); + }, + + createStates: function() { + this.states.add([ + new wp.media.controller.VideoDetails({ + media: this.media + }), + + new MediaLibrary( { + type: 'video', + id: 'replace-video', + title: l10n.videoReplaceTitle, + toolbar: 'replace-video', + media: this.media, + menu: 'video-details' + } ), + + new MediaLibrary( { + type: 'video', + id: 'add-video-source', + title: l10n.videoAddSourceTitle, + toolbar: 'add-video-source', + media: this.media, + menu: false + } ), + + new MediaLibrary( { + type: 'image', + id: 'select-poster-image', + title: l10n.videoSelectPosterImageTitle, + toolbar: 'select-poster-image', + media: this.media, + menu: 'video-details' + } ), + + new MediaLibrary( { + type: 'text', + id: 'add-track', + title: l10n.videoAddTrackTitle, + toolbar: 'add-track', + media: this.media, + menu: 'video-details' + } ) + ]); + }, + + renderSelectPosterImageToolbar: function() { + this.setPrimaryButton( l10n.videoSelectPosterImageTitle, function( controller, state ) { + var urls = [], attachment = state.get( 'selection' ).single(); + + controller.media.set( 'poster', attachment.get( 'url' ) ); + state.trigger( 'set-poster-image', controller.media.toJSON() ); + + _.each( wp.media.view.settings.embedExts, function (ext) { + if ( controller.media.get( ext ) ) { + urls.push( controller.media.get( ext ) ); + } + } ); + + wp.ajax.send( 'set-attachment-thumbnail', { + data : { + urls: urls, + thumbnail_id: attachment.get( 'id' ) + } + } ); + } ); + }, + + renderAddTrackToolbar: function() { + this.setPrimaryButton( l10n.videoAddTrackTitle, function( controller, state ) { + var attachment = state.get( 'selection' ).single(), + content = controller.media.get( 'content' ); + + if ( -1 === content.indexOf( attachment.get( 'url' ) ) ) { + content += [ + '' + ].join(''); + + controller.media.set( 'content', content ); + } + state.trigger( 'add-track', controller.media.toJSON() ); + } ); + } +}); + +module.exports = VideoDetails; + + +/***/ }), +/* 8 */ +/***/ (function(module, exports) { + +/* global MediaElementPlayer */ +var AttachmentDisplay = wp.media.view.Settings.AttachmentDisplay, + $ = jQuery, + MediaDetails; + +/** + * wp.media.view.MediaDetails + * + * @memberOf wp.media.view + * + * @class + * @augments wp.media.view.Settings.AttachmentDisplay + * @augments wp.media.view.Settings + * @augments wp.media.View + * @augments wp.Backbone.View + * @augments Backbone.View + */ +MediaDetails = AttachmentDisplay.extend(/** @lends wp.media.view.MediaDetails.prototype */{ + initialize: function() { + _.bindAll(this, 'success'); + this.players = []; + this.listenTo( this.controller, 'close', wp.media.mixin.unsetPlayers ); + this.on( 'ready', this.setPlayer ); + this.on( 'media:setting:remove', wp.media.mixin.unsetPlayers, this ); + this.on( 'media:setting:remove', this.render ); + this.on( 'media:setting:remove', this.setPlayer ); + + AttachmentDisplay.prototype.initialize.apply( this, arguments ); + }, + + events: function(){ + return _.extend( { + 'click .remove-setting' : 'removeSetting', + 'change .content-track' : 'setTracks', + 'click .remove-track' : 'setTracks', + 'click .add-media-source' : 'addSource' + }, AttachmentDisplay.prototype.events ); + }, + + prepare: function() { + return _.defaults({ + model: this.model.toJSON() + }, this.options ); + }, + + /** + * Remove a setting's UI when the model unsets it + * + * @fires wp.media.view.MediaDetails#media:setting:remove + * + * @param {Event} e + */ + removeSetting : function(e) { + var wrap = $( e.currentTarget ).parent(), setting; + setting = wrap.find( 'input' ).data( 'setting' ); + + if ( setting ) { + this.model.unset( setting ); + this.trigger( 'media:setting:remove', this ); + } + + wrap.remove(); + }, + + /** + * + * @fires wp.media.view.MediaDetails#media:setting:remove + */ + setTracks : function() { + var tracks = ''; + + _.each( this.$('.content-track'), function(track) { + tracks += $( track ).val(); + } ); + + this.model.set( 'content', tracks ); + this.trigger( 'media:setting:remove', this ); + }, + + addSource : function( e ) { + this.controller.lastMime = $( e.currentTarget ).data( 'mime' ); + this.controller.setState( 'add-' + this.controller.defaults.id + '-source' ); + }, + + loadPlayer: function () { + this.players.push( new MediaElementPlayer( this.media, this.settings ) ); + this.scriptXhr = false; + }, + + setPlayer : function() { + var src; + + if ( this.players.length || ! this.media || this.scriptXhr ) { + return; + } + + src = this.model.get( 'src' ); + + if ( src && src.indexOf( 'vimeo' ) > -1 && ! ( 'Vimeo' in window ) ) { + this.scriptXhr = $.getScript( 'https://player.vimeo.com/api/player.js', _.bind( this.loadPlayer, this ) ); + } else { + this.loadPlayer(); + } + }, + + /** + * @abstract + */ + setMedia : function() { + return this; + }, + + success : function(mejs) { + var autoplay = mejs.attributes.autoplay && 'false' !== mejs.attributes.autoplay; + + if ( 'flash' === mejs.pluginType && autoplay ) { + mejs.addEventListener( 'canplay', function() { + mejs.play(); + }, false ); + } + + this.mejs = mejs; + }, + + /** + * @returns {media.view.MediaDetails} Returns itself to allow chaining + */ + render: function() { + AttachmentDisplay.prototype.render.apply( this, arguments ); + + setTimeout( _.bind( function() { + this.resetFocus(); + }, this ), 10 ); + + this.settings = _.defaults( { + success : this.success + }, wp.media.mixin.mejsSettings ); + + return this.setMedia(); + }, + + resetFocus: function() { + this.$( '.embed-media-settings' ).scrollTop( 0 ); + } +},/** @lends wp.media.view.MediaDetails */{ + instances : 0, + /** + * When multiple players in the DOM contain the same src, things get weird. + * + * @param {HTMLElement} elem + * @returns {HTMLElement} + */ + prepareSrc : function( elem ) { + var i = MediaDetails.instances++; + _.each( $( elem ).find( 'source' ), function( source ) { + source.src = [ + source.src, + source.src.indexOf('?') > -1 ? '&' : '?', + '_=', + i + ].join(''); + } ); + + return elem; + } +}); + +module.exports = MediaDetails; + + +/***/ }), +/* 9 */ +/***/ (function(module, exports) { + +var MediaDetails = wp.media.view.MediaDetails, + AudioDetails; + +/** + * wp.media.view.AudioDetails + * + * @memberOf wp.media.view + * + * @class + * @augments wp.media.view.MediaDetails + * @augments wp.media.view.Settings.AttachmentDisplay + * @augments wp.media.view.Settings + * @augments wp.media.View + * @augments wp.Backbone.View + * @augments Backbone.View + */ +AudioDetails = MediaDetails.extend(/** @lends wp.media.view.AudioDetails.prototype */{ + className: 'audio-details', + template: wp.template('audio-details'), + + setMedia: function() { + var audio = this.$('.wp-audio-shortcode'); + + if ( audio.find( 'source' ).length ) { + if ( audio.is(':hidden') ) { + audio.show(); + } + this.media = MediaDetails.prepareSrc( audio.get(0) ); + } else { + audio.hide(); + this.media = false; + } + + return this; + } +}); + +module.exports = AudioDetails; + + +/***/ }), +/* 10 */ +/***/ (function(module, exports) { + +var MediaDetails = wp.media.view.MediaDetails, + VideoDetails; + +/** + * wp.media.view.VideoDetails + * + * @memberOf wp.media.view + * + * @class + * @augments wp.media.view.MediaDetails + * @augments wp.media.view.Settings.AttachmentDisplay + * @augments wp.media.view.Settings + * @augments wp.media.View + * @augments wp.Backbone.View + * @augments Backbone.View + */ +VideoDetails = MediaDetails.extend(/** @lends wp.media.view.VideoDetails.prototype */{ + className: 'video-details', + template: wp.template('video-details'), + + setMedia: function() { + var video = this.$('.wp-video-shortcode'); + + if ( video.find( 'source' ).length ) { + if ( video.is(':hidden') ) { + video.show(); + } + + if ( ! video.hasClass( 'youtube-video' ) && ! video.hasClass( 'vimeo-video' ) ) { + this.media = MediaDetails.prepareSrc( video.get(0) ); + } else { + this.media = video.get(0); + } + } else { + video.hide(); + this.media = false; + } + + return this; + } +}); + +module.exports = VideoDetails; + /***/ }) - -/******/ }); \ No newline at end of file +/******/ ]); \ No newline at end of file diff --git a/wp-includes/js/media-audiovideo.min.js b/wp-includes/js/media-audiovideo.min.js index 3d64355c6f..4f1b443f86 100644 --- a/wp-includes/js/media-audiovideo.min.js +++ b/wp-includes/js/media-audiovideo.min.js @@ -1 +1 @@ -!function(a){function b(d){if(c[d])return c[d].exports;var e=c[d]={i:d,l:!1,exports:{}};return a[d].call(e.exports,e,e.exports,b),e.l=!0,e.exports}var c={};return b.m=a,b.c=c,b.d=function(a,c,d){b.o(a,c)||Object.defineProperty(a,c,{enumerable:!0,get:d})},b.r=function(a){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(a,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(a,"__esModule",{value:!0})},b.t=function(a,c){if(1&c&&(a=b(a)),8&c)return a;if(4&c&&"object"==typeof a&&a&&a.__esModule)return a;var d=Object.create(null);if(b.r(d),Object.defineProperty(d,"default",{enumerable:!0,value:a}),2&c&&"string"!=typeof a)for(var e in a)b.d(d,e,function(b){return a[b]}.bind(null,e));return d},b.n=function(a){var c=a&&a.__esModule?function(){return a["default"]}:function(){return a};return b.d(c,"a",c),c},b.o=function(a,b){return Object.prototype.hasOwnProperty.call(a,b)},b.p="",b(b.s=0)}({"./src/js/_enqueues/wp/media/audiovideo.js":function(module,exports,__webpack_require__){eval("/**\n * @output wp-includes/js/media-audiovideo.js\n */\n\nvar media = wp.media,\n\tbaseSettings = window._wpmejsSettings || {},\n\tl10n = window._wpMediaViewsL10n || {};\n\n/**\n *\n * Defines the wp.media.mixin object.\n *\n * @mixin\n *\n * @since 4.2.0\n */\nwp.media.mixin = {\n\tmejsSettings: baseSettings,\n\n\t/**\n\t * Pauses and removes all players.\n\t *\n\t * @since 4.2.0\n\t *\n\t * @return {void}\n\t */\n\tremoveAllPlayers: function() {\n\t\tvar p;\n\n\t\tif ( window.mejs && window.mejs.players ) {\n\t\t\tfor ( p in window.mejs.players ) {\n\t\t\t\twindow.mejs.players[p].pause();\n\t\t\t\tthis.removePlayer( window.mejs.players[p] );\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Removes the player.\n\t *\n\t * Override the MediaElement method for removing a player.\n\t * MediaElement tries to pull the audio/video tag out of\n\t * its container and re-add it to the DOM.\n\t *\n\t * @since 4.2.0\n\t *\n\t * @return {void}\n\t */\n\tremovePlayer: function(t) {\n\t\tvar featureIndex, feature;\n\n\t\tif ( ! t.options ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// invoke features cleanup\n\t\tfor ( featureIndex in t.options.features ) {\n\t\t\tfeature = t.options.features[featureIndex];\n\t\t\tif ( t['clean' + feature] ) {\n\t\t\t\ttry {\n\t\t\t\t\tt['clean' + feature](t);\n\t\t\t\t} catch (e) {}\n\t\t\t}\n\t\t}\n\n\t\tif ( ! t.isDynamic ) {\n\t\t\tt.node.remove();\n\t\t}\n\n\t\tif ( 'html5' !== t.media.rendererName ) {\n\t\t\tt.media.remove();\n\t\t}\n\n\t\tdelete window.mejs.players[t.id];\n\n\t\tt.container.remove();\n\t\tt.globalUnbind('resize', t.globalResizeCallback);\n\t\tt.globalUnbind('keydown', t.globalKeydownCallback);\n\t\tt.globalUnbind('click', t.globalClickCallback);\n\t\tdelete t.media.player;\n\t},\n\n\t/**\n\t *\n\t * Removes and resets all players.\n\t *\n\t * Allows any class that has set 'player' to a MediaElementPlayer\n\t * instance to remove the player when listening to events.\n\t *\n\t * Examples: modal closes, shortcode properties are removed, etc.\n\t *\n\t * @since 4.2.0\n\t */\n\tunsetPlayers : function() {\n\t\tif ( this.players && this.players.length ) {\n\t\t\t_.each( this.players, function (player) {\n\t\t\t\tplayer.pause();\n\t\t\t\twp.media.mixin.removePlayer( player );\n\t\t\t} );\n\t\t\tthis.players = [];\n\t\t}\n\t}\n};\n\n/**\n * Shortcode modeling for playlists.\n *\n * @since 4.2.0\n */\nwp.media.playlist = new wp.media.collection({\n\ttag: 'playlist',\n\teditTitle : l10n.editPlaylistTitle,\n\tdefaults : {\n\t\tid: wp.media.view.settings.post.id,\n\t\tstyle: 'light',\n\t\ttracklist: true,\n\t\ttracknumbers: true,\n\t\timages: true,\n\t\tartists: true,\n\t\ttype: 'audio'\n\t}\n});\n\n/**\n * Shortcode modeling for audio.\n *\n * `edit()` prepares the shortcode for the media modal.\n * `shortcode()` builds the new shortcode after an update.\n *\n * @namespace\n *\n * @since 4.2.0\n */\nwp.media.audio = {\n\tcoerce : wp.media.coerce,\n\n\tdefaults : {\n\t\tid : wp.media.view.settings.post.id,\n\t\tsrc : '',\n\t\tloop : false,\n\t\tautoplay : false,\n\t\tpreload : 'none',\n\t\twidth : 400\n\t},\n\n\t/**\n\t * Instantiates a new media object with the next matching shortcode.\n\t *\n\t * @since 4.2.0\n\t *\n\t * @param {string} data The text to apply the shortcode on.\n\t * @returns {wp.media} The media object.\n\t */\n\tedit : function( data ) {\n\t\tvar frame, shortcode = wp.shortcode.next( 'audio', data ).shortcode;\n\n\t\tframe = wp.media({\n\t\t\tframe: 'audio',\n\t\t\tstate: 'audio-details',\n\t\t\tmetadata: _.defaults( shortcode.attrs.named, this.defaults )\n\t\t});\n\n\t\treturn frame;\n\t},\n\n\t/**\n\t * Generates an audio shortcode.\n\t *\n\t * @since 4.2.0\n\t *\n\t * @param {Array} model Array with attributes for the shortcode.\n\t * @returns {wp.shortcode} The audio shortcode object.\n\t */\n\tshortcode : function( model ) {\n\t\tvar content;\n\n\t\t_.each( this.defaults, function( value, key ) {\n\t\t\tmodel[ key ] = this.coerce( model, key );\n\n\t\t\tif ( value === model[ key ] ) {\n\t\t\t\tdelete model[ key ];\n\t\t\t}\n\t\t}, this );\n\n\t\tcontent = model.content;\n\t\tdelete model.content;\n\n\t\treturn new wp.shortcode({\n\t\t\ttag: 'audio',\n\t\t\tattrs: model,\n\t\t\tcontent: content\n\t\t});\n\t}\n};\n\n/**\n * Shortcode modeling for video.\n *\n * `edit()` prepares the shortcode for the media modal.\n * `shortcode()` builds the new shortcode after update.\n *\n * @since 4.2.0\n *\n * @namespace\n */\nwp.media.video = {\n\tcoerce : wp.media.coerce,\n\n\tdefaults : {\n\t\tid : wp.media.view.settings.post.id,\n\t\tsrc : '',\n\t\tposter : '',\n\t\tloop : false,\n\t\tautoplay : false,\n\t\tpreload : 'metadata',\n\t\tcontent : '',\n\t\twidth : 640,\n\t\theight : 360\n\t},\n\n\t/**\n\t * Instantiates a new media object with the next matching shortcode.\n\t *\n\t * @since 4.2.0\n\t *\n\t * @param {string} data The text to apply the shortcode on.\n\t * @returns {wp.media} The media object.\n\t */\n\tedit : function( data ) {\n\t\tvar frame,\n\t\t\tshortcode = wp.shortcode.next( 'video', data ).shortcode,\n\t\t\tattrs;\n\n\t\tattrs = shortcode.attrs.named;\n\t\tattrs.content = shortcode.content;\n\n\t\tframe = wp.media({\n\t\t\tframe: 'video',\n\t\t\tstate: 'video-details',\n\t\t\tmetadata: _.defaults( attrs, this.defaults )\n\t\t});\n\n\t\treturn frame;\n\t},\n\n\t/**\n\t * Generates an video shortcode.\n\t *\n\t * @since 4.2.0\n\t *\n\t * @param {Array} model Array with attributes for the shortcode.\n\t * @returns {wp.shortcode} The video shortcode object.\n\t */\n\tshortcode : function( model ) {\n\t\tvar content;\n\n\t\t_.each( this.defaults, function( value, key ) {\n\t\t\tmodel[ key ] = this.coerce( model, key );\n\n\t\t\tif ( value === model[ key ] ) {\n\t\t\t\tdelete model[ key ];\n\t\t\t}\n\t\t}, this );\n\n\t\tcontent = model.content;\n\t\tdelete model.content;\n\n\t\treturn new wp.shortcode({\n\t\t\ttag: 'video',\n\t\t\tattrs: model,\n\t\t\tcontent: content\n\t\t});\n\t}\n};\n\nmedia.model.PostMedia = __webpack_require__( /*! ../../../media/models/post-media.js */ \"./src/js/media/models/post-media.js\" );\nmedia.controller.AudioDetails = __webpack_require__( /*! ../../../media/controllers/audio-details.js */ \"./src/js/media/controllers/audio-details.js\" );\nmedia.controller.VideoDetails = __webpack_require__( /*! ../../../media/controllers/video-details.js */ \"./src/js/media/controllers/video-details.js\" );\nmedia.view.MediaFrame.MediaDetails = __webpack_require__( /*! ../../../media/views/frame/media-details.js */ \"./src/js/media/views/frame/media-details.js\" );\nmedia.view.MediaFrame.AudioDetails = __webpack_require__( /*! ../../../media/views/frame/audio-details.js */ \"./src/js/media/views/frame/audio-details.js\" );\nmedia.view.MediaFrame.VideoDetails = __webpack_require__( /*! ../../../media/views/frame/video-details.js */ \"./src/js/media/views/frame/video-details.js\" );\nmedia.view.MediaDetails = __webpack_require__( /*! ../../../media/views/media-details.js */ \"./src/js/media/views/media-details.js\" );\nmedia.view.AudioDetails = __webpack_require__( /*! ../../../media/views/audio-details.js */ \"./src/js/media/views/audio-details.js\" );\nmedia.view.VideoDetails = __webpack_require__( /*! ../../../media/views/video-details.js */ \"./src/js/media/views/video-details.js\" );\n\n\n//# sourceURL=webpack:///./src/js/_enqueues/wp/media/audiovideo.js?")},"./src/js/media/controllers/audio-details.js":function(module,exports){eval("var State = wp.media.controller.State,\n\tl10n = wp.media.view.l10n,\n\tAudioDetails;\n\n/**\n * wp.media.controller.AudioDetails\n *\n * The controller for the Audio Details state\n *\n * @memberOf wp.media.controller\n *\n * @class\n * @augments wp.media.controller.State\n * @augments Backbone.Model\n */\nAudioDetails = State.extend(/** @lends wp.media.controller.AudioDetails.prototype */{\n\tdefaults: {\n\t\tid: 'audio-details',\n\t\ttoolbar: 'audio-details',\n\t\ttitle: l10n.audioDetailsTitle,\n\t\tcontent: 'audio-details',\n\t\tmenu: 'audio-details',\n\t\trouter: false,\n\t\tpriority: 60\n\t},\n\n\tinitialize: function( options ) {\n\t\tthis.media = options.media;\n\t\tState.prototype.initialize.apply( this, arguments );\n\t}\n});\n\nmodule.exports = AudioDetails;\n\n\n//# sourceURL=webpack:///./src/js/media/controllers/audio-details.js?")},"./src/js/media/controllers/video-details.js":function(module,exports){eval("/**\n * wp.media.controller.VideoDetails\n *\n * The controller for the Video Details state\n *\n * @memberOf wp.media.controller\n *\n * @class\n * @augments wp.media.controller.State\n * @augments Backbone.Model\n */\nvar State = wp.media.controller.State,\n\tl10n = wp.media.view.l10n,\n\tVideoDetails;\n\nVideoDetails = State.extend(/** @lends wp.media.controller.VideoDetails.prototype */{\n\tdefaults: {\n\t\tid: 'video-details',\n\t\ttoolbar: 'video-details',\n\t\ttitle: l10n.videoDetailsTitle,\n\t\tcontent: 'video-details',\n\t\tmenu: 'video-details',\n\t\trouter: false,\n\t\tpriority: 60\n\t},\n\n\tinitialize: function( options ) {\n\t\tthis.media = options.media;\n\t\tState.prototype.initialize.apply( this, arguments );\n\t}\n});\n\nmodule.exports = VideoDetails;\n\n\n//# sourceURL=webpack:///./src/js/media/controllers/video-details.js?")},"./src/js/media/models/post-media.js":function(module,exports){eval("/**\n * wp.media.model.PostMedia\n *\n * Shared model class for audio and video. Updates the model after\n * \"Add Audio|Video Source\" and \"Replace Audio|Video\" states return\n *\n * @memberOf wp.media.model\n *\n * @class\n * @augments Backbone.Model\n */\nvar PostMedia = Backbone.Model.extend(/** @lends wp.media.model.PostMedia.prototype */{\n\tinitialize: function() {\n\t\tthis.attachment = false;\n\t},\n\n\tsetSource: function( attachment ) {\n\t\tthis.attachment = attachment;\n\t\tthis.extension = attachment.get( 'filename' ).split('.').pop();\n\n\t\tif ( this.get( 'src' ) && this.extension === this.get( 'src' ).split('.').pop() ) {\n\t\t\tthis.unset( 'src' );\n\t\t}\n\n\t\tif ( _.contains( wp.media.view.settings.embedExts, this.extension ) ) {\n\t\t\tthis.set( this.extension, this.attachment.get( 'url' ) );\n\t\t} else {\n\t\t\tthis.unset( this.extension );\n\t\t}\n\t},\n\n\tchangeAttachment: function( attachment ) {\n\t\tthis.setSource( attachment );\n\n\t\tthis.unset( 'src' );\n\t\t_.each( _.without( wp.media.view.settings.embedExts, this.extension ), function( ext ) {\n\t\t\tthis.unset( ext );\n\t\t}, this );\n\t}\n});\n\nmodule.exports = PostMedia;\n\n\n//# sourceURL=webpack:///./src/js/media/models/post-media.js?")},"./src/js/media/views/audio-details.js":function(module,exports){eval("var MediaDetails = wp.media.view.MediaDetails,\n\tAudioDetails;\n\n/**\n * wp.media.view.AudioDetails\n *\n * @memberOf wp.media.view\n *\n * @class\n * @augments wp.media.view.MediaDetails\n * @augments wp.media.view.Settings.AttachmentDisplay\n * @augments wp.media.view.Settings\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n */\nAudioDetails = MediaDetails.extend(/** @lends wp.media.view.AudioDetails.prototype */{\n\tclassName: 'audio-details',\n\ttemplate: wp.template('audio-details'),\n\n\tsetMedia: function() {\n\t\tvar audio = this.$('.wp-audio-shortcode');\n\n\t\tif ( audio.find( 'source' ).length ) {\n\t\t\tif ( audio.is(':hidden') ) {\n\t\t\t\taudio.show();\n\t\t\t}\n\t\t\tthis.media = MediaDetails.prepareSrc( audio.get(0) );\n\t\t} else {\n\t\t\taudio.hide();\n\t\t\tthis.media = false;\n\t\t}\n\n\t\treturn this;\n\t}\n});\n\nmodule.exports = AudioDetails;\n\n\n//# sourceURL=webpack:///./src/js/media/views/audio-details.js?")},"./src/js/media/views/frame/audio-details.js":function(module,exports){eval("var MediaDetails = wp.media.view.MediaFrame.MediaDetails,\n\tMediaLibrary = wp.media.controller.MediaLibrary,\n\n\tl10n = wp.media.view.l10n,\n\tAudioDetails;\n\n/**\n * wp.media.view.MediaFrame.AudioDetails\n *\n * @memberOf wp.media.view.MediaFrame\n *\n * @class\n * @augments wp.media.view.MediaFrame.MediaDetails\n * @augments wp.media.view.MediaFrame.Select\n * @augments wp.media.view.MediaFrame\n * @augments wp.media.view.Frame\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n * @mixes wp.media.controller.StateMachine\n */\nAudioDetails = MediaDetails.extend(/** @lends wp.media.view.MediaFrame.AudioDetails.prototype */{\n\tdefaults: {\n\t\tid: 'audio',\n\t\turl: '',\n\t\tmenu: 'audio-details',\n\t\tcontent: 'audio-details',\n\t\ttoolbar: 'audio-details',\n\t\ttype: 'link',\n\t\ttitle: l10n.audioDetailsTitle,\n\t\tpriority: 120\n\t},\n\n\tinitialize: function( options ) {\n\t\toptions.DetailsView = wp.media.view.AudioDetails;\n\t\toptions.cancelText = l10n.audioDetailsCancel;\n\t\toptions.addText = l10n.audioAddSourceTitle;\n\n\t\tMediaDetails.prototype.initialize.call( this, options );\n\t},\n\n\tbindHandlers: function() {\n\t\tMediaDetails.prototype.bindHandlers.apply( this, arguments );\n\n\t\tthis.on( 'toolbar:render:replace-audio', this.renderReplaceToolbar, this );\n\t\tthis.on( 'toolbar:render:add-audio-source', this.renderAddSourceToolbar, this );\n\t},\n\n\tcreateStates: function() {\n\t\tthis.states.add([\n\t\t\tnew wp.media.controller.AudioDetails( {\n\t\t\t\tmedia: this.media\n\t\t\t} ),\n\n\t\t\tnew MediaLibrary( {\n\t\t\t\ttype: 'audio',\n\t\t\t\tid: 'replace-audio',\n\t\t\t\ttitle: l10n.audioReplaceTitle,\n\t\t\t\ttoolbar: 'replace-audio',\n\t\t\t\tmedia: this.media,\n\t\t\t\tmenu: 'audio-details'\n\t\t\t} ),\n\n\t\t\tnew MediaLibrary( {\n\t\t\t\ttype: 'audio',\n\t\t\t\tid: 'add-audio-source',\n\t\t\t\ttitle: l10n.audioAddSourceTitle,\n\t\t\t\ttoolbar: 'add-audio-source',\n\t\t\t\tmedia: this.media,\n\t\t\t\tmenu: false\n\t\t\t} )\n\t\t]);\n\t}\n});\n\nmodule.exports = AudioDetails;\n\n\n//# sourceURL=webpack:///./src/js/media/views/frame/audio-details.js?")},"./src/js/media/views/frame/media-details.js":function(module,exports){eval("var Select = wp.media.view.MediaFrame.Select,\n\tl10n = wp.media.view.l10n,\n\tMediaDetails;\n\n/**\n * wp.media.view.MediaFrame.MediaDetails\n *\n * @memberOf wp.media.view.MediaFrame\n *\n * @class\n * @augments wp.media.view.MediaFrame.Select\n * @augments wp.media.view.MediaFrame\n * @augments wp.media.view.Frame\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n * @mixes wp.media.controller.StateMachine\n */\nMediaDetails = Select.extend(/** @lends wp.media.view.MediaFrame.MediaDetails.prototype */{\n\tdefaults: {\n\t\tid: 'media',\n\t\turl: '',\n\t\tmenu: 'media-details',\n\t\tcontent: 'media-details',\n\t\ttoolbar: 'media-details',\n\t\ttype: 'link',\n\t\tpriority: 120\n\t},\n\n\tinitialize: function( options ) {\n\t\tthis.DetailsView = options.DetailsView;\n\t\tthis.cancelText = options.cancelText;\n\t\tthis.addText = options.addText;\n\n\t\tthis.media = new wp.media.model.PostMedia( options.metadata );\n\t\tthis.options.selection = new wp.media.model.Selection( this.media.attachment, { multiple: false } );\n\t\tSelect.prototype.initialize.apply( this, arguments );\n\t},\n\n\tbindHandlers: function() {\n\t\tvar menu = this.defaults.menu;\n\n\t\tSelect.prototype.bindHandlers.apply( this, arguments );\n\n\t\tthis.on( 'menu:create:' + menu, this.createMenu, this );\n\t\tthis.on( 'content:render:' + menu, this.renderDetailsContent, this );\n\t\tthis.on( 'menu:render:' + menu, this.renderMenu, this );\n\t\tthis.on( 'toolbar:render:' + menu, this.renderDetailsToolbar, this );\n\t},\n\n\trenderDetailsContent: function() {\n\t\tvar view = new this.DetailsView({\n\t\t\tcontroller: this,\n\t\t\tmodel: this.state().media,\n\t\t\tattachment: this.state().media.attachment\n\t\t}).render();\n\n\t\tthis.content.set( view );\n\t},\n\n\trenderMenu: function( view ) {\n\t\tvar lastState = this.lastState(),\n\t\t\tprevious = lastState && lastState.id,\n\t\t\tframe = this;\n\n\t\tview.set({\n\t\t\tcancel: {\n\t\t\t\ttext: this.cancelText,\n\t\t\t\tpriority: 20,\n\t\t\t\tclick: function() {\n\t\t\t\t\tif ( previous ) {\n\t\t\t\t\t\tframe.setState( previous );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tframe.close();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\tseparateCancel: new wp.media.View({\n\t\t\t\tclassName: 'separator',\n\t\t\t\tpriority: 40\n\t\t\t})\n\t\t});\n\n\t},\n\n\tsetPrimaryButton: function(text, handler) {\n\t\tthis.toolbar.set( new wp.media.view.Toolbar({\n\t\t\tcontroller: this,\n\t\t\titems: {\n\t\t\t\tbutton: {\n\t\t\t\t\tstyle: 'primary',\n\t\t\t\t\ttext: text,\n\t\t\t\t\tpriority: 80,\n\t\t\t\t\tclick: function() {\n\t\t\t\t\t\tvar controller = this.controller;\n\t\t\t\t\t\thandler.call( this, controller, controller.state() );\n\t\t\t\t\t\t// Restore and reset the default state.\n\t\t\t\t\t\tcontroller.setState( controller.options.state );\n\t\t\t\t\t\tcontroller.reset();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}) );\n\t},\n\n\trenderDetailsToolbar: function() {\n\t\tthis.setPrimaryButton( l10n.update, function( controller, state ) {\n\t\t\tcontroller.close();\n\t\t\tstate.trigger( 'update', controller.media.toJSON() );\n\t\t} );\n\t},\n\n\trenderReplaceToolbar: function() {\n\t\tthis.setPrimaryButton( l10n.replace, function( controller, state ) {\n\t\t\tvar attachment = state.get( 'selection' ).single();\n\t\t\tcontroller.media.changeAttachment( attachment );\n\t\t\tstate.trigger( 'replace', controller.media.toJSON() );\n\t\t} );\n\t},\n\n\trenderAddSourceToolbar: function() {\n\t\tthis.setPrimaryButton( this.addText, function( controller, state ) {\n\t\t\tvar attachment = state.get( 'selection' ).single();\n\t\t\tcontroller.media.setSource( attachment );\n\t\t\tstate.trigger( 'add-source', controller.media.toJSON() );\n\t\t} );\n\t}\n});\n\nmodule.exports = MediaDetails;\n\n\n//# sourceURL=webpack:///./src/js/media/views/frame/media-details.js?")},"./src/js/media/views/frame/video-details.js":function(module,exports){eval("var MediaDetails = wp.media.view.MediaFrame.MediaDetails,\n\tMediaLibrary = wp.media.controller.MediaLibrary,\n\tl10n = wp.media.view.l10n,\n\tVideoDetails;\n\n/**\n * wp.media.view.MediaFrame.VideoDetails\n *\n * @memberOf wp.media.view.MediaFrame\n *\n * @class\n * @augments wp.media.view.MediaFrame.MediaDetails\n * @augments wp.media.view.MediaFrame.Select\n * @augments wp.media.view.MediaFrame\n * @augments wp.media.view.Frame\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n * @mixes wp.media.controller.StateMachine\n */\nVideoDetails = MediaDetails.extend(/** @lends wp.media.view.MediaFrame.VideoDetails.prototype */{\n\tdefaults: {\n\t\tid: 'video',\n\t\turl: '',\n\t\tmenu: 'video-details',\n\t\tcontent: 'video-details',\n\t\ttoolbar: 'video-details',\n\t\ttype: 'link',\n\t\ttitle: l10n.videoDetailsTitle,\n\t\tpriority: 120\n\t},\n\n\tinitialize: function( options ) {\n\t\toptions.DetailsView = wp.media.view.VideoDetails;\n\t\toptions.cancelText = l10n.videoDetailsCancel;\n\t\toptions.addText = l10n.videoAddSourceTitle;\n\n\t\tMediaDetails.prototype.initialize.call( this, options );\n\t},\n\n\tbindHandlers: function() {\n\t\tMediaDetails.prototype.bindHandlers.apply( this, arguments );\n\n\t\tthis.on( 'toolbar:render:replace-video', this.renderReplaceToolbar, this );\n\t\tthis.on( 'toolbar:render:add-video-source', this.renderAddSourceToolbar, this );\n\t\tthis.on( 'toolbar:render:select-poster-image', this.renderSelectPosterImageToolbar, this );\n\t\tthis.on( 'toolbar:render:add-track', this.renderAddTrackToolbar, this );\n\t},\n\n\tcreateStates: function() {\n\t\tthis.states.add([\n\t\t\tnew wp.media.controller.VideoDetails({\n\t\t\t\tmedia: this.media\n\t\t\t}),\n\n\t\t\tnew MediaLibrary( {\n\t\t\t\ttype: 'video',\n\t\t\t\tid: 'replace-video',\n\t\t\t\ttitle: l10n.videoReplaceTitle,\n\t\t\t\ttoolbar: 'replace-video',\n\t\t\t\tmedia: this.media,\n\t\t\t\tmenu: 'video-details'\n\t\t\t} ),\n\n\t\t\tnew MediaLibrary( {\n\t\t\t\ttype: 'video',\n\t\t\t\tid: 'add-video-source',\n\t\t\t\ttitle: l10n.videoAddSourceTitle,\n\t\t\t\ttoolbar: 'add-video-source',\n\t\t\t\tmedia: this.media,\n\t\t\t\tmenu: false\n\t\t\t} ),\n\n\t\t\tnew MediaLibrary( {\n\t\t\t\ttype: 'image',\n\t\t\t\tid: 'select-poster-image',\n\t\t\t\ttitle: l10n.videoSelectPosterImageTitle,\n\t\t\t\ttoolbar: 'select-poster-image',\n\t\t\t\tmedia: this.media,\n\t\t\t\tmenu: 'video-details'\n\t\t\t} ),\n\n\t\t\tnew MediaLibrary( {\n\t\t\t\ttype: 'text',\n\t\t\t\tid: 'add-track',\n\t\t\t\ttitle: l10n.videoAddTrackTitle,\n\t\t\t\ttoolbar: 'add-track',\n\t\t\t\tmedia: this.media,\n\t\t\t\tmenu: 'video-details'\n\t\t\t} )\n\t\t]);\n\t},\n\n\trenderSelectPosterImageToolbar: function() {\n\t\tthis.setPrimaryButton( l10n.videoSelectPosterImageTitle, function( controller, state ) {\n\t\t\tvar urls = [], attachment = state.get( 'selection' ).single();\n\n\t\t\tcontroller.media.set( 'poster', attachment.get( 'url' ) );\n\t\t\tstate.trigger( 'set-poster-image', controller.media.toJSON() );\n\n\t\t\t_.each( wp.media.view.settings.embedExts, function (ext) {\n\t\t\t\tif ( controller.media.get( ext ) ) {\n\t\t\t\t\turls.push( controller.media.get( ext ) );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\twp.ajax.send( 'set-attachment-thumbnail', {\n\t\t\t\tdata : {\n\t\t\t\t\turls: urls,\n\t\t\t\t\tthumbnail_id: attachment.get( 'id' )\n\t\t\t\t}\n\t\t\t} );\n\t\t} );\n\t},\n\n\trenderAddTrackToolbar: function() {\n\t\tthis.setPrimaryButton( l10n.videoAddTrackTitle, function( controller, state ) {\n\t\t\tvar attachment = state.get( 'selection' ).single(),\n\t\t\t\tcontent = controller.media.get( 'content' );\n\n\t\t\tif ( -1 === content.indexOf( attachment.get( 'url' ) ) ) {\n\t\t\t\tcontent += [\n\t\t\t\t\t''\n\t\t\t\t].join('');\n\n\t\t\t\tcontroller.media.set( 'content', content );\n\t\t\t}\n\t\t\tstate.trigger( 'add-track', controller.media.toJSON() );\n\t\t} );\n\t}\n});\n\nmodule.exports = VideoDetails;\n\n\n//# sourceURL=webpack:///./src/js/media/views/frame/video-details.js?")},"./src/js/media/views/media-details.js":function(module,exports){eval("/* global MediaElementPlayer */\nvar AttachmentDisplay = wp.media.view.Settings.AttachmentDisplay,\n\t$ = jQuery,\n\tMediaDetails;\n\n/**\n * wp.media.view.MediaDetails\n *\n * @memberOf wp.media.view\n *\n * @class\n * @augments wp.media.view.Settings.AttachmentDisplay\n * @augments wp.media.view.Settings\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n */\nMediaDetails = AttachmentDisplay.extend(/** @lends wp.media.view.MediaDetails.prototype */{\n\tinitialize: function() {\n\t\t_.bindAll(this, 'success');\n\t\tthis.players = [];\n\t\tthis.listenTo( this.controller, 'close', wp.media.mixin.unsetPlayers );\n\t\tthis.on( 'ready', this.setPlayer );\n\t\tthis.on( 'media:setting:remove', wp.media.mixin.unsetPlayers, this );\n\t\tthis.on( 'media:setting:remove', this.render );\n\t\tthis.on( 'media:setting:remove', this.setPlayer );\n\n\t\tAttachmentDisplay.prototype.initialize.apply( this, arguments );\n\t},\n\n\tevents: function(){\n\t\treturn _.extend( {\n\t\t\t'click .remove-setting' : 'removeSetting',\n\t\t\t'change .content-track' : 'setTracks',\n\t\t\t'click .remove-track' : 'setTracks',\n\t\t\t'click .add-media-source' : 'addSource'\n\t\t}, AttachmentDisplay.prototype.events );\n\t},\n\n\tprepare: function() {\n\t\treturn _.defaults({\n\t\t\tmodel: this.model.toJSON()\n\t\t}, this.options );\n\t},\n\n\t/**\n\t * Remove a setting's UI when the model unsets it\n\t *\n\t * @fires wp.media.view.MediaDetails#media:setting:remove\n\t *\n\t * @param {Event} e\n\t */\n\tremoveSetting : function(e) {\n\t\tvar wrap = $( e.currentTarget ).parent(), setting;\n\t\tsetting = wrap.find( 'input' ).data( 'setting' );\n\n\t\tif ( setting ) {\n\t\t\tthis.model.unset( setting );\n\t\t\tthis.trigger( 'media:setting:remove', this );\n\t\t}\n\n\t\twrap.remove();\n\t},\n\n\t/**\n\t *\n\t * @fires wp.media.view.MediaDetails#media:setting:remove\n\t */\n\tsetTracks : function() {\n\t\tvar tracks = '';\n\n\t\t_.each( this.$('.content-track'), function(track) {\n\t\t\ttracks += $( track ).val();\n\t\t} );\n\n\t\tthis.model.set( 'content', tracks );\n\t\tthis.trigger( 'media:setting:remove', this );\n\t},\n\n\taddSource : function( e ) {\n\t\tthis.controller.lastMime = $( e.currentTarget ).data( 'mime' );\n\t\tthis.controller.setState( 'add-' + this.controller.defaults.id + '-source' );\n\t},\n\n\tloadPlayer: function () {\n\t\tthis.players.push( new MediaElementPlayer( this.media, this.settings ) );\n\t\tthis.scriptXhr = false;\n\t},\n\n\tsetPlayer : function() {\n\t\tvar src;\n\n\t\tif ( this.players.length || ! this.media || this.scriptXhr ) {\n\t\t\treturn;\n\t\t}\n\n\t\tsrc = this.model.get( 'src' );\n\n\t\tif ( src && src.indexOf( 'vimeo' ) > -1 && ! ( 'Vimeo' in window ) ) {\n\t\t\tthis.scriptXhr = $.getScript( 'https://player.vimeo.com/api/player.js', _.bind( this.loadPlayer, this ) );\n\t\t} else {\n\t\t\tthis.loadPlayer();\n\t\t}\n\t},\n\n\t/**\n\t * @abstract\n\t */\n\tsetMedia : function() {\n\t\treturn this;\n\t},\n\n\tsuccess : function(mejs) {\n\t\tvar autoplay = mejs.attributes.autoplay && 'false' !== mejs.attributes.autoplay;\n\n\t\tif ( 'flash' === mejs.pluginType && autoplay ) {\n\t\t\tmejs.addEventListener( 'canplay', function() {\n\t\t\t\tmejs.play();\n\t\t\t}, false );\n\t\t}\n\n\t\tthis.mejs = mejs;\n\t},\n\n\t/**\n\t * @returns {media.view.MediaDetails} Returns itself to allow chaining\n\t */\n\trender: function() {\n\t\tAttachmentDisplay.prototype.render.apply( this, arguments );\n\n\t\tsetTimeout( _.bind( function() {\n\t\t\tthis.resetFocus();\n\t\t}, this ), 10 );\n\n\t\tthis.settings = _.defaults( {\n\t\t\tsuccess : this.success\n\t\t}, wp.media.mixin.mejsSettings );\n\n\t\treturn this.setMedia();\n\t},\n\n\tresetFocus: function() {\n\t\tthis.$( '.embed-media-settings' ).scrollTop( 0 );\n\t}\n},/** @lends wp.media.view.MediaDetails */{\n\tinstances : 0,\n\t/**\n\t * When multiple players in the DOM contain the same src, things get weird.\n\t *\n\t * @param {HTMLElement} elem\n\t * @returns {HTMLElement}\n\t */\n\tprepareSrc : function( elem ) {\n\t\tvar i = MediaDetails.instances++;\n\t\t_.each( $( elem ).find( 'source' ), function( source ) {\n\t\t\tsource.src = [\n\t\t\t\tsource.src,\n\t\t\t\tsource.src.indexOf('?') > -1 ? '&' : '?',\n\t\t\t\t'_=',\n\t\t\t\ti\n\t\t\t].join('');\n\t\t} );\n\n\t\treturn elem;\n\t}\n});\n\nmodule.exports = MediaDetails;\n\n\n//# sourceURL=webpack:///./src/js/media/views/media-details.js?")},"./src/js/media/views/video-details.js":function(module,exports){eval("var MediaDetails = wp.media.view.MediaDetails,\n\tVideoDetails;\n\n/**\n * wp.media.view.VideoDetails\n *\n * @memberOf wp.media.view\n *\n * @class\n * @augments wp.media.view.MediaDetails\n * @augments wp.media.view.Settings.AttachmentDisplay\n * @augments wp.media.view.Settings\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n */\nVideoDetails = MediaDetails.extend(/** @lends wp.media.view.VideoDetails.prototype */{\n\tclassName: 'video-details',\n\ttemplate: wp.template('video-details'),\n\n\tsetMedia: function() {\n\t\tvar video = this.$('.wp-video-shortcode');\n\n\t\tif ( video.find( 'source' ).length ) {\n\t\t\tif ( video.is(':hidden') ) {\n\t\t\t\tvideo.show();\n\t\t\t}\n\n\t\t\tif ( ! video.hasClass( 'youtube-video' ) && ! video.hasClass( 'vimeo-video' ) ) {\n\t\t\t\tthis.media = MediaDetails.prepareSrc( video.get(0) );\n\t\t\t} else {\n\t\t\t\tthis.media = video.get(0);\n\t\t\t}\n\t\t} else {\n\t\t\tvideo.hide();\n\t\t\tthis.media = false;\n\t\t}\n\n\t\treturn this;\n\t}\n});\n\nmodule.exports = VideoDetails;\n\n\n//# sourceURL=webpack:///./src/js/media/views/video-details.js?")},0:function(module,exports,__webpack_require__){eval('module.exports = __webpack_require__(/*! ./src/js/_enqueues/wp/media/audiovideo.js */"./src/js/_enqueues/wp/media/audiovideo.js");\n\n\n//# sourceURL=webpack:///multi_./src/js/_enqueues/wp/media/audiovideo.js?')}}); \ No newline at end of file +!function(a){function b(d){if(c[d])return c[d].exports;var e=c[d]={i:d,l:!1,exports:{}};return a[d].call(e.exports,e,e.exports,b),e.l=!0,e.exports}var c={};return b.m=a,b.c=c,b.d=function(a,c,d){b.o(a,c)||Object.defineProperty(a,c,{enumerable:!0,get:d})},b.r=function(a){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(a,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(a,"__esModule",{value:!0})},b.t=function(a,c){if(1&c&&(a=b(a)),8&c)return a;if(4&c&&"object"==typeof a&&a&&a.__esModule)return a;var d=Object.create(null);if(b.r(d),Object.defineProperty(d,"default",{enumerable:!0,value:a}),2&c&&"string"!=typeof a)for(var e in a)b.d(d,e,function(b){return a[b]}.bind(null,e));return d},b.n=function(a){var c=a&&a.__esModule?function(){return a["default"]}:function(){return a};return b.d(c,"a",c),c},b.o=function(a,b){return Object.prototype.hasOwnProperty.call(a,b)},b.p="",b(b.s=0)}([function(a,b,c){a.exports=c(1)},function(a,b,c){var d=wp.media,e=window._wpmejsSettings||{},f=window._wpMediaViewsL10n||{};wp.media.mixin={mejsSettings:e,removeAllPlayers:function(){var a;if(window.mejs&&window.mejs.players)for(a in window.mejs.players)window.mejs.players[a].pause(),this.removePlayer(window.mejs.players[a])},removePlayer:function(a){var b,c;if(a.options){for(b in a.options.features)if(c=a.options.features[b],a["clean"+c])try{a["clean"+c](a)}catch(d){}a.isDynamic||a.node.remove(),"html5"!==a.media.rendererName&&a.media.remove(),delete window.mejs.players[a.id],a.container.remove(),a.globalUnbind("resize",a.globalResizeCallback),a.globalUnbind("keydown",a.globalKeydownCallback),a.globalUnbind("click",a.globalClickCallback),delete a.media.player}},unsetPlayers:function(){this.players&&this.players.length&&(_.each(this.players,function(a){a.pause(),wp.media.mixin.removePlayer(a)}),this.players=[])}},wp.media.playlist=new wp.media.collection({tag:"playlist",editTitle:f.editPlaylistTitle,defaults:{id:wp.media.view.settings.post.id,style:"light",tracklist:!0,tracknumbers:!0,images:!0,artists:!0,type:"audio"}}),wp.media.audio={coerce:wp.media.coerce,defaults:{id:wp.media.view.settings.post.id,src:"",loop:!1,autoplay:!1,preload:"none",width:400},edit:function(a){var b,c=wp.shortcode.next("audio",a).shortcode;return b=wp.media({frame:"audio",state:"audio-details",metadata:_.defaults(c.attrs.named,this.defaults)})},shortcode:function(a){var b;return _.each(this.defaults,function(b,c){a[c]=this.coerce(a,c),b===a[c]&&delete a[c]},this),b=a.content,delete a.content,new wp.shortcode({tag:"audio",attrs:a,content:b})}},wp.media.video={coerce:wp.media.coerce,defaults:{id:wp.media.view.settings.post.id,src:"",poster:"",loop:!1,autoplay:!1,preload:"metadata",content:"",width:640,height:360},edit:function(a){var b,c,d=wp.shortcode.next("video",a).shortcode;return c=d.attrs.named,c.content=d.content,b=wp.media({frame:"video",state:"video-details",metadata:_.defaults(c,this.defaults)})},shortcode:function(a){var b;return _.each(this.defaults,function(b,c){a[c]=this.coerce(a,c),b===a[c]&&delete a[c]},this),b=a.content,delete a.content,new wp.shortcode({tag:"video",attrs:a,content:b})}},d.model.PostMedia=c(2),d.controller.AudioDetails=c(3),d.controller.VideoDetails=c(4),d.view.MediaFrame.MediaDetails=c(5),d.view.MediaFrame.AudioDetails=c(6),d.view.MediaFrame.VideoDetails=c(7),d.view.MediaDetails=c(8),d.view.AudioDetails=c(9),d.view.VideoDetails=c(10)},function(a,b){var c=Backbone.Model.extend({initialize:function(){this.attachment=!1},setSource:function(a){this.attachment=a,this.extension=a.get("filename").split(".").pop(),this.get("src")&&this.extension===this.get("src").split(".").pop()&&this.unset("src"),_.contains(wp.media.view.settings.embedExts,this.extension)?this.set(this.extension,this.attachment.get("url")):this.unset(this.extension)},changeAttachment:function(a){this.setSource(a),this.unset("src"),_.each(_.without(wp.media.view.settings.embedExts,this.extension),function(a){this.unset(a)},this)}});a.exports=c},function(a,b){var c,d=wp.media.controller.State,e=wp.media.view.l10n;c=d.extend({defaults:{id:"audio-details",toolbar:"audio-details",title:e.audioDetailsTitle,content:"audio-details",menu:"audio-details",router:!1,priority:60},initialize:function(a){this.media=a.media,d.prototype.initialize.apply(this,arguments)}}),a.exports=c},function(a,b){var c,d=wp.media.controller.State,e=wp.media.view.l10n;c=d.extend({defaults:{id:"video-details",toolbar:"video-details",title:e.videoDetailsTitle,content:"video-details",menu:"video-details",router:!1,priority:60},initialize:function(a){this.media=a.media,d.prototype.initialize.apply(this,arguments)}}),a.exports=c},function(a,b){var c,d=wp.media.view.MediaFrame.Select,e=wp.media.view.l10n;c=d.extend({defaults:{id:"media",url:"",menu:"media-details",content:"media-details",toolbar:"media-details",type:"link",priority:120},initialize:function(a){this.DetailsView=a.DetailsView,this.cancelText=a.cancelText,this.addText=a.addText,this.media=new wp.media.model.PostMedia(a.metadata),this.options.selection=new wp.media.model.Selection(this.media.attachment,{multiple:!1}),d.prototype.initialize.apply(this,arguments)},bindHandlers:function(){var a=this.defaults.menu;d.prototype.bindHandlers.apply(this,arguments),this.on("menu:create:"+a,this.createMenu,this),this.on("content:render:"+a,this.renderDetailsContent,this),this.on("menu:render:"+a,this.renderMenu,this),this.on("toolbar:render:"+a,this.renderDetailsToolbar,this)},renderDetailsContent:function(){var a=new this.DetailsView({controller:this,model:this.state().media,attachment:this.state().media.attachment}).render();this.content.set(a)},renderMenu:function(a){var b=this.lastState(),c=b&&b.id,d=this;a.set({cancel:{text:this.cancelText,priority:20,click:function(){c?d.setState(c):d.close()}},separateCancel:new wp.media.View({className:"separator",priority:40})})},setPrimaryButton:function(a,b){this.toolbar.set(new wp.media.view.Toolbar({controller:this,items:{button:{style:"primary",text:a,priority:80,click:function(){var a=this.controller;b.call(this,a,a.state()),a.setState(a.options.state),a.reset()}}}}))},renderDetailsToolbar:function(){this.setPrimaryButton(e.update,function(a,b){a.close(),b.trigger("update",a.media.toJSON())})},renderReplaceToolbar:function(){this.setPrimaryButton(e.replace,function(a,b){var c=b.get("selection").single();a.media.changeAttachment(c),b.trigger("replace",a.media.toJSON())})},renderAddSourceToolbar:function(){this.setPrimaryButton(this.addText,function(a,b){var c=b.get("selection").single();a.media.setSource(c),b.trigger("add-source",a.media.toJSON())})}}),a.exports=c},function(a,b){var c,d=wp.media.view.MediaFrame.MediaDetails,e=wp.media.controller.MediaLibrary,f=wp.media.view.l10n;c=d.extend({defaults:{id:"audio",url:"",menu:"audio-details",content:"audio-details",toolbar:"audio-details",type:"link",title:f.audioDetailsTitle,priority:120},initialize:function(a){a.DetailsView=wp.media.view.AudioDetails,a.cancelText=f.audioDetailsCancel,a.addText=f.audioAddSourceTitle,d.prototype.initialize.call(this,a)},bindHandlers:function(){d.prototype.bindHandlers.apply(this,arguments),this.on("toolbar:render:replace-audio",this.renderReplaceToolbar,this),this.on("toolbar:render:add-audio-source",this.renderAddSourceToolbar,this)},createStates:function(){this.states.add([new wp.media.controller.AudioDetails({media:this.media}),new e({type:"audio",id:"replace-audio",title:f.audioReplaceTitle,toolbar:"replace-audio",media:this.media,menu:"audio-details"}),new e({type:"audio",id:"add-audio-source",title:f.audioAddSourceTitle,toolbar:"add-audio-source",media:this.media,menu:!1})])}}),a.exports=c},function(a,b){var c,d=wp.media.view.MediaFrame.MediaDetails,e=wp.media.controller.MediaLibrary,f=wp.media.view.l10n;c=d.extend({defaults:{id:"video",url:"",menu:"video-details",content:"video-details",toolbar:"video-details",type:"link",title:f.videoDetailsTitle,priority:120},initialize:function(a){a.DetailsView=wp.media.view.VideoDetails,a.cancelText=f.videoDetailsCancel,a.addText=f.videoAddSourceTitle,d.prototype.initialize.call(this,a)},bindHandlers:function(){d.prototype.bindHandlers.apply(this,arguments),this.on("toolbar:render:replace-video",this.renderReplaceToolbar,this),this.on("toolbar:render:add-video-source",this.renderAddSourceToolbar,this),this.on("toolbar:render:select-poster-image",this.renderSelectPosterImageToolbar,this),this.on("toolbar:render:add-track",this.renderAddTrackToolbar,this)},createStates:function(){this.states.add([new wp.media.controller.VideoDetails({media:this.media}),new e({type:"video",id:"replace-video",title:f.videoReplaceTitle,toolbar:"replace-video",media:this.media,menu:"video-details"}),new e({type:"video",id:"add-video-source",title:f.videoAddSourceTitle,toolbar:"add-video-source",media:this.media,menu:!1}),new e({type:"image",id:"select-poster-image",title:f.videoSelectPosterImageTitle,toolbar:"select-poster-image",media:this.media,menu:"video-details"}),new e({type:"text",id:"add-track",title:f.videoAddTrackTitle,toolbar:"add-track",media:this.media,menu:"video-details"})])},renderSelectPosterImageToolbar:function(){this.setPrimaryButton(f.videoSelectPosterImageTitle,function(a,b){var c=[],d=b.get("selection").single();a.media.set("poster",d.get("url")),b.trigger("set-poster-image",a.media.toJSON()),_.each(wp.media.view.settings.embedExts,function(b){a.media.get(b)&&c.push(a.media.get(b))}),wp.ajax.send("set-attachment-thumbnail",{data:{urls:c,thumbnail_id:d.get("id")}})})},renderAddTrackToolbar:function(){this.setPrimaryButton(f.videoAddTrackTitle,function(a,b){var c=b.get("selection").single(),d=a.media.get("content");-1===d.indexOf(c.get("url"))&&(d+=[''].join(""),a.media.set("content",d)),b.trigger("add-track",a.media.toJSON())})}}),a.exports=c},function(a,b){var c,d=wp.media.view.Settings.AttachmentDisplay,e=jQuery;c=d.extend({initialize:function(){_.bindAll(this,"success"),this.players=[],this.listenTo(this.controller,"close",wp.media.mixin.unsetPlayers),this.on("ready",this.setPlayer),this.on("media:setting:remove",wp.media.mixin.unsetPlayers,this),this.on("media:setting:remove",this.render),this.on("media:setting:remove",this.setPlayer),d.prototype.initialize.apply(this,arguments)},events:function(){return _.extend({"click .remove-setting":"removeSetting","change .content-track":"setTracks","click .remove-track":"setTracks","click .add-media-source":"addSource"},d.prototype.events)},prepare:function(){return _.defaults({model:this.model.toJSON()},this.options)},removeSetting:function(a){var b,c=e(a.currentTarget).parent();b=c.find("input").data("setting"),b&&(this.model.unset(b),this.trigger("media:setting:remove",this)),c.remove()},setTracks:function(){var a="";_.each(this.$(".content-track"),function(b){a+=e(b).val()}),this.model.set("content",a),this.trigger("media:setting:remove",this)},addSource:function(a){this.controller.lastMime=e(a.currentTarget).data("mime"),this.controller.setState("add-"+this.controller.defaults.id+"-source")},loadPlayer:function(){this.players.push(new MediaElementPlayer(this.media,this.settings)),this.scriptXhr=!1},setPlayer:function(){var a;this.players.length||!this.media||this.scriptXhr||(a=this.model.get("src"),a&&a.indexOf("vimeo")>-1&&!("Vimeo"in window)?this.scriptXhr=e.getScript("https://player.vimeo.com/api/player.js",_.bind(this.loadPlayer,this)):this.loadPlayer())},setMedia:function(){return this},success:function(a){var b=a.attributes.autoplay&&"false"!==a.attributes.autoplay;"flash"===a.pluginType&&b&&a.addEventListener("canplay",function(){a.play()},!1),this.mejs=a},render:function(){return d.prototype.render.apply(this,arguments),setTimeout(_.bind(function(){this.resetFocus()},this),10),this.settings=_.defaults({success:this.success},wp.media.mixin.mejsSettings),this.setMedia()},resetFocus:function(){this.$(".embed-media-settings").scrollTop(0)}},{instances:0,prepareSrc:function(a){var b=c.instances++;return _.each(e(a).find("source"),function(a){a.src=[a.src,a.src.indexOf("?")>-1?"&":"?","_=",b].join("")}),a}}),a.exports=c},function(a,b){var c,d=wp.media.view.MediaDetails;c=d.extend({className:"audio-details",template:wp.template("audio-details"),setMedia:function(){var a=this.$(".wp-audio-shortcode");return a.find("source").length?(a.is(":hidden")&&a.show(),this.media=d.prepareSrc(a.get(0))):(a.hide(),this.media=!1),this}}),a.exports=c},function(a,b){var c,d=wp.media.view.MediaDetails;c=d.extend({className:"video-details",template:wp.template("video-details"),setMedia:function(){var a=this.$(".wp-video-shortcode");return a.find("source").length?(a.is(":hidden")&&a.show(),a.hasClass("youtube-video")||a.hasClass("vimeo-video")?this.media=a.get(0):this.media=d.prepareSrc(a.get(0))):(a.hide(),this.media=!1),this}}),a.exports=c}]); \ No newline at end of file diff --git a/wp-includes/js/media-grid.js b/wp-includes/js/media-grid.js index f98aa0d0c9..b957ed654c 100644 --- a/wp-includes/js/media-grid.js +++ b/wp-includes/js/media-grid.js @@ -81,130 +81,1002 @@ /******/ /******/ /******/ // Load entry module and return exports -/******/ return __webpack_require__(__webpack_require__.s = 1); +/******/ return __webpack_require__(__webpack_require__.s = 11); /******/ }) /************************************************************************/ -/******/ ({ - -/***/ "./src/js/_enqueues/wp/media/grid.js": -/*!*******************************************!*\ - !*** ./src/js/_enqueues/wp/media/grid.js ***! - \*******************************************/ -/*! no static exports found */ +/******/ ([ +/* 0 */, +/* 1 */, +/* 2 */, +/* 3 */, +/* 4 */, +/* 5 */, +/* 6 */, +/* 7 */, +/* 8 */, +/* 9 */, +/* 10 */, +/* 11 */ /***/ (function(module, exports, __webpack_require__) { -eval("/**\n * @output wp-includes/js/media-grid.js\n */\n\nvar media = wp.media;\n\nmedia.controller.EditAttachmentMetadata = __webpack_require__( /*! ../../../media/controllers/edit-attachment-metadata.js */ \"./src/js/media/controllers/edit-attachment-metadata.js\" );\nmedia.view.MediaFrame.Manage = __webpack_require__( /*! ../../../media/views/frame/manage.js */ \"./src/js/media/views/frame/manage.js\" );\nmedia.view.Attachment.Details.TwoColumn = __webpack_require__( /*! ../../../media/views/attachment/details-two-column.js */ \"./src/js/media/views/attachment/details-two-column.js\" );\nmedia.view.MediaFrame.Manage.Router = __webpack_require__( /*! ../../../media/routers/manage.js */ \"./src/js/media/routers/manage.js\" );\nmedia.view.EditImage.Details = __webpack_require__( /*! ../../../media/views/edit-image-details.js */ \"./src/js/media/views/edit-image-details.js\" );\nmedia.view.MediaFrame.EditAttachments = __webpack_require__( /*! ../../../media/views/frame/edit-attachments.js */ \"./src/js/media/views/frame/edit-attachments.js\" );\nmedia.view.SelectModeToggleButton = __webpack_require__( /*! ../../../media/views/button/select-mode-toggle.js */ \"./src/js/media/views/button/select-mode-toggle.js\" );\nmedia.view.DeleteSelectedButton = __webpack_require__( /*! ../../../media/views/button/delete-selected.js */ \"./src/js/media/views/button/delete-selected.js\" );\nmedia.view.DeleteSelectedPermanentlyButton = __webpack_require__( /*! ../../../media/views/button/delete-selected-permanently.js */ \"./src/js/media/views/button/delete-selected-permanently.js\" );\n\n\n//# sourceURL=webpack:///./src/js/_enqueues/wp/media/grid.js?"); +module.exports = __webpack_require__(12); + /***/ }), - -/***/ "./src/js/media/controllers/edit-attachment-metadata.js": -/*!**************************************************************!*\ - !*** ./src/js/media/controllers/edit-attachment-metadata.js ***! - \**************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("var l10n = wp.media.view.l10n,\n\tEditAttachmentMetadata;\n\n/**\n * wp.media.controller.EditAttachmentMetadata\n *\n * A state for editing an attachment's metadata.\n *\n * @memberOf wp.media.controller\n *\n * @class\n * @augments wp.media.controller.State\n * @augments Backbone.Model\n */\nEditAttachmentMetadata = wp.media.controller.State.extend(/** @lends wp.media.controller.EditAttachmentMetadata.prototype */{\n\tdefaults: {\n\t\tid: 'edit-attachment',\n\t\t// Title string passed to the frame's title region view.\n\t\ttitle: l10n.attachmentDetails,\n\t\t// Region mode defaults.\n\t\tcontent: 'edit-metadata',\n\t\tmenu: false,\n\t\ttoolbar: false,\n\t\trouter: false\n\t}\n});\n\nmodule.exports = EditAttachmentMetadata;\n\n\n//# sourceURL=webpack:///./src/js/media/controllers/edit-attachment-metadata.js?"); - -/***/ }), - -/***/ "./src/js/media/routers/manage.js": -/*!****************************************!*\ - !*** ./src/js/media/routers/manage.js ***! - \****************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("/**\n * wp.media.view.MediaFrame.Manage.Router\n *\n * A router for handling the browser history and application state.\n *\n * @memberOf wp.media.view.MediaFrame.Manage\n *\n * @class\n * @augments Backbone.Router\n */\nvar Router = Backbone.Router.extend(/** @lends wp.media.view.MediaFrame.Manage.Router.prototype */{\n\troutes: {\n\t\t'upload.php?item=:slug&mode=edit': 'editItem',\n\t\t'upload.php?item=:slug': 'showItem',\n\t\t'upload.php?search=:query': 'search',\n\t\t'upload.php': 'reset'\n\t},\n\n\t// Map routes against the page URL\n\tbaseUrl: function( url ) {\n\t\treturn 'upload.php' + url;\n\t},\n\n\treset: function() {\n\t\tvar frame = wp.media.frames.edit;\n\n\t\tif ( frame ) {\n\t\t\tframe.close();\n\t\t}\n\t},\n\n\t// Respond to the search route by filling the search field and trigggering the input event\n\tsearch: function( query ) {\n\t\tjQuery( '#media-search-input' ).val( query ).trigger( 'input' );\n\t},\n\n\t// Show the modal with a specific item\n\tshowItem: function( query ) {\n\t\tvar media = wp.media,\n\t\t\tframe = media.frames.browse,\n\t\t\tlibrary = frame.state().get('library'),\n\t\t\titem;\n\n\t\t// Trigger the media frame to open the correct item\n\t\titem = library.findWhere( { id: parseInt( query, 10 ) } );\n\t\titem.set( 'skipHistory', true );\n\n\t\tif ( item ) {\n\t\t\tframe.trigger( 'edit:attachment', item );\n\t\t} else {\n\t\t\titem = media.attachment( query );\n\t\t\tframe.listenTo( item, 'change', function( model ) {\n\t\t\t\tframe.stopListening( item );\n\t\t\t\tframe.trigger( 'edit:attachment', model );\n\t\t\t} );\n\t\t\titem.fetch();\n\t\t}\n\t},\n\n\t// Show the modal in edit mode with a specific item.\n\teditItem: function( query ) {\n\t\tthis.showItem( query );\n\t\twp.media.frames.edit.content.mode( 'edit-details' );\n\t}\n});\n\nmodule.exports = Router;\n\n\n//# sourceURL=webpack:///./src/js/media/routers/manage.js?"); - -/***/ }), - -/***/ "./src/js/media/views/attachment/details-two-column.js": -/*!*************************************************************!*\ - !*** ./src/js/media/views/attachment/details-two-column.js ***! - \*************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("var Details = wp.media.view.Attachment.Details,\n\tTwoColumn;\n\n/**\n * wp.media.view.Attachment.Details.TwoColumn\n *\n * A similar view to media.view.Attachment.Details\n * for use in the Edit Attachment modal.\n *\n * @memberOf wp.media.view.Attachment.Details\n *\n * @class\n * @augments wp.media.view.Attachment.Details\n * @augments wp.media.view.Attachment\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n */\nTwoColumn = Details.extend(/** @lends wp.media.view.Attachment.Details.TowColumn.prototype */{\n\ttemplate: wp.template( 'attachment-details-two-column' ),\n\n\tinitialize: function() {\n\t\tthis.controller.on( 'content:activate:edit-details', _.bind( this.editAttachment, this ) );\n\n\t\tDetails.prototype.initialize.apply( this, arguments );\n\t},\n\n\teditAttachment: function( event ) {\n\t\tif ( event ) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t\tthis.controller.content.mode( 'edit-image' );\n\t},\n\n\t/**\n\t * Noop this from parent class, doesn't apply here.\n\t */\n\ttoggleSelectionHandler: function() {},\n\n\trender: function() {\n\t\tDetails.prototype.render.apply( this, arguments );\n\n\t\twp.media.mixin.removeAllPlayers();\n\t\tthis.$( 'audio, video' ).each( function (i, elem) {\n\t\t\tvar el = wp.media.view.MediaDetails.prepareSrc( elem );\n\t\t\tnew window.MediaElementPlayer( el, wp.media.mixin.mejsSettings );\n\t\t} );\n\t}\n});\n\nmodule.exports = TwoColumn;\n\n\n//# sourceURL=webpack:///./src/js/media/views/attachment/details-two-column.js?"); - -/***/ }), - -/***/ "./src/js/media/views/button/delete-selected-permanently.js": -/*!******************************************************************!*\ - !*** ./src/js/media/views/button/delete-selected-permanently.js ***! - \******************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("var Button = wp.media.view.Button,\n\tDeleteSelected = wp.media.view.DeleteSelectedButton,\n\tDeleteSelectedPermanently;\n\n/**\n * wp.media.view.DeleteSelectedPermanentlyButton\n *\n * When MEDIA_TRASH is true, a button that handles bulk Delete Permanently logic\n *\n * @memberOf wp.media.view\n *\n * @class\n * @augments wp.media.view.DeleteSelectedButton\n * @augments wp.media.view.Button\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n */\nDeleteSelectedPermanently = DeleteSelected.extend(/** @lends wp.media.view.DeleteSelectedPermanentlyButton.prototype */{\n\tinitialize: function() {\n\t\tDeleteSelected.prototype.initialize.apply( this, arguments );\n\t\tthis.controller.on( 'select:activate', this.selectActivate, this );\n\t\tthis.controller.on( 'select:deactivate', this.selectDeactivate, this );\n\t},\n\n\tfilterChange: function( model ) {\n\t\tthis.canShow = ( 'trash' === model.get( 'status' ) );\n\t},\n\n\tselectActivate: function() {\n\t\tthis.toggleDisabled();\n\t\tthis.$el.toggleClass( 'hidden', ! this.canShow );\n\t},\n\n\tselectDeactivate: function() {\n\t\tthis.toggleDisabled();\n\t\tthis.$el.addClass( 'hidden' );\n\t},\n\n\trender: function() {\n\t\tButton.prototype.render.apply( this, arguments );\n\t\tthis.selectActivate();\n\t\treturn this;\n\t}\n});\n\nmodule.exports = DeleteSelectedPermanently;\n\n\n//# sourceURL=webpack:///./src/js/media/views/button/delete-selected-permanently.js?"); - -/***/ }), - -/***/ "./src/js/media/views/button/delete-selected.js": -/*!******************************************************!*\ - !*** ./src/js/media/views/button/delete-selected.js ***! - \******************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("var Button = wp.media.view.Button,\n\tl10n = wp.media.view.l10n,\n\tDeleteSelected;\n\n/**\n * wp.media.view.DeleteSelectedButton\n *\n * A button that handles bulk Delete/Trash logic\n *\n * @memberOf wp.media.view\n *\n * @class\n * @augments wp.media.view.Button\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n */\nDeleteSelected = Button.extend(/** @lends wp.media.view.DeleteSelectedButton.prototype */{\n\tinitialize: function() {\n\t\tButton.prototype.initialize.apply( this, arguments );\n\t\tif ( this.options.filters ) {\n\t\t\tthis.options.filters.model.on( 'change', this.filterChange, this );\n\t\t}\n\t\tthis.controller.on( 'selection:toggle', this.toggleDisabled, this );\n\t},\n\n\tfilterChange: function( model ) {\n\t\tif ( 'trash' === model.get( 'status' ) ) {\n\t\t\tthis.model.set( 'text', l10n.untrashSelected );\n\t\t} else if ( wp.media.view.settings.mediaTrash ) {\n\t\t\tthis.model.set( 'text', l10n.trashSelected );\n\t\t} else {\n\t\t\tthis.model.set( 'text', l10n.deleteSelected );\n\t\t}\n\t},\n\n\ttoggleDisabled: function() {\n\t\tthis.model.set( 'disabled', ! this.controller.state().get( 'selection' ).length );\n\t},\n\n\trender: function() {\n\t\tButton.prototype.render.apply( this, arguments );\n\t\tif ( this.controller.isModeActive( 'select' ) ) {\n\t\t\tthis.$el.addClass( 'delete-selected-button' );\n\t\t} else {\n\t\t\tthis.$el.addClass( 'delete-selected-button hidden' );\n\t\t}\n\t\tthis.toggleDisabled();\n\t\treturn this;\n\t}\n});\n\nmodule.exports = DeleteSelected;\n\n\n//# sourceURL=webpack:///./src/js/media/views/button/delete-selected.js?"); - -/***/ }), - -/***/ "./src/js/media/views/button/select-mode-toggle.js": -/*!*********************************************************!*\ - !*** ./src/js/media/views/button/select-mode-toggle.js ***! - \*********************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("\nvar Button = wp.media.view.Button,\n\tl10n = wp.media.view.l10n,\n\tSelectModeToggle;\n\n/**\n * wp.media.view.SelectModeToggleButton\n *\n * @memberOf wp.media.view\n *\n * @class\n * @augments wp.media.view.Button\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n */\nSelectModeToggle = Button.extend(/** @lends wp.media.view.SelectModeToggle.prototype */{\n\tinitialize: function() {\n\t\t_.defaults( this.options, {\n\t\t\tsize : ''\n\t\t} );\n\n\t\tButton.prototype.initialize.apply( this, arguments );\n\t\tthis.controller.on( 'select:activate select:deactivate', this.toggleBulkEditHandler, this );\n\t\tthis.controller.on( 'selection:action:done', this.back, this );\n\t},\n\n\tback: function () {\n\t\tthis.controller.deactivateMode( 'select' ).activateMode( 'edit' );\n\t},\n\n\tclick: function() {\n\t\tButton.prototype.click.apply( this, arguments );\n\t\tif ( this.controller.isModeActive( 'select' ) ) {\n\t\t\tthis.back();\n\t\t} else {\n\t\t\tthis.controller.deactivateMode( 'edit' ).activateMode( 'select' );\n\t\t}\n\t},\n\n\trender: function() {\n\t\tButton.prototype.render.apply( this, arguments );\n\t\tthis.$el.addClass( 'select-mode-toggle-button' );\n\t\treturn this;\n\t},\n\n\ttoggleBulkEditHandler: function() {\n\t\tvar toolbar = this.controller.content.get().toolbar, children;\n\n\t\tchildren = toolbar.$( '.media-toolbar-secondary > *, .media-toolbar-primary > *' );\n\n\t\t// TODO: the Frame should be doing all of this.\n\t\tif ( this.controller.isModeActive( 'select' ) ) {\n\t\t\tthis.model.set( {\n\t\t\t\tsize: 'large',\n\t\t\t\ttext: l10n.cancelSelection\n\t\t\t} );\n\t\t\tchildren.not( '.spinner, .media-button' ).hide();\n\t\t\tthis.$el.show();\n\t\t\ttoolbar.$( '.delete-selected-button' ).removeClass( 'hidden' );\n\t\t} else {\n\t\t\tthis.model.set( {\n\t\t\t\tsize: '',\n\t\t\t\ttext: l10n.bulkSelect\n\t\t\t} );\n\t\t\tthis.controller.content.get().$el.removeClass( 'fixed' );\n\t\t\ttoolbar.$el.css( 'width', '' );\n\t\t\ttoolbar.$( '.delete-selected-button' ).addClass( 'hidden' );\n\t\t\tchildren.not( '.media-button' ).show();\n\t\t\tthis.controller.state().get( 'selection' ).reset();\n\t\t}\n\t}\n});\n\nmodule.exports = SelectModeToggle;\n\n\n//# sourceURL=webpack:///./src/js/media/views/button/select-mode-toggle.js?"); - -/***/ }), - -/***/ "./src/js/media/views/edit-image-details.js": -/*!**************************************************!*\ - !*** ./src/js/media/views/edit-image-details.js ***! - \**************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("var View = wp.media.View,\n\tEditImage = wp.media.view.EditImage,\n\tDetails;\n\n/**\n * wp.media.view.EditImage.Details\n *\n * @memberOf wp.media.view.EditImage\n *\n * @class\n * @augments wp.media.view.EditImage\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n */\nDetails = EditImage.extend(/** @lends wp.media.view.EditImage.Details.prototype */{\n\tinitialize: function( options ) {\n\t\tthis.editor = window.imageEdit;\n\t\tthis.frame = options.frame;\n\t\tthis.controller = options.controller;\n\t\tView.prototype.initialize.apply( this, arguments );\n\t},\n\n\tback: function() {\n\t\tthis.frame.content.mode( 'edit-metadata' );\n\t},\n\n\tsave: function() {\n\t\tthis.model.fetch().done( _.bind( function() {\n\t\t\tthis.frame.content.mode( 'edit-metadata' );\n\t\t}, this ) );\n\t}\n});\n\nmodule.exports = Details;\n\n\n//# sourceURL=webpack:///./src/js/media/views/edit-image-details.js?"); - -/***/ }), - -/***/ "./src/js/media/views/frame/edit-attachments.js": -/*!******************************************************!*\ - !*** ./src/js/media/views/frame/edit-attachments.js ***! - \******************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("var Frame = wp.media.view.Frame,\n\tMediaFrame = wp.media.view.MediaFrame,\n\n\t$ = jQuery,\n\tEditAttachments;\n\n/**\n * wp.media.view.MediaFrame.EditAttachments\n *\n * A frame for editing the details of a specific media item.\n *\n * Opens in a modal by default.\n *\n * Requires an attachment model to be passed in the options hash under `model`.\n *\n * @memberOf wp.media.view.MediaFrame\n *\n * @class\n * @augments wp.media.view.Frame\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n * @mixes wp.media.controller.StateMachine\n */\nEditAttachments = MediaFrame.extend(/** @lends wp.media.view.MediaFrame.EditAttachments.prototype */{\n\n\tclassName: 'edit-attachment-frame',\n\ttemplate: wp.template( 'edit-attachment-frame' ),\n\tregions: [ 'title', 'content' ],\n\n\tevents: {\n\t\t'click .left': 'previousMediaItem',\n\t\t'click .right': 'nextMediaItem'\n\t},\n\n\tinitialize: function() {\n\t\tFrame.prototype.initialize.apply( this, arguments );\n\n\t\t_.defaults( this.options, {\n\t\t\tmodal: true,\n\t\t\tstate: 'edit-attachment'\n\t\t});\n\n\t\tthis.controller = this.options.controller;\n\t\tthis.gridRouter = this.controller.gridRouter;\n\t\tthis.library = this.options.library;\n\n\t\tif ( this.options.model ) {\n\t\t\tthis.model = this.options.model;\n\t\t}\n\n\t\tthis.bindHandlers();\n\t\tthis.createStates();\n\t\tthis.createModal();\n\n\t\tthis.title.mode( 'default' );\n\t\tthis.toggleNav();\n\t},\n\n\tbindHandlers: function() {\n\t\t// Bind default title creation.\n\t\tthis.on( 'title:create:default', this.createTitle, this );\n\n\t\tthis.on( 'content:create:edit-metadata', this.editMetadataMode, this );\n\t\tthis.on( 'content:create:edit-image', this.editImageMode, this );\n\t\tthis.on( 'content:render:edit-image', this.editImageModeRender, this );\n\t\tthis.on( 'refresh', this.rerender, this );\n\t\tthis.on( 'close', this.detach );\n\n\t\tthis.bindModelHandlers();\n\t\tthis.listenTo( this.gridRouter, 'route:search', this.close, this );\n\t},\n\n\tbindModelHandlers: function() {\n\t\t// Close the modal if the attachment is deleted.\n\t\tthis.listenTo( this.model, 'change:status destroy', this.close, this );\n\t},\n\n\tcreateModal: function() {\n\t\t// Initialize modal container view.\n\t\tif ( this.options.modal ) {\n\t\t\tthis.modal = new wp.media.view.Modal({\n\t\t\t\tcontroller: this,\n\t\t\t\ttitle: this.options.title\n\t\t\t});\n\n\t\t\tthis.modal.on( 'open', _.bind( function () {\n\t\t\t\t$( 'body' ).on( 'keydown.media-modal', _.bind( this.keyEvent, this ) );\n\t\t\t}, this ) );\n\n\t\t\t// Completely destroy the modal DOM element when closing it.\n\t\t\tthis.modal.on( 'close', _.bind( function() {\n\t\t\t\t$( 'body' ).off( 'keydown.media-modal' ); /* remove the keydown event */\n\t\t\t\t// Restore the original focus item if possible\n\t\t\t\t$( 'li.attachment[data-id=\"' + this.model.get( 'id' ) +'\"]' ).focus();\n\t\t\t\tthis.resetRoute();\n\t\t\t}, this ) );\n\n\t\t\t// Set this frame as the modal's content.\n\t\t\tthis.modal.content( this );\n\t\t\tthis.modal.open();\n\t\t}\n\t},\n\n\t/**\n\t * Add the default states to the frame.\n\t */\n\tcreateStates: function() {\n\t\tthis.states.add([\n\t\t\tnew wp.media.controller.EditAttachmentMetadata({\n\t\t\t\tmodel: this.model,\n\t\t\t\tlibrary: this.library\n\t\t\t})\n\t\t]);\n\t},\n\n\t/**\n\t * Content region rendering callback for the `edit-metadata` mode.\n\t *\n\t * @param {Object} contentRegion Basic object with a `view` property, which\n\t * should be set with the proper region view.\n\t */\n\teditMetadataMode: function( contentRegion ) {\n\t\tcontentRegion.view = new wp.media.view.Attachment.Details.TwoColumn({\n\t\t\tcontroller: this,\n\t\t\tmodel: this.model\n\t\t});\n\n\t\t/**\n\t\t * Attach a subview to display fields added via the\n\t\t * `attachment_fields_to_edit` filter.\n\t\t */\n\t\tcontentRegion.view.views.set( '.attachment-compat', new wp.media.view.AttachmentCompat({\n\t\t\tcontroller: this,\n\t\t\tmodel: this.model\n\t\t}) );\n\n\t\t// Update browser url when navigating media details, except on load.\n\t\tif ( this.model && ! this.model.get( 'skipHistory' ) ) {\n\t\t\tthis.gridRouter.navigate( this.gridRouter.baseUrl( '?item=' + this.model.id ) );\n\t\t}\n\t},\n\n\t/**\n\t * Render the EditImage view into the frame's content region.\n\t *\n\t * @param {Object} contentRegion Basic object with a `view` property, which\n\t * should be set with the proper region view.\n\t */\n\teditImageMode: function( contentRegion ) {\n\t\tvar editImageController = new wp.media.controller.EditImage( {\n\t\t\tmodel: this.model,\n\t\t\tframe: this\n\t\t} );\n\t\t// Noop some methods.\n\t\teditImageController._toolbar = function() {};\n\t\teditImageController._router = function() {};\n\t\teditImageController._menu = function() {};\n\n\t\tcontentRegion.view = new wp.media.view.EditImage.Details( {\n\t\t\tmodel: this.model,\n\t\t\tframe: this,\n\t\t\tcontroller: editImageController\n\t\t} );\n\n\t\tthis.gridRouter.navigate( this.gridRouter.baseUrl( '?item=' + this.model.id + '&mode=edit' ) );\n\n\t},\n\n\teditImageModeRender: function( view ) {\n\t\tview.on( 'ready', view.loadEditor );\n\t},\n\n\ttoggleNav: function() {\n\t\tthis.$('.left').toggleClass( 'disabled', ! this.hasPrevious() );\n\t\tthis.$('.right').toggleClass( 'disabled', ! this.hasNext() );\n\t},\n\n\t/**\n\t * Rerender the view.\n\t */\n\trerender: function( model ) {\n\t\tthis.stopListening( this.model );\n\n\t\tthis.model = model;\n\n\t\tthis.bindModelHandlers();\n\n\t\t// Only rerender the `content` region.\n\t\tif ( this.content.mode() !== 'edit-metadata' ) {\n\t\t\tthis.content.mode( 'edit-metadata' );\n\t\t} else {\n\t\t\tthis.content.render();\n\t\t}\n\n\t\tthis.toggleNav();\n\t},\n\n\t/**\n\t * Click handler to switch to the previous media item.\n\t */\n\tpreviousMediaItem: function() {\n\t\tif ( ! this.hasPrevious() ) {\n\t\t\treturn;\n\t\t}\n\t\tthis.trigger( 'refresh', this.library.at( this.getCurrentIndex() - 1 ) );\n\t\tthis.$( '.left' ).focus();\n\t},\n\n\t/**\n\t * Click handler to switch to the next media item.\n\t */\n\tnextMediaItem: function() {\n\t\tif ( ! this.hasNext() ) {\n\t\t\treturn;\n\t\t}\n\t\tthis.trigger( 'refresh', this.library.at( this.getCurrentIndex() + 1 ) );\n\t\tthis.$( '.right' ).focus();\n\t},\n\n\tgetCurrentIndex: function() {\n\t\treturn this.library.indexOf( this.model );\n\t},\n\n\thasNext: function() {\n\t\treturn ( this.getCurrentIndex() + 1 ) < this.library.length;\n\t},\n\n\thasPrevious: function() {\n\t\treturn ( this.getCurrentIndex() - 1 ) > -1;\n\t},\n\t/**\n\t * Respond to the keyboard events: right arrow, left arrow, except when\n\t * focus is in a textarea or input field.\n\t */\n\tkeyEvent: function( event ) {\n\t\tif ( ( 'INPUT' === event.target.nodeName || 'TEXTAREA' === event.target.nodeName ) && ! ( event.target.readOnly || event.target.disabled ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// The right arrow key\n\t\tif ( 39 === event.keyCode ) {\n\t\t\tthis.nextMediaItem();\n\t\t}\n\t\t// The left arrow key\n\t\tif ( 37 === event.keyCode ) {\n\t\t\tthis.previousMediaItem();\n\t\t}\n\t},\n\n\tresetRoute: function() {\n\t\tvar searchTerm = this.controller.browserView.toolbar.get( 'search' ).$el.val(),\n\t\t\turl = '' !== searchTerm ? '?search=' + searchTerm : '';\n\t\tthis.gridRouter.navigate( this.gridRouter.baseUrl( url ), { replace: true } );\n\t}\n});\n\nmodule.exports = EditAttachments;\n\n\n//# sourceURL=webpack:///./src/js/media/views/frame/edit-attachments.js?"); - -/***/ }), - -/***/ "./src/js/media/views/frame/manage.js": -/*!********************************************!*\ - !*** ./src/js/media/views/frame/manage.js ***! - \********************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("var MediaFrame = wp.media.view.MediaFrame,\n\tLibrary = wp.media.controller.Library,\n\n\t$ = Backbone.$,\n\tManage;\n\n/**\n * wp.media.view.MediaFrame.Manage\n *\n * A generic management frame workflow.\n *\n * Used in the media grid view.\n *\n * @memberOf wp.media.view.MediaFrame\n *\n * @class\n * @augments wp.media.view.MediaFrame\n * @augments wp.media.view.Frame\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n * @mixes wp.media.controller.StateMachine\n */\nManage = MediaFrame.extend(/** @lends wp.media.view.MediaFrame.Manage.prototype */{\n\t/**\n\t * @constructs\n\t */\n\tinitialize: function() {\n\t\t_.defaults( this.options, {\n\t\t\ttitle: '',\n\t\t\tmodal: false,\n\t\t\tselection: [],\n\t\t\tlibrary: {}, // Options hash for the query to the media library.\n\t\t\tmultiple: 'add',\n\t\t\tstate: 'library',\n\t\t\tuploader: true,\n\t\t\tmode: [ 'grid', 'edit' ]\n\t\t});\n\n\t\tthis.$body = $( document.body );\n\t\tthis.$window = $( window );\n\t\tthis.$adminBar = $( '#wpadminbar' );\n\t\t// Store the Add New button for later reuse in wp.media.view.UploaderInline.\n\t\tthis.$uploaderToggler = $( '.page-title-action' )\n\t\t\t.attr( 'aria-expanded', 'false' )\n\t\t\t.on( 'click', _.bind( this.addNewClickHandler, this ) );\n\n\t\tthis.$window.on( 'scroll resize', _.debounce( _.bind( this.fixPosition, this ), 15 ) );\n\n\t\t// Ensure core and media grid view UI is enabled.\n\t\tthis.$el.addClass('wp-core-ui');\n\n\t\t// Force the uploader off if the upload limit has been exceeded or\n\t\t// if the browser isn't supported.\n\t\tif ( wp.Uploader.limitExceeded || ! wp.Uploader.browser.supported ) {\n\t\t\tthis.options.uploader = false;\n\t\t}\n\n\t\t// Initialize a window-wide uploader.\n\t\tif ( this.options.uploader ) {\n\t\t\tthis.uploader = new wp.media.view.UploaderWindow({\n\t\t\t\tcontroller: this,\n\t\t\t\tuploader: {\n\t\t\t\t\tdropzone: document.body,\n\t\t\t\t\tcontainer: document.body\n\t\t\t\t}\n\t\t\t}).render();\n\t\t\tthis.uploader.ready();\n\t\t\t$('body').append( this.uploader.el );\n\n\t\t\tthis.options.uploader = false;\n\t\t}\n\n\t\tthis.gridRouter = new wp.media.view.MediaFrame.Manage.Router();\n\n\t\t// Call 'initialize' directly on the parent class.\n\t\tMediaFrame.prototype.initialize.apply( this, arguments );\n\n\t\t// Append the frame view directly the supplied container.\n\t\tthis.$el.appendTo( this.options.container );\n\n\t\tthis.createStates();\n\t\tthis.bindRegionModeHandlers();\n\t\tthis.render();\n\t\tthis.bindSearchHandler();\n\n\t\twp.media.frames.browse = this;\n\t},\n\n\tbindSearchHandler: function() {\n\t\tvar search = this.$( '#media-search-input' ),\n\t\t\tsearchView = this.browserView.toolbar.get( 'search' ).$el,\n\t\t\tlistMode = this.$( '.view-list' ),\n\n\t\t\tinput = _.throttle( function (e) {\n\t\t\t\tvar val = $( e.currentTarget ).val(),\n\t\t\t\t\turl = '';\n\n\t\t\t\tif ( val ) {\n\t\t\t\t\turl += '?search=' + val;\n\t\t\t\t\tthis.gridRouter.navigate( this.gridRouter.baseUrl( url ), { replace: true } );\n\t\t\t\t}\n\t\t\t}, 1000 );\n\n\t\t// Update the URL when entering search string (at most once per second)\n\t\tsearch.on( 'input', _.bind( input, this ) );\n\n\t\tthis.gridRouter\n\t\t\t.on( 'route:search', function () {\n\t\t\t\tvar href = window.location.href;\n\t\t\t\tif ( href.indexOf( 'mode=' ) > -1 ) {\n\t\t\t\t\thref = href.replace( /mode=[^&]+/g, 'mode=list' );\n\t\t\t\t} else {\n\t\t\t\t\thref += href.indexOf( '?' ) > -1 ? '&mode=list' : '?mode=list';\n\t\t\t\t}\n\t\t\t\thref = href.replace( 'search=', 's=' );\n\t\t\t\tlistMode.prop( 'href', href );\n\t\t\t})\n\t\t\t.on( 'route:reset', function() {\n\t\t\t\tsearchView.val( '' ).trigger( 'input' );\n\t\t\t});\n\t},\n\n\t/**\n\t * Create the default states for the frame.\n\t */\n\tcreateStates: function() {\n\t\tvar options = this.options;\n\n\t\tif ( this.options.states ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Add the default states.\n\t\tthis.states.add([\n\t\t\tnew Library({\n\t\t\t\tlibrary: wp.media.query( options.library ),\n\t\t\t\tmultiple: options.multiple,\n\t\t\t\ttitle: options.title,\n\t\t\t\tcontent: 'browse',\n\t\t\t\ttoolbar: 'select',\n\t\t\t\tcontentUserSetting: false,\n\t\t\t\tfilterable: 'all',\n\t\t\t\tautoSelect: false\n\t\t\t})\n\t\t]);\n\t},\n\n\t/**\n\t * Bind region mode activation events to proper handlers.\n\t */\n\tbindRegionModeHandlers: function() {\n\t\tthis.on( 'content:create:browse', this.browseContent, this );\n\n\t\t// Handle a frame-level event for editing an attachment.\n\t\tthis.on( 'edit:attachment', this.openEditAttachmentModal, this );\n\n\t\tthis.on( 'select:activate', this.bindKeydown, this );\n\t\tthis.on( 'select:deactivate', this.unbindKeydown, this );\n\t},\n\n\thandleKeydown: function( e ) {\n\t\tif ( 27 === e.which ) {\n\t\t\te.preventDefault();\n\t\t\tthis.deactivateMode( 'select' ).activateMode( 'edit' );\n\t\t}\n\t},\n\n\tbindKeydown: function() {\n\t\tthis.$body.on( 'keydown.select', _.bind( this.handleKeydown, this ) );\n\t},\n\n\tunbindKeydown: function() {\n\t\tthis.$body.off( 'keydown.select' );\n\t},\n\n\tfixPosition: function() {\n\t\tvar $browser, $toolbar;\n\t\tif ( ! this.isModeActive( 'select' ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t$browser = this.$('.attachments-browser');\n\t\t$toolbar = $browser.find('.media-toolbar');\n\n\t\t// Offset doesn't appear to take top margin into account, hence +16\n\t\tif ( ( $browser.offset().top + 16 ) < this.$window.scrollTop() + this.$adminBar.height() ) {\n\t\t\t$browser.addClass( 'fixed' );\n\t\t\t$toolbar.css('width', $browser.width() + 'px');\n\t\t} else {\n\t\t\t$browser.removeClass( 'fixed' );\n\t\t\t$toolbar.css('width', '');\n\t\t}\n\t},\n\n\t/**\n\t * Click handler for the `Add New` button.\n\t */\n\taddNewClickHandler: function( event ) {\n\t\tevent.preventDefault();\n\t\tthis.trigger( 'toggle:upload:attachment' );\n\n\t\tif ( this.uploader ) {\n\t\t\tthis.uploader.refresh();\n\t\t}\n\t},\n\n\t/**\n\t * Open the Edit Attachment modal.\n\t */\n\topenEditAttachmentModal: function( model ) {\n\t\t// Create a new EditAttachment frame, passing along the library and the attachment model.\n\t\tif ( wp.media.frames.edit ) {\n\t\t\twp.media.frames.edit.open().trigger( 'refresh', model );\n\t\t} else {\n\t\t\twp.media.frames.edit = wp.media( {\n\t\t\t\tframe: 'edit-attachments',\n\t\t\t\tcontroller: this,\n\t\t\t\tlibrary: this.state().get('library'),\n\t\t\t\tmodel: model\n\t\t\t} );\n\t\t}\n\t},\n\n\t/**\n\t * Create an attachments browser view within the content region.\n\t *\n\t * @param {Object} contentRegion Basic object with a `view` property, which\n\t * should be set with the proper region view.\n\t * @this wp.media.controller.Region\n\t */\n\tbrowseContent: function( contentRegion ) {\n\t\tvar state = this.state();\n\n\t\t// Browse our library of attachments.\n\t\tthis.browserView = contentRegion.view = new wp.media.view.AttachmentsBrowser({\n\t\t\tcontroller: this,\n\t\t\tcollection: state.get('library'),\n\t\t\tselection: state.get('selection'),\n\t\t\tmodel: state,\n\t\t\tsortable: state.get('sortable'),\n\t\t\tsearch: state.get('searchable'),\n\t\t\tfilters: state.get('filterable'),\n\t\t\tdate: state.get('date'),\n\t\t\tdisplay: state.get('displaySettings'),\n\t\t\tdragInfo: state.get('dragInfo'),\n\t\t\tsidebar: 'errors',\n\n\t\t\tsuggestedWidth: state.get('suggestedWidth'),\n\t\t\tsuggestedHeight: state.get('suggestedHeight'),\n\n\t\t\tAttachmentView: state.get('AttachmentView'),\n\n\t\t\tscrollElement: document\n\t\t});\n\t\tthis.browserView.on( 'ready', _.bind( this.bindDeferred, this ) );\n\n\t\tthis.errors = wp.Uploader.errors;\n\t\tthis.errors.on( 'add remove reset', this.sidebarVisibility, this );\n\t},\n\n\tsidebarVisibility: function() {\n\t\tthis.browserView.$( '.media-sidebar' ).toggle( !! this.errors.length );\n\t},\n\n\tbindDeferred: function() {\n\t\tif ( ! this.browserView.dfd ) {\n\t\t\treturn;\n\t\t}\n\t\tthis.browserView.dfd.done( _.bind( this.startHistory, this ) );\n\t},\n\n\tstartHistory: function() {\n\t\t// Verify pushState support and activate\n\t\tif ( window.history && window.history.pushState ) {\n\t\t\tif ( Backbone.History.started ) {\n\t\t\t\tBackbone.history.stop();\n\t\t\t}\n\t\t\tBackbone.history.start( {\n\t\t\t\troot: window._wpMediaGridSettings.adminUrl,\n\t\t\t\tpushState: true\n\t\t\t} );\n\t\t}\n\t}\n});\n\nmodule.exports = Manage;\n\n\n//# sourceURL=webpack:///./src/js/media/views/frame/manage.js?"); - -/***/ }), - -/***/ 1: -/*!*************************************************!*\ - !*** multi ./src/js/_enqueues/wp/media/grid.js ***! - \*************************************************/ -/*! no static exports found */ +/* 12 */ /***/ (function(module, exports, __webpack_require__) { -eval("module.exports = __webpack_require__(/*! ./src/js/_enqueues/wp/media/grid.js */\"./src/js/_enqueues/wp/media/grid.js\");\n\n\n//# sourceURL=webpack:///multi_./src/js/_enqueues/wp/media/grid.js?"); +/** + * @output wp-includes/js/media-grid.js + */ + +var media = wp.media; + +media.controller.EditAttachmentMetadata = __webpack_require__( 13 ); +media.view.MediaFrame.Manage = __webpack_require__( 14 ); +media.view.Attachment.Details.TwoColumn = __webpack_require__( 15 ); +media.view.MediaFrame.Manage.Router = __webpack_require__( 16 ); +media.view.EditImage.Details = __webpack_require__( 17 ); +media.view.MediaFrame.EditAttachments = __webpack_require__( 18 ); +media.view.SelectModeToggleButton = __webpack_require__( 19 ); +media.view.DeleteSelectedButton = __webpack_require__( 20 ); +media.view.DeleteSelectedPermanentlyButton = __webpack_require__( 21 ); + + +/***/ }), +/* 13 */ +/***/ (function(module, exports) { + +var l10n = wp.media.view.l10n, + EditAttachmentMetadata; + +/** + * wp.media.controller.EditAttachmentMetadata + * + * A state for editing an attachment's metadata. + * + * @memberOf wp.media.controller + * + * @class + * @augments wp.media.controller.State + * @augments Backbone.Model + */ +EditAttachmentMetadata = wp.media.controller.State.extend(/** @lends wp.media.controller.EditAttachmentMetadata.prototype */{ + defaults: { + id: 'edit-attachment', + // Title string passed to the frame's title region view. + title: l10n.attachmentDetails, + // Region mode defaults. + content: 'edit-metadata', + menu: false, + toolbar: false, + router: false + } +}); + +module.exports = EditAttachmentMetadata; + + +/***/ }), +/* 14 */ +/***/ (function(module, exports) { + +var MediaFrame = wp.media.view.MediaFrame, + Library = wp.media.controller.Library, + + $ = Backbone.$, + Manage; + +/** + * wp.media.view.MediaFrame.Manage + * + * A generic management frame workflow. + * + * Used in the media grid view. + * + * @memberOf wp.media.view.MediaFrame + * + * @class + * @augments wp.media.view.MediaFrame + * @augments wp.media.view.Frame + * @augments wp.media.View + * @augments wp.Backbone.View + * @augments Backbone.View + * @mixes wp.media.controller.StateMachine + */ +Manage = MediaFrame.extend(/** @lends wp.media.view.MediaFrame.Manage.prototype */{ + /** + * @constructs + */ + initialize: function() { + _.defaults( this.options, { + title: '', + modal: false, + selection: [], + library: {}, // Options hash for the query to the media library. + multiple: 'add', + state: 'library', + uploader: true, + mode: [ 'grid', 'edit' ] + }); + + this.$body = $( document.body ); + this.$window = $( window ); + this.$adminBar = $( '#wpadminbar' ); + // Store the Add New button for later reuse in wp.media.view.UploaderInline. + this.$uploaderToggler = $( '.page-title-action' ) + .attr( 'aria-expanded', 'false' ) + .on( 'click', _.bind( this.addNewClickHandler, this ) ); + + this.$window.on( 'scroll resize', _.debounce( _.bind( this.fixPosition, this ), 15 ) ); + + // Ensure core and media grid view UI is enabled. + this.$el.addClass('wp-core-ui'); + + // Force the uploader off if the upload limit has been exceeded or + // if the browser isn't supported. + if ( wp.Uploader.limitExceeded || ! wp.Uploader.browser.supported ) { + this.options.uploader = false; + } + + // Initialize a window-wide uploader. + if ( this.options.uploader ) { + this.uploader = new wp.media.view.UploaderWindow({ + controller: this, + uploader: { + dropzone: document.body, + container: document.body + } + }).render(); + this.uploader.ready(); + $('body').append( this.uploader.el ); + + this.options.uploader = false; + } + + this.gridRouter = new wp.media.view.MediaFrame.Manage.Router(); + + // Call 'initialize' directly on the parent class. + MediaFrame.prototype.initialize.apply( this, arguments ); + + // Append the frame view directly the supplied container. + this.$el.appendTo( this.options.container ); + + this.createStates(); + this.bindRegionModeHandlers(); + this.render(); + this.bindSearchHandler(); + + wp.media.frames.browse = this; + }, + + bindSearchHandler: function() { + var search = this.$( '#media-search-input' ), + searchView = this.browserView.toolbar.get( 'search' ).$el, + listMode = this.$( '.view-list' ), + + input = _.throttle( function (e) { + var val = $( e.currentTarget ).val(), + url = ''; + + if ( val ) { + url += '?search=' + val; + this.gridRouter.navigate( this.gridRouter.baseUrl( url ), { replace: true } ); + } + }, 1000 ); + + // Update the URL when entering search string (at most once per second) + search.on( 'input', _.bind( input, this ) ); + + this.gridRouter + .on( 'route:search', function () { + var href = window.location.href; + if ( href.indexOf( 'mode=' ) > -1 ) { + href = href.replace( /mode=[^&]+/g, 'mode=list' ); + } else { + href += href.indexOf( '?' ) > -1 ? '&mode=list' : '?mode=list'; + } + href = href.replace( 'search=', 's=' ); + listMode.prop( 'href', href ); + }) + .on( 'route:reset', function() { + searchView.val( '' ).trigger( 'input' ); + }); + }, + + /** + * Create the default states for the frame. + */ + createStates: function() { + var options = this.options; + + if ( this.options.states ) { + return; + } + + // Add the default states. + this.states.add([ + new Library({ + library: wp.media.query( options.library ), + multiple: options.multiple, + title: options.title, + content: 'browse', + toolbar: 'select', + contentUserSetting: false, + filterable: 'all', + autoSelect: false + }) + ]); + }, + + /** + * Bind region mode activation events to proper handlers. + */ + bindRegionModeHandlers: function() { + this.on( 'content:create:browse', this.browseContent, this ); + + // Handle a frame-level event for editing an attachment. + this.on( 'edit:attachment', this.openEditAttachmentModal, this ); + + this.on( 'select:activate', this.bindKeydown, this ); + this.on( 'select:deactivate', this.unbindKeydown, this ); + }, + + handleKeydown: function( e ) { + if ( 27 === e.which ) { + e.preventDefault(); + this.deactivateMode( 'select' ).activateMode( 'edit' ); + } + }, + + bindKeydown: function() { + this.$body.on( 'keydown.select', _.bind( this.handleKeydown, this ) ); + }, + + unbindKeydown: function() { + this.$body.off( 'keydown.select' ); + }, + + fixPosition: function() { + var $browser, $toolbar; + if ( ! this.isModeActive( 'select' ) ) { + return; + } + + $browser = this.$('.attachments-browser'); + $toolbar = $browser.find('.media-toolbar'); + + // Offset doesn't appear to take top margin into account, hence +16 + if ( ( $browser.offset().top + 16 ) < this.$window.scrollTop() + this.$adminBar.height() ) { + $browser.addClass( 'fixed' ); + $toolbar.css('width', $browser.width() + 'px'); + } else { + $browser.removeClass( 'fixed' ); + $toolbar.css('width', ''); + } + }, + + /** + * Click handler for the `Add New` button. + */ + addNewClickHandler: function( event ) { + event.preventDefault(); + this.trigger( 'toggle:upload:attachment' ); + + if ( this.uploader ) { + this.uploader.refresh(); + } + }, + + /** + * Open the Edit Attachment modal. + */ + openEditAttachmentModal: function( model ) { + // Create a new EditAttachment frame, passing along the library and the attachment model. + if ( wp.media.frames.edit ) { + wp.media.frames.edit.open().trigger( 'refresh', model ); + } else { + wp.media.frames.edit = wp.media( { + frame: 'edit-attachments', + controller: this, + library: this.state().get('library'), + model: model + } ); + } + }, + + /** + * Create an attachments browser view within the content region. + * + * @param {Object} contentRegion Basic object with a `view` property, which + * should be set with the proper region view. + * @this wp.media.controller.Region + */ + browseContent: function( contentRegion ) { + var state = this.state(); + + // Browse our library of attachments. + this.browserView = contentRegion.view = new wp.media.view.AttachmentsBrowser({ + controller: this, + collection: state.get('library'), + selection: state.get('selection'), + model: state, + sortable: state.get('sortable'), + search: state.get('searchable'), + filters: state.get('filterable'), + date: state.get('date'), + display: state.get('displaySettings'), + dragInfo: state.get('dragInfo'), + sidebar: 'errors', + + suggestedWidth: state.get('suggestedWidth'), + suggestedHeight: state.get('suggestedHeight'), + + AttachmentView: state.get('AttachmentView'), + + scrollElement: document + }); + this.browserView.on( 'ready', _.bind( this.bindDeferred, this ) ); + + this.errors = wp.Uploader.errors; + this.errors.on( 'add remove reset', this.sidebarVisibility, this ); + }, + + sidebarVisibility: function() { + this.browserView.$( '.media-sidebar' ).toggle( !! this.errors.length ); + }, + + bindDeferred: function() { + if ( ! this.browserView.dfd ) { + return; + } + this.browserView.dfd.done( _.bind( this.startHistory, this ) ); + }, + + startHistory: function() { + // Verify pushState support and activate + if ( window.history && window.history.pushState ) { + if ( Backbone.History.started ) { + Backbone.history.stop(); + } + Backbone.history.start( { + root: window._wpMediaGridSettings.adminUrl, + pushState: true + } ); + } + } +}); + +module.exports = Manage; + + +/***/ }), +/* 15 */ +/***/ (function(module, exports) { + +var Details = wp.media.view.Attachment.Details, + TwoColumn; + +/** + * wp.media.view.Attachment.Details.TwoColumn + * + * A similar view to media.view.Attachment.Details + * for use in the Edit Attachment modal. + * + * @memberOf wp.media.view.Attachment.Details + * + * @class + * @augments wp.media.view.Attachment.Details + * @augments wp.media.view.Attachment + * @augments wp.media.View + * @augments wp.Backbone.View + * @augments Backbone.View + */ +TwoColumn = Details.extend(/** @lends wp.media.view.Attachment.Details.TowColumn.prototype */{ + template: wp.template( 'attachment-details-two-column' ), + + initialize: function() { + this.controller.on( 'content:activate:edit-details', _.bind( this.editAttachment, this ) ); + + Details.prototype.initialize.apply( this, arguments ); + }, + + editAttachment: function( event ) { + if ( event ) { + event.preventDefault(); + } + this.controller.content.mode( 'edit-image' ); + }, + + /** + * Noop this from parent class, doesn't apply here. + */ + toggleSelectionHandler: function() {}, + + render: function() { + Details.prototype.render.apply( this, arguments ); + + wp.media.mixin.removeAllPlayers(); + this.$( 'audio, video' ).each( function (i, elem) { + var el = wp.media.view.MediaDetails.prepareSrc( elem ); + new window.MediaElementPlayer( el, wp.media.mixin.mejsSettings ); + } ); + } +}); + +module.exports = TwoColumn; + + +/***/ }), +/* 16 */ +/***/ (function(module, exports) { + +/** + * wp.media.view.MediaFrame.Manage.Router + * + * A router for handling the browser history and application state. + * + * @memberOf wp.media.view.MediaFrame.Manage + * + * @class + * @augments Backbone.Router + */ +var Router = Backbone.Router.extend(/** @lends wp.media.view.MediaFrame.Manage.Router.prototype */{ + routes: { + 'upload.php?item=:slug&mode=edit': 'editItem', + 'upload.php?item=:slug': 'showItem', + 'upload.php?search=:query': 'search', + 'upload.php': 'reset' + }, + + // Map routes against the page URL + baseUrl: function( url ) { + return 'upload.php' + url; + }, + + reset: function() { + var frame = wp.media.frames.edit; + + if ( frame ) { + frame.close(); + } + }, + + // Respond to the search route by filling the search field and trigggering the input event + search: function( query ) { + jQuery( '#media-search-input' ).val( query ).trigger( 'input' ); + }, + + // Show the modal with a specific item + showItem: function( query ) { + var media = wp.media, + frame = media.frames.browse, + library = frame.state().get('library'), + item; + + // Trigger the media frame to open the correct item + item = library.findWhere( { id: parseInt( query, 10 ) } ); + item.set( 'skipHistory', true ); + + if ( item ) { + frame.trigger( 'edit:attachment', item ); + } else { + item = media.attachment( query ); + frame.listenTo( item, 'change', function( model ) { + frame.stopListening( item ); + frame.trigger( 'edit:attachment', model ); + } ); + item.fetch(); + } + }, + + // Show the modal in edit mode with a specific item. + editItem: function( query ) { + this.showItem( query ); + wp.media.frames.edit.content.mode( 'edit-details' ); + } +}); + +module.exports = Router; + + +/***/ }), +/* 17 */ +/***/ (function(module, exports) { + +var View = wp.media.View, + EditImage = wp.media.view.EditImage, + Details; + +/** + * wp.media.view.EditImage.Details + * + * @memberOf wp.media.view.EditImage + * + * @class + * @augments wp.media.view.EditImage + * @augments wp.media.View + * @augments wp.Backbone.View + * @augments Backbone.View + */ +Details = EditImage.extend(/** @lends wp.media.view.EditImage.Details.prototype */{ + initialize: function( options ) { + this.editor = window.imageEdit; + this.frame = options.frame; + this.controller = options.controller; + View.prototype.initialize.apply( this, arguments ); + }, + + back: function() { + this.frame.content.mode( 'edit-metadata' ); + }, + + save: function() { + this.model.fetch().done( _.bind( function() { + this.frame.content.mode( 'edit-metadata' ); + }, this ) ); + } +}); + +module.exports = Details; + + +/***/ }), +/* 18 */ +/***/ (function(module, exports) { + +var Frame = wp.media.view.Frame, + MediaFrame = wp.media.view.MediaFrame, + + $ = jQuery, + EditAttachments; + +/** + * wp.media.view.MediaFrame.EditAttachments + * + * A frame for editing the details of a specific media item. + * + * Opens in a modal by default. + * + * Requires an attachment model to be passed in the options hash under `model`. + * + * @memberOf wp.media.view.MediaFrame + * + * @class + * @augments wp.media.view.Frame + * @augments wp.media.View + * @augments wp.Backbone.View + * @augments Backbone.View + * @mixes wp.media.controller.StateMachine + */ +EditAttachments = MediaFrame.extend(/** @lends wp.media.view.MediaFrame.EditAttachments.prototype */{ + + className: 'edit-attachment-frame', + template: wp.template( 'edit-attachment-frame' ), + regions: [ 'title', 'content' ], + + events: { + 'click .left': 'previousMediaItem', + 'click .right': 'nextMediaItem' + }, + + initialize: function() { + Frame.prototype.initialize.apply( this, arguments ); + + _.defaults( this.options, { + modal: true, + state: 'edit-attachment' + }); + + this.controller = this.options.controller; + this.gridRouter = this.controller.gridRouter; + this.library = this.options.library; + + if ( this.options.model ) { + this.model = this.options.model; + } + + this.bindHandlers(); + this.createStates(); + this.createModal(); + + this.title.mode( 'default' ); + this.toggleNav(); + }, + + bindHandlers: function() { + // Bind default title creation. + this.on( 'title:create:default', this.createTitle, this ); + + this.on( 'content:create:edit-metadata', this.editMetadataMode, this ); + this.on( 'content:create:edit-image', this.editImageMode, this ); + this.on( 'content:render:edit-image', this.editImageModeRender, this ); + this.on( 'refresh', this.rerender, this ); + this.on( 'close', this.detach ); + + this.bindModelHandlers(); + this.listenTo( this.gridRouter, 'route:search', this.close, this ); + }, + + bindModelHandlers: function() { + // Close the modal if the attachment is deleted. + this.listenTo( this.model, 'change:status destroy', this.close, this ); + }, + + createModal: function() { + // Initialize modal container view. + if ( this.options.modal ) { + this.modal = new wp.media.view.Modal({ + controller: this, + title: this.options.title + }); + + this.modal.on( 'open', _.bind( function () { + $( 'body' ).on( 'keydown.media-modal', _.bind( this.keyEvent, this ) ); + }, this ) ); + + // Completely destroy the modal DOM element when closing it. + this.modal.on( 'close', _.bind( function() { + $( 'body' ).off( 'keydown.media-modal' ); /* remove the keydown event */ + // Restore the original focus item if possible + $( 'li.attachment[data-id="' + this.model.get( 'id' ) +'"]' ).focus(); + this.resetRoute(); + }, this ) ); + + // Set this frame as the modal's content. + this.modal.content( this ); + this.modal.open(); + } + }, + + /** + * Add the default states to the frame. + */ + createStates: function() { + this.states.add([ + new wp.media.controller.EditAttachmentMetadata({ + model: this.model, + library: this.library + }) + ]); + }, + + /** + * Content region rendering callback for the `edit-metadata` mode. + * + * @param {Object} contentRegion Basic object with a `view` property, which + * should be set with the proper region view. + */ + editMetadataMode: function( contentRegion ) { + contentRegion.view = new wp.media.view.Attachment.Details.TwoColumn({ + controller: this, + model: this.model + }); + + /** + * Attach a subview to display fields added via the + * `attachment_fields_to_edit` filter. + */ + contentRegion.view.views.set( '.attachment-compat', new wp.media.view.AttachmentCompat({ + controller: this, + model: this.model + }) ); + + // Update browser url when navigating media details, except on load. + if ( this.model && ! this.model.get( 'skipHistory' ) ) { + this.gridRouter.navigate( this.gridRouter.baseUrl( '?item=' + this.model.id ) ); + } + }, + + /** + * Render the EditImage view into the frame's content region. + * + * @param {Object} contentRegion Basic object with a `view` property, which + * should be set with the proper region view. + */ + editImageMode: function( contentRegion ) { + var editImageController = new wp.media.controller.EditImage( { + model: this.model, + frame: this + } ); + // Noop some methods. + editImageController._toolbar = function() {}; + editImageController._router = function() {}; + editImageController._menu = function() {}; + + contentRegion.view = new wp.media.view.EditImage.Details( { + model: this.model, + frame: this, + controller: editImageController + } ); + + this.gridRouter.navigate( this.gridRouter.baseUrl( '?item=' + this.model.id + '&mode=edit' ) ); + + }, + + editImageModeRender: function( view ) { + view.on( 'ready', view.loadEditor ); + }, + + toggleNav: function() { + this.$('.left').toggleClass( 'disabled', ! this.hasPrevious() ); + this.$('.right').toggleClass( 'disabled', ! this.hasNext() ); + }, + + /** + * Rerender the view. + */ + rerender: function( model ) { + this.stopListening( this.model ); + + this.model = model; + + this.bindModelHandlers(); + + // Only rerender the `content` region. + if ( this.content.mode() !== 'edit-metadata' ) { + this.content.mode( 'edit-metadata' ); + } else { + this.content.render(); + } + + this.toggleNav(); + }, + + /** + * Click handler to switch to the previous media item. + */ + previousMediaItem: function() { + if ( ! this.hasPrevious() ) { + return; + } + this.trigger( 'refresh', this.library.at( this.getCurrentIndex() - 1 ) ); + this.$( '.left' ).focus(); + }, + + /** + * Click handler to switch to the next media item. + */ + nextMediaItem: function() { + if ( ! this.hasNext() ) { + return; + } + this.trigger( 'refresh', this.library.at( this.getCurrentIndex() + 1 ) ); + this.$( '.right' ).focus(); + }, + + getCurrentIndex: function() { + return this.library.indexOf( this.model ); + }, + + hasNext: function() { + return ( this.getCurrentIndex() + 1 ) < this.library.length; + }, + + hasPrevious: function() { + return ( this.getCurrentIndex() - 1 ) > -1; + }, + /** + * Respond to the keyboard events: right arrow, left arrow, except when + * focus is in a textarea or input field. + */ + keyEvent: function( event ) { + if ( ( 'INPUT' === event.target.nodeName || 'TEXTAREA' === event.target.nodeName ) && ! ( event.target.readOnly || event.target.disabled ) ) { + return; + } + + // The right arrow key + if ( 39 === event.keyCode ) { + this.nextMediaItem(); + } + // The left arrow key + if ( 37 === event.keyCode ) { + this.previousMediaItem(); + } + }, + + resetRoute: function() { + var searchTerm = this.controller.browserView.toolbar.get( 'search' ).$el.val(), + url = '' !== searchTerm ? '?search=' + searchTerm : ''; + this.gridRouter.navigate( this.gridRouter.baseUrl( url ), { replace: true } ); + } +}); + +module.exports = EditAttachments; + + +/***/ }), +/* 19 */ +/***/ (function(module, exports) { + + +var Button = wp.media.view.Button, + l10n = wp.media.view.l10n, + SelectModeToggle; + +/** + * wp.media.view.SelectModeToggleButton + * + * @memberOf wp.media.view + * + * @class + * @augments wp.media.view.Button + * @augments wp.media.View + * @augments wp.Backbone.View + * @augments Backbone.View + */ +SelectModeToggle = Button.extend(/** @lends wp.media.view.SelectModeToggle.prototype */{ + initialize: function() { + _.defaults( this.options, { + size : '' + } ); + + Button.prototype.initialize.apply( this, arguments ); + this.controller.on( 'select:activate select:deactivate', this.toggleBulkEditHandler, this ); + this.controller.on( 'selection:action:done', this.back, this ); + }, + + back: function () { + this.controller.deactivateMode( 'select' ).activateMode( 'edit' ); + }, + + click: function() { + Button.prototype.click.apply( this, arguments ); + if ( this.controller.isModeActive( 'select' ) ) { + this.back(); + } else { + this.controller.deactivateMode( 'edit' ).activateMode( 'select' ); + } + }, + + render: function() { + Button.prototype.render.apply( this, arguments ); + this.$el.addClass( 'select-mode-toggle-button' ); + return this; + }, + + toggleBulkEditHandler: function() { + var toolbar = this.controller.content.get().toolbar, children; + + children = toolbar.$( '.media-toolbar-secondary > *, .media-toolbar-primary > *' ); + + // TODO: the Frame should be doing all of this. + if ( this.controller.isModeActive( 'select' ) ) { + this.model.set( { + size: 'large', + text: l10n.cancelSelection + } ); + children.not( '.spinner, .media-button' ).hide(); + this.$el.show(); + toolbar.$( '.delete-selected-button' ).removeClass( 'hidden' ); + } else { + this.model.set( { + size: '', + text: l10n.bulkSelect + } ); + this.controller.content.get().$el.removeClass( 'fixed' ); + toolbar.$el.css( 'width', '' ); + toolbar.$( '.delete-selected-button' ).addClass( 'hidden' ); + children.not( '.media-button' ).show(); + this.controller.state().get( 'selection' ).reset(); + } + } +}); + +module.exports = SelectModeToggle; + + +/***/ }), +/* 20 */ +/***/ (function(module, exports) { + +var Button = wp.media.view.Button, + l10n = wp.media.view.l10n, + DeleteSelected; + +/** + * wp.media.view.DeleteSelectedButton + * + * A button that handles bulk Delete/Trash logic + * + * @memberOf wp.media.view + * + * @class + * @augments wp.media.view.Button + * @augments wp.media.View + * @augments wp.Backbone.View + * @augments Backbone.View + */ +DeleteSelected = Button.extend(/** @lends wp.media.view.DeleteSelectedButton.prototype */{ + initialize: function() { + Button.prototype.initialize.apply( this, arguments ); + if ( this.options.filters ) { + this.options.filters.model.on( 'change', this.filterChange, this ); + } + this.controller.on( 'selection:toggle', this.toggleDisabled, this ); + }, + + filterChange: function( model ) { + if ( 'trash' === model.get( 'status' ) ) { + this.model.set( 'text', l10n.untrashSelected ); + } else if ( wp.media.view.settings.mediaTrash ) { + this.model.set( 'text', l10n.trashSelected ); + } else { + this.model.set( 'text', l10n.deleteSelected ); + } + }, + + toggleDisabled: function() { + this.model.set( 'disabled', ! this.controller.state().get( 'selection' ).length ); + }, + + render: function() { + Button.prototype.render.apply( this, arguments ); + if ( this.controller.isModeActive( 'select' ) ) { + this.$el.addClass( 'delete-selected-button' ); + } else { + this.$el.addClass( 'delete-selected-button hidden' ); + } + this.toggleDisabled(); + return this; + } +}); + +module.exports = DeleteSelected; + + +/***/ }), +/* 21 */ +/***/ (function(module, exports) { + +var Button = wp.media.view.Button, + DeleteSelected = wp.media.view.DeleteSelectedButton, + DeleteSelectedPermanently; + +/** + * wp.media.view.DeleteSelectedPermanentlyButton + * + * When MEDIA_TRASH is true, a button that handles bulk Delete Permanently logic + * + * @memberOf wp.media.view + * + * @class + * @augments wp.media.view.DeleteSelectedButton + * @augments wp.media.view.Button + * @augments wp.media.View + * @augments wp.Backbone.View + * @augments Backbone.View + */ +DeleteSelectedPermanently = DeleteSelected.extend(/** @lends wp.media.view.DeleteSelectedPermanentlyButton.prototype */{ + initialize: function() { + DeleteSelected.prototype.initialize.apply( this, arguments ); + this.controller.on( 'select:activate', this.selectActivate, this ); + this.controller.on( 'select:deactivate', this.selectDeactivate, this ); + }, + + filterChange: function( model ) { + this.canShow = ( 'trash' === model.get( 'status' ) ); + }, + + selectActivate: function() { + this.toggleDisabled(); + this.$el.toggleClass( 'hidden', ! this.canShow ); + }, + + selectDeactivate: function() { + this.toggleDisabled(); + this.$el.addClass( 'hidden' ); + }, + + render: function() { + Button.prototype.render.apply( this, arguments ); + this.selectActivate(); + return this; + } +}); + +module.exports = DeleteSelectedPermanently; + /***/ }) - -/******/ }); \ No newline at end of file +/******/ ]); \ No newline at end of file diff --git a/wp-includes/js/media-grid.min.js b/wp-includes/js/media-grid.min.js index 498d5d294e..2be3503f66 100644 --- a/wp-includes/js/media-grid.min.js +++ b/wp-includes/js/media-grid.min.js @@ -1 +1 @@ -!function(a){function b(d){if(c[d])return c[d].exports;var e=c[d]={i:d,l:!1,exports:{}};return a[d].call(e.exports,e,e.exports,b),e.l=!0,e.exports}var c={};return b.m=a,b.c=c,b.d=function(a,c,d){b.o(a,c)||Object.defineProperty(a,c,{enumerable:!0,get:d})},b.r=function(a){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(a,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(a,"__esModule",{value:!0})},b.t=function(a,c){if(1&c&&(a=b(a)),8&c)return a;if(4&c&&"object"==typeof a&&a&&a.__esModule)return a;var d=Object.create(null);if(b.r(d),Object.defineProperty(d,"default",{enumerable:!0,value:a}),2&c&&"string"!=typeof a)for(var e in a)b.d(d,e,function(b){return a[b]}.bind(null,e));return d},b.n=function(a){var c=a&&a.__esModule?function(){return a["default"]}:function(){return a};return b.d(c,"a",c),c},b.o=function(a,b){return Object.prototype.hasOwnProperty.call(a,b)},b.p="",b(b.s=1)}({"./src/js/_enqueues/wp/media/grid.js":function(module,exports,__webpack_require__){eval('/**\n * @output wp-includes/js/media-grid.js\n */\n\nvar media = wp.media;\n\nmedia.controller.EditAttachmentMetadata = __webpack_require__( /*! ../../../media/controllers/edit-attachment-metadata.js */ "./src/js/media/controllers/edit-attachment-metadata.js" );\nmedia.view.MediaFrame.Manage = __webpack_require__( /*! ../../../media/views/frame/manage.js */ "./src/js/media/views/frame/manage.js" );\nmedia.view.Attachment.Details.TwoColumn = __webpack_require__( /*! ../../../media/views/attachment/details-two-column.js */ "./src/js/media/views/attachment/details-two-column.js" );\nmedia.view.MediaFrame.Manage.Router = __webpack_require__( /*! ../../../media/routers/manage.js */ "./src/js/media/routers/manage.js" );\nmedia.view.EditImage.Details = __webpack_require__( /*! ../../../media/views/edit-image-details.js */ "./src/js/media/views/edit-image-details.js" );\nmedia.view.MediaFrame.EditAttachments = __webpack_require__( /*! ../../../media/views/frame/edit-attachments.js */ "./src/js/media/views/frame/edit-attachments.js" );\nmedia.view.SelectModeToggleButton = __webpack_require__( /*! ../../../media/views/button/select-mode-toggle.js */ "./src/js/media/views/button/select-mode-toggle.js" );\nmedia.view.DeleteSelectedButton = __webpack_require__( /*! ../../../media/views/button/delete-selected.js */ "./src/js/media/views/button/delete-selected.js" );\nmedia.view.DeleteSelectedPermanentlyButton = __webpack_require__( /*! ../../../media/views/button/delete-selected-permanently.js */ "./src/js/media/views/button/delete-selected-permanently.js" );\n\n\n//# sourceURL=webpack:///./src/js/_enqueues/wp/media/grid.js?')},"./src/js/media/controllers/edit-attachment-metadata.js":function(module,exports){eval("var l10n = wp.media.view.l10n,\n\tEditAttachmentMetadata;\n\n/**\n * wp.media.controller.EditAttachmentMetadata\n *\n * A state for editing an attachment's metadata.\n *\n * @memberOf wp.media.controller\n *\n * @class\n * @augments wp.media.controller.State\n * @augments Backbone.Model\n */\nEditAttachmentMetadata = wp.media.controller.State.extend(/** @lends wp.media.controller.EditAttachmentMetadata.prototype */{\n\tdefaults: {\n\t\tid: 'edit-attachment',\n\t\t// Title string passed to the frame's title region view.\n\t\ttitle: l10n.attachmentDetails,\n\t\t// Region mode defaults.\n\t\tcontent: 'edit-metadata',\n\t\tmenu: false,\n\t\ttoolbar: false,\n\t\trouter: false\n\t}\n});\n\nmodule.exports = EditAttachmentMetadata;\n\n\n//# sourceURL=webpack:///./src/js/media/controllers/edit-attachment-metadata.js?")},"./src/js/media/routers/manage.js":function(module,exports){eval("/**\n * wp.media.view.MediaFrame.Manage.Router\n *\n * A router for handling the browser history and application state.\n *\n * @memberOf wp.media.view.MediaFrame.Manage\n *\n * @class\n * @augments Backbone.Router\n */\nvar Router = Backbone.Router.extend(/** @lends wp.media.view.MediaFrame.Manage.Router.prototype */{\n\troutes: {\n\t\t'upload.php?item=:slug&mode=edit': 'editItem',\n\t\t'upload.php?item=:slug': 'showItem',\n\t\t'upload.php?search=:query': 'search',\n\t\t'upload.php': 'reset'\n\t},\n\n\t// Map routes against the page URL\n\tbaseUrl: function( url ) {\n\t\treturn 'upload.php' + url;\n\t},\n\n\treset: function() {\n\t\tvar frame = wp.media.frames.edit;\n\n\t\tif ( frame ) {\n\t\t\tframe.close();\n\t\t}\n\t},\n\n\t// Respond to the search route by filling the search field and trigggering the input event\n\tsearch: function( query ) {\n\t\tjQuery( '#media-search-input' ).val( query ).trigger( 'input' );\n\t},\n\n\t// Show the modal with a specific item\n\tshowItem: function( query ) {\n\t\tvar media = wp.media,\n\t\t\tframe = media.frames.browse,\n\t\t\tlibrary = frame.state().get('library'),\n\t\t\titem;\n\n\t\t// Trigger the media frame to open the correct item\n\t\titem = library.findWhere( { id: parseInt( query, 10 ) } );\n\t\titem.set( 'skipHistory', true );\n\n\t\tif ( item ) {\n\t\t\tframe.trigger( 'edit:attachment', item );\n\t\t} else {\n\t\t\titem = media.attachment( query );\n\t\t\tframe.listenTo( item, 'change', function( model ) {\n\t\t\t\tframe.stopListening( item );\n\t\t\t\tframe.trigger( 'edit:attachment', model );\n\t\t\t} );\n\t\t\titem.fetch();\n\t\t}\n\t},\n\n\t// Show the modal in edit mode with a specific item.\n\teditItem: function( query ) {\n\t\tthis.showItem( query );\n\t\twp.media.frames.edit.content.mode( 'edit-details' );\n\t}\n});\n\nmodule.exports = Router;\n\n\n//# sourceURL=webpack:///./src/js/media/routers/manage.js?")},"./src/js/media/views/attachment/details-two-column.js":function(module,exports){eval("var Details = wp.media.view.Attachment.Details,\n\tTwoColumn;\n\n/**\n * wp.media.view.Attachment.Details.TwoColumn\n *\n * A similar view to media.view.Attachment.Details\n * for use in the Edit Attachment modal.\n *\n * @memberOf wp.media.view.Attachment.Details\n *\n * @class\n * @augments wp.media.view.Attachment.Details\n * @augments wp.media.view.Attachment\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n */\nTwoColumn = Details.extend(/** @lends wp.media.view.Attachment.Details.TowColumn.prototype */{\n\ttemplate: wp.template( 'attachment-details-two-column' ),\n\n\tinitialize: function() {\n\t\tthis.controller.on( 'content:activate:edit-details', _.bind( this.editAttachment, this ) );\n\n\t\tDetails.prototype.initialize.apply( this, arguments );\n\t},\n\n\teditAttachment: function( event ) {\n\t\tif ( event ) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t\tthis.controller.content.mode( 'edit-image' );\n\t},\n\n\t/**\n\t * Noop this from parent class, doesn't apply here.\n\t */\n\ttoggleSelectionHandler: function() {},\n\n\trender: function() {\n\t\tDetails.prototype.render.apply( this, arguments );\n\n\t\twp.media.mixin.removeAllPlayers();\n\t\tthis.$( 'audio, video' ).each( function (i, elem) {\n\t\t\tvar el = wp.media.view.MediaDetails.prepareSrc( elem );\n\t\t\tnew window.MediaElementPlayer( el, wp.media.mixin.mejsSettings );\n\t\t} );\n\t}\n});\n\nmodule.exports = TwoColumn;\n\n\n//# sourceURL=webpack:///./src/js/media/views/attachment/details-two-column.js?")},"./src/js/media/views/button/delete-selected-permanently.js":function(module,exports){eval("var Button = wp.media.view.Button,\n\tDeleteSelected = wp.media.view.DeleteSelectedButton,\n\tDeleteSelectedPermanently;\n\n/**\n * wp.media.view.DeleteSelectedPermanentlyButton\n *\n * When MEDIA_TRASH is true, a button that handles bulk Delete Permanently logic\n *\n * @memberOf wp.media.view\n *\n * @class\n * @augments wp.media.view.DeleteSelectedButton\n * @augments wp.media.view.Button\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n */\nDeleteSelectedPermanently = DeleteSelected.extend(/** @lends wp.media.view.DeleteSelectedPermanentlyButton.prototype */{\n\tinitialize: function() {\n\t\tDeleteSelected.prototype.initialize.apply( this, arguments );\n\t\tthis.controller.on( 'select:activate', this.selectActivate, this );\n\t\tthis.controller.on( 'select:deactivate', this.selectDeactivate, this );\n\t},\n\n\tfilterChange: function( model ) {\n\t\tthis.canShow = ( 'trash' === model.get( 'status' ) );\n\t},\n\n\tselectActivate: function() {\n\t\tthis.toggleDisabled();\n\t\tthis.$el.toggleClass( 'hidden', ! this.canShow );\n\t},\n\n\tselectDeactivate: function() {\n\t\tthis.toggleDisabled();\n\t\tthis.$el.addClass( 'hidden' );\n\t},\n\n\trender: function() {\n\t\tButton.prototype.render.apply( this, arguments );\n\t\tthis.selectActivate();\n\t\treturn this;\n\t}\n});\n\nmodule.exports = DeleteSelectedPermanently;\n\n\n//# sourceURL=webpack:///./src/js/media/views/button/delete-selected-permanently.js?")},"./src/js/media/views/button/delete-selected.js":function(module,exports){eval("var Button = wp.media.view.Button,\n\tl10n = wp.media.view.l10n,\n\tDeleteSelected;\n\n/**\n * wp.media.view.DeleteSelectedButton\n *\n * A button that handles bulk Delete/Trash logic\n *\n * @memberOf wp.media.view\n *\n * @class\n * @augments wp.media.view.Button\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n */\nDeleteSelected = Button.extend(/** @lends wp.media.view.DeleteSelectedButton.prototype */{\n\tinitialize: function() {\n\t\tButton.prototype.initialize.apply( this, arguments );\n\t\tif ( this.options.filters ) {\n\t\t\tthis.options.filters.model.on( 'change', this.filterChange, this );\n\t\t}\n\t\tthis.controller.on( 'selection:toggle', this.toggleDisabled, this );\n\t},\n\n\tfilterChange: function( model ) {\n\t\tif ( 'trash' === model.get( 'status' ) ) {\n\t\t\tthis.model.set( 'text', l10n.untrashSelected );\n\t\t} else if ( wp.media.view.settings.mediaTrash ) {\n\t\t\tthis.model.set( 'text', l10n.trashSelected );\n\t\t} else {\n\t\t\tthis.model.set( 'text', l10n.deleteSelected );\n\t\t}\n\t},\n\n\ttoggleDisabled: function() {\n\t\tthis.model.set( 'disabled', ! this.controller.state().get( 'selection' ).length );\n\t},\n\n\trender: function() {\n\t\tButton.prototype.render.apply( this, arguments );\n\t\tif ( this.controller.isModeActive( 'select' ) ) {\n\t\t\tthis.$el.addClass( 'delete-selected-button' );\n\t\t} else {\n\t\t\tthis.$el.addClass( 'delete-selected-button hidden' );\n\t\t}\n\t\tthis.toggleDisabled();\n\t\treturn this;\n\t}\n});\n\nmodule.exports = DeleteSelected;\n\n\n//# sourceURL=webpack:///./src/js/media/views/button/delete-selected.js?")},"./src/js/media/views/button/select-mode-toggle.js":function(module,exports){eval("\nvar Button = wp.media.view.Button,\n\tl10n = wp.media.view.l10n,\n\tSelectModeToggle;\n\n/**\n * wp.media.view.SelectModeToggleButton\n *\n * @memberOf wp.media.view\n *\n * @class\n * @augments wp.media.view.Button\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n */\nSelectModeToggle = Button.extend(/** @lends wp.media.view.SelectModeToggle.prototype */{\n\tinitialize: function() {\n\t\t_.defaults( this.options, {\n\t\t\tsize : ''\n\t\t} );\n\n\t\tButton.prototype.initialize.apply( this, arguments );\n\t\tthis.controller.on( 'select:activate select:deactivate', this.toggleBulkEditHandler, this );\n\t\tthis.controller.on( 'selection:action:done', this.back, this );\n\t},\n\n\tback: function () {\n\t\tthis.controller.deactivateMode( 'select' ).activateMode( 'edit' );\n\t},\n\n\tclick: function() {\n\t\tButton.prototype.click.apply( this, arguments );\n\t\tif ( this.controller.isModeActive( 'select' ) ) {\n\t\t\tthis.back();\n\t\t} else {\n\t\t\tthis.controller.deactivateMode( 'edit' ).activateMode( 'select' );\n\t\t}\n\t},\n\n\trender: function() {\n\t\tButton.prototype.render.apply( this, arguments );\n\t\tthis.$el.addClass( 'select-mode-toggle-button' );\n\t\treturn this;\n\t},\n\n\ttoggleBulkEditHandler: function() {\n\t\tvar toolbar = this.controller.content.get().toolbar, children;\n\n\t\tchildren = toolbar.$( '.media-toolbar-secondary > *, .media-toolbar-primary > *' );\n\n\t\t// TODO: the Frame should be doing all of this.\n\t\tif ( this.controller.isModeActive( 'select' ) ) {\n\t\t\tthis.model.set( {\n\t\t\t\tsize: 'large',\n\t\t\t\ttext: l10n.cancelSelection\n\t\t\t} );\n\t\t\tchildren.not( '.spinner, .media-button' ).hide();\n\t\t\tthis.$el.show();\n\t\t\ttoolbar.$( '.delete-selected-button' ).removeClass( 'hidden' );\n\t\t} else {\n\t\t\tthis.model.set( {\n\t\t\t\tsize: '',\n\t\t\t\ttext: l10n.bulkSelect\n\t\t\t} );\n\t\t\tthis.controller.content.get().$el.removeClass( 'fixed' );\n\t\t\ttoolbar.$el.css( 'width', '' );\n\t\t\ttoolbar.$( '.delete-selected-button' ).addClass( 'hidden' );\n\t\t\tchildren.not( '.media-button' ).show();\n\t\t\tthis.controller.state().get( 'selection' ).reset();\n\t\t}\n\t}\n});\n\nmodule.exports = SelectModeToggle;\n\n\n//# sourceURL=webpack:///./src/js/media/views/button/select-mode-toggle.js?")},"./src/js/media/views/edit-image-details.js":function(module,exports){eval("var View = wp.media.View,\n\tEditImage = wp.media.view.EditImage,\n\tDetails;\n\n/**\n * wp.media.view.EditImage.Details\n *\n * @memberOf wp.media.view.EditImage\n *\n * @class\n * @augments wp.media.view.EditImage\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n */\nDetails = EditImage.extend(/** @lends wp.media.view.EditImage.Details.prototype */{\n\tinitialize: function( options ) {\n\t\tthis.editor = window.imageEdit;\n\t\tthis.frame = options.frame;\n\t\tthis.controller = options.controller;\n\t\tView.prototype.initialize.apply( this, arguments );\n\t},\n\n\tback: function() {\n\t\tthis.frame.content.mode( 'edit-metadata' );\n\t},\n\n\tsave: function() {\n\t\tthis.model.fetch().done( _.bind( function() {\n\t\t\tthis.frame.content.mode( 'edit-metadata' );\n\t\t}, this ) );\n\t}\n});\n\nmodule.exports = Details;\n\n\n//# sourceURL=webpack:///./src/js/media/views/edit-image-details.js?")},"./src/js/media/views/frame/edit-attachments.js":function(module,exports){eval("var Frame = wp.media.view.Frame,\n\tMediaFrame = wp.media.view.MediaFrame,\n\n\t$ = jQuery,\n\tEditAttachments;\n\n/**\n * wp.media.view.MediaFrame.EditAttachments\n *\n * A frame for editing the details of a specific media item.\n *\n * Opens in a modal by default.\n *\n * Requires an attachment model to be passed in the options hash under `model`.\n *\n * @memberOf wp.media.view.MediaFrame\n *\n * @class\n * @augments wp.media.view.Frame\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n * @mixes wp.media.controller.StateMachine\n */\nEditAttachments = MediaFrame.extend(/** @lends wp.media.view.MediaFrame.EditAttachments.prototype */{\n\n\tclassName: 'edit-attachment-frame',\n\ttemplate: wp.template( 'edit-attachment-frame' ),\n\tregions: [ 'title', 'content' ],\n\n\tevents: {\n\t\t'click .left': 'previousMediaItem',\n\t\t'click .right': 'nextMediaItem'\n\t},\n\n\tinitialize: function() {\n\t\tFrame.prototype.initialize.apply( this, arguments );\n\n\t\t_.defaults( this.options, {\n\t\t\tmodal: true,\n\t\t\tstate: 'edit-attachment'\n\t\t});\n\n\t\tthis.controller = this.options.controller;\n\t\tthis.gridRouter = this.controller.gridRouter;\n\t\tthis.library = this.options.library;\n\n\t\tif ( this.options.model ) {\n\t\t\tthis.model = this.options.model;\n\t\t}\n\n\t\tthis.bindHandlers();\n\t\tthis.createStates();\n\t\tthis.createModal();\n\n\t\tthis.title.mode( 'default' );\n\t\tthis.toggleNav();\n\t},\n\n\tbindHandlers: function() {\n\t\t// Bind default title creation.\n\t\tthis.on( 'title:create:default', this.createTitle, this );\n\n\t\tthis.on( 'content:create:edit-metadata', this.editMetadataMode, this );\n\t\tthis.on( 'content:create:edit-image', this.editImageMode, this );\n\t\tthis.on( 'content:render:edit-image', this.editImageModeRender, this );\n\t\tthis.on( 'refresh', this.rerender, this );\n\t\tthis.on( 'close', this.detach );\n\n\t\tthis.bindModelHandlers();\n\t\tthis.listenTo( this.gridRouter, 'route:search', this.close, this );\n\t},\n\n\tbindModelHandlers: function() {\n\t\t// Close the modal if the attachment is deleted.\n\t\tthis.listenTo( this.model, 'change:status destroy', this.close, this );\n\t},\n\n\tcreateModal: function() {\n\t\t// Initialize modal container view.\n\t\tif ( this.options.modal ) {\n\t\t\tthis.modal = new wp.media.view.Modal({\n\t\t\t\tcontroller: this,\n\t\t\t\ttitle: this.options.title\n\t\t\t});\n\n\t\t\tthis.modal.on( 'open', _.bind( function () {\n\t\t\t\t$( 'body' ).on( 'keydown.media-modal', _.bind( this.keyEvent, this ) );\n\t\t\t}, this ) );\n\n\t\t\t// Completely destroy the modal DOM element when closing it.\n\t\t\tthis.modal.on( 'close', _.bind( function() {\n\t\t\t\t$( 'body' ).off( 'keydown.media-modal' ); /* remove the keydown event */\n\t\t\t\t// Restore the original focus item if possible\n\t\t\t\t$( 'li.attachment[data-id=\"' + this.model.get( 'id' ) +'\"]' ).focus();\n\t\t\t\tthis.resetRoute();\n\t\t\t}, this ) );\n\n\t\t\t// Set this frame as the modal's content.\n\t\t\tthis.modal.content( this );\n\t\t\tthis.modal.open();\n\t\t}\n\t},\n\n\t/**\n\t * Add the default states to the frame.\n\t */\n\tcreateStates: function() {\n\t\tthis.states.add([\n\t\t\tnew wp.media.controller.EditAttachmentMetadata({\n\t\t\t\tmodel: this.model,\n\t\t\t\tlibrary: this.library\n\t\t\t})\n\t\t]);\n\t},\n\n\t/**\n\t * Content region rendering callback for the `edit-metadata` mode.\n\t *\n\t * @param {Object} contentRegion Basic object with a `view` property, which\n\t * should be set with the proper region view.\n\t */\n\teditMetadataMode: function( contentRegion ) {\n\t\tcontentRegion.view = new wp.media.view.Attachment.Details.TwoColumn({\n\t\t\tcontroller: this,\n\t\t\tmodel: this.model\n\t\t});\n\n\t\t/**\n\t\t * Attach a subview to display fields added via the\n\t\t * `attachment_fields_to_edit` filter.\n\t\t */\n\t\tcontentRegion.view.views.set( '.attachment-compat', new wp.media.view.AttachmentCompat({\n\t\t\tcontroller: this,\n\t\t\tmodel: this.model\n\t\t}) );\n\n\t\t// Update browser url when navigating media details, except on load.\n\t\tif ( this.model && ! this.model.get( 'skipHistory' ) ) {\n\t\t\tthis.gridRouter.navigate( this.gridRouter.baseUrl( '?item=' + this.model.id ) );\n\t\t}\n\t},\n\n\t/**\n\t * Render the EditImage view into the frame's content region.\n\t *\n\t * @param {Object} contentRegion Basic object with a `view` property, which\n\t * should be set with the proper region view.\n\t */\n\teditImageMode: function( contentRegion ) {\n\t\tvar editImageController = new wp.media.controller.EditImage( {\n\t\t\tmodel: this.model,\n\t\t\tframe: this\n\t\t} );\n\t\t// Noop some methods.\n\t\teditImageController._toolbar = function() {};\n\t\teditImageController._router = function() {};\n\t\teditImageController._menu = function() {};\n\n\t\tcontentRegion.view = new wp.media.view.EditImage.Details( {\n\t\t\tmodel: this.model,\n\t\t\tframe: this,\n\t\t\tcontroller: editImageController\n\t\t} );\n\n\t\tthis.gridRouter.navigate( this.gridRouter.baseUrl( '?item=' + this.model.id + '&mode=edit' ) );\n\n\t},\n\n\teditImageModeRender: function( view ) {\n\t\tview.on( 'ready', view.loadEditor );\n\t},\n\n\ttoggleNav: function() {\n\t\tthis.$('.left').toggleClass( 'disabled', ! this.hasPrevious() );\n\t\tthis.$('.right').toggleClass( 'disabled', ! this.hasNext() );\n\t},\n\n\t/**\n\t * Rerender the view.\n\t */\n\trerender: function( model ) {\n\t\tthis.stopListening( this.model );\n\n\t\tthis.model = model;\n\n\t\tthis.bindModelHandlers();\n\n\t\t// Only rerender the `content` region.\n\t\tif ( this.content.mode() !== 'edit-metadata' ) {\n\t\t\tthis.content.mode( 'edit-metadata' );\n\t\t} else {\n\t\t\tthis.content.render();\n\t\t}\n\n\t\tthis.toggleNav();\n\t},\n\n\t/**\n\t * Click handler to switch to the previous media item.\n\t */\n\tpreviousMediaItem: function() {\n\t\tif ( ! this.hasPrevious() ) {\n\t\t\treturn;\n\t\t}\n\t\tthis.trigger( 'refresh', this.library.at( this.getCurrentIndex() - 1 ) );\n\t\tthis.$( '.left' ).focus();\n\t},\n\n\t/**\n\t * Click handler to switch to the next media item.\n\t */\n\tnextMediaItem: function() {\n\t\tif ( ! this.hasNext() ) {\n\t\t\treturn;\n\t\t}\n\t\tthis.trigger( 'refresh', this.library.at( this.getCurrentIndex() + 1 ) );\n\t\tthis.$( '.right' ).focus();\n\t},\n\n\tgetCurrentIndex: function() {\n\t\treturn this.library.indexOf( this.model );\n\t},\n\n\thasNext: function() {\n\t\treturn ( this.getCurrentIndex() + 1 ) < this.library.length;\n\t},\n\n\thasPrevious: function() {\n\t\treturn ( this.getCurrentIndex() - 1 ) > -1;\n\t},\n\t/**\n\t * Respond to the keyboard events: right arrow, left arrow, except when\n\t * focus is in a textarea or input field.\n\t */\n\tkeyEvent: function( event ) {\n\t\tif ( ( 'INPUT' === event.target.nodeName || 'TEXTAREA' === event.target.nodeName ) && ! ( event.target.readOnly || event.target.disabled ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// The right arrow key\n\t\tif ( 39 === event.keyCode ) {\n\t\t\tthis.nextMediaItem();\n\t\t}\n\t\t// The left arrow key\n\t\tif ( 37 === event.keyCode ) {\n\t\t\tthis.previousMediaItem();\n\t\t}\n\t},\n\n\tresetRoute: function() {\n\t\tvar searchTerm = this.controller.browserView.toolbar.get( 'search' ).$el.val(),\n\t\t\turl = '' !== searchTerm ? '?search=' + searchTerm : '';\n\t\tthis.gridRouter.navigate( this.gridRouter.baseUrl( url ), { replace: true } );\n\t}\n});\n\nmodule.exports = EditAttachments;\n\n\n//# sourceURL=webpack:///./src/js/media/views/frame/edit-attachments.js?")},"./src/js/media/views/frame/manage.js":function(module,exports){eval("var MediaFrame = wp.media.view.MediaFrame,\n\tLibrary = wp.media.controller.Library,\n\n\t$ = Backbone.$,\n\tManage;\n\n/**\n * wp.media.view.MediaFrame.Manage\n *\n * A generic management frame workflow.\n *\n * Used in the media grid view.\n *\n * @memberOf wp.media.view.MediaFrame\n *\n * @class\n * @augments wp.media.view.MediaFrame\n * @augments wp.media.view.Frame\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n * @mixes wp.media.controller.StateMachine\n */\nManage = MediaFrame.extend(/** @lends wp.media.view.MediaFrame.Manage.prototype */{\n\t/**\n\t * @constructs\n\t */\n\tinitialize: function() {\n\t\t_.defaults( this.options, {\n\t\t\ttitle: '',\n\t\t\tmodal: false,\n\t\t\tselection: [],\n\t\t\tlibrary: {}, // Options hash for the query to the media library.\n\t\t\tmultiple: 'add',\n\t\t\tstate: 'library',\n\t\t\tuploader: true,\n\t\t\tmode: [ 'grid', 'edit' ]\n\t\t});\n\n\t\tthis.$body = $( document.body );\n\t\tthis.$window = $( window );\n\t\tthis.$adminBar = $( '#wpadminbar' );\n\t\t// Store the Add New button for later reuse in wp.media.view.UploaderInline.\n\t\tthis.$uploaderToggler = $( '.page-title-action' )\n\t\t\t.attr( 'aria-expanded', 'false' )\n\t\t\t.on( 'click', _.bind( this.addNewClickHandler, this ) );\n\n\t\tthis.$window.on( 'scroll resize', _.debounce( _.bind( this.fixPosition, this ), 15 ) );\n\n\t\t// Ensure core and media grid view UI is enabled.\n\t\tthis.$el.addClass('wp-core-ui');\n\n\t\t// Force the uploader off if the upload limit has been exceeded or\n\t\t// if the browser isn't supported.\n\t\tif ( wp.Uploader.limitExceeded || ! wp.Uploader.browser.supported ) {\n\t\t\tthis.options.uploader = false;\n\t\t}\n\n\t\t// Initialize a window-wide uploader.\n\t\tif ( this.options.uploader ) {\n\t\t\tthis.uploader = new wp.media.view.UploaderWindow({\n\t\t\t\tcontroller: this,\n\t\t\t\tuploader: {\n\t\t\t\t\tdropzone: document.body,\n\t\t\t\t\tcontainer: document.body\n\t\t\t\t}\n\t\t\t}).render();\n\t\t\tthis.uploader.ready();\n\t\t\t$('body').append( this.uploader.el );\n\n\t\t\tthis.options.uploader = false;\n\t\t}\n\n\t\tthis.gridRouter = new wp.media.view.MediaFrame.Manage.Router();\n\n\t\t// Call 'initialize' directly on the parent class.\n\t\tMediaFrame.prototype.initialize.apply( this, arguments );\n\n\t\t// Append the frame view directly the supplied container.\n\t\tthis.$el.appendTo( this.options.container );\n\n\t\tthis.createStates();\n\t\tthis.bindRegionModeHandlers();\n\t\tthis.render();\n\t\tthis.bindSearchHandler();\n\n\t\twp.media.frames.browse = this;\n\t},\n\n\tbindSearchHandler: function() {\n\t\tvar search = this.$( '#media-search-input' ),\n\t\t\tsearchView = this.browserView.toolbar.get( 'search' ).$el,\n\t\t\tlistMode = this.$( '.view-list' ),\n\n\t\t\tinput = _.throttle( function (e) {\n\t\t\t\tvar val = $( e.currentTarget ).val(),\n\t\t\t\t\turl = '';\n\n\t\t\t\tif ( val ) {\n\t\t\t\t\turl += '?search=' + val;\n\t\t\t\t\tthis.gridRouter.navigate( this.gridRouter.baseUrl( url ), { replace: true } );\n\t\t\t\t}\n\t\t\t}, 1000 );\n\n\t\t// Update the URL when entering search string (at most once per second)\n\t\tsearch.on( 'input', _.bind( input, this ) );\n\n\t\tthis.gridRouter\n\t\t\t.on( 'route:search', function () {\n\t\t\t\tvar href = window.location.href;\n\t\t\t\tif ( href.indexOf( 'mode=' ) > -1 ) {\n\t\t\t\t\thref = href.replace( /mode=[^&]+/g, 'mode=list' );\n\t\t\t\t} else {\n\t\t\t\t\thref += href.indexOf( '?' ) > -1 ? '&mode=list' : '?mode=list';\n\t\t\t\t}\n\t\t\t\thref = href.replace( 'search=', 's=' );\n\t\t\t\tlistMode.prop( 'href', href );\n\t\t\t})\n\t\t\t.on( 'route:reset', function() {\n\t\t\t\tsearchView.val( '' ).trigger( 'input' );\n\t\t\t});\n\t},\n\n\t/**\n\t * Create the default states for the frame.\n\t */\n\tcreateStates: function() {\n\t\tvar options = this.options;\n\n\t\tif ( this.options.states ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Add the default states.\n\t\tthis.states.add([\n\t\t\tnew Library({\n\t\t\t\tlibrary: wp.media.query( options.library ),\n\t\t\t\tmultiple: options.multiple,\n\t\t\t\ttitle: options.title,\n\t\t\t\tcontent: 'browse',\n\t\t\t\ttoolbar: 'select',\n\t\t\t\tcontentUserSetting: false,\n\t\t\t\tfilterable: 'all',\n\t\t\t\tautoSelect: false\n\t\t\t})\n\t\t]);\n\t},\n\n\t/**\n\t * Bind region mode activation events to proper handlers.\n\t */\n\tbindRegionModeHandlers: function() {\n\t\tthis.on( 'content:create:browse', this.browseContent, this );\n\n\t\t// Handle a frame-level event for editing an attachment.\n\t\tthis.on( 'edit:attachment', this.openEditAttachmentModal, this );\n\n\t\tthis.on( 'select:activate', this.bindKeydown, this );\n\t\tthis.on( 'select:deactivate', this.unbindKeydown, this );\n\t},\n\n\thandleKeydown: function( e ) {\n\t\tif ( 27 === e.which ) {\n\t\t\te.preventDefault();\n\t\t\tthis.deactivateMode( 'select' ).activateMode( 'edit' );\n\t\t}\n\t},\n\n\tbindKeydown: function() {\n\t\tthis.$body.on( 'keydown.select', _.bind( this.handleKeydown, this ) );\n\t},\n\n\tunbindKeydown: function() {\n\t\tthis.$body.off( 'keydown.select' );\n\t},\n\n\tfixPosition: function() {\n\t\tvar $browser, $toolbar;\n\t\tif ( ! this.isModeActive( 'select' ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t$browser = this.$('.attachments-browser');\n\t\t$toolbar = $browser.find('.media-toolbar');\n\n\t\t// Offset doesn't appear to take top margin into account, hence +16\n\t\tif ( ( $browser.offset().top + 16 ) < this.$window.scrollTop() + this.$adminBar.height() ) {\n\t\t\t$browser.addClass( 'fixed' );\n\t\t\t$toolbar.css('width', $browser.width() + 'px');\n\t\t} else {\n\t\t\t$browser.removeClass( 'fixed' );\n\t\t\t$toolbar.css('width', '');\n\t\t}\n\t},\n\n\t/**\n\t * Click handler for the `Add New` button.\n\t */\n\taddNewClickHandler: function( event ) {\n\t\tevent.preventDefault();\n\t\tthis.trigger( 'toggle:upload:attachment' );\n\n\t\tif ( this.uploader ) {\n\t\t\tthis.uploader.refresh();\n\t\t}\n\t},\n\n\t/**\n\t * Open the Edit Attachment modal.\n\t */\n\topenEditAttachmentModal: function( model ) {\n\t\t// Create a new EditAttachment frame, passing along the library and the attachment model.\n\t\tif ( wp.media.frames.edit ) {\n\t\t\twp.media.frames.edit.open().trigger( 'refresh', model );\n\t\t} else {\n\t\t\twp.media.frames.edit = wp.media( {\n\t\t\t\tframe: 'edit-attachments',\n\t\t\t\tcontroller: this,\n\t\t\t\tlibrary: this.state().get('library'),\n\t\t\t\tmodel: model\n\t\t\t} );\n\t\t}\n\t},\n\n\t/**\n\t * Create an attachments browser view within the content region.\n\t *\n\t * @param {Object} contentRegion Basic object with a `view` property, which\n\t * should be set with the proper region view.\n\t * @this wp.media.controller.Region\n\t */\n\tbrowseContent: function( contentRegion ) {\n\t\tvar state = this.state();\n\n\t\t// Browse our library of attachments.\n\t\tthis.browserView = contentRegion.view = new wp.media.view.AttachmentsBrowser({\n\t\t\tcontroller: this,\n\t\t\tcollection: state.get('library'),\n\t\t\tselection: state.get('selection'),\n\t\t\tmodel: state,\n\t\t\tsortable: state.get('sortable'),\n\t\t\tsearch: state.get('searchable'),\n\t\t\tfilters: state.get('filterable'),\n\t\t\tdate: state.get('date'),\n\t\t\tdisplay: state.get('displaySettings'),\n\t\t\tdragInfo: state.get('dragInfo'),\n\t\t\tsidebar: 'errors',\n\n\t\t\tsuggestedWidth: state.get('suggestedWidth'),\n\t\t\tsuggestedHeight: state.get('suggestedHeight'),\n\n\t\t\tAttachmentView: state.get('AttachmentView'),\n\n\t\t\tscrollElement: document\n\t\t});\n\t\tthis.browserView.on( 'ready', _.bind( this.bindDeferred, this ) );\n\n\t\tthis.errors = wp.Uploader.errors;\n\t\tthis.errors.on( 'add remove reset', this.sidebarVisibility, this );\n\t},\n\n\tsidebarVisibility: function() {\n\t\tthis.browserView.$( '.media-sidebar' ).toggle( !! this.errors.length );\n\t},\n\n\tbindDeferred: function() {\n\t\tif ( ! this.browserView.dfd ) {\n\t\t\treturn;\n\t\t}\n\t\tthis.browserView.dfd.done( _.bind( this.startHistory, this ) );\n\t},\n\n\tstartHistory: function() {\n\t\t// Verify pushState support and activate\n\t\tif ( window.history && window.history.pushState ) {\n\t\t\tif ( Backbone.History.started ) {\n\t\t\t\tBackbone.history.stop();\n\t\t\t}\n\t\t\tBackbone.history.start( {\n\t\t\t\troot: window._wpMediaGridSettings.adminUrl,\n\t\t\t\tpushState: true\n\t\t\t} );\n\t\t}\n\t}\n});\n\nmodule.exports = Manage;\n\n\n//# sourceURL=webpack:///./src/js/media/views/frame/manage.js?")},1:function(module,exports,__webpack_require__){eval('module.exports = __webpack_require__(/*! ./src/js/_enqueues/wp/media/grid.js */"./src/js/_enqueues/wp/media/grid.js");\n\n\n//# sourceURL=webpack:///multi_./src/js/_enqueues/wp/media/grid.js?')}}); \ No newline at end of file +!function(a){function b(d){if(c[d])return c[d].exports;var e=c[d]={i:d,l:!1,exports:{}};return a[d].call(e.exports,e,e.exports,b),e.l=!0,e.exports}var c={};return b.m=a,b.c=c,b.d=function(a,c,d){b.o(a,c)||Object.defineProperty(a,c,{enumerable:!0,get:d})},b.r=function(a){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(a,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(a,"__esModule",{value:!0})},b.t=function(a,c){if(1&c&&(a=b(a)),8&c)return a;if(4&c&&"object"==typeof a&&a&&a.__esModule)return a;var d=Object.create(null);if(b.r(d),Object.defineProperty(d,"default",{enumerable:!0,value:a}),2&c&&"string"!=typeof a)for(var e in a)b.d(d,e,function(b){return a[b]}.bind(null,e));return d},b.n=function(a){var c=a&&a.__esModule?function(){return a["default"]}:function(){return a};return b.d(c,"a",c),c},b.o=function(a,b){return Object.prototype.hasOwnProperty.call(a,b)},b.p="",b(b.s=11)}([,,,,,,,,,,,function(a,b,c){a.exports=c(12)},function(a,b,c){var d=wp.media;d.controller.EditAttachmentMetadata=c(13),d.view.MediaFrame.Manage=c(14),d.view.Attachment.Details.TwoColumn=c(15),d.view.MediaFrame.Manage.Router=c(16),d.view.EditImage.Details=c(17),d.view.MediaFrame.EditAttachments=c(18),d.view.SelectModeToggleButton=c(19),d.view.DeleteSelectedButton=c(20),d.view.DeleteSelectedPermanentlyButton=c(21)},function(a,b){var c,d=wp.media.view.l10n;c=wp.media.controller.State.extend({defaults:{id:"edit-attachment",title:d.attachmentDetails,content:"edit-metadata",menu:!1,toolbar:!1,router:!1}}),a.exports=c},function(a,b){var c,d=wp.media.view.MediaFrame,e=wp.media.controller.Library,f=Backbone.$;c=d.extend({initialize:function(){_.defaults(this.options,{title:"",modal:!1,selection:[],library:{},multiple:"add",state:"library",uploader:!0,mode:["grid","edit"]}),this.$body=f(document.body),this.$window=f(window),this.$adminBar=f("#wpadminbar"),this.$uploaderToggler=f(".page-title-action").attr("aria-expanded","false").on("click",_.bind(this.addNewClickHandler,this)),this.$window.on("scroll resize",_.debounce(_.bind(this.fixPosition,this),15)),this.$el.addClass("wp-core-ui"),!wp.Uploader.limitExceeded&&wp.Uploader.browser.supported||(this.options.uploader=!1),this.options.uploader&&(this.uploader=new wp.media.view.UploaderWindow({controller:this,uploader:{dropzone:document.body,container:document.body}}).render(),this.uploader.ready(),f("body").append(this.uploader.el),this.options.uploader=!1),this.gridRouter=new wp.media.view.MediaFrame.Manage.Router,d.prototype.initialize.apply(this,arguments),this.$el.appendTo(this.options.container),this.createStates(),this.bindRegionModeHandlers(),this.render(),this.bindSearchHandler(),wp.media.frames.browse=this},bindSearchHandler:function(){var a=this.$("#media-search-input"),b=this.browserView.toolbar.get("search").$el,c=this.$(".view-list"),d=_.throttle(function(a){var b=f(a.currentTarget).val(),c="";b&&(c+="?search="+b,this.gridRouter.navigate(this.gridRouter.baseUrl(c),{replace:!0}))},1e3);a.on("input",_.bind(d,this)),this.gridRouter.on("route:search",function(){var a=window.location.href;a.indexOf("mode=")>-1?a=a.replace(/mode=[^&]+/g,"mode=list"):a+=a.indexOf("?")>-1?"&mode=list":"?mode=list",a=a.replace("search=","s="),c.prop("href",a)}).on("route:reset",function(){b.val("").trigger("input")})},createStates:function(){var a=this.options;this.options.states||this.states.add([new e({library:wp.media.query(a.library),multiple:a.multiple,title:a.title,content:"browse",toolbar:"select",contentUserSetting:!1,filterable:"all",autoSelect:!1})])},bindRegionModeHandlers:function(){this.on("content:create:browse",this.browseContent,this),this.on("edit:attachment",this.openEditAttachmentModal,this),this.on("select:activate",this.bindKeydown,this),this.on("select:deactivate",this.unbindKeydown,this)},handleKeydown:function(a){27===a.which&&(a.preventDefault(),this.deactivateMode("select").activateMode("edit"))},bindKeydown:function(){this.$body.on("keydown.select",_.bind(this.handleKeydown,this))},unbindKeydown:function(){this.$body.off("keydown.select")},fixPosition:function(){var a,b;this.isModeActive("select")&&(a=this.$(".attachments-browser"),b=a.find(".media-toolbar"),a.offset().top+16-1},keyEvent:function(a){("INPUT"!==a.target.nodeName&&"TEXTAREA"!==a.target.nodeName||a.target.readOnly||a.target.disabled)&&(39===a.keyCode&&this.nextMediaItem(),37===a.keyCode&&this.previousMediaItem())},resetRoute:function(){var a=this.controller.browserView.toolbar.get("search").$el.val(),b=""!==a?"?search="+a:"";this.gridRouter.navigate(this.gridRouter.baseUrl(b),{replace:!0})}}),a.exports=c},function(a,b){var c,d=wp.media.view.Button,e=wp.media.view.l10n;c=d.extend({initialize:function(){_.defaults(this.options,{size:""}),d.prototype.initialize.apply(this,arguments),this.controller.on("select:activate select:deactivate",this.toggleBulkEditHandler,this),this.controller.on("selection:action:done",this.back,this)},back:function(){this.controller.deactivateMode("select").activateMode("edit")},click:function(){d.prototype.click.apply(this,arguments),this.controller.isModeActive("select")?this.back():this.controller.deactivateMode("edit").activateMode("select")},render:function(){return d.prototype.render.apply(this,arguments),this.$el.addClass("select-mode-toggle-button"),this},toggleBulkEditHandler:function(){var a,b=this.controller.content.get().toolbar;a=b.$(".media-toolbar-secondary > *, .media-toolbar-primary > *"),this.controller.isModeActive("select")?(this.model.set({size:"large",text:e.cancelSelection}),a.not(".spinner, .media-button").hide(),this.$el.show(),b.$(".delete-selected-button").removeClass("hidden")):(this.model.set({size:"",text:e.bulkSelect}),this.controller.content.get().$el.removeClass("fixed"),b.$el.css("width",""),b.$(".delete-selected-button").addClass("hidden"),a.not(".media-button").show(),this.controller.state().get("selection").reset())}}),a.exports=c},function(a,b){var c,d=wp.media.view.Button,e=wp.media.view.l10n;c=d.extend({initialize:function(){d.prototype.initialize.apply(this,arguments),this.options.filters&&this.options.filters.model.on("change",this.filterChange,this),this.controller.on("selection:toggle",this.toggleDisabled,this)},filterChange:function(a){"trash"===a.get("status")?this.model.set("text",e.untrashSelected):wp.media.view.settings.mediaTrash?this.model.set("text",e.trashSelected):this.model.set("text",e.deleteSelected)},toggleDisabled:function(){this.model.set("disabled",!this.controller.state().get("selection").length)},render:function(){return d.prototype.render.apply(this,arguments),this.controller.isModeActive("select")?this.$el.addClass("delete-selected-button"):this.$el.addClass("delete-selected-button hidden"),this.toggleDisabled(),this}}),a.exports=c},function(a,b){var c,d=wp.media.view.Button,e=wp.media.view.DeleteSelectedButton;c=e.extend({initialize:function(){e.prototype.initialize.apply(this,arguments),this.controller.on("select:activate",this.selectActivate,this),this.controller.on("select:deactivate",this.selectDeactivate,this)},filterChange:function(a){this.canShow="trash"===a.get("status")},selectActivate:function(){this.toggleDisabled(),this.$el.toggleClass("hidden",!this.canShow)},selectDeactivate:function(){this.toggleDisabled(),this.$el.addClass("hidden")},render:function(){return d.prototype.render.apply(this,arguments),this.selectActivate(),this}}),a.exports=c}]); \ No newline at end of file diff --git a/wp-includes/js/media-models.js b/wp-includes/js/media-models.js index e3e0e3b1d1..f7b2f8e885 100644 --- a/wp-includes/js/media-models.js +++ b/wp-includes/js/media-models.js @@ -81,85 +81,1580 @@ /******/ /******/ /******/ // Load entry module and return exports -/******/ return __webpack_require__(__webpack_require__.s = 2); +/******/ return __webpack_require__(__webpack_require__.s = 22); /******/ }) /************************************************************************/ /******/ ({ -/***/ "./src/js/_enqueues/wp/media/models.js": -/*!*********************************************!*\ - !*** ./src/js/_enqueues/wp/media/models.js ***! - \*********************************************/ -/*! no static exports found */ +/***/ 22: /***/ (function(module, exports, __webpack_require__) { -eval("/**\n * @output wp-includes/js/media-models.js\n */\n\nvar $ = jQuery,\n\tAttachment, Attachments, l10n, media;\n\n/** @namespace wp */\nwindow.wp = window.wp || {};\n\n/**\n * Create and return a media frame.\n *\n * Handles the default media experience.\n *\n * @alias wp.media\n * @memberOf wp\n * @namespace\n *\n * @param {object} attributes The properties passed to the main media controller.\n * @return {wp.media.view.MediaFrame} A media workflow.\n */\nmedia = wp.media = function( attributes ) {\n\tvar MediaFrame = media.view.MediaFrame,\n\t\tframe;\n\n\tif ( ! MediaFrame ) {\n\t\treturn;\n\t}\n\n\tattributes = _.defaults( attributes || {}, {\n\t\tframe: 'select'\n\t});\n\n\tif ( 'select' === attributes.frame && MediaFrame.Select ) {\n\t\tframe = new MediaFrame.Select( attributes );\n\t} else if ( 'post' === attributes.frame && MediaFrame.Post ) {\n\t\tframe = new MediaFrame.Post( attributes );\n\t} else if ( 'manage' === attributes.frame && MediaFrame.Manage ) {\n\t\tframe = new MediaFrame.Manage( attributes );\n\t} else if ( 'image' === attributes.frame && MediaFrame.ImageDetails ) {\n\t\tframe = new MediaFrame.ImageDetails( attributes );\n\t} else if ( 'audio' === attributes.frame && MediaFrame.AudioDetails ) {\n\t\tframe = new MediaFrame.AudioDetails( attributes );\n\t} else if ( 'video' === attributes.frame && MediaFrame.VideoDetails ) {\n\t\tframe = new MediaFrame.VideoDetails( attributes );\n\t} else if ( 'edit-attachments' === attributes.frame && MediaFrame.EditAttachments ) {\n\t\tframe = new MediaFrame.EditAttachments( attributes );\n\t}\n\n\tdelete attributes.frame;\n\n\tmedia.frame = frame;\n\n\treturn frame;\n};\n\n/** @namespace wp.media.model */\n/** @namespace wp.media.view */\n/** @namespace wp.media.controller */\n/** @namespace wp.media.frames */\n_.extend( media, { model: {}, view: {}, controller: {}, frames: {} });\n\n// Link any localized strings.\nl10n = media.model.l10n = window._wpMediaModelsL10n || {};\n\n// Link any settings.\nmedia.model.settings = l10n.settings || {};\ndelete l10n.settings;\n\nAttachment = media.model.Attachment = __webpack_require__( /*! ../../../media/models/attachment.js */ \"./src/js/media/models/attachment.js\" );\nAttachments = media.model.Attachments = __webpack_require__( /*! ../../../media/models/attachments.js */ \"./src/js/media/models/attachments.js\" );\n\nmedia.model.Query = __webpack_require__( /*! ../../../media/models/query.js */ \"./src/js/media/models/query.js\" );\nmedia.model.PostImage = __webpack_require__( /*! ../../../media/models/post-image.js */ \"./src/js/media/models/post-image.js\" );\nmedia.model.Selection = __webpack_require__( /*! ../../../media/models/selection.js */ \"./src/js/media/models/selection.js\" );\n\n/**\n * ========================================================================\n * UTILITIES\n * ========================================================================\n */\n\n/**\n * A basic equality comparator for Backbone models.\n *\n * Used to order models within a collection - @see wp.media.model.Attachments.comparator().\n *\n * @param {mixed} a The primary parameter to compare.\n * @param {mixed} b The primary parameter to compare.\n * @param {string} ac The fallback parameter to compare, a's cid.\n * @param {string} bc The fallback parameter to compare, b's cid.\n * @return {number} -1: a should come before b.\n * 0: a and b are of the same rank.\n * 1: b should come before a.\n */\nmedia.compare = function( a, b, ac, bc ) {\n\tif ( _.isEqual( a, b ) ) {\n\t\treturn ac === bc ? 0 : (ac > bc ? -1 : 1);\n\t} else {\n\t\treturn a > b ? -1 : 1;\n\t}\n};\n\n_.extend( media, /** @lends wp.media */{\n\t/**\n\t * media.template( id )\n\t *\n\t * Fetch a JavaScript template for an id, and return a templating function for it.\n\t *\n\t * See wp.template() in `wp-includes/js/wp-util.js`.\n\t *\n\t * @borrows wp.template as template\n\t */\n\ttemplate: wp.template,\n\n\t/**\n\t * media.post( [action], [data] )\n\t *\n\t * Sends a POST request to WordPress.\n\t * See wp.ajax.post() in `wp-includes/js/wp-util.js`.\n\t *\n\t * @borrows wp.ajax.post as post\n\t */\n\tpost: wp.ajax.post,\n\n\t/**\n\t * media.ajax( [action], [options] )\n\t *\n\t * Sends an XHR request to WordPress.\n\t * See wp.ajax.send() in `wp-includes/js/wp-util.js`.\n\t *\n\t * @borrows wp.ajax.send as ajax\n\t */\n\tajax: wp.ajax.send,\n\n\t/**\n\t * Scales a set of dimensions to fit within bounding dimensions.\n\t *\n\t * @param {Object} dimensions\n\t * @returns {Object}\n\t */\n\tfit: function( dimensions ) {\n\t\tvar width = dimensions.width,\n\t\t\theight = dimensions.height,\n\t\t\tmaxWidth = dimensions.maxWidth,\n\t\t\tmaxHeight = dimensions.maxHeight,\n\t\t\tconstraint;\n\n\t\t// Compare ratios between the two values to determine which\n\t\t// max to constrain by. If a max value doesn't exist, then the\n\t\t// opposite side is the constraint.\n\t\tif ( ! _.isUndefined( maxWidth ) && ! _.isUndefined( maxHeight ) ) {\n\t\t\tconstraint = ( width / height > maxWidth / maxHeight ) ? 'width' : 'height';\n\t\t} else if ( _.isUndefined( maxHeight ) ) {\n\t\t\tconstraint = 'width';\n\t\t} else if ( _.isUndefined( maxWidth ) && height > maxHeight ) {\n\t\t\tconstraint = 'height';\n\t\t}\n\n\t\t// If the value of the constrained side is larger than the max,\n\t\t// then scale the values. Otherwise return the originals; they fit.\n\t\tif ( 'width' === constraint && width > maxWidth ) {\n\t\t\treturn {\n\t\t\t\twidth : maxWidth,\n\t\t\t\theight: Math.round( maxWidth * height / width )\n\t\t\t};\n\t\t} else if ( 'height' === constraint && height > maxHeight ) {\n\t\t\treturn {\n\t\t\t\twidth : Math.round( maxHeight * width / height ),\n\t\t\t\theight: maxHeight\n\t\t\t};\n\t\t} else {\n\t\t\treturn {\n\t\t\t\twidth : width,\n\t\t\t\theight: height\n\t\t\t};\n\t\t}\n\t},\n\t/**\n\t * Truncates a string by injecting an ellipsis into the middle.\n\t * Useful for filenames.\n\t *\n\t * @param {String} string\n\t * @param {Number} [length=30]\n\t * @param {String} [replacement=…]\n\t * @returns {String} The string, unless length is greater than string.length.\n\t */\n\ttruncate: function( string, length, replacement ) {\n\t\tlength = length || 30;\n\t\treplacement = replacement || '…';\n\n\t\tif ( string.length <= length ) {\n\t\t\treturn string;\n\t\t}\n\n\t\treturn string.substr( 0, length / 2 ) + replacement + string.substr( -1 * length / 2 );\n\t}\n});\n\n/**\n * ========================================================================\n * MODELS\n * ========================================================================\n */\n/**\n * wp.media.attachment\n *\n * @static\n * @param {String} id A string used to identify a model.\n * @returns {wp.media.model.Attachment}\n */\nmedia.attachment = function( id ) {\n\treturn Attachment.get( id );\n};\n\n/**\n * A collection of all attachments that have been fetched from the server.\n *\n * @static\n * @member {wp.media.model.Attachments}\n */\nAttachments.all = new Attachments();\n\n/**\n * wp.media.query\n *\n * Shorthand for creating a new Attachments Query.\n *\n * @param {object} [props]\n * @returns {wp.media.model.Attachments}\n */\nmedia.query = function( props ) {\n\treturn new Attachments( null, {\n\t\tprops: _.extend( _.defaults( props || {}, { orderby: 'date' } ), { query: true } )\n\t});\n};\n\n// Clean up. Prevents mobile browsers caching\n$(window).on('unload', function(){\n\twindow.wp = null;\n});\n\n\n//# sourceURL=webpack:///./src/js/_enqueues/wp/media/models.js?"); +module.exports = __webpack_require__(23); + /***/ }), -/***/ "./src/js/media/models/attachment.js": -/*!*******************************************!*\ - !*** ./src/js/media/models/attachment.js ***! - \*******************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("var $ = Backbone.$,\n\tAttachment;\n\n/**\n * wp.media.model.Attachment\n *\n * @memberOf wp.media.model\n *\n * @class\n * @augments Backbone.Model\n */\nAttachment = Backbone.Model.extend(/** @lends wp.media.model.Attachment.prototype */{\n\t/**\n\t * Triggered when attachment details change\n\t * Overrides Backbone.Model.sync\n\t *\n\t * @param {string} method\n\t * @param {wp.media.model.Attachment} model\n\t * @param {Object} [options={}]\n\t *\n\t * @returns {Promise}\n\t */\n\tsync: function( method, model, options ) {\n\t\t// If the attachment does not yet have an `id`, return an instantly\n\t\t// rejected promise. Otherwise, all of our requests will fail.\n\t\tif ( _.isUndefined( this.id ) ) {\n\t\t\treturn $.Deferred().rejectWith( this ).promise();\n\t\t}\n\n\t\t// Overload the `read` request so Attachment.fetch() functions correctly.\n\t\tif ( 'read' === method ) {\n\t\t\toptions = options || {};\n\t\t\toptions.context = this;\n\t\t\toptions.data = _.extend( options.data || {}, {\n\t\t\t\taction: 'get-attachment',\n\t\t\t\tid: this.id\n\t\t\t});\n\t\t\treturn wp.media.ajax( options );\n\n\t\t// Overload the `update` request so properties can be saved.\n\t\t} else if ( 'update' === method ) {\n\t\t\t// If we do not have the necessary nonce, fail immeditately.\n\t\t\tif ( ! this.get('nonces') || ! this.get('nonces').update ) {\n\t\t\t\treturn $.Deferred().rejectWith( this ).promise();\n\t\t\t}\n\n\t\t\toptions = options || {};\n\t\t\toptions.context = this;\n\n\t\t\t// Set the action and ID.\n\t\t\toptions.data = _.extend( options.data || {}, {\n\t\t\t\taction: 'save-attachment',\n\t\t\t\tid: this.id,\n\t\t\t\tnonce: this.get('nonces').update,\n\t\t\t\tpost_id: wp.media.model.settings.post.id\n\t\t\t});\n\n\t\t\t// Record the values of the changed attributes.\n\t\t\tif ( model.hasChanged() ) {\n\t\t\t\toptions.data.changes = {};\n\n\t\t\t\t_.each( model.changed, function( value, key ) {\n\t\t\t\t\toptions.data.changes[ key ] = this.get( key );\n\t\t\t\t}, this );\n\t\t\t}\n\n\t\t\treturn wp.media.ajax( options );\n\n\t\t// Overload the `delete` request so attachments can be removed.\n\t\t// This will permanently delete an attachment.\n\t\t} else if ( 'delete' === method ) {\n\t\t\toptions = options || {};\n\n\t\t\tif ( ! options.wait ) {\n\t\t\t\tthis.destroyed = true;\n\t\t\t}\n\n\t\t\toptions.context = this;\n\t\t\toptions.data = _.extend( options.data || {}, {\n\t\t\t\taction: 'delete-post',\n\t\t\t\tid: this.id,\n\t\t\t\t_wpnonce: this.get('nonces')['delete']\n\t\t\t});\n\n\t\t\treturn wp.media.ajax( options ).done( function() {\n\t\t\t\tthis.destroyed = true;\n\t\t\t}).fail( function() {\n\t\t\t\tthis.destroyed = false;\n\t\t\t});\n\n\t\t// Otherwise, fall back to `Backbone.sync()`.\n\t\t} else {\n\t\t\t/**\n\t\t\t * Call `sync` directly on Backbone.Model\n\t\t\t */\n\t\t\treturn Backbone.Model.prototype.sync.apply( this, arguments );\n\t\t}\n\t},\n\t/**\n\t * Convert date strings into Date objects.\n\t *\n\t * @param {Object} resp The raw response object, typically returned by fetch()\n\t * @returns {Object} The modified response object, which is the attributes hash\n\t * to be set on the model.\n\t */\n\tparse: function( resp ) {\n\t\tif ( ! resp ) {\n\t\t\treturn resp;\n\t\t}\n\n\t\tresp.date = new Date( resp.date );\n\t\tresp.modified = new Date( resp.modified );\n\t\treturn resp;\n\t},\n\t/**\n\t * @param {Object} data The properties to be saved.\n\t * @param {Object} options Sync options. e.g. patch, wait, success, error.\n\t *\n\t * @this Backbone.Model\n\t *\n\t * @returns {Promise}\n\t */\n\tsaveCompat: function( data, options ) {\n\t\tvar model = this;\n\n\t\t// If we do not have the necessary nonce, fail immeditately.\n\t\tif ( ! this.get('nonces') || ! this.get('nonces').update ) {\n\t\t\treturn $.Deferred().rejectWith( this ).promise();\n\t\t}\n\n\t\treturn wp.media.post( 'save-attachment-compat', _.defaults({\n\t\t\tid: this.id,\n\t\t\tnonce: this.get('nonces').update,\n\t\t\tpost_id: wp.media.model.settings.post.id\n\t\t}, data ) ).done( function( resp, status, xhr ) {\n\t\t\tmodel.set( model.parse( resp, xhr ), options );\n\t\t});\n\t}\n},/** @lends wp.media.model.Attachment */{\n\t/**\n\t * Create a new model on the static 'all' attachments collection and return it.\n\t *\n\t * @static\n\t *\n\t * @param {Object} attrs\n\t * @returns {wp.media.model.Attachment}\n\t */\n\tcreate: function( attrs ) {\n\t\tvar Attachments = wp.media.model.Attachments;\n\t\treturn Attachments.all.push( attrs );\n\t},\n\t/**\n\t * Create a new model on the static 'all' attachments collection and return it.\n\t *\n\t * If this function has already been called for the id,\n\t * it returns the specified attachment.\n\t *\n\t * @static\n\t * @param {string} id A string used to identify a model.\n\t * @param {Backbone.Model|undefined} attachment\n\t * @returns {wp.media.model.Attachment}\n\t */\n\tget: _.memoize( function( id, attachment ) {\n\t\tvar Attachments = wp.media.model.Attachments;\n\t\treturn Attachments.all.push( attachment || { id: id } );\n\t})\n});\n\nmodule.exports = Attachment;\n\n\n//# sourceURL=webpack:///./src/js/media/models/attachment.js?"); - -/***/ }), - -/***/ "./src/js/media/models/attachments.js": -/*!********************************************!*\ - !*** ./src/js/media/models/attachments.js ***! - \********************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("/**\n * wp.media.model.Attachments\n *\n * A collection of attachments.\n *\n * This collection has no persistence with the server without supplying\n * 'options.props.query = true', which will mirror the collection\n * to an Attachments Query collection - @see wp.media.model.Attachments.mirror().\n *\n * @memberOf wp.media.model\n *\n * @class\n * @augments Backbone.Collection\n *\n * @param {array} [models] Models to initialize with the collection.\n * @param {object} [options] Options hash for the collection.\n * @param {string} [options.props] Options hash for the initial query properties.\n * @param {string} [options.props.order] Initial order (ASC or DESC) for the collection.\n * @param {string} [options.props.orderby] Initial attribute key to order the collection by.\n * @param {string} [options.props.query] Whether the collection is linked to an attachments query.\n * @param {string} [options.observe]\n * @param {string} [options.filters]\n *\n */\nvar Attachments = Backbone.Collection.extend(/** @lends wp.media.model.Attachments.prototype */{\n\t/**\n\t * @type {wp.media.model.Attachment}\n\t */\n\tmodel: wp.media.model.Attachment,\n\t/**\n\t * @param {Array} [models=[]] Array of models used to populate the collection.\n\t * @param {Object} [options={}]\n\t */\n\tinitialize: function( models, options ) {\n\t\toptions = options || {};\n\n\t\tthis.props = new Backbone.Model();\n\t\tthis.filters = options.filters || {};\n\n\t\t// Bind default `change` events to the `props` model.\n\t\tthis.props.on( 'change', this._changeFilteredProps, this );\n\n\t\tthis.props.on( 'change:order', this._changeOrder, this );\n\t\tthis.props.on( 'change:orderby', this._changeOrderby, this );\n\t\tthis.props.on( 'change:query', this._changeQuery, this );\n\n\t\tthis.props.set( _.defaults( options.props || {} ) );\n\n\t\tif ( options.observe ) {\n\t\t\tthis.observe( options.observe );\n\t\t}\n\t},\n\t/**\n\t * Sort the collection when the order attribute changes.\n\t *\n\t * @access private\n\t */\n\t_changeOrder: function() {\n\t\tif ( this.comparator ) {\n\t\t\tthis.sort();\n\t\t}\n\t},\n\t/**\n\t * Set the default comparator only when the `orderby` property is set.\n\t *\n\t * @access private\n\t *\n\t * @param {Backbone.Model} model\n\t * @param {string} orderby\n\t */\n\t_changeOrderby: function( model, orderby ) {\n\t\t// If a different comparator is defined, bail.\n\t\tif ( this.comparator && this.comparator !== Attachments.comparator ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( orderby && 'post__in' !== orderby ) {\n\t\t\tthis.comparator = Attachments.comparator;\n\t\t} else {\n\t\t\tdelete this.comparator;\n\t\t}\n\t},\n\t/**\n\t * If the `query` property is set to true, query the server using\n\t * the `props` values, and sync the results to this collection.\n\t *\n\t * @access private\n\t *\n\t * @param {Backbone.Model} model\n\t * @param {Boolean} query\n\t */\n\t_changeQuery: function( model, query ) {\n\t\tif ( query ) {\n\t\t\tthis.props.on( 'change', this._requery, this );\n\t\t\tthis._requery();\n\t\t} else {\n\t\t\tthis.props.off( 'change', this._requery, this );\n\t\t}\n\t},\n\t/**\n\t * @access private\n\t *\n\t * @param {Backbone.Model} model\n\t */\n\t_changeFilteredProps: function( model ) {\n\t\t// If this is a query, updating the collection will be handled by\n\t\t// `this._requery()`.\n\t\tif ( this.props.get('query') ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar changed = _.chain( model.changed ).map( function( t, prop ) {\n\t\t\tvar filter = Attachments.filters[ prop ],\n\t\t\t\tterm = model.get( prop );\n\n\t\t\tif ( ! filter ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( term && ! this.filters[ prop ] ) {\n\t\t\t\tthis.filters[ prop ] = filter;\n\t\t\t} else if ( ! term && this.filters[ prop ] === filter ) {\n\t\t\t\tdelete this.filters[ prop ];\n\t\t\t} else {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Record the change.\n\t\t\treturn true;\n\t\t}, this ).any().value();\n\n\t\tif ( ! changed ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If no `Attachments` model is provided to source the searches\n\t\t// from, then automatically generate a source from the existing\n\t\t// models.\n\t\tif ( ! this._source ) {\n\t\t\tthis._source = new Attachments( this.models );\n\t\t}\n\n\t\tthis.reset( this._source.filter( this.validator, this ) );\n\t},\n\n\tvalidateDestroyed: false,\n\t/**\n\t * Checks whether an attachment is valid.\n\t *\n\t * @param {wp.media.model.Attachment} attachment\n\t * @returns {Boolean}\n\t */\n\tvalidator: function( attachment ) {\n\n\t\t// Filter out contextually created attachments (e.g. headers, logos, etc.).\n\t\tif (\n\t\t\t! _.isUndefined( attachment.attributes.context ) &&\n\t\t\t'' !== attachment.attributes.context\n\t\t) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( ! this.validateDestroyed && attachment.destroyed ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn _.all( this.filters, function( filter ) {\n\t\t\treturn !! filter.call( this, attachment );\n\t\t}, this );\n\t},\n\t/**\n\t * Add or remove an attachment to the collection depending on its validity.\n\t *\n\t * @param {wp.media.model.Attachment} attachment\n\t * @param {Object} options\n\t * @returns {wp.media.model.Attachments} Returns itself to allow chaining\n\t */\n\tvalidate: function( attachment, options ) {\n\t\tvar valid = this.validator( attachment ),\n\t\t\thasAttachment = !! this.get( attachment.cid );\n\n\t\tif ( ! valid && hasAttachment ) {\n\t\t\tthis.remove( attachment, options );\n\t\t} else if ( valid && ! hasAttachment ) {\n\t\t\tthis.add( attachment, options );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\t/**\n\t * Add or remove all attachments from another collection depending on each one's validity.\n\t *\n\t * @param {wp.media.model.Attachments} attachments\n\t * @param {object} [options={}]\n\t *\n\t * @fires wp.media.model.Attachments#reset\n\t *\n\t * @returns {wp.media.model.Attachments} Returns itself to allow chaining\n\t */\n\tvalidateAll: function( attachments, options ) {\n\t\toptions = options || {};\n\n\t\t_.each( attachments.models, function( attachment ) {\n\t\t\tthis.validate( attachment, { silent: true });\n\t\t}, this );\n\n\t\tif ( ! options.silent ) {\n\t\t\tthis.trigger( 'reset', this, options );\n\t\t}\n\t\treturn this;\n\t},\n\t/**\n\t * Start observing another attachments collection change events\n\t * and replicate them on this collection.\n\t *\n\t * @param {wp.media.model.Attachments} The attachments collection to observe.\n\t * @returns {wp.media.model.Attachments} Returns itself to allow chaining.\n\t */\n\tobserve: function( attachments ) {\n\t\tthis.observers = this.observers || [];\n\t\tthis.observers.push( attachments );\n\n\t\tattachments.on( 'add change remove', this._validateHandler, this );\n\t\tattachments.on( 'reset', this._validateAllHandler, this );\n\t\tthis.validateAll( attachments );\n\t\treturn this;\n\t},\n\t/**\n\t * Stop replicating collection change events from another attachments collection.\n\t *\n\t * @param {wp.media.model.Attachments} The attachments collection to stop observing.\n\t * @returns {wp.media.model.Attachments} Returns itself to allow chaining\n\t */\n\tunobserve: function( attachments ) {\n\t\tif ( attachments ) {\n\t\t\tattachments.off( null, null, this );\n\t\t\tthis.observers = _.without( this.observers, attachments );\n\n\t\t} else {\n\t\t\t_.each( this.observers, function( attachments ) {\n\t\t\t\tattachments.off( null, null, this );\n\t\t\t}, this );\n\t\t\tdelete this.observers;\n\t\t}\n\n\t\treturn this;\n\t},\n\t/**\n\t * @access private\n\t *\n\t * @param {wp.media.model.Attachments} attachment\n\t * @param {wp.media.model.Attachments} attachments\n\t * @param {Object} options\n\t *\n\t * @returns {wp.media.model.Attachments} Returns itself to allow chaining\n\t */\n\t_validateHandler: function( attachment, attachments, options ) {\n\t\t// If we're not mirroring this `attachments` collection,\n\t\t// only retain the `silent` option.\n\t\toptions = attachments === this.mirroring ? options : {\n\t\t\tsilent: options && options.silent\n\t\t};\n\n\t\treturn this.validate( attachment, options );\n\t},\n\t/**\n\t * @access private\n\t *\n\t * @param {wp.media.model.Attachments} attachments\n\t * @param {Object} options\n\t * @returns {wp.media.model.Attachments} Returns itself to allow chaining\n\t */\n\t_validateAllHandler: function( attachments, options ) {\n\t\treturn this.validateAll( attachments, options );\n\t},\n\t/**\n\t * Start mirroring another attachments collection, clearing out any models already\n\t * in the collection.\n\t *\n\t * @param {wp.media.model.Attachments} The attachments collection to mirror.\n\t * @returns {wp.media.model.Attachments} Returns itself to allow chaining\n\t */\n\tmirror: function( attachments ) {\n\t\tif ( this.mirroring && this.mirroring === attachments ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tthis.unmirror();\n\t\tthis.mirroring = attachments;\n\n\t\t// Clear the collection silently. A `reset` event will be fired\n\t\t// when `observe()` calls `validateAll()`.\n\t\tthis.reset( [], { silent: true } );\n\t\tthis.observe( attachments );\n\n\t\treturn this;\n\t},\n\t/**\n\t * Stop mirroring another attachments collection.\n\t */\n\tunmirror: function() {\n\t\tif ( ! this.mirroring ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.unobserve( this.mirroring );\n\t\tdelete this.mirroring;\n\t},\n\t/**\n\t * Retrieve more attachments from the server for the collection.\n\t *\n\t * Only works if the collection is mirroring a Query Attachments collection,\n\t * and forwards to its `more` method. This collection class doesn't have\n\t * server persistence by itself.\n\t *\n\t * @param {object} options\n\t * @returns {Promise}\n\t */\n\tmore: function( options ) {\n\t\tvar deferred = jQuery.Deferred(),\n\t\t\tmirroring = this.mirroring,\n\t\t\tattachments = this;\n\n\t\tif ( ! mirroring || ! mirroring.more ) {\n\t\t\treturn deferred.resolveWith( this ).promise();\n\t\t}\n\t\t// If we're mirroring another collection, forward `more` to\n\t\t// the mirrored collection. Account for a race condition by\n\t\t// checking if we're still mirroring that collection when\n\t\t// the request resolves.\n\t\tmirroring.more( options ).done( function() {\n\t\t\tif ( this === attachments.mirroring ) {\n\t\t\t\tdeferred.resolveWith( this );\n\t\t\t}\n\t\t});\n\n\t\treturn deferred.promise();\n\t},\n\t/**\n\t * Whether there are more attachments that haven't been sync'd from the server\n\t * that match the collection's query.\n\t *\n\t * Only works if the collection is mirroring a Query Attachments collection,\n\t * and forwards to its `hasMore` method. This collection class doesn't have\n\t * server persistence by itself.\n\t *\n\t * @returns {boolean}\n\t */\n\thasMore: function() {\n\t\treturn this.mirroring ? this.mirroring.hasMore() : false;\n\t},\n\t/**\n\t * A custom AJAX-response parser.\n\t *\n\t * See trac ticket #24753\n\t *\n\t * @param {Object|Array} resp The raw response Object/Array.\n\t * @param {Object} xhr\n\t * @returns {Array} The array of model attributes to be added to the collection\n\t */\n\tparse: function( resp, xhr ) {\n\t\tif ( ! _.isArray( resp ) ) {\n\t\t\tresp = [resp];\n\t\t}\n\n\t\treturn _.map( resp, function( attrs ) {\n\t\t\tvar id, attachment, newAttributes;\n\n\t\t\tif ( attrs instanceof Backbone.Model ) {\n\t\t\t\tid = attrs.get( 'id' );\n\t\t\t\tattrs = attrs.attributes;\n\t\t\t} else {\n\t\t\t\tid = attrs.id;\n\t\t\t}\n\n\t\t\tattachment = wp.media.model.Attachment.get( id );\n\t\t\tnewAttributes = attachment.parse( attrs, xhr );\n\n\t\t\tif ( ! _.isEqual( attachment.attributes, newAttributes ) ) {\n\t\t\t\tattachment.set( newAttributes );\n\t\t\t}\n\n\t\t\treturn attachment;\n\t\t});\n\t},\n\t/**\n\t * If the collection is a query, create and mirror an Attachments Query collection.\n\t *\n\t * @access private\n\t */\n\t_requery: function( refresh ) {\n\t\tvar props;\n\t\tif ( this.props.get('query') ) {\n\t\t\tprops = this.props.toJSON();\n\t\t\tprops.cache = ( true !== refresh );\n\t\t\tthis.mirror( wp.media.model.Query.get( props ) );\n\t\t}\n\t},\n\t/**\n\t * If this collection is sorted by `menuOrder`, recalculates and saves\n\t * the menu order to the database.\n\t *\n\t * @returns {undefined|Promise}\n\t */\n\tsaveMenuOrder: function() {\n\t\tif ( 'menuOrder' !== this.props.get('orderby') ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Removes any uploading attachments, updates each attachment's\n\t\t// menu order, and returns an object with an { id: menuOrder }\n\t\t// mapping to pass to the request.\n\t\tvar attachments = this.chain().filter( function( attachment ) {\n\t\t\treturn ! _.isUndefined( attachment.id );\n\t\t}).map( function( attachment, index ) {\n\t\t\t// Indices start at 1.\n\t\t\tindex = index + 1;\n\t\t\tattachment.set( 'menuOrder', index );\n\t\t\treturn [ attachment.id, index ];\n\t\t}).object().value();\n\n\t\tif ( _.isEmpty( attachments ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\treturn wp.media.post( 'save-attachment-order', {\n\t\t\tnonce: wp.media.model.settings.post.nonce,\n\t\t\tpost_id: wp.media.model.settings.post.id,\n\t\t\tattachments: attachments\n\t\t});\n\t}\n},/** @lends wp.media.model.Attachments */{\n\t/**\n\t * A function to compare two attachment models in an attachments collection.\n\t *\n\t * Used as the default comparator for instances of wp.media.model.Attachments\n\t * and its subclasses. @see wp.media.model.Attachments._changeOrderby().\n\t *\n\t * @param {Backbone.Model} a\n\t * @param {Backbone.Model} b\n\t * @param {Object} options\n\t * @returns {Number} -1 if the first model should come before the second,\n\t * 0 if they are of the same rank and\n\t * 1 if the first model should come after.\n\t */\n\tcomparator: function( a, b, options ) {\n\t\tvar key = this.props.get('orderby'),\n\t\t\torder = this.props.get('order') || 'DESC',\n\t\t\tac = a.cid,\n\t\t\tbc = b.cid;\n\n\t\ta = a.get( key );\n\t\tb = b.get( key );\n\n\t\tif ( 'date' === key || 'modified' === key ) {\n\t\t\ta = a || new Date();\n\t\t\tb = b || new Date();\n\t\t}\n\n\t\t// If `options.ties` is set, don't enforce the `cid` tiebreaker.\n\t\tif ( options && options.ties ) {\n\t\t\tac = bc = null;\n\t\t}\n\n\t\treturn ( 'DESC' === order ) ? wp.media.compare( a, b, ac, bc ) : wp.media.compare( b, a, bc, ac );\n\t},\n\t/** @namespace wp.media.model.Attachments.filters */\n\tfilters: {\n\t\t/**\n\t\t * @static\n\t\t * Note that this client-side searching is *not* equivalent\n\t\t * to our server-side searching.\n\t\t *\n\t\t * @param {wp.media.model.Attachment} attachment\n\t\t *\n\t\t * @this wp.media.model.Attachments\n\t\t *\n\t\t * @returns {Boolean}\n\t\t */\n\t\tsearch: function( attachment ) {\n\t\t\tif ( ! this.props.get('search') ) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn _.any(['title','filename','description','caption','name'], function( key ) {\n\t\t\t\tvar value = attachment.get( key );\n\t\t\t\treturn value && -1 !== value.search( this.props.get('search') );\n\t\t\t}, this );\n\t\t},\n\t\t/**\n\t\t * @static\n\t\t * @param {wp.media.model.Attachment} attachment\n\t\t *\n\t\t * @this wp.media.model.Attachments\n\t\t *\n\t\t * @returns {Boolean}\n\t\t */\n\t\ttype: function( attachment ) {\n\t\t\tvar type = this.props.get('type'), atts = attachment.toJSON(), mime, found;\n\n\t\t\tif ( ! type || ( _.isArray( type ) && ! type.length ) ) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tmime = atts.mime || ( atts.file && atts.file.type ) || '';\n\n\t\t\tif ( _.isArray( type ) ) {\n\t\t\t\tfound = _.find( type, function (t) {\n\t\t\t\t\treturn -1 !== mime.indexOf( t );\n\t\t\t\t} );\n\t\t\t} else {\n\t\t\t\tfound = -1 !== mime.indexOf( type );\n\t\t\t}\n\n\t\t\treturn found;\n\t\t},\n\t\t/**\n\t\t * @static\n\t\t * @param {wp.media.model.Attachment} attachment\n\t\t *\n\t\t * @this wp.media.model.Attachments\n\t\t *\n\t\t * @returns {Boolean}\n\t\t */\n\t\tuploadedTo: function( attachment ) {\n\t\t\tvar uploadedTo = this.props.get('uploadedTo');\n\t\t\tif ( _.isUndefined( uploadedTo ) ) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn uploadedTo === attachment.get('uploadedTo');\n\t\t},\n\t\t/**\n\t\t * @static\n\t\t * @param {wp.media.model.Attachment} attachment\n\t\t *\n\t\t * @this wp.media.model.Attachments\n\t\t *\n\t\t * @returns {Boolean}\n\t\t */\n\t\tstatus: function( attachment ) {\n\t\t\tvar status = this.props.get('status');\n\t\t\tif ( _.isUndefined( status ) ) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn status === attachment.get('status');\n\t\t}\n\t}\n});\n\nmodule.exports = Attachments;\n\n\n//# sourceURL=webpack:///./src/js/media/models/attachments.js?"); - -/***/ }), - -/***/ "./src/js/media/models/post-image.js": -/*!*******************************************!*\ - !*** ./src/js/media/models/post-image.js ***! - \*******************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("/**\n * wp.media.model.PostImage\n *\n * An instance of an image that's been embedded into a post.\n *\n * Used in the embedded image attachment display settings modal - @see wp.media.view.MediaFrame.ImageDetails.\n *\n * @memberOf wp.media.model\n *\n * @class\n * @augments Backbone.Model\n *\n * @param {int} [attributes] Initial model attributes.\n * @param {int} [attributes.attachment_id] ID of the attachment.\n **/\nvar PostImage = Backbone.Model.extend(/** @lends wp.media.model.PostImage.prototype */{\n\n\tinitialize: function( attributes ) {\n\t\tvar Attachment = wp.media.model.Attachment;\n\t\tthis.attachment = false;\n\n\t\tif ( attributes.attachment_id ) {\n\t\t\tthis.attachment = Attachment.get( attributes.attachment_id );\n\t\t\tif ( this.attachment.get( 'url' ) ) {\n\t\t\t\tthis.dfd = jQuery.Deferred();\n\t\t\t\tthis.dfd.resolve();\n\t\t\t} else {\n\t\t\t\tthis.dfd = this.attachment.fetch();\n\t\t\t}\n\t\t\tthis.bindAttachmentListeners();\n\t\t}\n\n\t\t// keep url in sync with changes to the type of link\n\t\tthis.on( 'change:link', this.updateLinkUrl, this );\n\t\tthis.on( 'change:size', this.updateSize, this );\n\n\t\tthis.setLinkTypeFromUrl();\n\t\tthis.setAspectRatio();\n\n\t\tthis.set( 'originalUrl', attributes.url );\n\t},\n\n\tbindAttachmentListeners: function() {\n\t\tthis.listenTo( this.attachment, 'sync', this.setLinkTypeFromUrl );\n\t\tthis.listenTo( this.attachment, 'sync', this.setAspectRatio );\n\t\tthis.listenTo( this.attachment, 'change', this.updateSize );\n\t},\n\n\tchangeAttachment: function( attachment, props ) {\n\t\tthis.stopListening( this.attachment );\n\t\tthis.attachment = attachment;\n\t\tthis.bindAttachmentListeners();\n\n\t\tthis.set( 'attachment_id', this.attachment.get( 'id' ) );\n\t\tthis.set( 'caption', this.attachment.get( 'caption' ) );\n\t\tthis.set( 'alt', this.attachment.get( 'alt' ) );\n\t\tthis.set( 'size', props.get( 'size' ) );\n\t\tthis.set( 'align', props.get( 'align' ) );\n\t\tthis.set( 'link', props.get( 'link' ) );\n\t\tthis.updateLinkUrl();\n\t\tthis.updateSize();\n\t},\n\n\tsetLinkTypeFromUrl: function() {\n\t\tvar linkUrl = this.get( 'linkUrl' ),\n\t\t\ttype;\n\n\t\tif ( ! linkUrl ) {\n\t\t\tthis.set( 'link', 'none' );\n\t\t\treturn;\n\t\t}\n\n\t\t// default to custom if there is a linkUrl\n\t\ttype = 'custom';\n\n\t\tif ( this.attachment ) {\n\t\t\tif ( this.attachment.get( 'url' ) === linkUrl ) {\n\t\t\t\ttype = 'file';\n\t\t\t} else if ( this.attachment.get( 'link' ) === linkUrl ) {\n\t\t\t\ttype = 'post';\n\t\t\t}\n\t\t} else {\n\t\t\tif ( this.get( 'url' ) === linkUrl ) {\n\t\t\t\ttype = 'file';\n\t\t\t}\n\t\t}\n\n\t\tthis.set( 'link', type );\n\t},\n\n\tupdateLinkUrl: function() {\n\t\tvar link = this.get( 'link' ),\n\t\t\turl;\n\n\t\tswitch( link ) {\n\t\t\tcase 'file':\n\t\t\t\tif ( this.attachment ) {\n\t\t\t\t\turl = this.attachment.get( 'url' );\n\t\t\t\t} else {\n\t\t\t\t\turl = this.get( 'url' );\n\t\t\t\t}\n\t\t\t\tthis.set( 'linkUrl', url );\n\t\t\t\tbreak;\n\t\t\tcase 'post':\n\t\t\t\tthis.set( 'linkUrl', this.attachment.get( 'link' ) );\n\t\t\t\tbreak;\n\t\t\tcase 'none':\n\t\t\t\tthis.set( 'linkUrl', '' );\n\t\t\t\tbreak;\n\t\t}\n\t},\n\n\tupdateSize: function() {\n\t\tvar size;\n\n\t\tif ( ! this.attachment ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( this.get( 'size' ) === 'custom' ) {\n\t\t\tthis.set( 'width', this.get( 'customWidth' ) );\n\t\t\tthis.set( 'height', this.get( 'customHeight' ) );\n\t\t\tthis.set( 'url', this.get( 'originalUrl' ) );\n\t\t\treturn;\n\t\t}\n\n\t\tsize = this.attachment.get( 'sizes' )[ this.get( 'size' ) ];\n\n\t\tif ( ! size ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.set( 'url', size.url );\n\t\tthis.set( 'width', size.width );\n\t\tthis.set( 'height', size.height );\n\t},\n\n\tsetAspectRatio: function() {\n\t\tvar full;\n\n\t\tif ( this.attachment && this.attachment.get( 'sizes' ) ) {\n\t\t\tfull = this.attachment.get( 'sizes' ).full;\n\n\t\t\tif ( full ) {\n\t\t\t\tthis.set( 'aspectRatio', full.width / full.height );\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tthis.set( 'aspectRatio', this.get( 'customWidth' ) / this.get( 'customHeight' ) );\n\t}\n});\n\nmodule.exports = PostImage;\n\n\n//# sourceURL=webpack:///./src/js/media/models/post-image.js?"); - -/***/ }), - -/***/ "./src/js/media/models/query.js": -/*!**************************************!*\ - !*** ./src/js/media/models/query.js ***! - \**************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("var Attachments = wp.media.model.Attachments,\n\tQuery;\n\n/**\n * wp.media.model.Query\n *\n * A collection of attachments that match the supplied query arguments.\n *\n * Note: Do NOT change this.args after the query has been initialized.\n * Things will break.\n *\n * @memberOf wp.media.model\n *\n * @class\n * @augments wp.media.model.Attachments\n * @augments Backbone.Collection\n *\n * @param {array} [models] Models to initialize with the collection.\n * @param {object} [options] Options hash.\n * @param {object} [options.args] Attachments query arguments.\n * @param {object} [options.args.posts_per_page]\n */\nQuery = Attachments.extend(/** @lends wp.media.model.Query.prototype */{\n\t/**\n\t * @param {array} [models=[]] Array of initial models to populate the collection.\n\t * @param {object} [options={}]\n\t */\n\tinitialize: function( models, options ) {\n\t\tvar allowed;\n\n\t\toptions = options || {};\n\t\tAttachments.prototype.initialize.apply( this, arguments );\n\n\t\tthis.args = options.args;\n\t\tthis._hasMore = true;\n\t\tthis.created = new Date();\n\n\t\tthis.filters.order = function( attachment ) {\n\t\t\tvar orderby = this.props.get('orderby'),\n\t\t\t\torder = this.props.get('order');\n\n\t\t\tif ( ! this.comparator ) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t// We want any items that can be placed before the last\n\t\t\t// item in the set. If we add any items after the last\n\t\t\t// item, then we can't guarantee the set is complete.\n\t\t\tif ( this.length ) {\n\t\t\t\treturn 1 !== this.comparator( attachment, this.last(), { ties: true });\n\n\t\t\t// Handle the case where there are no items yet and\n\t\t\t// we're sorting for recent items. In that case, we want\n\t\t\t// changes that occurred after we created the query.\n\t\t\t} else if ( 'DESC' === order && ( 'date' === orderby || 'modified' === orderby ) ) {\n\t\t\t\treturn attachment.get( orderby ) >= this.created;\n\n\t\t\t// If we're sorting by menu order and we have no items,\n\t\t\t// accept any items that have the default menu order (0).\n\t\t\t} else if ( 'ASC' === order && 'menuOrder' === orderby ) {\n\t\t\t\treturn attachment.get( orderby ) === 0;\n\t\t\t}\n\n\t\t\t// Otherwise, we don't want any items yet.\n\t\t\treturn false;\n\t\t};\n\n\t\t// Observe the central `wp.Uploader.queue` collection to watch for\n\t\t// new matches for the query.\n\t\t//\n\t\t// Only observe when a limited number of query args are set. There\n\t\t// are no filters for other properties, so observing will result in\n\t\t// false positives in those queries.\n\t\tallowed = [ 's', 'order', 'orderby', 'posts_per_page', 'post_mime_type', 'post_parent', 'author' ];\n\t\tif ( wp.Uploader && _( this.args ).chain().keys().difference( allowed ).isEmpty().value() ) {\n\t\t\tthis.observe( wp.Uploader.queue );\n\t\t}\n\t},\n\t/**\n\t * Whether there are more attachments that haven't been sync'd from the server\n\t * that match the collection's query.\n\t *\n\t * @returns {boolean}\n\t */\n\thasMore: function() {\n\t\treturn this._hasMore;\n\t},\n\t/**\n\t * Fetch more attachments from the server for the collection.\n\t *\n\t * @param {object} [options={}]\n\t * @returns {Promise}\n\t */\n\tmore: function( options ) {\n\t\tvar query = this;\n\n\t\t// If there is already a request pending, return early with the Deferred object.\n\t\tif ( this._more && 'pending' === this._more.state() ) {\n\t\t\treturn this._more;\n\t\t}\n\n\t\tif ( ! this.hasMore() ) {\n\t\t\treturn jQuery.Deferred().resolveWith( this ).promise();\n\t\t}\n\n\t\toptions = options || {};\n\t\toptions.remove = false;\n\n\t\treturn this._more = this.fetch( options ).done( function( resp ) {\n\t\t\tif ( _.isEmpty( resp ) || -1 === this.args.posts_per_page || resp.length < this.args.posts_per_page ) {\n\t\t\t\tquery._hasMore = false;\n\t\t\t}\n\t\t});\n\t},\n\t/**\n\t * Overrides Backbone.Collection.sync\n\t * Overrides wp.media.model.Attachments.sync\n\t *\n\t * @param {String} method\n\t * @param {Backbone.Model} model\n\t * @param {Object} [options={}]\n\t * @returns {Promise}\n\t */\n\tsync: function( method, model, options ) {\n\t\tvar args, fallback;\n\n\t\t// Overload the read method so Attachment.fetch() functions correctly.\n\t\tif ( 'read' === method ) {\n\t\t\toptions = options || {};\n\t\t\toptions.context = this;\n\t\t\toptions.data = _.extend( options.data || {}, {\n\t\t\t\taction: 'query-attachments',\n\t\t\t\tpost_id: wp.media.model.settings.post.id\n\t\t\t});\n\n\t\t\t// Clone the args so manipulation is non-destructive.\n\t\t\targs = _.clone( this.args );\n\n\t\t\t// Determine which page to query.\n\t\t\tif ( -1 !== args.posts_per_page ) {\n\t\t\t\targs.paged = Math.round( this.length / args.posts_per_page ) + 1;\n\t\t\t}\n\n\t\t\toptions.data.query = args;\n\t\t\treturn wp.media.ajax( options );\n\n\t\t// Otherwise, fall back to Backbone.sync()\n\t\t} else {\n\t\t\t/**\n\t\t\t * Call wp.media.model.Attachments.sync or Backbone.sync\n\t\t\t */\n\t\t\tfallback = Attachments.prototype.sync ? Attachments.prototype : Backbone;\n\t\t\treturn fallback.sync.apply( this, arguments );\n\t\t}\n\t}\n}, /** @lends wp.media.model.Query */{\n\t/**\n\t * @readonly\n\t */\n\tdefaultProps: {\n\t\torderby: 'date',\n\t\torder: 'DESC'\n\t},\n\t/**\n\t * @readonly\n\t */\n\tdefaultArgs: {\n\t\tposts_per_page: 40\n\t},\n\t/**\n\t * @readonly\n\t */\n\torderby: {\n\t\tallowed: [ 'name', 'author', 'date', 'title', 'modified', 'uploadedTo', 'id', 'post__in', 'menuOrder' ],\n\t\t/**\n\t\t * A map of JavaScript orderby values to their WP_Query equivalents.\n\t\t * @type {Object}\n\t\t */\n\t\tvaluemap: {\n\t\t\t'id': 'ID',\n\t\t\t'uploadedTo': 'parent',\n\t\t\t'menuOrder': 'menu_order ID'\n\t\t}\n\t},\n\t/**\n\t * A map of JavaScript query properties to their WP_Query equivalents.\n\t *\n\t * @readonly\n\t */\n\tpropmap: {\n\t\t'search':\t\t's',\n\t\t'type':\t\t\t'post_mime_type',\n\t\t'perPage':\t\t'posts_per_page',\n\t\t'menuOrder':\t'menu_order',\n\t\t'uploadedTo':\t'post_parent',\n\t\t'status':\t\t'post_status',\n\t\t'include':\t\t'post__in',\n\t\t'exclude':\t\t'post__not_in',\n\t\t'author':\t\t'author'\n\t},\n\t/**\n\t * Creates and returns an Attachments Query collection given the properties.\n\t *\n\t * Caches query objects and reuses where possible.\n\t *\n\t * @static\n\t * @method\n\t *\n\t * @param {object} [props]\n\t * @param {Object} [props.cache=true] Whether to use the query cache or not.\n\t * @param {Object} [props.order]\n\t * @param {Object} [props.orderby]\n\t * @param {Object} [props.include]\n\t * @param {Object} [props.exclude]\n\t * @param {Object} [props.s]\n\t * @param {Object} [props.post_mime_type]\n\t * @param {Object} [props.posts_per_page]\n\t * @param {Object} [props.menu_order]\n\t * @param {Object} [props.post_parent]\n\t * @param {Object} [props.post_status]\n\t * @param {Object} [props.author]\n\t * @param {Object} [options]\n\t *\n\t * @returns {wp.media.model.Query} A new Attachments Query collection.\n\t */\n\tget: (function(){\n\t\t/**\n\t\t * @static\n\t\t * @type Array\n\t\t */\n\t\tvar queries = [];\n\n\t\t/**\n\t\t * @returns {Query}\n\t\t */\n\t\treturn function( props, options ) {\n\t\t\tvar args = {},\n\t\t\t\torderby = Query.orderby,\n\t\t\t\tdefaults = Query.defaultProps,\n\t\t\t\tquery,\n\t\t\t\tcache = !! props.cache || _.isUndefined( props.cache );\n\n\t\t\t// Remove the `query` property. This isn't linked to a query,\n\t\t\t// this *is* the query.\n\t\t\tdelete props.query;\n\t\t\tdelete props.cache;\n\n\t\t\t// Fill default args.\n\t\t\t_.defaults( props, defaults );\n\n\t\t\t// Normalize the order.\n\t\t\tprops.order = props.order.toUpperCase();\n\t\t\tif ( 'DESC' !== props.order && 'ASC' !== props.order ) {\n\t\t\t\tprops.order = defaults.order.toUpperCase();\n\t\t\t}\n\n\t\t\t// Ensure we have a valid orderby value.\n\t\t\tif ( ! _.contains( orderby.allowed, props.orderby ) ) {\n\t\t\t\tprops.orderby = defaults.orderby;\n\t\t\t}\n\n\t\t\t_.each( [ 'include', 'exclude' ], function( prop ) {\n\t\t\t\tif ( props[ prop ] && ! _.isArray( props[ prop ] ) ) {\n\t\t\t\t\tprops[ prop ] = [ props[ prop ] ];\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\t// Generate the query `args` object.\n\t\t\t// Correct any differing property names.\n\t\t\t_.each( props, function( value, prop ) {\n\t\t\t\tif ( _.isNull( value ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\targs[ Query.propmap[ prop ] || prop ] = value;\n\t\t\t});\n\n\t\t\t// Fill any other default query args.\n\t\t\t_.defaults( args, Query.defaultArgs );\n\n\t\t\t// `props.orderby` does not always map directly to `args.orderby`.\n\t\t\t// Substitute exceptions specified in orderby.keymap.\n\t\t\targs.orderby = orderby.valuemap[ props.orderby ] || props.orderby;\n\n\t\t\t// Search the query cache for a matching query.\n\t\t\tif ( cache ) {\n\t\t\t\tquery = _.find( queries, function( query ) {\n\t\t\t\t\treturn _.isEqual( query.args, args );\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tqueries = [];\n\t\t\t}\n\n\t\t\t// Otherwise, create a new query and add it to the cache.\n\t\t\tif ( ! query ) {\n\t\t\t\tquery = new Query( [], _.extend( options || {}, {\n\t\t\t\t\tprops: props,\n\t\t\t\t\targs: args\n\t\t\t\t} ) );\n\t\t\t\tqueries.push( query );\n\t\t\t}\n\n\t\t\treturn query;\n\t\t};\n\t}())\n});\n\nmodule.exports = Query;\n\n\n//# sourceURL=webpack:///./src/js/media/models/query.js?"); - -/***/ }), - -/***/ "./src/js/media/models/selection.js": -/*!******************************************!*\ - !*** ./src/js/media/models/selection.js ***! - \******************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("var Attachments = wp.media.model.Attachments,\n\tSelection;\n\n/**\n * wp.media.model.Selection\n *\n * A selection of attachments.\n *\n * @memberOf wp.media.model\n *\n * @class\n * @augments wp.media.model.Attachments\n * @augments Backbone.Collection\n */\nSelection = Attachments.extend(/** @lends wp.media.model.Selection.prototype */{\n\t/**\n\t * Refresh the `single` model whenever the selection changes.\n\t * Binds `single` instead of using the context argument to ensure\n\t * it receives no parameters.\n\t *\n\t * @param {Array} [models=[]] Array of models used to populate the collection.\n\t * @param {Object} [options={}]\n\t */\n\tinitialize: function( models, options ) {\n\t\t/**\n\t\t * call 'initialize' directly on the parent class\n\t\t */\n\t\tAttachments.prototype.initialize.apply( this, arguments );\n\t\tthis.multiple = options && options.multiple;\n\n\t\tthis.on( 'add remove reset', _.bind( this.single, this, false ) );\n\t},\n\n\t/**\n\t * If the workflow does not support multi-select, clear out the selection\n\t * before adding a new attachment to it.\n\t *\n\t * @param {Array} models\n\t * @param {Object} options\n\t * @returns {wp.media.model.Attachment[]}\n\t */\n\tadd: function( models, options ) {\n\t\tif ( ! this.multiple ) {\n\t\t\tthis.remove( this.models );\n\t\t}\n\t\t/**\n\t\t * call 'add' directly on the parent class\n\t\t */\n\t\treturn Attachments.prototype.add.call( this, models, options );\n\t},\n\n\t/**\n\t * Fired when toggling (clicking on) an attachment in the modal.\n\t *\n\t * @param {undefined|boolean|wp.media.model.Attachment} model\n\t *\n\t * @fires wp.media.model.Selection#selection:single\n\t * @fires wp.media.model.Selection#selection:unsingle\n\t *\n\t * @returns {Backbone.Model}\n\t */\n\tsingle: function( model ) {\n\t\tvar previous = this._single;\n\n\t\t// If a `model` is provided, use it as the single model.\n\t\tif ( model ) {\n\t\t\tthis._single = model;\n\t\t}\n\t\t// If the single model isn't in the selection, remove it.\n\t\tif ( this._single && ! this.get( this._single.cid ) ) {\n\t\t\tdelete this._single;\n\t\t}\n\n\t\tthis._single = this._single || this.last();\n\n\t\t// If single has changed, fire an event.\n\t\tif ( this._single !== previous ) {\n\t\t\tif ( previous ) {\n\t\t\t\tprevious.trigger( 'selection:unsingle', previous, this );\n\n\t\t\t\t// If the model was already removed, trigger the collection\n\t\t\t\t// event manually.\n\t\t\t\tif ( ! this.get( previous.cid ) ) {\n\t\t\t\t\tthis.trigger( 'selection:unsingle', previous, this );\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( this._single ) {\n\t\t\t\tthis._single.trigger( 'selection:single', this._single, this );\n\t\t\t}\n\t\t}\n\n\t\t// Return the single model, or the last model as a fallback.\n\t\treturn this._single;\n\t}\n});\n\nmodule.exports = Selection;\n\n\n//# sourceURL=webpack:///./src/js/media/models/selection.js?"); - -/***/ }), - -/***/ 2: -/*!***************************************************!*\ - !*** multi ./src/js/_enqueues/wp/media/models.js ***! - \***************************************************/ -/*! no static exports found */ +/***/ 23: /***/ (function(module, exports, __webpack_require__) { -eval("module.exports = __webpack_require__(/*! ./src/js/_enqueues/wp/media/models.js */\"./src/js/_enqueues/wp/media/models.js\");\n\n\n//# sourceURL=webpack:///multi_./src/js/_enqueues/wp/media/models.js?"); +/** + * @output wp-includes/js/media-models.js + */ + +var $ = jQuery, + Attachment, Attachments, l10n, media; + +/** @namespace wp */ +window.wp = window.wp || {}; + +/** + * Create and return a media frame. + * + * Handles the default media experience. + * + * @alias wp.media + * @memberOf wp + * @namespace + * + * @param {object} attributes The properties passed to the main media controller. + * @return {wp.media.view.MediaFrame} A media workflow. + */ +media = wp.media = function( attributes ) { + var MediaFrame = media.view.MediaFrame, + frame; + + if ( ! MediaFrame ) { + return; + } + + attributes = _.defaults( attributes || {}, { + frame: 'select' + }); + + if ( 'select' === attributes.frame && MediaFrame.Select ) { + frame = new MediaFrame.Select( attributes ); + } else if ( 'post' === attributes.frame && MediaFrame.Post ) { + frame = new MediaFrame.Post( attributes ); + } else if ( 'manage' === attributes.frame && MediaFrame.Manage ) { + frame = new MediaFrame.Manage( attributes ); + } else if ( 'image' === attributes.frame && MediaFrame.ImageDetails ) { + frame = new MediaFrame.ImageDetails( attributes ); + } else if ( 'audio' === attributes.frame && MediaFrame.AudioDetails ) { + frame = new MediaFrame.AudioDetails( attributes ); + } else if ( 'video' === attributes.frame && MediaFrame.VideoDetails ) { + frame = new MediaFrame.VideoDetails( attributes ); + } else if ( 'edit-attachments' === attributes.frame && MediaFrame.EditAttachments ) { + frame = new MediaFrame.EditAttachments( attributes ); + } + + delete attributes.frame; + + media.frame = frame; + + return frame; +}; + +/** @namespace wp.media.model */ +/** @namespace wp.media.view */ +/** @namespace wp.media.controller */ +/** @namespace wp.media.frames */ +_.extend( media, { model: {}, view: {}, controller: {}, frames: {} }); + +// Link any localized strings. +l10n = media.model.l10n = window._wpMediaModelsL10n || {}; + +// Link any settings. +media.model.settings = l10n.settings || {}; +delete l10n.settings; + +Attachment = media.model.Attachment = __webpack_require__( 24 ); +Attachments = media.model.Attachments = __webpack_require__( 25 ); + +media.model.Query = __webpack_require__( 26 ); +media.model.PostImage = __webpack_require__( 27 ); +media.model.Selection = __webpack_require__( 28 ); + +/** + * ======================================================================== + * UTILITIES + * ======================================================================== + */ + +/** + * A basic equality comparator for Backbone models. + * + * Used to order models within a collection - @see wp.media.model.Attachments.comparator(). + * + * @param {mixed} a The primary parameter to compare. + * @param {mixed} b The primary parameter to compare. + * @param {string} ac The fallback parameter to compare, a's cid. + * @param {string} bc The fallback parameter to compare, b's cid. + * @return {number} -1: a should come before b. + * 0: a and b are of the same rank. + * 1: b should come before a. + */ +media.compare = function( a, b, ac, bc ) { + if ( _.isEqual( a, b ) ) { + return ac === bc ? 0 : (ac > bc ? -1 : 1); + } else { + return a > b ? -1 : 1; + } +}; + +_.extend( media, /** @lends wp.media */{ + /** + * media.template( id ) + * + * Fetch a JavaScript template for an id, and return a templating function for it. + * + * See wp.template() in `wp-includes/js/wp-util.js`. + * + * @borrows wp.template as template + */ + template: wp.template, + + /** + * media.post( [action], [data] ) + * + * Sends a POST request to WordPress. + * See wp.ajax.post() in `wp-includes/js/wp-util.js`. + * + * @borrows wp.ajax.post as post + */ + post: wp.ajax.post, + + /** + * media.ajax( [action], [options] ) + * + * Sends an XHR request to WordPress. + * See wp.ajax.send() in `wp-includes/js/wp-util.js`. + * + * @borrows wp.ajax.send as ajax + */ + ajax: wp.ajax.send, + + /** + * Scales a set of dimensions to fit within bounding dimensions. + * + * @param {Object} dimensions + * @returns {Object} + */ + fit: function( dimensions ) { + var width = dimensions.width, + height = dimensions.height, + maxWidth = dimensions.maxWidth, + maxHeight = dimensions.maxHeight, + constraint; + + // Compare ratios between the two values to determine which + // max to constrain by. If a max value doesn't exist, then the + // opposite side is the constraint. + if ( ! _.isUndefined( maxWidth ) && ! _.isUndefined( maxHeight ) ) { + constraint = ( width / height > maxWidth / maxHeight ) ? 'width' : 'height'; + } else if ( _.isUndefined( maxHeight ) ) { + constraint = 'width'; + } else if ( _.isUndefined( maxWidth ) && height > maxHeight ) { + constraint = 'height'; + } + + // If the value of the constrained side is larger than the max, + // then scale the values. Otherwise return the originals; they fit. + if ( 'width' === constraint && width > maxWidth ) { + return { + width : maxWidth, + height: Math.round( maxWidth * height / width ) + }; + } else if ( 'height' === constraint && height > maxHeight ) { + return { + width : Math.round( maxHeight * width / height ), + height: maxHeight + }; + } else { + return { + width : width, + height: height + }; + } + }, + /** + * Truncates a string by injecting an ellipsis into the middle. + * Useful for filenames. + * + * @param {String} string + * @param {Number} [length=30] + * @param {String} [replacement=…] + * @returns {String} The string, unless length is greater than string.length. + */ + truncate: function( string, length, replacement ) { + length = length || 30; + replacement = replacement || '…'; + + if ( string.length <= length ) { + return string; + } + + return string.substr( 0, length / 2 ) + replacement + string.substr( -1 * length / 2 ); + } +}); + +/** + * ======================================================================== + * MODELS + * ======================================================================== + */ +/** + * wp.media.attachment + * + * @static + * @param {String} id A string used to identify a model. + * @returns {wp.media.model.Attachment} + */ +media.attachment = function( id ) { + return Attachment.get( id ); +}; + +/** + * A collection of all attachments that have been fetched from the server. + * + * @static + * @member {wp.media.model.Attachments} + */ +Attachments.all = new Attachments(); + +/** + * wp.media.query + * + * Shorthand for creating a new Attachments Query. + * + * @param {object} [props] + * @returns {wp.media.model.Attachments} + */ +media.query = function( props ) { + return new Attachments( null, { + props: _.extend( _.defaults( props || {}, { orderby: 'date' } ), { query: true } ) + }); +}; + +// Clean up. Prevents mobile browsers caching +$(window).on('unload', function(){ + window.wp = null; +}); + + +/***/ }), + +/***/ 24: +/***/ (function(module, exports) { + +var $ = Backbone.$, + Attachment; + +/** + * wp.media.model.Attachment + * + * @memberOf wp.media.model + * + * @class + * @augments Backbone.Model + */ +Attachment = Backbone.Model.extend(/** @lends wp.media.model.Attachment.prototype */{ + /** + * Triggered when attachment details change + * Overrides Backbone.Model.sync + * + * @param {string} method + * @param {wp.media.model.Attachment} model + * @param {Object} [options={}] + * + * @returns {Promise} + */ + sync: function( method, model, options ) { + // If the attachment does not yet have an `id`, return an instantly + // rejected promise. Otherwise, all of our requests will fail. + if ( _.isUndefined( this.id ) ) { + return $.Deferred().rejectWith( this ).promise(); + } + + // Overload the `read` request so Attachment.fetch() functions correctly. + if ( 'read' === method ) { + options = options || {}; + options.context = this; + options.data = _.extend( options.data || {}, { + action: 'get-attachment', + id: this.id + }); + return wp.media.ajax( options ); + + // Overload the `update` request so properties can be saved. + } else if ( 'update' === method ) { + // If we do not have the necessary nonce, fail immeditately. + if ( ! this.get('nonces') || ! this.get('nonces').update ) { + return $.Deferred().rejectWith( this ).promise(); + } + + options = options || {}; + options.context = this; + + // Set the action and ID. + options.data = _.extend( options.data || {}, { + action: 'save-attachment', + id: this.id, + nonce: this.get('nonces').update, + post_id: wp.media.model.settings.post.id + }); + + // Record the values of the changed attributes. + if ( model.hasChanged() ) { + options.data.changes = {}; + + _.each( model.changed, function( value, key ) { + options.data.changes[ key ] = this.get( key ); + }, this ); + } + + return wp.media.ajax( options ); + + // Overload the `delete` request so attachments can be removed. + // This will permanently delete an attachment. + } else if ( 'delete' === method ) { + options = options || {}; + + if ( ! options.wait ) { + this.destroyed = true; + } + + options.context = this; + options.data = _.extend( options.data || {}, { + action: 'delete-post', + id: this.id, + _wpnonce: this.get('nonces')['delete'] + }); + + return wp.media.ajax( options ).done( function() { + this.destroyed = true; + }).fail( function() { + this.destroyed = false; + }); + + // Otherwise, fall back to `Backbone.sync()`. + } else { + /** + * Call `sync` directly on Backbone.Model + */ + return Backbone.Model.prototype.sync.apply( this, arguments ); + } + }, + /** + * Convert date strings into Date objects. + * + * @param {Object} resp The raw response object, typically returned by fetch() + * @returns {Object} The modified response object, which is the attributes hash + * to be set on the model. + */ + parse: function( resp ) { + if ( ! resp ) { + return resp; + } + + resp.date = new Date( resp.date ); + resp.modified = new Date( resp.modified ); + return resp; + }, + /** + * @param {Object} data The properties to be saved. + * @param {Object} options Sync options. e.g. patch, wait, success, error. + * + * @this Backbone.Model + * + * @returns {Promise} + */ + saveCompat: function( data, options ) { + var model = this; + + // If we do not have the necessary nonce, fail immeditately. + if ( ! this.get('nonces') || ! this.get('nonces').update ) { + return $.Deferred().rejectWith( this ).promise(); + } + + return wp.media.post( 'save-attachment-compat', _.defaults({ + id: this.id, + nonce: this.get('nonces').update, + post_id: wp.media.model.settings.post.id + }, data ) ).done( function( resp, status, xhr ) { + model.set( model.parse( resp, xhr ), options ); + }); + } +},/** @lends wp.media.model.Attachment */{ + /** + * Create a new model on the static 'all' attachments collection and return it. + * + * @static + * + * @param {Object} attrs + * @returns {wp.media.model.Attachment} + */ + create: function( attrs ) { + var Attachments = wp.media.model.Attachments; + return Attachments.all.push( attrs ); + }, + /** + * Create a new model on the static 'all' attachments collection and return it. + * + * If this function has already been called for the id, + * it returns the specified attachment. + * + * @static + * @param {string} id A string used to identify a model. + * @param {Backbone.Model|undefined} attachment + * @returns {wp.media.model.Attachment} + */ + get: _.memoize( function( id, attachment ) { + var Attachments = wp.media.model.Attachments; + return Attachments.all.push( attachment || { id: id } ); + }) +}); + +module.exports = Attachment; + + +/***/ }), + +/***/ 25: +/***/ (function(module, exports) { + +/** + * wp.media.model.Attachments + * + * A collection of attachments. + * + * This collection has no persistence with the server without supplying + * 'options.props.query = true', which will mirror the collection + * to an Attachments Query collection - @see wp.media.model.Attachments.mirror(). + * + * @memberOf wp.media.model + * + * @class + * @augments Backbone.Collection + * + * @param {array} [models] Models to initialize with the collection. + * @param {object} [options] Options hash for the collection. + * @param {string} [options.props] Options hash for the initial query properties. + * @param {string} [options.props.order] Initial order (ASC or DESC) for the collection. + * @param {string} [options.props.orderby] Initial attribute key to order the collection by. + * @param {string} [options.props.query] Whether the collection is linked to an attachments query. + * @param {string} [options.observe] + * @param {string} [options.filters] + * + */ +var Attachments = Backbone.Collection.extend(/** @lends wp.media.model.Attachments.prototype */{ + /** + * @type {wp.media.model.Attachment} + */ + model: wp.media.model.Attachment, + /** + * @param {Array} [models=[]] Array of models used to populate the collection. + * @param {Object} [options={}] + */ + initialize: function( models, options ) { + options = options || {}; + + this.props = new Backbone.Model(); + this.filters = options.filters || {}; + + // Bind default `change` events to the `props` model. + this.props.on( 'change', this._changeFilteredProps, this ); + + this.props.on( 'change:order', this._changeOrder, this ); + this.props.on( 'change:orderby', this._changeOrderby, this ); + this.props.on( 'change:query', this._changeQuery, this ); + + this.props.set( _.defaults( options.props || {} ) ); + + if ( options.observe ) { + this.observe( options.observe ); + } + }, + /** + * Sort the collection when the order attribute changes. + * + * @access private + */ + _changeOrder: function() { + if ( this.comparator ) { + this.sort(); + } + }, + /** + * Set the default comparator only when the `orderby` property is set. + * + * @access private + * + * @param {Backbone.Model} model + * @param {string} orderby + */ + _changeOrderby: function( model, orderby ) { + // If a different comparator is defined, bail. + if ( this.comparator && this.comparator !== Attachments.comparator ) { + return; + } + + if ( orderby && 'post__in' !== orderby ) { + this.comparator = Attachments.comparator; + } else { + delete this.comparator; + } + }, + /** + * If the `query` property is set to true, query the server using + * the `props` values, and sync the results to this collection. + * + * @access private + * + * @param {Backbone.Model} model + * @param {Boolean} query + */ + _changeQuery: function( model, query ) { + if ( query ) { + this.props.on( 'change', this._requery, this ); + this._requery(); + } else { + this.props.off( 'change', this._requery, this ); + } + }, + /** + * @access private + * + * @param {Backbone.Model} model + */ + _changeFilteredProps: function( model ) { + // If this is a query, updating the collection will be handled by + // `this._requery()`. + if ( this.props.get('query') ) { + return; + } + + var changed = _.chain( model.changed ).map( function( t, prop ) { + var filter = Attachments.filters[ prop ], + term = model.get( prop ); + + if ( ! filter ) { + return; + } + + if ( term && ! this.filters[ prop ] ) { + this.filters[ prop ] = filter; + } else if ( ! term && this.filters[ prop ] === filter ) { + delete this.filters[ prop ]; + } else { + return; + } + + // Record the change. + return true; + }, this ).any().value(); + + if ( ! changed ) { + return; + } + + // If no `Attachments` model is provided to source the searches + // from, then automatically generate a source from the existing + // models. + if ( ! this._source ) { + this._source = new Attachments( this.models ); + } + + this.reset( this._source.filter( this.validator, this ) ); + }, + + validateDestroyed: false, + /** + * Checks whether an attachment is valid. + * + * @param {wp.media.model.Attachment} attachment + * @returns {Boolean} + */ + validator: function( attachment ) { + + // Filter out contextually created attachments (e.g. headers, logos, etc.). + if ( + ! _.isUndefined( attachment.attributes.context ) && + '' !== attachment.attributes.context + ) { + return false; + } + + if ( ! this.validateDestroyed && attachment.destroyed ) { + return false; + } + return _.all( this.filters, function( filter ) { + return !! filter.call( this, attachment ); + }, this ); + }, + /** + * Add or remove an attachment to the collection depending on its validity. + * + * @param {wp.media.model.Attachment} attachment + * @param {Object} options + * @returns {wp.media.model.Attachments} Returns itself to allow chaining + */ + validate: function( attachment, options ) { + var valid = this.validator( attachment ), + hasAttachment = !! this.get( attachment.cid ); + + if ( ! valid && hasAttachment ) { + this.remove( attachment, options ); + } else if ( valid && ! hasAttachment ) { + this.add( attachment, options ); + } + + return this; + }, + + /** + * Add or remove all attachments from another collection depending on each one's validity. + * + * @param {wp.media.model.Attachments} attachments + * @param {object} [options={}] + * + * @fires wp.media.model.Attachments#reset + * + * @returns {wp.media.model.Attachments} Returns itself to allow chaining + */ + validateAll: function( attachments, options ) { + options = options || {}; + + _.each( attachments.models, function( attachment ) { + this.validate( attachment, { silent: true }); + }, this ); + + if ( ! options.silent ) { + this.trigger( 'reset', this, options ); + } + return this; + }, + /** + * Start observing another attachments collection change events + * and replicate them on this collection. + * + * @param {wp.media.model.Attachments} The attachments collection to observe. + * @returns {wp.media.model.Attachments} Returns itself to allow chaining. + */ + observe: function( attachments ) { + this.observers = this.observers || []; + this.observers.push( attachments ); + + attachments.on( 'add change remove', this._validateHandler, this ); + attachments.on( 'reset', this._validateAllHandler, this ); + this.validateAll( attachments ); + return this; + }, + /** + * Stop replicating collection change events from another attachments collection. + * + * @param {wp.media.model.Attachments} The attachments collection to stop observing. + * @returns {wp.media.model.Attachments} Returns itself to allow chaining + */ + unobserve: function( attachments ) { + if ( attachments ) { + attachments.off( null, null, this ); + this.observers = _.without( this.observers, attachments ); + + } else { + _.each( this.observers, function( attachments ) { + attachments.off( null, null, this ); + }, this ); + delete this.observers; + } + + return this; + }, + /** + * @access private + * + * @param {wp.media.model.Attachments} attachment + * @param {wp.media.model.Attachments} attachments + * @param {Object} options + * + * @returns {wp.media.model.Attachments} Returns itself to allow chaining + */ + _validateHandler: function( attachment, attachments, options ) { + // If we're not mirroring this `attachments` collection, + // only retain the `silent` option. + options = attachments === this.mirroring ? options : { + silent: options && options.silent + }; + + return this.validate( attachment, options ); + }, + /** + * @access private + * + * @param {wp.media.model.Attachments} attachments + * @param {Object} options + * @returns {wp.media.model.Attachments} Returns itself to allow chaining + */ + _validateAllHandler: function( attachments, options ) { + return this.validateAll( attachments, options ); + }, + /** + * Start mirroring another attachments collection, clearing out any models already + * in the collection. + * + * @param {wp.media.model.Attachments} The attachments collection to mirror. + * @returns {wp.media.model.Attachments} Returns itself to allow chaining + */ + mirror: function( attachments ) { + if ( this.mirroring && this.mirroring === attachments ) { + return this; + } + + this.unmirror(); + this.mirroring = attachments; + + // Clear the collection silently. A `reset` event will be fired + // when `observe()` calls `validateAll()`. + this.reset( [], { silent: true } ); + this.observe( attachments ); + + return this; + }, + /** + * Stop mirroring another attachments collection. + */ + unmirror: function() { + if ( ! this.mirroring ) { + return; + } + + this.unobserve( this.mirroring ); + delete this.mirroring; + }, + /** + * Retrieve more attachments from the server for the collection. + * + * Only works if the collection is mirroring a Query Attachments collection, + * and forwards to its `more` method. This collection class doesn't have + * server persistence by itself. + * + * @param {object} options + * @returns {Promise} + */ + more: function( options ) { + var deferred = jQuery.Deferred(), + mirroring = this.mirroring, + attachments = this; + + if ( ! mirroring || ! mirroring.more ) { + return deferred.resolveWith( this ).promise(); + } + // If we're mirroring another collection, forward `more` to + // the mirrored collection. Account for a race condition by + // checking if we're still mirroring that collection when + // the request resolves. + mirroring.more( options ).done( function() { + if ( this === attachments.mirroring ) { + deferred.resolveWith( this ); + } + }); + + return deferred.promise(); + }, + /** + * Whether there are more attachments that haven't been sync'd from the server + * that match the collection's query. + * + * Only works if the collection is mirroring a Query Attachments collection, + * and forwards to its `hasMore` method. This collection class doesn't have + * server persistence by itself. + * + * @returns {boolean} + */ + hasMore: function() { + return this.mirroring ? this.mirroring.hasMore() : false; + }, + /** + * A custom AJAX-response parser. + * + * See trac ticket #24753 + * + * @param {Object|Array} resp The raw response Object/Array. + * @param {Object} xhr + * @returns {Array} The array of model attributes to be added to the collection + */ + parse: function( resp, xhr ) { + if ( ! _.isArray( resp ) ) { + resp = [resp]; + } + + return _.map( resp, function( attrs ) { + var id, attachment, newAttributes; + + if ( attrs instanceof Backbone.Model ) { + id = attrs.get( 'id' ); + attrs = attrs.attributes; + } else { + id = attrs.id; + } + + attachment = wp.media.model.Attachment.get( id ); + newAttributes = attachment.parse( attrs, xhr ); + + if ( ! _.isEqual( attachment.attributes, newAttributes ) ) { + attachment.set( newAttributes ); + } + + return attachment; + }); + }, + /** + * If the collection is a query, create and mirror an Attachments Query collection. + * + * @access private + */ + _requery: function( refresh ) { + var props; + if ( this.props.get('query') ) { + props = this.props.toJSON(); + props.cache = ( true !== refresh ); + this.mirror( wp.media.model.Query.get( props ) ); + } + }, + /** + * If this collection is sorted by `menuOrder`, recalculates and saves + * the menu order to the database. + * + * @returns {undefined|Promise} + */ + saveMenuOrder: function() { + if ( 'menuOrder' !== this.props.get('orderby') ) { + return; + } + + // Removes any uploading attachments, updates each attachment's + // menu order, and returns an object with an { id: menuOrder } + // mapping to pass to the request. + var attachments = this.chain().filter( function( attachment ) { + return ! _.isUndefined( attachment.id ); + }).map( function( attachment, index ) { + // Indices start at 1. + index = index + 1; + attachment.set( 'menuOrder', index ); + return [ attachment.id, index ]; + }).object().value(); + + if ( _.isEmpty( attachments ) ) { + return; + } + + return wp.media.post( 'save-attachment-order', { + nonce: wp.media.model.settings.post.nonce, + post_id: wp.media.model.settings.post.id, + attachments: attachments + }); + } +},/** @lends wp.media.model.Attachments */{ + /** + * A function to compare two attachment models in an attachments collection. + * + * Used as the default comparator for instances of wp.media.model.Attachments + * and its subclasses. @see wp.media.model.Attachments._changeOrderby(). + * + * @param {Backbone.Model} a + * @param {Backbone.Model} b + * @param {Object} options + * @returns {Number} -1 if the first model should come before the second, + * 0 if they are of the same rank and + * 1 if the first model should come after. + */ + comparator: function( a, b, options ) { + var key = this.props.get('orderby'), + order = this.props.get('order') || 'DESC', + ac = a.cid, + bc = b.cid; + + a = a.get( key ); + b = b.get( key ); + + if ( 'date' === key || 'modified' === key ) { + a = a || new Date(); + b = b || new Date(); + } + + // If `options.ties` is set, don't enforce the `cid` tiebreaker. + if ( options && options.ties ) { + ac = bc = null; + } + + return ( 'DESC' === order ) ? wp.media.compare( a, b, ac, bc ) : wp.media.compare( b, a, bc, ac ); + }, + /** @namespace wp.media.model.Attachments.filters */ + filters: { + /** + * @static + * Note that this client-side searching is *not* equivalent + * to our server-side searching. + * + * @param {wp.media.model.Attachment} attachment + * + * @this wp.media.model.Attachments + * + * @returns {Boolean} + */ + search: function( attachment ) { + if ( ! this.props.get('search') ) { + return true; + } + + return _.any(['title','filename','description','caption','name'], function( key ) { + var value = attachment.get( key ); + return value && -1 !== value.search( this.props.get('search') ); + }, this ); + }, + /** + * @static + * @param {wp.media.model.Attachment} attachment + * + * @this wp.media.model.Attachments + * + * @returns {Boolean} + */ + type: function( attachment ) { + var type = this.props.get('type'), atts = attachment.toJSON(), mime, found; + + if ( ! type || ( _.isArray( type ) && ! type.length ) ) { + return true; + } + + mime = atts.mime || ( atts.file && atts.file.type ) || ''; + + if ( _.isArray( type ) ) { + found = _.find( type, function (t) { + return -1 !== mime.indexOf( t ); + } ); + } else { + found = -1 !== mime.indexOf( type ); + } + + return found; + }, + /** + * @static + * @param {wp.media.model.Attachment} attachment + * + * @this wp.media.model.Attachments + * + * @returns {Boolean} + */ + uploadedTo: function( attachment ) { + var uploadedTo = this.props.get('uploadedTo'); + if ( _.isUndefined( uploadedTo ) ) { + return true; + } + + return uploadedTo === attachment.get('uploadedTo'); + }, + /** + * @static + * @param {wp.media.model.Attachment} attachment + * + * @this wp.media.model.Attachments + * + * @returns {Boolean} + */ + status: function( attachment ) { + var status = this.props.get('status'); + if ( _.isUndefined( status ) ) { + return true; + } + + return status === attachment.get('status'); + } + } +}); + +module.exports = Attachments; + + +/***/ }), + +/***/ 26: +/***/ (function(module, exports) { + +var Attachments = wp.media.model.Attachments, + Query; + +/** + * wp.media.model.Query + * + * A collection of attachments that match the supplied query arguments. + * + * Note: Do NOT change this.args after the query has been initialized. + * Things will break. + * + * @memberOf wp.media.model + * + * @class + * @augments wp.media.model.Attachments + * @augments Backbone.Collection + * + * @param {array} [models] Models to initialize with the collection. + * @param {object} [options] Options hash. + * @param {object} [options.args] Attachments query arguments. + * @param {object} [options.args.posts_per_page] + */ +Query = Attachments.extend(/** @lends wp.media.model.Query.prototype */{ + /** + * @param {array} [models=[]] Array of initial models to populate the collection. + * @param {object} [options={}] + */ + initialize: function( models, options ) { + var allowed; + + options = options || {}; + Attachments.prototype.initialize.apply( this, arguments ); + + this.args = options.args; + this._hasMore = true; + this.created = new Date(); + + this.filters.order = function( attachment ) { + var orderby = this.props.get('orderby'), + order = this.props.get('order'); + + if ( ! this.comparator ) { + return true; + } + + // We want any items that can be placed before the last + // item in the set. If we add any items after the last + // item, then we can't guarantee the set is complete. + if ( this.length ) { + return 1 !== this.comparator( attachment, this.last(), { ties: true }); + + // Handle the case where there are no items yet and + // we're sorting for recent items. In that case, we want + // changes that occurred after we created the query. + } else if ( 'DESC' === order && ( 'date' === orderby || 'modified' === orderby ) ) { + return attachment.get( orderby ) >= this.created; + + // If we're sorting by menu order and we have no items, + // accept any items that have the default menu order (0). + } else if ( 'ASC' === order && 'menuOrder' === orderby ) { + return attachment.get( orderby ) === 0; + } + + // Otherwise, we don't want any items yet. + return false; + }; + + // Observe the central `wp.Uploader.queue` collection to watch for + // new matches for the query. + // + // Only observe when a limited number of query args are set. There + // are no filters for other properties, so observing will result in + // false positives in those queries. + allowed = [ 's', 'order', 'orderby', 'posts_per_page', 'post_mime_type', 'post_parent', 'author' ]; + if ( wp.Uploader && _( this.args ).chain().keys().difference( allowed ).isEmpty().value() ) { + this.observe( wp.Uploader.queue ); + } + }, + /** + * Whether there are more attachments that haven't been sync'd from the server + * that match the collection's query. + * + * @returns {boolean} + */ + hasMore: function() { + return this._hasMore; + }, + /** + * Fetch more attachments from the server for the collection. + * + * @param {object} [options={}] + * @returns {Promise} + */ + more: function( options ) { + var query = this; + + // If there is already a request pending, return early with the Deferred object. + if ( this._more && 'pending' === this._more.state() ) { + return this._more; + } + + if ( ! this.hasMore() ) { + return jQuery.Deferred().resolveWith( this ).promise(); + } + + options = options || {}; + options.remove = false; + + return this._more = this.fetch( options ).done( function( resp ) { + if ( _.isEmpty( resp ) || -1 === this.args.posts_per_page || resp.length < this.args.posts_per_page ) { + query._hasMore = false; + } + }); + }, + /** + * Overrides Backbone.Collection.sync + * Overrides wp.media.model.Attachments.sync + * + * @param {String} method + * @param {Backbone.Model} model + * @param {Object} [options={}] + * @returns {Promise} + */ + sync: function( method, model, options ) { + var args, fallback; + + // Overload the read method so Attachment.fetch() functions correctly. + if ( 'read' === method ) { + options = options || {}; + options.context = this; + options.data = _.extend( options.data || {}, { + action: 'query-attachments', + post_id: wp.media.model.settings.post.id + }); + + // Clone the args so manipulation is non-destructive. + args = _.clone( this.args ); + + // Determine which page to query. + if ( -1 !== args.posts_per_page ) { + args.paged = Math.round( this.length / args.posts_per_page ) + 1; + } + + options.data.query = args; + return wp.media.ajax( options ); + + // Otherwise, fall back to Backbone.sync() + } else { + /** + * Call wp.media.model.Attachments.sync or Backbone.sync + */ + fallback = Attachments.prototype.sync ? Attachments.prototype : Backbone; + return fallback.sync.apply( this, arguments ); + } + } +}, /** @lends wp.media.model.Query */{ + /** + * @readonly + */ + defaultProps: { + orderby: 'date', + order: 'DESC' + }, + /** + * @readonly + */ + defaultArgs: { + posts_per_page: 40 + }, + /** + * @readonly + */ + orderby: { + allowed: [ 'name', 'author', 'date', 'title', 'modified', 'uploadedTo', 'id', 'post__in', 'menuOrder' ], + /** + * A map of JavaScript orderby values to their WP_Query equivalents. + * @type {Object} + */ + valuemap: { + 'id': 'ID', + 'uploadedTo': 'parent', + 'menuOrder': 'menu_order ID' + } + }, + /** + * A map of JavaScript query properties to their WP_Query equivalents. + * + * @readonly + */ + propmap: { + 'search': 's', + 'type': 'post_mime_type', + 'perPage': 'posts_per_page', + 'menuOrder': 'menu_order', + 'uploadedTo': 'post_parent', + 'status': 'post_status', + 'include': 'post__in', + 'exclude': 'post__not_in', + 'author': 'author' + }, + /** + * Creates and returns an Attachments Query collection given the properties. + * + * Caches query objects and reuses where possible. + * + * @static + * @method + * + * @param {object} [props] + * @param {Object} [props.cache=true] Whether to use the query cache or not. + * @param {Object} [props.order] + * @param {Object} [props.orderby] + * @param {Object} [props.include] + * @param {Object} [props.exclude] + * @param {Object} [props.s] + * @param {Object} [props.post_mime_type] + * @param {Object} [props.posts_per_page] + * @param {Object} [props.menu_order] + * @param {Object} [props.post_parent] + * @param {Object} [props.post_status] + * @param {Object} [props.author] + * @param {Object} [options] + * + * @returns {wp.media.model.Query} A new Attachments Query collection. + */ + get: (function(){ + /** + * @static + * @type Array + */ + var queries = []; + + /** + * @returns {Query} + */ + return function( props, options ) { + var args = {}, + orderby = Query.orderby, + defaults = Query.defaultProps, + query, + cache = !! props.cache || _.isUndefined( props.cache ); + + // Remove the `query` property. This isn't linked to a query, + // this *is* the query. + delete props.query; + delete props.cache; + + // Fill default args. + _.defaults( props, defaults ); + + // Normalize the order. + props.order = props.order.toUpperCase(); + if ( 'DESC' !== props.order && 'ASC' !== props.order ) { + props.order = defaults.order.toUpperCase(); + } + + // Ensure we have a valid orderby value. + if ( ! _.contains( orderby.allowed, props.orderby ) ) { + props.orderby = defaults.orderby; + } + + _.each( [ 'include', 'exclude' ], function( prop ) { + if ( props[ prop ] && ! _.isArray( props[ prop ] ) ) { + props[ prop ] = [ props[ prop ] ]; + } + } ); + + // Generate the query `args` object. + // Correct any differing property names. + _.each( props, function( value, prop ) { + if ( _.isNull( value ) ) { + return; + } + + args[ Query.propmap[ prop ] || prop ] = value; + }); + + // Fill any other default query args. + _.defaults( args, Query.defaultArgs ); + + // `props.orderby` does not always map directly to `args.orderby`. + // Substitute exceptions specified in orderby.keymap. + args.orderby = orderby.valuemap[ props.orderby ] || props.orderby; + + // Search the query cache for a matching query. + if ( cache ) { + query = _.find( queries, function( query ) { + return _.isEqual( query.args, args ); + }); + } else { + queries = []; + } + + // Otherwise, create a new query and add it to the cache. + if ( ! query ) { + query = new Query( [], _.extend( options || {}, { + props: props, + args: args + } ) ); + queries.push( query ); + } + + return query; + }; + }()) +}); + +module.exports = Query; + + +/***/ }), + +/***/ 27: +/***/ (function(module, exports) { + +/** + * wp.media.model.PostImage + * + * An instance of an image that's been embedded into a post. + * + * Used in the embedded image attachment display settings modal - @see wp.media.view.MediaFrame.ImageDetails. + * + * @memberOf wp.media.model + * + * @class + * @augments Backbone.Model + * + * @param {int} [attributes] Initial model attributes. + * @param {int} [attributes.attachment_id] ID of the attachment. + **/ +var PostImage = Backbone.Model.extend(/** @lends wp.media.model.PostImage.prototype */{ + + initialize: function( attributes ) { + var Attachment = wp.media.model.Attachment; + this.attachment = false; + + if ( attributes.attachment_id ) { + this.attachment = Attachment.get( attributes.attachment_id ); + if ( this.attachment.get( 'url' ) ) { + this.dfd = jQuery.Deferred(); + this.dfd.resolve(); + } else { + this.dfd = this.attachment.fetch(); + } + this.bindAttachmentListeners(); + } + + // keep url in sync with changes to the type of link + this.on( 'change:link', this.updateLinkUrl, this ); + this.on( 'change:size', this.updateSize, this ); + + this.setLinkTypeFromUrl(); + this.setAspectRatio(); + + this.set( 'originalUrl', attributes.url ); + }, + + bindAttachmentListeners: function() { + this.listenTo( this.attachment, 'sync', this.setLinkTypeFromUrl ); + this.listenTo( this.attachment, 'sync', this.setAspectRatio ); + this.listenTo( this.attachment, 'change', this.updateSize ); + }, + + changeAttachment: function( attachment, props ) { + this.stopListening( this.attachment ); + this.attachment = attachment; + this.bindAttachmentListeners(); + + this.set( 'attachment_id', this.attachment.get( 'id' ) ); + this.set( 'caption', this.attachment.get( 'caption' ) ); + this.set( 'alt', this.attachment.get( 'alt' ) ); + this.set( 'size', props.get( 'size' ) ); + this.set( 'align', props.get( 'align' ) ); + this.set( 'link', props.get( 'link' ) ); + this.updateLinkUrl(); + this.updateSize(); + }, + + setLinkTypeFromUrl: function() { + var linkUrl = this.get( 'linkUrl' ), + type; + + if ( ! linkUrl ) { + this.set( 'link', 'none' ); + return; + } + + // default to custom if there is a linkUrl + type = 'custom'; + + if ( this.attachment ) { + if ( this.attachment.get( 'url' ) === linkUrl ) { + type = 'file'; + } else if ( this.attachment.get( 'link' ) === linkUrl ) { + type = 'post'; + } + } else { + if ( this.get( 'url' ) === linkUrl ) { + type = 'file'; + } + } + + this.set( 'link', type ); + }, + + updateLinkUrl: function() { + var link = this.get( 'link' ), + url; + + switch( link ) { + case 'file': + if ( this.attachment ) { + url = this.attachment.get( 'url' ); + } else { + url = this.get( 'url' ); + } + this.set( 'linkUrl', url ); + break; + case 'post': + this.set( 'linkUrl', this.attachment.get( 'link' ) ); + break; + case 'none': + this.set( 'linkUrl', '' ); + break; + } + }, + + updateSize: function() { + var size; + + if ( ! this.attachment ) { + return; + } + + if ( this.get( 'size' ) === 'custom' ) { + this.set( 'width', this.get( 'customWidth' ) ); + this.set( 'height', this.get( 'customHeight' ) ); + this.set( 'url', this.get( 'originalUrl' ) ); + return; + } + + size = this.attachment.get( 'sizes' )[ this.get( 'size' ) ]; + + if ( ! size ) { + return; + } + + this.set( 'url', size.url ); + this.set( 'width', size.width ); + this.set( 'height', size.height ); + }, + + setAspectRatio: function() { + var full; + + if ( this.attachment && this.attachment.get( 'sizes' ) ) { + full = this.attachment.get( 'sizes' ).full; + + if ( full ) { + this.set( 'aspectRatio', full.width / full.height ); + return; + } + } + + this.set( 'aspectRatio', this.get( 'customWidth' ) / this.get( 'customHeight' ) ); + } +}); + +module.exports = PostImage; + + +/***/ }), + +/***/ 28: +/***/ (function(module, exports) { + +var Attachments = wp.media.model.Attachments, + Selection; + +/** + * wp.media.model.Selection + * + * A selection of attachments. + * + * @memberOf wp.media.model + * + * @class + * @augments wp.media.model.Attachments + * @augments Backbone.Collection + */ +Selection = Attachments.extend(/** @lends wp.media.model.Selection.prototype */{ + /** + * Refresh the `single` model whenever the selection changes. + * Binds `single` instead of using the context argument to ensure + * it receives no parameters. + * + * @param {Array} [models=[]] Array of models used to populate the collection. + * @param {Object} [options={}] + */ + initialize: function( models, options ) { + /** + * call 'initialize' directly on the parent class + */ + Attachments.prototype.initialize.apply( this, arguments ); + this.multiple = options && options.multiple; + + this.on( 'add remove reset', _.bind( this.single, this, false ) ); + }, + + /** + * If the workflow does not support multi-select, clear out the selection + * before adding a new attachment to it. + * + * @param {Array} models + * @param {Object} options + * @returns {wp.media.model.Attachment[]} + */ + add: function( models, options ) { + if ( ! this.multiple ) { + this.remove( this.models ); + } + /** + * call 'add' directly on the parent class + */ + return Attachments.prototype.add.call( this, models, options ); + }, + + /** + * Fired when toggling (clicking on) an attachment in the modal. + * + * @param {undefined|boolean|wp.media.model.Attachment} model + * + * @fires wp.media.model.Selection#selection:single + * @fires wp.media.model.Selection#selection:unsingle + * + * @returns {Backbone.Model} + */ + single: function( model ) { + var previous = this._single; + + // If a `model` is provided, use it as the single model. + if ( model ) { + this._single = model; + } + // If the single model isn't in the selection, remove it. + if ( this._single && ! this.get( this._single.cid ) ) { + delete this._single; + } + + this._single = this._single || this.last(); + + // If single has changed, fire an event. + if ( this._single !== previous ) { + if ( previous ) { + previous.trigger( 'selection:unsingle', previous, this ); + + // If the model was already removed, trigger the collection + // event manually. + if ( ! this.get( previous.cid ) ) { + this.trigger( 'selection:unsingle', previous, this ); + } + } + if ( this._single ) { + this._single.trigger( 'selection:single', this._single, this ); + } + } + + // Return the single model, or the last model as a fallback. + return this._single; + } +}); + +module.exports = Selection; + /***/ }) diff --git a/wp-includes/js/media-models.min.js b/wp-includes/js/media-models.min.js index 26ff59d3a3..ef5e2f09cb 100644 --- a/wp-includes/js/media-models.min.js +++ b/wp-includes/js/media-models.min.js @@ -1,2 +1 @@ -!function(a){function b(d){if(c[d])return c[d].exports;var e=c[d]={i:d,l:!1,exports:{}};return a[d].call(e.exports,e,e.exports,b),e.l=!0,e.exports}var c={};return b.m=a,b.c=c,b.d=function(a,c,d){b.o(a,c)||Object.defineProperty(a,c,{enumerable:!0,get:d})},b.r=function(a){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(a,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(a,"__esModule",{value:!0})},b.t=function(a,c){if(1&c&&(a=b(a)),8&c)return a;if(4&c&&"object"==typeof a&&a&&a.__esModule)return a;var d=Object.create(null);if(b.r(d),Object.defineProperty(d,"default",{enumerable:!0,value:a}),2&c&&"string"!=typeof a)for(var e in a)b.d(d,e,function(b){return a[b]}.bind(null,e));return d},b.n=function(a){var c=a&&a.__esModule?function(){return a["default"]}:function(){return a};return b.d(c,"a",c),c},b.o=function(a,b){return Object.prototype.hasOwnProperty.call(a,b)},b.p="",b(b.s=2)}({"./src/js/_enqueues/wp/media/models.js":function(module,exports,__webpack_require__){eval("/**\n * @output wp-includes/js/media-models.js\n */\n\nvar $ = jQuery,\n\tAttachment, Attachments, l10n, media;\n\n/** @namespace wp */\nwindow.wp = window.wp || {};\n\n/**\n * Create and return a media frame.\n *\n * Handles the default media experience.\n *\n * @alias wp.media\n * @memberOf wp\n * @namespace\n *\n * @param {object} attributes The properties passed to the main media controller.\n * @return {wp.media.view.MediaFrame} A media workflow.\n */\nmedia = wp.media = function( attributes ) {\n\tvar MediaFrame = media.view.MediaFrame,\n\t\tframe;\n\n\tif ( ! MediaFrame ) {\n\t\treturn;\n\t}\n\n\tattributes = _.defaults( attributes || {}, {\n\t\tframe: 'select'\n\t});\n\n\tif ( 'select' === attributes.frame && MediaFrame.Select ) {\n\t\tframe = new MediaFrame.Select( attributes );\n\t} else if ( 'post' === attributes.frame && MediaFrame.Post ) {\n\t\tframe = new MediaFrame.Post( attributes );\n\t} else if ( 'manage' === attributes.frame && MediaFrame.Manage ) {\n\t\tframe = new MediaFrame.Manage( attributes );\n\t} else if ( 'image' === attributes.frame && MediaFrame.ImageDetails ) {\n\t\tframe = new MediaFrame.ImageDetails( attributes );\n\t} else if ( 'audio' === attributes.frame && MediaFrame.AudioDetails ) {\n\t\tframe = new MediaFrame.AudioDetails( attributes );\n\t} else if ( 'video' === attributes.frame && MediaFrame.VideoDetails ) {\n\t\tframe = new MediaFrame.VideoDetails( attributes );\n\t} else if ( 'edit-attachments' === attributes.frame && MediaFrame.EditAttachments ) {\n\t\tframe = new MediaFrame.EditAttachments( attributes );\n\t}\n\n\tdelete attributes.frame;\n\n\tmedia.frame = frame;\n\n\treturn frame;\n};\n\n/** @namespace wp.media.model */\n/** @namespace wp.media.view */\n/** @namespace wp.media.controller */\n/** @namespace wp.media.frames */\n_.extend( media, { model: {}, view: {}, controller: {}, frames: {} });\n\n// Link any localized strings.\nl10n = media.model.l10n = window._wpMediaModelsL10n || {};\n\n// Link any settings.\nmedia.model.settings = l10n.settings || {};\ndelete l10n.settings;\n\nAttachment = media.model.Attachment = __webpack_require__( /*! ../../../media/models/attachment.js */ \"./src/js/media/models/attachment.js\" );\nAttachments = media.model.Attachments = __webpack_require__( /*! ../../../media/models/attachments.js */ \"./src/js/media/models/attachments.js\" );\n\nmedia.model.Query = __webpack_require__( /*! ../../../media/models/query.js */ \"./src/js/media/models/query.js\" );\nmedia.model.PostImage = __webpack_require__( /*! ../../../media/models/post-image.js */ \"./src/js/media/models/post-image.js\" );\nmedia.model.Selection = __webpack_require__( /*! ../../../media/models/selection.js */ \"./src/js/media/models/selection.js\" );\n\n/**\n * ========================================================================\n * UTILITIES\n * ========================================================================\n */\n\n/**\n * A basic equality comparator for Backbone models.\n *\n * Used to order models within a collection - @see wp.media.model.Attachments.comparator().\n *\n * @param {mixed} a The primary parameter to compare.\n * @param {mixed} b The primary parameter to compare.\n * @param {string} ac The fallback parameter to compare, a's cid.\n * @param {string} bc The fallback parameter to compare, b's cid.\n * @return {number} -1: a should come before b.\n * 0: a and b are of the same rank.\n * 1: b should come before a.\n */\nmedia.compare = function( a, b, ac, bc ) {\n\tif ( _.isEqual( a, b ) ) {\n\t\treturn ac === bc ? 0 : (ac > bc ? -1 : 1);\n\t} else {\n\t\treturn a > b ? -1 : 1;\n\t}\n};\n\n_.extend( media, /** @lends wp.media */{\n\t/**\n\t * media.template( id )\n\t *\n\t * Fetch a JavaScript template for an id, and return a templating function for it.\n\t *\n\t * See wp.template() in `wp-includes/js/wp-util.js`.\n\t *\n\t * @borrows wp.template as template\n\t */\n\ttemplate: wp.template,\n\n\t/**\n\t * media.post( [action], [data] )\n\t *\n\t * Sends a POST request to WordPress.\n\t * See wp.ajax.post() in `wp-includes/js/wp-util.js`.\n\t *\n\t * @borrows wp.ajax.post as post\n\t */\n\tpost: wp.ajax.post,\n\n\t/**\n\t * media.ajax( [action], [options] )\n\t *\n\t * Sends an XHR request to WordPress.\n\t * See wp.ajax.send() in `wp-includes/js/wp-util.js`.\n\t *\n\t * @borrows wp.ajax.send as ajax\n\t */\n\tajax: wp.ajax.send,\n\n\t/**\n\t * Scales a set of dimensions to fit within bounding dimensions.\n\t *\n\t * @param {Object} dimensions\n\t * @returns {Object}\n\t */\n\tfit: function( dimensions ) {\n\t\tvar width = dimensions.width,\n\t\t\theight = dimensions.height,\n\t\t\tmaxWidth = dimensions.maxWidth,\n\t\t\tmaxHeight = dimensions.maxHeight,\n\t\t\tconstraint;\n\n\t\t// Compare ratios between the two values to determine which\n\t\t// max to constrain by. If a max value doesn't exist, then the\n\t\t// opposite side is the constraint.\n\t\tif ( ! _.isUndefined( maxWidth ) && ! _.isUndefined( maxHeight ) ) {\n\t\t\tconstraint = ( width / height > maxWidth / maxHeight ) ? 'width' : 'height';\n\t\t} else if ( _.isUndefined( maxHeight ) ) {\n\t\t\tconstraint = 'width';\n\t\t} else if ( _.isUndefined( maxWidth ) && height > maxHeight ) {\n\t\t\tconstraint = 'height';\n\t\t}\n\n\t\t// If the value of the constrained side is larger than the max,\n\t\t// then scale the values. Otherwise return the originals; they fit.\n\t\tif ( 'width' === constraint && width > maxWidth ) {\n\t\t\treturn {\n\t\t\t\twidth : maxWidth,\n\t\t\t\theight: Math.round( maxWidth * height / width )\n\t\t\t};\n\t\t} else if ( 'height' === constraint && height > maxHeight ) {\n\t\t\treturn {\n\t\t\t\twidth : Math.round( maxHeight * width / height ),\n\t\t\t\theight: maxHeight\n\t\t\t};\n\t\t} else {\n\t\t\treturn {\n\t\t\t\twidth : width,\n\t\t\t\theight: height\n\t\t\t};\n\t\t}\n\t},\n\t/**\n\t * Truncates a string by injecting an ellipsis into the middle.\n\t * Useful for filenames.\n\t *\n\t * @param {String} string\n\t * @param {Number} [length=30]\n\t * @param {String} [replacement=…]\n\t * @returns {String} The string, unless length is greater than string.length.\n\t */\n\ttruncate: function( string, length, replacement ) {\n\t\tlength = length || 30;\n\t\treplacement = replacement || '…';\n\n\t\tif ( string.length <= length ) {\n\t\t\treturn string;\n\t\t}\n\n\t\treturn string.substr( 0, length / 2 ) + replacement + string.substr( -1 * length / 2 );\n\t}\n});\n\n/**\n * ========================================================================\n * MODELS\n * ========================================================================\n */\n/**\n * wp.media.attachment\n *\n * @static\n * @param {String} id A string used to identify a model.\n * @returns {wp.media.model.Attachment}\n */\nmedia.attachment = function( id ) {\n\treturn Attachment.get( id );\n};\n\n/**\n * A collection of all attachments that have been fetched from the server.\n *\n * @static\n * @member {wp.media.model.Attachments}\n */\nAttachments.all = new Attachments();\n\n/**\n * wp.media.query\n *\n * Shorthand for creating a new Attachments Query.\n *\n * @param {object} [props]\n * @returns {wp.media.model.Attachments}\n */\nmedia.query = function( props ) {\n\treturn new Attachments( null, {\n\t\tprops: _.extend( _.defaults( props || {}, { orderby: 'date' } ), { query: true } )\n\t});\n};\n\n// Clean up. Prevents mobile browsers caching\n$(window).on('unload', function(){\n\twindow.wp = null;\n});\n\n\n//# sourceURL=webpack:///./src/js/_enqueues/wp/media/models.js?")},"./src/js/media/models/attachment.js":function(module,exports){eval("var $ = Backbone.$,\n\tAttachment;\n\n/**\n * wp.media.model.Attachment\n *\n * @memberOf wp.media.model\n *\n * @class\n * @augments Backbone.Model\n */\nAttachment = Backbone.Model.extend(/** @lends wp.media.model.Attachment.prototype */{\n\t/**\n\t * Triggered when attachment details change\n\t * Overrides Backbone.Model.sync\n\t *\n\t * @param {string} method\n\t * @param {wp.media.model.Attachment} model\n\t * @param {Object} [options={}]\n\t *\n\t * @returns {Promise}\n\t */\n\tsync: function( method, model, options ) {\n\t\t// If the attachment does not yet have an `id`, return an instantly\n\t\t// rejected promise. Otherwise, all of our requests will fail.\n\t\tif ( _.isUndefined( this.id ) ) {\n\t\t\treturn $.Deferred().rejectWith( this ).promise();\n\t\t}\n\n\t\t// Overload the `read` request so Attachment.fetch() functions correctly.\n\t\tif ( 'read' === method ) {\n\t\t\toptions = options || {};\n\t\t\toptions.context = this;\n\t\t\toptions.data = _.extend( options.data || {}, {\n\t\t\t\taction: 'get-attachment',\n\t\t\t\tid: this.id\n\t\t\t});\n\t\t\treturn wp.media.ajax( options );\n\n\t\t// Overload the `update` request so properties can be saved.\n\t\t} else if ( 'update' === method ) {\n\t\t\t// If we do not have the necessary nonce, fail immeditately.\n\t\t\tif ( ! this.get('nonces') || ! this.get('nonces').update ) {\n\t\t\t\treturn $.Deferred().rejectWith( this ).promise();\n\t\t\t}\n\n\t\t\toptions = options || {};\n\t\t\toptions.context = this;\n\n\t\t\t// Set the action and ID.\n\t\t\toptions.data = _.extend( options.data || {}, {\n\t\t\t\taction: 'save-attachment',\n\t\t\t\tid: this.id,\n\t\t\t\tnonce: this.get('nonces').update,\n\t\t\t\tpost_id: wp.media.model.settings.post.id\n\t\t\t});\n\n\t\t\t// Record the values of the changed attributes.\n\t\t\tif ( model.hasChanged() ) {\n\t\t\t\toptions.data.changes = {};\n\n\t\t\t\t_.each( model.changed, function( value, key ) {\n\t\t\t\t\toptions.data.changes[ key ] = this.get( key );\n\t\t\t\t}, this );\n\t\t\t}\n\n\t\t\treturn wp.media.ajax( options );\n\n\t\t// Overload the `delete` request so attachments can be removed.\n\t\t// This will permanently delete an attachment.\n\t\t} else if ( 'delete' === method ) {\n\t\t\toptions = options || {};\n\n\t\t\tif ( ! options.wait ) {\n\t\t\t\tthis.destroyed = true;\n\t\t\t}\n\n\t\t\toptions.context = this;\n\t\t\toptions.data = _.extend( options.data || {}, {\n\t\t\t\taction: 'delete-post',\n\t\t\t\tid: this.id,\n\t\t\t\t_wpnonce: this.get('nonces')['delete']\n\t\t\t});\n\n\t\t\treturn wp.media.ajax( options ).done( function() {\n\t\t\t\tthis.destroyed = true;\n\t\t\t}).fail( function() {\n\t\t\t\tthis.destroyed = false;\n\t\t\t});\n\n\t\t// Otherwise, fall back to `Backbone.sync()`.\n\t\t} else {\n\t\t\t/**\n\t\t\t * Call `sync` directly on Backbone.Model\n\t\t\t */\n\t\t\treturn Backbone.Model.prototype.sync.apply( this, arguments );\n\t\t}\n\t},\n\t/**\n\t * Convert date strings into Date objects.\n\t *\n\t * @param {Object} resp The raw response object, typically returned by fetch()\n\t * @returns {Object} The modified response object, which is the attributes hash\n\t * to be set on the model.\n\t */\n\tparse: function( resp ) {\n\t\tif ( ! resp ) {\n\t\t\treturn resp;\n\t\t}\n\n\t\tresp.date = new Date( resp.date );\n\t\tresp.modified = new Date( resp.modified );\n\t\treturn resp;\n\t},\n\t/**\n\t * @param {Object} data The properties to be saved.\n\t * @param {Object} options Sync options. e.g. patch, wait, success, error.\n\t *\n\t * @this Backbone.Model\n\t *\n\t * @returns {Promise}\n\t */\n\tsaveCompat: function( data, options ) {\n\t\tvar model = this;\n\n\t\t// If we do not have the necessary nonce, fail immeditately.\n\t\tif ( ! this.get('nonces') || ! this.get('nonces').update ) {\n\t\t\treturn $.Deferred().rejectWith( this ).promise();\n\t\t}\n\n\t\treturn wp.media.post( 'save-attachment-compat', _.defaults({\n\t\t\tid: this.id,\n\t\t\tnonce: this.get('nonces').update,\n\t\t\tpost_id: wp.media.model.settings.post.id\n\t\t}, data ) ).done( function( resp, status, xhr ) {\n\t\t\tmodel.set( model.parse( resp, xhr ), options );\n\t\t});\n\t}\n},/** @lends wp.media.model.Attachment */{\n\t/**\n\t * Create a new model on the static 'all' attachments collection and return it.\n\t *\n\t * @static\n\t *\n\t * @param {Object} attrs\n\t * @returns {wp.media.model.Attachment}\n\t */\n\tcreate: function( attrs ) {\n\t\tvar Attachments = wp.media.model.Attachments;\n\t\treturn Attachments.all.push( attrs );\n\t},\n\t/**\n\t * Create a new model on the static 'all' attachments collection and return it.\n\t *\n\t * If this function has already been called for the id,\n\t * it returns the specified attachment.\n\t *\n\t * @static\n\t * @param {string} id A string used to identify a model.\n\t * @param {Backbone.Model|undefined} attachment\n\t * @returns {wp.media.model.Attachment}\n\t */\n\tget: _.memoize( function( id, attachment ) {\n\t\tvar Attachments = wp.media.model.Attachments;\n\t\treturn Attachments.all.push( attachment || { id: id } );\n\t})\n});\n\nmodule.exports = Attachment;\n\n\n//# sourceURL=webpack:///./src/js/media/models/attachment.js?")},"./src/js/media/models/attachments.js":function(module,exports){eval("/**\n * wp.media.model.Attachments\n *\n * A collection of attachments.\n *\n * This collection has no persistence with the server without supplying\n * 'options.props.query = true', which will mirror the collection\n * to an Attachments Query collection - @see wp.media.model.Attachments.mirror().\n *\n * @memberOf wp.media.model\n *\n * @class\n * @augments Backbone.Collection\n *\n * @param {array} [models] Models to initialize with the collection.\n * @param {object} [options] Options hash for the collection.\n * @param {string} [options.props] Options hash for the initial query properties.\n * @param {string} [options.props.order] Initial order (ASC or DESC) for the collection.\n * @param {string} [options.props.orderby] Initial attribute key to order the collection by.\n * @param {string} [options.props.query] Whether the collection is linked to an attachments query.\n * @param {string} [options.observe]\n * @param {string} [options.filters]\n *\n */\nvar Attachments = Backbone.Collection.extend(/** @lends wp.media.model.Attachments.prototype */{\n\t/**\n\t * @type {wp.media.model.Attachment}\n\t */\n\tmodel: wp.media.model.Attachment,\n\t/**\n\t * @param {Array} [models=[]] Array of models used to populate the collection.\n\t * @param {Object} [options={}]\n\t */\n\tinitialize: function( models, options ) {\n\t\toptions = options || {};\n\n\t\tthis.props = new Backbone.Model();\n\t\tthis.filters = options.filters || {};\n\n\t\t// Bind default `change` events to the `props` model.\n\t\tthis.props.on( 'change', this._changeFilteredProps, this );\n\n\t\tthis.props.on( 'change:order', this._changeOrder, this );\n\t\tthis.props.on( 'change:orderby', this._changeOrderby, this );\n\t\tthis.props.on( 'change:query', this._changeQuery, this );\n\n\t\tthis.props.set( _.defaults( options.props || {} ) );\n\n\t\tif ( options.observe ) {\n\t\t\tthis.observe( options.observe );\n\t\t}\n\t},\n\t/**\n\t * Sort the collection when the order attribute changes.\n\t *\n\t * @access private\n\t */\n\t_changeOrder: function() {\n\t\tif ( this.comparator ) {\n\t\t\tthis.sort();\n\t\t}\n\t},\n\t/**\n\t * Set the default comparator only when the `orderby` property is set.\n\t *\n\t * @access private\n\t *\n\t * @param {Backbone.Model} model\n\t * @param {string} orderby\n\t */\n\t_changeOrderby: function( model, orderby ) {\n\t\t// If a different comparator is defined, bail.\n\t\tif ( this.comparator && this.comparator !== Attachments.comparator ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( orderby && 'post__in' !== orderby ) {\n\t\t\tthis.comparator = Attachments.comparator;\n\t\t} else {\n\t\t\tdelete this.comparator;\n\t\t}\n\t},\n\t/**\n\t * If the `query` property is set to true, query the server using\n\t * the `props` values, and sync the results to this collection.\n\t *\n\t * @access private\n\t *\n\t * @param {Backbone.Model} model\n\t * @param {Boolean} query\n\t */\n\t_changeQuery: function( model, query ) {\n\t\tif ( query ) {\n\t\t\tthis.props.on( 'change', this._requery, this );\n\t\t\tthis._requery();\n\t\t} else {\n\t\t\tthis.props.off( 'change', this._requery, this );\n\t\t}\n\t},\n\t/**\n\t * @access private\n\t *\n\t * @param {Backbone.Model} model\n\t */\n\t_changeFilteredProps: function( model ) {\n\t\t// If this is a query, updating the collection will be handled by\n\t\t// `this._requery()`.\n\t\tif ( this.props.get('query') ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar changed = _.chain( model.changed ).map( function( t, prop ) {\n\t\t\tvar filter = Attachments.filters[ prop ],\n\t\t\t\tterm = model.get( prop );\n\n\t\t\tif ( ! filter ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( term && ! this.filters[ prop ] ) {\n\t\t\t\tthis.filters[ prop ] = filter;\n\t\t\t} else if ( ! term && this.filters[ prop ] === filter ) {\n\t\t\t\tdelete this.filters[ prop ];\n\t\t\t} else {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Record the change.\n\t\t\treturn true;\n\t\t}, this ).any().value();\n\n\t\tif ( ! changed ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If no `Attachments` model is provided to source the searches\n\t\t// from, then automatically generate a source from the existing\n\t\t// models.\n\t\tif ( ! this._source ) {\n\t\t\tthis._source = new Attachments( this.models );\n\t\t}\n\n\t\tthis.reset( this._source.filter( this.validator, this ) );\n\t},\n\n\tvalidateDestroyed: false,\n\t/**\n\t * Checks whether an attachment is valid.\n\t *\n\t * @param {wp.media.model.Attachment} attachment\n\t * @returns {Boolean}\n\t */\n\tvalidator: function( attachment ) {\n\n\t\t// Filter out contextually created attachments (e.g. headers, logos, etc.).\n\t\tif (\n\t\t\t! _.isUndefined( attachment.attributes.context ) &&\n\t\t\t'' !== attachment.attributes.context\n\t\t) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( ! this.validateDestroyed && attachment.destroyed ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn _.all( this.filters, function( filter ) {\n\t\t\treturn !! filter.call( this, attachment );\n\t\t}, this );\n\t},\n\t/**\n\t * Add or remove an attachment to the collection depending on its validity.\n\t *\n\t * @param {wp.media.model.Attachment} attachment\n\t * @param {Object} options\n\t * @returns {wp.media.model.Attachments} Returns itself to allow chaining\n\t */\n\tvalidate: function( attachment, options ) {\n\t\tvar valid = this.validator( attachment ),\n\t\t\thasAttachment = !! this.get( attachment.cid );\n\n\t\tif ( ! valid && hasAttachment ) {\n\t\t\tthis.remove( attachment, options );\n\t\t} else if ( valid && ! hasAttachment ) {\n\t\t\tthis.add( attachment, options );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\t/**\n\t * Add or remove all attachments from another collection depending on each one's validity.\n\t *\n\t * @param {wp.media.model.Attachments} attachments\n\t * @param {object} [options={}]\n\t *\n\t * @fires wp.media.model.Attachments#reset\n\t *\n\t * @returns {wp.media.model.Attachments} Returns itself to allow chaining\n\t */\n\tvalidateAll: function( attachments, options ) {\n\t\toptions = options || {};\n\n\t\t_.each( attachments.models, function( attachment ) {\n\t\t\tthis.validate( attachment, { silent: true });\n\t\t}, this );\n\n\t\tif ( ! options.silent ) {\n\t\t\tthis.trigger( 'reset', this, options );\n\t\t}\n\t\treturn this;\n\t},\n\t/**\n\t * Start observing another attachments collection change events\n\t * and replicate them on this collection.\n\t *\n\t * @param {wp.media.model.Attachments} The attachments collection to observe.\n\t * @returns {wp.media.model.Attachments} Returns itself to allow chaining.\n\t */\n\tobserve: function( attachments ) {\n\t\tthis.observers = this.observers || [];\n\t\tthis.observers.push( attachments );\n\n\t\tattachments.on( 'add change remove', this._validateHandler, this );\n\t\tattachments.on( 'reset', this._validateAllHandler, this );\n\t\tthis.validateAll( attachments );\n\t\treturn this;\n\t},\n\t/**\n\t * Stop replicating collection change events from another attachments collection.\n\t *\n\t * @param {wp.media.model.Attachments} The attachments collection to stop observing.\n\t * @returns {wp.media.model.Attachments} Returns itself to allow chaining\n\t */\n\tunobserve: function( attachments ) {\n\t\tif ( attachments ) {\n\t\t\tattachments.off( null, null, this );\n\t\t\tthis.observers = _.without( this.observers, attachments );\n\n\t\t} else {\n\t\t\t_.each( this.observers, function( attachments ) {\n\t\t\t\tattachments.off( null, null, this );\n\t\t\t}, this );\n\t\t\tdelete this.observers;\n\t\t}\n\n\t\treturn this;\n\t},\n\t/**\n\t * @access private\n\t *\n\t * @param {wp.media.model.Attachments} attachment\n\t * @param {wp.media.model.Attachments} attachments\n\t * @param {Object} options\n\t *\n\t * @returns {wp.media.model.Attachments} Returns itself to allow chaining\n\t */\n\t_validateHandler: function( attachment, attachments, options ) {\n\t\t// If we're not mirroring this `attachments` collection,\n\t\t// only retain the `silent` option.\n\t\toptions = attachments === this.mirroring ? options : {\n\t\t\tsilent: options && options.silent\n\t\t};\n\n\t\treturn this.validate( attachment, options );\n\t},\n\t/**\n\t * @access private\n\t *\n\t * @param {wp.media.model.Attachments} attachments\n\t * @param {Object} options\n\t * @returns {wp.media.model.Attachments} Returns itself to allow chaining\n\t */\n\t_validateAllHandler: function( attachments, options ) {\n\t\treturn this.validateAll( attachments, options );\n\t},\n\t/**\n\t * Start mirroring another attachments collection, clearing out any models already\n\t * in the collection.\n\t *\n\t * @param {wp.media.model.Attachments} The attachments collection to mirror.\n\t * @returns {wp.media.model.Attachments} Returns itself to allow chaining\n\t */\n\tmirror: function( attachments ) {\n\t\tif ( this.mirroring && this.mirroring === attachments ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tthis.unmirror();\n\t\tthis.mirroring = attachments;\n\n\t\t// Clear the collection silently. A `reset` event will be fired\n\t\t// when `observe()` calls `validateAll()`.\n\t\tthis.reset( [], { silent: true } );\n\t\tthis.observe( attachments );\n\n\t\treturn this;\n\t},\n\t/**\n\t * Stop mirroring another attachments collection.\n\t */\n\tunmirror: function() {\n\t\tif ( ! this.mirroring ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.unobserve( this.mirroring );\n\t\tdelete this.mirroring;\n\t},\n\t/**\n\t * Retrieve more attachments from the server for the collection.\n\t *\n\t * Only works if the collection is mirroring a Query Attachments collection,\n\t * and forwards to its `more` method. This collection class doesn't have\n\t * server persistence by itself.\n\t *\n\t * @param {object} options\n\t * @returns {Promise}\n\t */\n\tmore: function( options ) {\n\t\tvar deferred = jQuery.Deferred(),\n\t\t\tmirroring = this.mirroring,\n\t\t\tattachments = this;\n\n\t\tif ( ! mirroring || ! mirroring.more ) {\n\t\t\treturn deferred.resolveWith( this ).promise();\n\t\t}\n\t\t// If we're mirroring another collection, forward `more` to\n\t\t// the mirrored collection. Account for a race condition by\n\t\t// checking if we're still mirroring that collection when\n\t\t// the request resolves.\n\t\tmirroring.more( options ).done( function() {\n\t\t\tif ( this === attachments.mirroring ) {\n\t\t\t\tdeferred.resolveWith( this );\n\t\t\t}\n\t\t});\n\n\t\treturn deferred.promise();\n\t},\n\t/**\n\t * Whether there are more attachments that haven't been sync'd from the server\n\t * that match the collection's query.\n\t *\n\t * Only works if the collection is mirroring a Query Attachments collection,\n\t * and forwards to its `hasMore` method. This collection class doesn't have\n\t * server persistence by itself.\n\t *\n\t * @returns {boolean}\n\t */\n\thasMore: function() {\n\t\treturn this.mirroring ? this.mirroring.hasMore() : false;\n\t},\n\t/**\n\t * A custom AJAX-response parser.\n\t *\n\t * See trac ticket #24753\n\t *\n\t * @param {Object|Array} resp The raw response Object/Array.\n\t * @param {Object} xhr\n\t * @returns {Array} The array of model attributes to be added to the collection\n\t */\n\tparse: function( resp, xhr ) {\n\t\tif ( ! _.isArray( resp ) ) {\n\t\t\tresp = [resp];\n\t\t}\n\n\t\treturn _.map( resp, function( attrs ) {\n\t\t\tvar id, attachment, newAttributes;\n\n\t\t\tif ( attrs instanceof Backbone.Model ) {\n\t\t\t\tid = attrs.get( 'id' );\n\t\t\t\tattrs = attrs.attributes;\n\t\t\t} else {\n\t\t\t\tid = attrs.id;\n\t\t\t}\n\n\t\t\tattachment = wp.media.model.Attachment.get( id );\n\t\t\tnewAttributes = attachment.parse( attrs, xhr );\n\n\t\t\tif ( ! _.isEqual( attachment.attributes, newAttributes ) ) {\n\t\t\t\tattachment.set( newAttributes );\n\t\t\t}\n\n\t\t\treturn attachment;\n\t\t});\n\t},\n\t/**\n\t * If the collection is a query, create and mirror an Attachments Query collection.\n\t *\n\t * @access private\n\t */\n\t_requery: function( refresh ) {\n\t\tvar props;\n\t\tif ( this.props.get('query') ) {\n\t\t\tprops = this.props.toJSON();\n\t\t\tprops.cache = ( true !== refresh );\n\t\t\tthis.mirror( wp.media.model.Query.get( props ) );\n\t\t}\n\t},\n\t/**\n\t * If this collection is sorted by `menuOrder`, recalculates and saves\n\t * the menu order to the database.\n\t *\n\t * @returns {undefined|Promise}\n\t */\n\tsaveMenuOrder: function() {\n\t\tif ( 'menuOrder' !== this.props.get('orderby') ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Removes any uploading attachments, updates each attachment's\n\t\t// menu order, and returns an object with an { id: menuOrder }\n\t\t// mapping to pass to the request.\n\t\tvar attachments = this.chain().filter( function( attachment ) {\n\t\t\treturn ! _.isUndefined( attachment.id );\n\t\t}).map( function( attachment, index ) {\n\t\t\t// Indices start at 1.\n\t\t\tindex = index + 1;\n\t\t\tattachment.set( 'menuOrder', index );\n\t\t\treturn [ attachment.id, index ];\n\t\t}).object().value();\n\n\t\tif ( _.isEmpty( attachments ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\treturn wp.media.post( 'save-attachment-order', {\n\t\t\tnonce: wp.media.model.settings.post.nonce,\n\t\t\tpost_id: wp.media.model.settings.post.id,\n\t\t\tattachments: attachments\n\t\t});\n\t}\n},/** @lends wp.media.model.Attachments */{\n\t/**\n\t * A function to compare two attachment models in an attachments collection.\n\t *\n\t * Used as the default comparator for instances of wp.media.model.Attachments\n\t * and its subclasses. @see wp.media.model.Attachments._changeOrderby().\n\t *\n\t * @param {Backbone.Model} a\n\t * @param {Backbone.Model} b\n\t * @param {Object} options\n\t * @returns {Number} -1 if the first model should come before the second,\n\t * 0 if they are of the same rank and\n\t * 1 if the first model should come after.\n\t */\n\tcomparator: function( a, b, options ) {\n\t\tvar key = this.props.get('orderby'),\n\t\t\torder = this.props.get('order') || 'DESC',\n\t\t\tac = a.cid,\n\t\t\tbc = b.cid;\n\n\t\ta = a.get( key );\n\t\tb = b.get( key );\n\n\t\tif ( 'date' === key || 'modified' === key ) {\n\t\t\ta = a || new Date();\n\t\t\tb = b || new Date();\n\t\t}\n\n\t\t// If `options.ties` is set, don't enforce the `cid` tiebreaker.\n\t\tif ( options && options.ties ) {\n\t\t\tac = bc = null;\n\t\t}\n\n\t\treturn ( 'DESC' === order ) ? wp.media.compare( a, b, ac, bc ) : wp.media.compare( b, a, bc, ac );\n\t},\n\t/** @namespace wp.media.model.Attachments.filters */\n\tfilters: {\n\t\t/**\n\t\t * @static\n\t\t * Note that this client-side searching is *not* equivalent\n\t\t * to our server-side searching.\n\t\t *\n\t\t * @param {wp.media.model.Attachment} attachment\n\t\t *\n\t\t * @this wp.media.model.Attachments\n\t\t *\n\t\t * @returns {Boolean}\n\t\t */\n\t\tsearch: function( attachment ) {\n\t\t\tif ( ! this.props.get('search') ) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn _.any(['title','filename','description','caption','name'], function( key ) {\n\t\t\t\tvar value = attachment.get( key );\n\t\t\t\treturn value && -1 !== value.search( this.props.get('search') );\n\t\t\t}, this );\n\t\t},\n\t\t/**\n\t\t * @static\n\t\t * @param {wp.media.model.Attachment} attachment\n\t\t *\n\t\t * @this wp.media.model.Attachments\n\t\t *\n\t\t * @returns {Boolean}\n\t\t */\n\t\ttype: function( attachment ) {\n\t\t\tvar type = this.props.get('type'), atts = attachment.toJSON(), mime, found;\n\n\t\t\tif ( ! type || ( _.isArray( type ) && ! type.length ) ) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tmime = atts.mime || ( atts.file && atts.file.type ) || '';\n\n\t\t\tif ( _.isArray( type ) ) {\n\t\t\t\tfound = _.find( type, function (t) {\n\t\t\t\t\treturn -1 !== mime.indexOf( t );\n\t\t\t\t} );\n\t\t\t} else {\n\t\t\t\tfound = -1 !== mime.indexOf( type );\n\t\t\t}\n\n\t\t\treturn found;\n\t\t},\n\t\t/**\n\t\t * @static\n\t\t * @param {wp.media.model.Attachment} attachment\n\t\t *\n\t\t * @this wp.media.model.Attachments\n\t\t *\n\t\t * @returns {Boolean}\n\t\t */\n\t\tuploadedTo: function( attachment ) {\n\t\t\tvar uploadedTo = this.props.get('uploadedTo');\n\t\t\tif ( _.isUndefined( uploadedTo ) ) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn uploadedTo === attachment.get('uploadedTo');\n\t\t},\n\t\t/**\n\t\t * @static\n\t\t * @param {wp.media.model.Attachment} attachment\n\t\t *\n\t\t * @this wp.media.model.Attachments\n\t\t *\n\t\t * @returns {Boolean}\n\t\t */\n\t\tstatus: function( attachment ) {\n\t\t\tvar status = this.props.get('status');\n\t\t\tif ( _.isUndefined( status ) ) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn status === attachment.get('status');\n\t\t}\n\t}\n});\n\nmodule.exports = Attachments;\n\n\n//# sourceURL=webpack:///./src/js/media/models/attachments.js?")},"./src/js/media/models/post-image.js":function(module,exports){eval("/**\n * wp.media.model.PostImage\n *\n * An instance of an image that's been embedded into a post.\n *\n * Used in the embedded image attachment display settings modal - @see wp.media.view.MediaFrame.ImageDetails.\n *\n * @memberOf wp.media.model\n *\n * @class\n * @augments Backbone.Model\n *\n * @param {int} [attributes] Initial model attributes.\n * @param {int} [attributes.attachment_id] ID of the attachment.\n **/\nvar PostImage = Backbone.Model.extend(/** @lends wp.media.model.PostImage.prototype */{\n\n\tinitialize: function( attributes ) {\n\t\tvar Attachment = wp.media.model.Attachment;\n\t\tthis.attachment = false;\n\n\t\tif ( attributes.attachment_id ) {\n\t\t\tthis.attachment = Attachment.get( attributes.attachment_id );\n\t\t\tif ( this.attachment.get( 'url' ) ) {\n\t\t\t\tthis.dfd = jQuery.Deferred();\n\t\t\t\tthis.dfd.resolve();\n\t\t\t} else {\n\t\t\t\tthis.dfd = this.attachment.fetch();\n\t\t\t}\n\t\t\tthis.bindAttachmentListeners();\n\t\t}\n\n\t\t// keep url in sync with changes to the type of link\n\t\tthis.on( 'change:link', this.updateLinkUrl, this );\n\t\tthis.on( 'change:size', this.updateSize, this );\n\n\t\tthis.setLinkTypeFromUrl();\n\t\tthis.setAspectRatio();\n\n\t\tthis.set( 'originalUrl', attributes.url );\n\t},\n\n\tbindAttachmentListeners: function() {\n\t\tthis.listenTo( this.attachment, 'sync', this.setLinkTypeFromUrl );\n\t\tthis.listenTo( this.attachment, 'sync', this.setAspectRatio );\n\t\tthis.listenTo( this.attachment, 'change', this.updateSize );\n\t},\n\n\tchangeAttachment: function( attachment, props ) {\n\t\tthis.stopListening( this.attachment );\n\t\tthis.attachment = attachment;\n\t\tthis.bindAttachmentListeners();\n\n\t\tthis.set( 'attachment_id', this.attachment.get( 'id' ) );\n\t\tthis.set( 'caption', this.attachment.get( 'caption' ) );\n\t\tthis.set( 'alt', this.attachment.get( 'alt' ) );\n\t\tthis.set( 'size', props.get( 'size' ) );\n\t\tthis.set( 'align', props.get( 'align' ) );\n\t\tthis.set( 'link', props.get( 'link' ) );\n\t\tthis.updateLinkUrl();\n\t\tthis.updateSize();\n\t},\n\n\tsetLinkTypeFromUrl: function() {\n\t\tvar linkUrl = this.get( 'linkUrl' ),\n\t\t\ttype;\n\n\t\tif ( ! linkUrl ) {\n\t\t\tthis.set( 'link', 'none' );\n\t\t\treturn;\n\t\t}\n\n\t\t// default to custom if there is a linkUrl\n\t\ttype = 'custom';\n\n\t\tif ( this.attachment ) {\n\t\t\tif ( this.attachment.get( 'url' ) === linkUrl ) {\n\t\t\t\ttype = 'file';\n\t\t\t} else if ( this.attachment.get( 'link' ) === linkUrl ) {\n\t\t\t\ttype = 'post';\n\t\t\t}\n\t\t} else {\n\t\t\tif ( this.get( 'url' ) === linkUrl ) {\n\t\t\t\ttype = 'file';\n\t\t\t}\n\t\t}\n\n\t\tthis.set( 'link', type );\n\t},\n\n\tupdateLinkUrl: function() {\n\t\tvar link = this.get( 'link' ),\n\t\t\turl;\n\n\t\tswitch( link ) {\n\t\t\tcase 'file':\n\t\t\t\tif ( this.attachment ) {\n\t\t\t\t\turl = this.attachment.get( 'url' );\n\t\t\t\t} else {\n\t\t\t\t\turl = this.get( 'url' );\n\t\t\t\t}\n\t\t\t\tthis.set( 'linkUrl', url );\n\t\t\t\tbreak;\n\t\t\tcase 'post':\n\t\t\t\tthis.set( 'linkUrl', this.attachment.get( 'link' ) );\n\t\t\t\tbreak;\n\t\t\tcase 'none':\n\t\t\t\tthis.set( 'linkUrl', '' );\n\t\t\t\tbreak;\n\t\t}\n\t},\n\n\tupdateSize: function() {\n\t\tvar size;\n\n\t\tif ( ! this.attachment ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( this.get( 'size' ) === 'custom' ) {\n\t\t\tthis.set( 'width', this.get( 'customWidth' ) );\n\t\t\tthis.set( 'height', this.get( 'customHeight' ) );\n\t\t\tthis.set( 'url', this.get( 'originalUrl' ) );\n\t\t\treturn;\n\t\t}\n\n\t\tsize = this.attachment.get( 'sizes' )[ this.get( 'size' ) ];\n\n\t\tif ( ! size ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.set( 'url', size.url );\n\t\tthis.set( 'width', size.width );\n\t\tthis.set( 'height', size.height );\n\t},\n\n\tsetAspectRatio: function() {\n\t\tvar full;\n\n\t\tif ( this.attachment && this.attachment.get( 'sizes' ) ) {\n\t\t\tfull = this.attachment.get( 'sizes' ).full;\n\n\t\t\tif ( full ) {\n\t\t\t\tthis.set( 'aspectRatio', full.width / full.height );\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tthis.set( 'aspectRatio', this.get( 'customWidth' ) / this.get( 'customHeight' ) );\n\t}\n});\n\nmodule.exports = PostImage;\n\n\n//# sourceURL=webpack:///./src/js/media/models/post-image.js?"); -},"./src/js/media/models/query.js":function(module,exports){eval("var Attachments = wp.media.model.Attachments,\n\tQuery;\n\n/**\n * wp.media.model.Query\n *\n * A collection of attachments that match the supplied query arguments.\n *\n * Note: Do NOT change this.args after the query has been initialized.\n * Things will break.\n *\n * @memberOf wp.media.model\n *\n * @class\n * @augments wp.media.model.Attachments\n * @augments Backbone.Collection\n *\n * @param {array} [models] Models to initialize with the collection.\n * @param {object} [options] Options hash.\n * @param {object} [options.args] Attachments query arguments.\n * @param {object} [options.args.posts_per_page]\n */\nQuery = Attachments.extend(/** @lends wp.media.model.Query.prototype */{\n\t/**\n\t * @param {array} [models=[]] Array of initial models to populate the collection.\n\t * @param {object} [options={}]\n\t */\n\tinitialize: function( models, options ) {\n\t\tvar allowed;\n\n\t\toptions = options || {};\n\t\tAttachments.prototype.initialize.apply( this, arguments );\n\n\t\tthis.args = options.args;\n\t\tthis._hasMore = true;\n\t\tthis.created = new Date();\n\n\t\tthis.filters.order = function( attachment ) {\n\t\t\tvar orderby = this.props.get('orderby'),\n\t\t\t\torder = this.props.get('order');\n\n\t\t\tif ( ! this.comparator ) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t// We want any items that can be placed before the last\n\t\t\t// item in the set. If we add any items after the last\n\t\t\t// item, then we can't guarantee the set is complete.\n\t\t\tif ( this.length ) {\n\t\t\t\treturn 1 !== this.comparator( attachment, this.last(), { ties: true });\n\n\t\t\t// Handle the case where there are no items yet and\n\t\t\t// we're sorting for recent items. In that case, we want\n\t\t\t// changes that occurred after we created the query.\n\t\t\t} else if ( 'DESC' === order && ( 'date' === orderby || 'modified' === orderby ) ) {\n\t\t\t\treturn attachment.get( orderby ) >= this.created;\n\n\t\t\t// If we're sorting by menu order and we have no items,\n\t\t\t// accept any items that have the default menu order (0).\n\t\t\t} else if ( 'ASC' === order && 'menuOrder' === orderby ) {\n\t\t\t\treturn attachment.get( orderby ) === 0;\n\t\t\t}\n\n\t\t\t// Otherwise, we don't want any items yet.\n\t\t\treturn false;\n\t\t};\n\n\t\t// Observe the central `wp.Uploader.queue` collection to watch for\n\t\t// new matches for the query.\n\t\t//\n\t\t// Only observe when a limited number of query args are set. There\n\t\t// are no filters for other properties, so observing will result in\n\t\t// false positives in those queries.\n\t\tallowed = [ 's', 'order', 'orderby', 'posts_per_page', 'post_mime_type', 'post_parent', 'author' ];\n\t\tif ( wp.Uploader && _( this.args ).chain().keys().difference( allowed ).isEmpty().value() ) {\n\t\t\tthis.observe( wp.Uploader.queue );\n\t\t}\n\t},\n\t/**\n\t * Whether there are more attachments that haven't been sync'd from the server\n\t * that match the collection's query.\n\t *\n\t * @returns {boolean}\n\t */\n\thasMore: function() {\n\t\treturn this._hasMore;\n\t},\n\t/**\n\t * Fetch more attachments from the server for the collection.\n\t *\n\t * @param {object} [options={}]\n\t * @returns {Promise}\n\t */\n\tmore: function( options ) {\n\t\tvar query = this;\n\n\t\t// If there is already a request pending, return early with the Deferred object.\n\t\tif ( this._more && 'pending' === this._more.state() ) {\n\t\t\treturn this._more;\n\t\t}\n\n\t\tif ( ! this.hasMore() ) {\n\t\t\treturn jQuery.Deferred().resolveWith( this ).promise();\n\t\t}\n\n\t\toptions = options || {};\n\t\toptions.remove = false;\n\n\t\treturn this._more = this.fetch( options ).done( function( resp ) {\n\t\t\tif ( _.isEmpty( resp ) || -1 === this.args.posts_per_page || resp.length < this.args.posts_per_page ) {\n\t\t\t\tquery._hasMore = false;\n\t\t\t}\n\t\t});\n\t},\n\t/**\n\t * Overrides Backbone.Collection.sync\n\t * Overrides wp.media.model.Attachments.sync\n\t *\n\t * @param {String} method\n\t * @param {Backbone.Model} model\n\t * @param {Object} [options={}]\n\t * @returns {Promise}\n\t */\n\tsync: function( method, model, options ) {\n\t\tvar args, fallback;\n\n\t\t// Overload the read method so Attachment.fetch() functions correctly.\n\t\tif ( 'read' === method ) {\n\t\t\toptions = options || {};\n\t\t\toptions.context = this;\n\t\t\toptions.data = _.extend( options.data || {}, {\n\t\t\t\taction: 'query-attachments',\n\t\t\t\tpost_id: wp.media.model.settings.post.id\n\t\t\t});\n\n\t\t\t// Clone the args so manipulation is non-destructive.\n\t\t\targs = _.clone( this.args );\n\n\t\t\t// Determine which page to query.\n\t\t\tif ( -1 !== args.posts_per_page ) {\n\t\t\t\targs.paged = Math.round( this.length / args.posts_per_page ) + 1;\n\t\t\t}\n\n\t\t\toptions.data.query = args;\n\t\t\treturn wp.media.ajax( options );\n\n\t\t// Otherwise, fall back to Backbone.sync()\n\t\t} else {\n\t\t\t/**\n\t\t\t * Call wp.media.model.Attachments.sync or Backbone.sync\n\t\t\t */\n\t\t\tfallback = Attachments.prototype.sync ? Attachments.prototype : Backbone;\n\t\t\treturn fallback.sync.apply( this, arguments );\n\t\t}\n\t}\n}, /** @lends wp.media.model.Query */{\n\t/**\n\t * @readonly\n\t */\n\tdefaultProps: {\n\t\torderby: 'date',\n\t\torder: 'DESC'\n\t},\n\t/**\n\t * @readonly\n\t */\n\tdefaultArgs: {\n\t\tposts_per_page: 40\n\t},\n\t/**\n\t * @readonly\n\t */\n\torderby: {\n\t\tallowed: [ 'name', 'author', 'date', 'title', 'modified', 'uploadedTo', 'id', 'post__in', 'menuOrder' ],\n\t\t/**\n\t\t * A map of JavaScript orderby values to their WP_Query equivalents.\n\t\t * @type {Object}\n\t\t */\n\t\tvaluemap: {\n\t\t\t'id': 'ID',\n\t\t\t'uploadedTo': 'parent',\n\t\t\t'menuOrder': 'menu_order ID'\n\t\t}\n\t},\n\t/**\n\t * A map of JavaScript query properties to their WP_Query equivalents.\n\t *\n\t * @readonly\n\t */\n\tpropmap: {\n\t\t'search':\t\t's',\n\t\t'type':\t\t\t'post_mime_type',\n\t\t'perPage':\t\t'posts_per_page',\n\t\t'menuOrder':\t'menu_order',\n\t\t'uploadedTo':\t'post_parent',\n\t\t'status':\t\t'post_status',\n\t\t'include':\t\t'post__in',\n\t\t'exclude':\t\t'post__not_in',\n\t\t'author':\t\t'author'\n\t},\n\t/**\n\t * Creates and returns an Attachments Query collection given the properties.\n\t *\n\t * Caches query objects and reuses where possible.\n\t *\n\t * @static\n\t * @method\n\t *\n\t * @param {object} [props]\n\t * @param {Object} [props.cache=true] Whether to use the query cache or not.\n\t * @param {Object} [props.order]\n\t * @param {Object} [props.orderby]\n\t * @param {Object} [props.include]\n\t * @param {Object} [props.exclude]\n\t * @param {Object} [props.s]\n\t * @param {Object} [props.post_mime_type]\n\t * @param {Object} [props.posts_per_page]\n\t * @param {Object} [props.menu_order]\n\t * @param {Object} [props.post_parent]\n\t * @param {Object} [props.post_status]\n\t * @param {Object} [props.author]\n\t * @param {Object} [options]\n\t *\n\t * @returns {wp.media.model.Query} A new Attachments Query collection.\n\t */\n\tget: (function(){\n\t\t/**\n\t\t * @static\n\t\t * @type Array\n\t\t */\n\t\tvar queries = [];\n\n\t\t/**\n\t\t * @returns {Query}\n\t\t */\n\t\treturn function( props, options ) {\n\t\t\tvar args = {},\n\t\t\t\torderby = Query.orderby,\n\t\t\t\tdefaults = Query.defaultProps,\n\t\t\t\tquery,\n\t\t\t\tcache = !! props.cache || _.isUndefined( props.cache );\n\n\t\t\t// Remove the `query` property. This isn't linked to a query,\n\t\t\t// this *is* the query.\n\t\t\tdelete props.query;\n\t\t\tdelete props.cache;\n\n\t\t\t// Fill default args.\n\t\t\t_.defaults( props, defaults );\n\n\t\t\t// Normalize the order.\n\t\t\tprops.order = props.order.toUpperCase();\n\t\t\tif ( 'DESC' !== props.order && 'ASC' !== props.order ) {\n\t\t\t\tprops.order = defaults.order.toUpperCase();\n\t\t\t}\n\n\t\t\t// Ensure we have a valid orderby value.\n\t\t\tif ( ! _.contains( orderby.allowed, props.orderby ) ) {\n\t\t\t\tprops.orderby = defaults.orderby;\n\t\t\t}\n\n\t\t\t_.each( [ 'include', 'exclude' ], function( prop ) {\n\t\t\t\tif ( props[ prop ] && ! _.isArray( props[ prop ] ) ) {\n\t\t\t\t\tprops[ prop ] = [ props[ prop ] ];\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\t// Generate the query `args` object.\n\t\t\t// Correct any differing property names.\n\t\t\t_.each( props, function( value, prop ) {\n\t\t\t\tif ( _.isNull( value ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\targs[ Query.propmap[ prop ] || prop ] = value;\n\t\t\t});\n\n\t\t\t// Fill any other default query args.\n\t\t\t_.defaults( args, Query.defaultArgs );\n\n\t\t\t// `props.orderby` does not always map directly to `args.orderby`.\n\t\t\t// Substitute exceptions specified in orderby.keymap.\n\t\t\targs.orderby = orderby.valuemap[ props.orderby ] || props.orderby;\n\n\t\t\t// Search the query cache for a matching query.\n\t\t\tif ( cache ) {\n\t\t\t\tquery = _.find( queries, function( query ) {\n\t\t\t\t\treturn _.isEqual( query.args, args );\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tqueries = [];\n\t\t\t}\n\n\t\t\t// Otherwise, create a new query and add it to the cache.\n\t\t\tif ( ! query ) {\n\t\t\t\tquery = new Query( [], _.extend( options || {}, {\n\t\t\t\t\tprops: props,\n\t\t\t\t\targs: args\n\t\t\t\t} ) );\n\t\t\t\tqueries.push( query );\n\t\t\t}\n\n\t\t\treturn query;\n\t\t};\n\t}())\n});\n\nmodule.exports = Query;\n\n\n//# sourceURL=webpack:///./src/js/media/models/query.js?")},"./src/js/media/models/selection.js":function(module,exports){eval("var Attachments = wp.media.model.Attachments,\n\tSelection;\n\n/**\n * wp.media.model.Selection\n *\n * A selection of attachments.\n *\n * @memberOf wp.media.model\n *\n * @class\n * @augments wp.media.model.Attachments\n * @augments Backbone.Collection\n */\nSelection = Attachments.extend(/** @lends wp.media.model.Selection.prototype */{\n\t/**\n\t * Refresh the `single` model whenever the selection changes.\n\t * Binds `single` instead of using the context argument to ensure\n\t * it receives no parameters.\n\t *\n\t * @param {Array} [models=[]] Array of models used to populate the collection.\n\t * @param {Object} [options={}]\n\t */\n\tinitialize: function( models, options ) {\n\t\t/**\n\t\t * call 'initialize' directly on the parent class\n\t\t */\n\t\tAttachments.prototype.initialize.apply( this, arguments );\n\t\tthis.multiple = options && options.multiple;\n\n\t\tthis.on( 'add remove reset', _.bind( this.single, this, false ) );\n\t},\n\n\t/**\n\t * If the workflow does not support multi-select, clear out the selection\n\t * before adding a new attachment to it.\n\t *\n\t * @param {Array} models\n\t * @param {Object} options\n\t * @returns {wp.media.model.Attachment[]}\n\t */\n\tadd: function( models, options ) {\n\t\tif ( ! this.multiple ) {\n\t\t\tthis.remove( this.models );\n\t\t}\n\t\t/**\n\t\t * call 'add' directly on the parent class\n\t\t */\n\t\treturn Attachments.prototype.add.call( this, models, options );\n\t},\n\n\t/**\n\t * Fired when toggling (clicking on) an attachment in the modal.\n\t *\n\t * @param {undefined|boolean|wp.media.model.Attachment} model\n\t *\n\t * @fires wp.media.model.Selection#selection:single\n\t * @fires wp.media.model.Selection#selection:unsingle\n\t *\n\t * @returns {Backbone.Model}\n\t */\n\tsingle: function( model ) {\n\t\tvar previous = this._single;\n\n\t\t// If a `model` is provided, use it as the single model.\n\t\tif ( model ) {\n\t\t\tthis._single = model;\n\t\t}\n\t\t// If the single model isn't in the selection, remove it.\n\t\tif ( this._single && ! this.get( this._single.cid ) ) {\n\t\t\tdelete this._single;\n\t\t}\n\n\t\tthis._single = this._single || this.last();\n\n\t\t// If single has changed, fire an event.\n\t\tif ( this._single !== previous ) {\n\t\t\tif ( previous ) {\n\t\t\t\tprevious.trigger( 'selection:unsingle', previous, this );\n\n\t\t\t\t// If the model was already removed, trigger the collection\n\t\t\t\t// event manually.\n\t\t\t\tif ( ! this.get( previous.cid ) ) {\n\t\t\t\t\tthis.trigger( 'selection:unsingle', previous, this );\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( this._single ) {\n\t\t\t\tthis._single.trigger( 'selection:single', this._single, this );\n\t\t\t}\n\t\t}\n\n\t\t// Return the single model, or the last model as a fallback.\n\t\treturn this._single;\n\t}\n});\n\nmodule.exports = Selection;\n\n\n//# sourceURL=webpack:///./src/js/media/models/selection.js?")},2:function(module,exports,__webpack_require__){eval('module.exports = __webpack_require__(/*! ./src/js/_enqueues/wp/media/models.js */"./src/js/_enqueues/wp/media/models.js");\n\n\n//# sourceURL=webpack:///multi_./src/js/_enqueues/wp/media/models.js?')}}); \ No newline at end of file +!function(a){function b(d){if(c[d])return c[d].exports;var e=c[d]={i:d,l:!1,exports:{}};return a[d].call(e.exports,e,e.exports,b),e.l=!0,e.exports}var c={};return b.m=a,b.c=c,b.d=function(a,c,d){b.o(a,c)||Object.defineProperty(a,c,{enumerable:!0,get:d})},b.r=function(a){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(a,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(a,"__esModule",{value:!0})},b.t=function(a,c){if(1&c&&(a=b(a)),8&c)return a;if(4&c&&"object"==typeof a&&a&&a.__esModule)return a;var d=Object.create(null);if(b.r(d),Object.defineProperty(d,"default",{enumerable:!0,value:a}),2&c&&"string"!=typeof a)for(var e in a)b.d(d,e,function(b){return a[b]}.bind(null,e));return d},b.n=function(a){var c=a&&a.__esModule?function(){return a["default"]}:function(){return a};return b.d(c,"a",c),c},b.o=function(a,b){return Object.prototype.hasOwnProperty.call(a,b)},b.p="",b(b.s=22)}({22:function(a,b,c){a.exports=c(23)},23:function(a,b,c){var d,e,f,g,h=jQuery;window.wp=window.wp||{},g=wp.media=function(a){var b,c=g.view.MediaFrame;if(c)return a=_.defaults(a||{},{frame:"select"}),"select"===a.frame&&c.Select?b=new c.Select(a):"post"===a.frame&&c.Post?b=new c.Post(a):"manage"===a.frame&&c.Manage?b=new c.Manage(a):"image"===a.frame&&c.ImageDetails?b=new c.ImageDetails(a):"audio"===a.frame&&c.AudioDetails?b=new c.AudioDetails(a):"video"===a.frame&&c.VideoDetails?b=new c.VideoDetails(a):"edit-attachments"===a.frame&&c.EditAttachments&&(b=new c.EditAttachments(a)),delete a.frame,g.frame=b,b},_.extend(g,{model:{},view:{},controller:{},frames:{}}),f=g.model.l10n=window._wpMediaModelsL10n||{},g.model.settings=f.settings||{},delete f.settings,d=g.model.Attachment=c(24),e=g.model.Attachments=c(25),g.model.Query=c(26),g.model.PostImage=c(27),g.model.Selection=c(28),g.compare=function(a,b,c,d){return _.isEqual(a,b)?c===d?0:c>d?-1:1:a>b?-1:1},_.extend(g,{template:wp.template,post:wp.ajax.post,ajax:wp.ajax.send,fit:function(a){var b,c=a.width,d=a.height,e=a.maxWidth,f=a.maxHeight;return _.isUndefined(e)||_.isUndefined(f)?_.isUndefined(f)?b="width":_.isUndefined(e)&&d>f&&(b="height"):b=c/d>e/f?"width":"height","width"===b&&c>e?{width:e,height:Math.round(e*d/c)}:"height"===b&&d>f?{width:Math.round(f*c/d),height:f}:{width:c,height:d}},truncate:function(a,b,c){return b=b||30,c=c||"…",a.length<=b?a:a.substr(0,b/2)+c+a.substr(-1*b/2)}}),g.attachment=function(a){return d.get(a)},e.all=new e,g.query=function(a){return new e(null,{props:_.extend(_.defaults(a||{},{orderby:"date"}),{query:!0})})},h(window).on("unload",function(){window.wp=null})},24:function(a,b){var c,d=Backbone.$;c=Backbone.Model.extend({sync:function(a,b,c){return _.isUndefined(this.id)?d.Deferred().rejectWith(this).promise():"read"===a?(c=c||{},c.context=this,c.data=_.extend(c.data||{},{action:"get-attachment",id:this.id}),wp.media.ajax(c)):"update"===a?this.get("nonces")&&this.get("nonces").update?(c=c||{},c.context=this,c.data=_.extend(c.data||{},{action:"save-attachment",id:this.id,nonce:this.get("nonces").update,post_id:wp.media.model.settings.post.id}),b.hasChanged()&&(c.data.changes={},_.each(b.changed,function(a,b){c.data.changes[b]=this.get(b)},this)),wp.media.ajax(c)):d.Deferred().rejectWith(this).promise():"delete"===a?(c=c||{},c.wait||(this.destroyed=!0),c.context=this,c.data=_.extend(c.data||{},{action:"delete-post",id:this.id,_wpnonce:this.get("nonces")["delete"]}),wp.media.ajax(c).done(function(){this.destroyed=!0}).fail(function(){this.destroyed=!1})):Backbone.Model.prototype.sync.apply(this,arguments)},parse:function(a){return a?(a.date=new Date(a.date),a.modified=new Date(a.modified),a):a},saveCompat:function(a,b){var c=this;return this.get("nonces")&&this.get("nonces").update?wp.media.post("save-attachment-compat",_.defaults({id:this.id,nonce:this.get("nonces").update,post_id:wp.media.model.settings.post.id},a)).done(function(a,d,e){c.set(c.parse(a,e),b)}):d.Deferred().rejectWith(this).promise()}},{create:function(a){var b=wp.media.model.Attachments;return b.all.push(a)},get:_.memoize(function(a,b){var c=wp.media.model.Attachments;return c.all.push(b||{id:a})})}),a.exports=c},25:function(a,b){var c=Backbone.Collection.extend({model:wp.media.model.Attachment,initialize:function(a,b){b=b||{},this.props=new Backbone.Model,this.filters=b.filters||{},this.props.on("change",this._changeFilteredProps,this),this.props.on("change:order",this._changeOrder,this),this.props.on("change:orderby",this._changeOrderby,this),this.props.on("change:query",this._changeQuery,this),this.props.set(_.defaults(b.props||{})),b.observe&&this.observe(b.observe)},_changeOrder:function(){this.comparator&&this.sort()},_changeOrderby:function(a,b){this.comparator&&this.comparator!==c.comparator||(b&&"post__in"!==b?this.comparator=c.comparator:delete this.comparator)},_changeQuery:function(a,b){b?(this.props.on("change",this._requery,this),this._requery()):this.props.off("change",this._requery,this)},_changeFilteredProps:function(a){if(!this.props.get("query")){var b=_.chain(a.changed).map(function(b,d){var e=c.filters[d],f=a.get(d);if(e){if(f&&!this.filters[d])this.filters[d]=e;else{if(f||this.filters[d]!==e)return;delete this.filters[d]}return!0}},this).any().value();b&&(this._source||(this._source=new c(this.models)),this.reset(this._source.filter(this.validator,this)))}},validateDestroyed:!1,validator:function(a){return!(!_.isUndefined(a.attributes.context)&&""!==a.attributes.context)&&(!(!this.validateDestroyed&&a.destroyed)&&_.all(this.filters,function(b){return!!b.call(this,a)},this))},validate:function(a,b){var c=this.validator(a),d=!!this.get(a.cid);return!c&&d?this.remove(a,b):c&&!d&&this.add(a,b),this},validateAll:function(a,b){return b=b||{},_.each(a.models,function(a){this.validate(a,{silent:!0})},this),b.silent||this.trigger("reset",this,b),this},observe:function(a){return this.observers=this.observers||[],this.observers.push(a),a.on("add change remove",this._validateHandler,this),a.on("reset",this._validateAllHandler,this),this.validateAll(a),this},unobserve:function(a){return a?(a.off(null,null,this),this.observers=_.without(this.observers,a)):(_.each(this.observers,function(a){a.off(null,null,this)},this),delete this.observers),this},_validateHandler:function(a,b,c){return c=b===this.mirroring?c:{silent:c&&c.silent},this.validate(a,c)},_validateAllHandler:function(a,b){return this.validateAll(a,b)},mirror:function(a){return this.mirroring&&this.mirroring===a?this:(this.unmirror(),this.mirroring=a,this.reset([],{silent:!0}),this.observe(a),this)},unmirror:function(){this.mirroring&&(this.unobserve(this.mirroring),delete this.mirroring)},more:function(a){var b=jQuery.Deferred(),c=this.mirroring,d=this;return c&&c.more?(c.more(a).done(function(){this===d.mirroring&&b.resolveWith(this)}),b.promise()):b.resolveWith(this).promise()},hasMore:function(){return!!this.mirroring&&this.mirroring.hasMore()},parse:function(a,b){return _.isArray(a)||(a=[a]),_.map(a,function(a){var c,d,e;return a instanceof Backbone.Model?(c=a.get("id"),a=a.attributes):c=a.id,d=wp.media.model.Attachment.get(c),e=d.parse(a,b),_.isEqual(d.attributes,e)||d.set(e),d})},_requery:function(a){var b;this.props.get("query")&&(b=this.props.toJSON(),b.cache=!0!==a,this.mirror(wp.media.model.Query.get(b)))},saveMenuOrder:function(){if("menuOrder"===this.props.get("orderby")){var a=this.chain().filter(function(a){return!_.isUndefined(a.id)}).map(function(a,b){return b+=1,a.set("menuOrder",b),[a.id,b]}).object().value();if(!_.isEmpty(a))return wp.media.post("save-attachment-order",{nonce:wp.media.model.settings.post.nonce,post_id:wp.media.model.settings.post.id,attachments:a})}}},{comparator:function(a,b,c){var d=this.props.get("orderby"),e=this.props.get("order")||"DESC",f=a.cid,g=b.cid;return a=a.get(d),b=b.get(d),"date"!==d&&"modified"!==d||(a=a||new Date,b=b||new Date),c&&c.ties&&(f=g=null),"DESC"===e?wp.media.compare(a,b,f,g):wp.media.compare(b,a,g,f)},filters:{search:function(a){return!this.props.get("search")||_.any(["title","filename","description","caption","name"],function(b){var c=a.get(b);return c&&-1!==c.search(this.props.get("search"))},this)},type:function(a){var b,c,d=this.props.get("type"),e=a.toJSON();return!(d&&(!_.isArray(d)||d.length))||(b=e.mime||e.file&&e.file.type||"",c=_.isArray(d)?_.find(d,function(a){return-1!==b.indexOf(a)}):-1!==b.indexOf(d))},uploadedTo:function(a){var b=this.props.get("uploadedTo");return!!_.isUndefined(b)||b===a.get("uploadedTo")},status:function(a){var b=this.props.get("status");return!!_.isUndefined(b)||b===a.get("status")}}});a.exports=c},26:function(a,b){var c,d=wp.media.model.Attachments;c=d.extend({initialize:function(a,b){var c;b=b||{},d.prototype.initialize.apply(this,arguments),this.args=b.args,this._hasMore=!0,this.created=new Date,this.filters.order=function(a){var b=this.props.get("orderby"),c=this.props.get("order");return!this.comparator||(this.length?1!==this.comparator(a,this.last(),{ties:!0}):"DESC"!==c||"date"!==b&&"modified"!==b?"ASC"===c&&"menuOrder"===b&&0===a.get(b):a.get(b)>=this.created)},c=["s","order","orderby","posts_per_page","post_mime_type","post_parent","author"],wp.Uploader&&_(this.args).chain().keys().difference(c).isEmpty().value()&&this.observe(wp.Uploader.queue)},hasMore:function(){return this._hasMore},more:function(a){var b=this;return this._more&&"pending"===this._more.state()?this._more:this.hasMore()?(a=a||{},a.remove=!1,this._more=this.fetch(a).done(function(a){(_.isEmpty(a)||-1===this.args.posts_per_page||a.length' + dragInfoText + '' )[0],\n\t\t\t\tpriority: -40\n\t\t\t}) );\n\t\t}\n\n\t\t// Add the 'Reverse order' button to the toolbar.\n\t\tattachmentsBrowserView.toolbar.set( 'reverse', {\n\t\t\ttext: l10n.reverseOrder,\n\t\t\tpriority: 80,\n\n\t\t\tclick: function() {\n\t\t\t\tlibrary.reset( library.toArray().reverse() );\n\t\t\t}\n\t\t});\n\t}\n});\n\nmodule.exports = CollectionEdit;\n\n\n//# sourceURL=webpack:///./src/js/media/controllers/collection-edit.js?"); - -/***/ }), - -/***/ "./src/js/media/controllers/cropper.js": -/*!*********************************************!*\ - !*** ./src/js/media/controllers/cropper.js ***! - \*********************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("var l10n = wp.media.view.l10n,\n\tCropper;\n\n/**\n * wp.media.controller.Cropper\n *\n * A class for cropping an image when called from the header media customization panel.\n *\n * @memberOf wp.media.controller\n *\n * @class\n * @augments wp.media.controller.State\n * @augments Backbone.Model\n */\nCropper = wp.media.controller.State.extend(/** @lends wp.media.controller.Cropper.prototype */{\n\tdefaults: {\n\t\tid: 'cropper',\n\t\ttitle: l10n.cropImage,\n\t\t// Region mode defaults.\n\t\ttoolbar: 'crop',\n\t\tcontent: 'crop',\n\t\trouter: false,\n\t\tcanSkipCrop: false,\n\n\t\t// Default doCrop Ajax arguments to allow the Customizer (for example) to inject state.\n\t\tdoCropArgs: {}\n\t},\n\n\t/**\n\t * Shows the crop image window when called from the Add new image button.\n\t *\n\t * @since 4.2.0\n\t *\n\t * @returns {void}\n\t */\n\tactivate: function() {\n\t\tthis.frame.on( 'content:create:crop', this.createCropContent, this );\n\t\tthis.frame.on( 'close', this.removeCropper, this );\n\t\tthis.set('selection', new Backbone.Collection(this.frame._selection.single));\n\t},\n\n\t/**\n\t * Changes the state of the toolbar window to browse mode.\n\t *\n\t * @since 4.2.0\n\t *\n\t * @returns {void}\n\t */\n\tdeactivate: function() {\n\t\tthis.frame.toolbar.mode('browse');\n\t},\n\n\t/**\n\t * Creates the crop image window.\n\t *\n\t * Initialized when clicking on the Select and Crop button.\n\t *\n\t * @since 4.2.0\n\t *\n\t * @fires crop window\n\t *\n\t * @returns {void}\n\t */\n\tcreateCropContent: function() {\n\t\tthis.cropperView = new wp.media.view.Cropper({\n\t\t\tcontroller: this,\n\t\t\tattachment: this.get('selection').first()\n\t\t});\n\t\tthis.cropperView.on('image-loaded', this.createCropToolbar, this);\n\t\tthis.frame.content.set(this.cropperView);\n\n\t},\n\n\t/**\n\t * Removes the image selection and closes the cropping window.\n\t *\n\t * @since 4.2.0\n\t *\n\t * @returns {void}\n\t */\n\tremoveCropper: function() {\n\t\tthis.imgSelect.cancelSelection();\n\t\tthis.imgSelect.setOptions({remove: true});\n\t\tthis.imgSelect.update();\n\t\tthis.cropperView.remove();\n\t},\n\n\t/**\n\t * Checks if cropping can be skipped and creates crop toolbar accordingly.\n\t *\n\t * @since 4.2.0\n\t *\n\t * @returns {void}\n\t */\n\tcreateCropToolbar: function() {\n\t\tvar canSkipCrop, toolbarOptions;\n\n\t\tcanSkipCrop = this.get('canSkipCrop') || false;\n\n\t\ttoolbarOptions = {\n\t\t\tcontroller: this.frame,\n\t\t\titems: {\n\t\t\t\tinsert: {\n\t\t\t\t\tstyle: 'primary',\n\t\t\t\t\ttext: l10n.cropImage,\n\t\t\t\t\tpriority: 80,\n\t\t\t\t\trequires: { library: false, selection: false },\n\n\t\t\t\t\tclick: function() {\n\t\t\t\t\t\tvar controller = this.controller,\n\t\t\t\t\t\t\tselection;\n\n\t\t\t\t\t\tselection = controller.state().get('selection').first();\n\t\t\t\t\t\tselection.set({cropDetails: controller.state().imgSelect.getSelection()});\n\n\t\t\t\t\t\tthis.$el.text(l10n.cropping);\n\t\t\t\t\t\tthis.$el.attr('disabled', true);\n\n\t\t\t\t\t\tcontroller.state().doCrop( selection ).done( function( croppedImage ) {\n\t\t\t\t\t\t\tcontroller.trigger('cropped', croppedImage );\n\t\t\t\t\t\t\tcontroller.close();\n\t\t\t\t\t\t}).fail( function() {\n\t\t\t\t\t\t\tcontroller.trigger('content:error:crop');\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tif ( canSkipCrop ) {\n\t\t\t_.extend( toolbarOptions.items, {\n\t\t\t\tskip: {\n\t\t\t\t\tstyle: 'secondary',\n\t\t\t\t\ttext: l10n.skipCropping,\n\t\t\t\t\tpriority: 70,\n\t\t\t\t\trequires: { library: false, selection: false },\n\t\t\t\t\tclick: function() {\n\t\t\t\t\t\tvar selection = this.controller.state().get('selection').first();\n\t\t\t\t\t\tthis.controller.state().cropperView.remove();\n\t\t\t\t\t\tthis.controller.trigger('skippedcrop', selection);\n\t\t\t\t\t\tthis.controller.close();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tthis.frame.toolbar.set( new wp.media.view.Toolbar(toolbarOptions) );\n\t},\n\n\t/**\n\t * Creates an object with the image attachment and crop properties.\n\t *\n\t * @since 4.2.0\n\t *\n\t * @returns {$.promise} A jQuery promise with the custom header crop details.\n\t */\n\tdoCrop: function( attachment ) {\n\t\treturn wp.ajax.post( 'custom-header-crop', _.extend(\n\t\t\t{},\n\t\t\tthis.defaults.doCropArgs,\n\t\t\t{\n\t\t\t\tnonce: attachment.get( 'nonces' ).edit,\n\t\t\t\tid: attachment.get( 'id' ),\n\t\t\t\tcropDetails: attachment.get( 'cropDetails' )\n\t\t\t}\n\t\t) );\n\t}\n});\n\nmodule.exports = Cropper;\n\n\n//# sourceURL=webpack:///./src/js/media/controllers/cropper.js?"); - -/***/ }), - -/***/ "./src/js/media/controllers/customize-image-cropper.js": -/*!*************************************************************!*\ - !*** ./src/js/media/controllers/customize-image-cropper.js ***! - \*************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("var Controller = wp.media.controller,\n\tCustomizeImageCropper;\n\n/**\n * A state for cropping an image in the customizer.\n *\n * @since 4.3.0\n *\n * @constructs wp.media.controller.CustomizeImageCropper\n * @memberOf wp.media.controller\n * @augments wp.media.controller.CustomizeImageCropper.Cropper\n * @inheritDoc\n */\nCustomizeImageCropper = Controller.Cropper.extend(/** @lends wp.media.controller.CustomizeImageCropper.prototype */{\n\t/**\n\t * Posts the crop details to the admin.\n\t *\n\t * Uses crop measurements when flexible in both directions.\n\t * Constrains flexible side based on image ratio and size of the fixed side.\n\t *\n\t * @since 4.3.0\n\t *\n\t * @param {Object} attachment The attachment to crop.\n\t *\n\t * @returns {$.promise} A jQuery promise that represents the crop image request.\n\t */\n\tdoCrop: function( attachment ) {\n\t\tvar cropDetails = attachment.get( 'cropDetails' ),\n\t\t\tcontrol = this.get( 'control' ),\n\t\t\tratio = cropDetails.width / cropDetails.height;\n\n\t\t// Use crop measurements when flexible in both directions.\n\t\tif ( control.params.flex_width && control.params.flex_height ) {\n\t\t\tcropDetails.dst_width = cropDetails.width;\n\t\t\tcropDetails.dst_height = cropDetails.height;\n\n\t\t// Constrain flexible side based on image ratio and size of the fixed side.\n\t\t} else {\n\t\t\tcropDetails.dst_width = control.params.flex_width ? control.params.height * ratio : control.params.width;\n\t\t\tcropDetails.dst_height = control.params.flex_height ? control.params.width / ratio : control.params.height;\n\t\t}\n\n\t\treturn wp.ajax.post( 'crop-image', {\n\t\t\twp_customize: 'on',\n\t\t\tnonce: attachment.get( 'nonces' ).edit,\n\t\t\tid: attachment.get( 'id' ),\n\t\t\tcontext: control.id,\n\t\t\tcropDetails: cropDetails\n\t\t} );\n\t}\n});\n\nmodule.exports = CustomizeImageCropper;\n\n\n//# sourceURL=webpack:///./src/js/media/controllers/customize-image-cropper.js?"); - -/***/ }), - -/***/ "./src/js/media/controllers/edit-image.js": -/*!************************************************!*\ - !*** ./src/js/media/controllers/edit-image.js ***! - \************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("var l10n = wp.media.view.l10n,\n\tEditImage;\n\n/**\n * wp.media.controller.EditImage\n *\n * A state for editing (cropping, etc.) an image.\n *\n * @memberOf wp.media.controller\n *\n * @class\n * @augments wp.media.controller.State\n * @augments Backbone.Model\n *\n * @param {object} attributes The attributes hash passed to the state.\n * @param {wp.media.model.Attachment} attributes.model The attachment.\n * @param {string} [attributes.id=edit-image] Unique identifier.\n * @param {string} [attributes.title=Edit Image] Title for the state. Displays in the media menu and the frame's title region.\n * @param {string} [attributes.content=edit-image] Initial mode for the content region.\n * @param {string} [attributes.toolbar=edit-image] Initial mode for the toolbar region.\n * @param {string} [attributes.menu=false] Initial mode for the menu region.\n * @param {string} [attributes.url] Unused. @todo Consider removal.\n */\nEditImage = wp.media.controller.State.extend(/** @lends wp.media.controller.EditImage.prototype */{\n\tdefaults: {\n\t\tid: 'edit-image',\n\t\ttitle: l10n.editImage,\n\t\tmenu: false,\n\t\ttoolbar: 'edit-image',\n\t\tcontent: 'edit-image',\n\t\turl: ''\n\t},\n\n\t/**\n\t * Activates a frame for editing a featured image.\n\t *\n\t * @since 3.9.0\n\t *\n\t * @returns {void}\n\t */\n\tactivate: function() {\n\t\tthis.frame.on( 'toolbar:render:edit-image', _.bind( this.toolbar, this ) );\n\t},\n\n\t/**\n\t * Deactivates a frame for editing a featured image.\n\t *\n\t * @since 3.9.0\n\t *\n\t * @returns {void}\n\t */\n\tdeactivate: function() {\n\t\tthis.frame.off( 'toolbar:render:edit-image' );\n\t},\n\n\t/**\n\t * Adds a toolbar with a back button.\n\t *\n\t * When the back button is pressed it checks whether there is a previous state.\n\t * In case there is a previous state it sets that previous state otherwise it\n\t * closes the frame.\n\t *\n\t * @since 3.9.0\n\t *\n\t * @returns {void}\n\t */\n\ttoolbar: function() {\n\t\tvar frame = this.frame,\n\t\t\tlastState = frame.lastState(),\n\t\t\tprevious = lastState && lastState.id;\n\n\t\tframe.toolbar.set( new wp.media.view.Toolbar({\n\t\t\tcontroller: frame,\n\t\t\titems: {\n\t\t\t\tback: {\n\t\t\t\t\tstyle: 'primary',\n\t\t\t\t\ttext: l10n.back,\n\t\t\t\t\tpriority: 20,\n\t\t\t\t\tclick: function() {\n\t\t\t\t\t\tif ( previous ) {\n\t\t\t\t\t\t\tframe.setState( previous );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tframe.close();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}) );\n\t}\n});\n\nmodule.exports = EditImage;\n\n\n//# sourceURL=webpack:///./src/js/media/controllers/edit-image.js?"); - -/***/ }), - -/***/ "./src/js/media/controllers/embed.js": -/*!*******************************************!*\ - !*** ./src/js/media/controllers/embed.js ***! - \*******************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("var l10n = wp.media.view.l10n,\n\t$ = Backbone.$,\n\tEmbed;\n\n/**\n * wp.media.controller.Embed\n *\n * A state for embedding media from a URL.\n *\n * @memberOf wp.media.controller\n *\n * @class\n * @augments wp.media.controller.State\n * @augments Backbone.Model\n *\n * @param {object} attributes The attributes hash passed to the state.\n * @param {string} [attributes.id=embed] Unique identifier.\n * @param {string} [attributes.title=Insert From URL] Title for the state. Displays in the media menu and the frame's title region.\n * @param {string} [attributes.content=embed] Initial mode for the content region.\n * @param {string} [attributes.menu=default] Initial mode for the menu region.\n * @param {string} [attributes.toolbar=main-embed] Initial mode for the toolbar region.\n * @param {string} [attributes.menu=false] Initial mode for the menu region.\n * @param {int} [attributes.priority=120] The priority for the state link in the media menu.\n * @param {string} [attributes.type=link] The type of embed. Currently only link is supported.\n * @param {string} [attributes.url] The embed URL.\n * @param {object} [attributes.metadata={}] Properties of the embed, which will override attributes.url if set.\n */\nEmbed = wp.media.controller.State.extend(/** @lends wp.media.controller.Embed.prototype */{\n\tdefaults: {\n\t\tid: 'embed',\n\t\ttitle: l10n.insertFromUrlTitle,\n\t\tcontent: 'embed',\n\t\tmenu: 'default',\n\t\ttoolbar: 'main-embed',\n\t\tpriority: 120,\n\t\ttype: 'link',\n\t\turl: '',\n\t\tmetadata: {}\n\t},\n\n\t// The amount of time used when debouncing the scan.\n\tsensitivity: 400,\n\n\tinitialize: function(options) {\n\t\tthis.metadata = options.metadata;\n\t\tthis.debouncedScan = _.debounce( _.bind( this.scan, this ), this.sensitivity );\n\t\tthis.props = new Backbone.Model( this.metadata || { url: '' });\n\t\tthis.props.on( 'change:url', this.debouncedScan, this );\n\t\tthis.props.on( 'change:url', this.refresh, this );\n\t\tthis.on( 'scan', this.scanImage, this );\n\t},\n\n\t/**\n\t * Trigger a scan of the embedded URL's content for metadata required to embed.\n\t *\n\t * @fires wp.media.controller.Embed#scan\n\t */\n\tscan: function() {\n\t\tvar scanners,\n\t\t\tembed = this,\n\t\t\tattributes = {\n\t\t\t\ttype: 'link',\n\t\t\t\tscanners: []\n\t\t\t};\n\n\t\t// Scan is triggered with the list of `attributes` to set on the\n\t\t// state, useful for the 'type' attribute and 'scanners' attribute,\n\t\t// an array of promise objects for asynchronous scan operations.\n\t\tif ( this.props.get('url') ) {\n\t\t\tthis.trigger( 'scan', attributes );\n\t\t}\n\n\t\tif ( attributes.scanners.length ) {\n\t\t\tscanners = attributes.scanners = $.when.apply( $, attributes.scanners );\n\t\t\tscanners.always( function() {\n\t\t\t\tif ( embed.get('scanners') === scanners ) {\n\t\t\t\t\tembed.set( 'loading', false );\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\tattributes.scanners = null;\n\t\t}\n\n\t\tattributes.loading = !! attributes.scanners;\n\t\tthis.set( attributes );\n\t},\n\t/**\n\t * Try scanning the embed as an image to discover its dimensions.\n\t *\n\t * @param {Object} attributes\n\t */\n\tscanImage: function( attributes ) {\n\t\tvar frame = this.frame,\n\t\t\tstate = this,\n\t\t\turl = this.props.get('url'),\n\t\t\timage = new Image(),\n\t\t\tdeferred = $.Deferred();\n\n\t\tattributes.scanners.push( deferred.promise() );\n\n\t\t// Try to load the image and find its width/height.\n\t\timage.onload = function() {\n\t\t\tdeferred.resolve();\n\n\t\t\tif ( state !== frame.state() || url !== state.props.get('url') ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tstate.set({\n\t\t\t\ttype: 'image'\n\t\t\t});\n\n\t\t\tstate.props.set({\n\t\t\t\twidth: image.width,\n\t\t\t\theight: image.height\n\t\t\t});\n\t\t};\n\n\t\timage.onerror = deferred.reject;\n\t\timage.src = url;\n\t},\n\n\trefresh: function() {\n\t\tthis.frame.toolbar.get().refresh();\n\t},\n\n\treset: function() {\n\t\tthis.props.clear().set({ url: '' });\n\n\t\tif ( this.active ) {\n\t\t\tthis.refresh();\n\t\t}\n\t}\n});\n\nmodule.exports = Embed;\n\n\n//# sourceURL=webpack:///./src/js/media/controllers/embed.js?"); - -/***/ }), - -/***/ "./src/js/media/controllers/featured-image.js": -/*!****************************************************!*\ - !*** ./src/js/media/controllers/featured-image.js ***! - \****************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("var Attachment = wp.media.model.Attachment,\n\tLibrary = wp.media.controller.Library,\n\tl10n = wp.media.view.l10n,\n\tFeaturedImage;\n\n/**\n * wp.media.controller.FeaturedImage\n *\n * A state for selecting a featured image for a post.\n *\n * @memberOf wp.media.controller\n *\n * @class\n * @augments wp.media.controller.Library\n * @augments wp.media.controller.State\n * @augments Backbone.Model\n *\n * @param {object} [attributes] The attributes hash passed to the state.\n * @param {string} [attributes.id=featured-image] Unique identifier.\n * @param {string} [attributes.title=Set Featured Image] Title for the state. Displays in the media menu and the frame's title region.\n * @param {wp.media.model.Attachments} [attributes.library] The attachments collection to browse.\n * If one is not supplied, a collection of all images will be created.\n * @param {boolean} [attributes.multiple=false] Whether multi-select is enabled.\n * @param {string} [attributes.content=upload] Initial mode for the content region.\n * Overridden by persistent user setting if 'contentUserSetting' is true.\n * @param {string} [attributes.menu=default] Initial mode for the menu region.\n * @param {string} [attributes.router=browse] Initial mode for the router region.\n * @param {string} [attributes.toolbar=featured-image] Initial mode for the toolbar region.\n * @param {int} [attributes.priority=60] The priority for the state link in the media menu.\n * @param {boolean} [attributes.searchable=true] Whether the library is searchable.\n * @param {boolean|string} [attributes.filterable=false] Whether the library is filterable, and if so what filters should be shown.\n * Accepts 'all', 'uploaded', or 'unattached'.\n * @param {boolean} [attributes.sortable=true] Whether the Attachments should be sortable. Depends on the orderby property being set to menuOrder on the attachments collection.\n * @param {boolean} [attributes.autoSelect=true] Whether an uploaded attachment should be automatically added to the selection.\n * @param {boolean} [attributes.describe=false] Whether to offer UI to describe attachments - e.g. captioning images in a gallery.\n * @param {boolean} [attributes.contentUserSetting=true] Whether the content region's mode should be set and persisted per user.\n * @param {boolean} [attributes.syncSelection=true] Whether the Attachments selection should be persisted from the last state.\n */\nFeaturedImage = Library.extend(/** @lends wp.media.controller.FeaturedImage.prototype */{\n\tdefaults: _.defaults({\n\t\tid: 'featured-image',\n\t\ttitle: l10n.setFeaturedImageTitle,\n\t\tmultiple: false,\n\t\tfilterable: 'uploaded',\n\t\ttoolbar: 'featured-image',\n\t\tpriority: 60,\n\t\tsyncSelection: true\n\t}, Library.prototype.defaults ),\n\n\t/**\n\t * @since 3.5.0\n\t */\n\tinitialize: function() {\n\t\tvar library, comparator;\n\n\t\t// If we haven't been provided a `library`, create a `Selection`.\n\t\tif ( ! this.get('library') ) {\n\t\t\tthis.set( 'library', wp.media.query({ type: 'image' }) );\n\t\t}\n\n\t\tLibrary.prototype.initialize.apply( this, arguments );\n\n\t\tlibrary = this.get('library');\n\t\tcomparator = library.comparator;\n\n\t\t// Overload the library's comparator to push items that are not in\n\t\t// the mirrored query to the front of the aggregate collection.\n\t\tlibrary.comparator = function( a, b ) {\n\t\t\tvar aInQuery = !! this.mirroring.get( a.cid ),\n\t\t\t\tbInQuery = !! this.mirroring.get( b.cid );\n\n\t\t\tif ( ! aInQuery && bInQuery ) {\n\t\t\t\treturn -1;\n\t\t\t} else if ( aInQuery && ! bInQuery ) {\n\t\t\t\treturn 1;\n\t\t\t} else {\n\t\t\t\treturn comparator.apply( this, arguments );\n\t\t\t}\n\t\t};\n\n\t\t// Add all items in the selection to the library, so any featured\n\t\t// images that are not initially loaded still appear.\n\t\tlibrary.observe( this.get('selection') );\n\t},\n\n\t/**\n\t * @since 3.5.0\n\t */\n\tactivate: function() {\n\t\tthis.updateSelection();\n\t\tthis.frame.on( 'open', this.updateSelection, this );\n\n\t\tLibrary.prototype.activate.apply( this, arguments );\n\t},\n\n\t/**\n\t * @since 3.5.0\n\t */\n\tdeactivate: function() {\n\t\tthis.frame.off( 'open', this.updateSelection, this );\n\n\t\tLibrary.prototype.deactivate.apply( this, arguments );\n\t},\n\n\t/**\n\t * @since 3.5.0\n\t */\n\tupdateSelection: function() {\n\t\tvar selection = this.get('selection'),\n\t\t\tid = wp.media.view.settings.post.featuredImageId,\n\t\t\tattachment;\n\n\t\tif ( '' !== id && -1 !== id ) {\n\t\t\tattachment = Attachment.get( id );\n\t\t\tattachment.fetch();\n\t\t}\n\n\t\tselection.reset( attachment ? [ attachment ] : [] );\n\t}\n});\n\nmodule.exports = FeaturedImage;\n\n\n//# sourceURL=webpack:///./src/js/media/controllers/featured-image.js?"); - -/***/ }), - -/***/ "./src/js/media/controllers/gallery-add.js": -/*!*************************************************!*\ - !*** ./src/js/media/controllers/gallery-add.js ***! - \*************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("var Selection = wp.media.model.Selection,\n\tLibrary = wp.media.controller.Library,\n\tl10n = wp.media.view.l10n,\n\tGalleryAdd;\n\n/**\n * wp.media.controller.GalleryAdd\n *\n * A state for selecting more images to add to a gallery.\n *\n * @since 3.5.0\n *\n * @class\n * @augments wp.media.controller.Library\n * @augments wp.media.controller.State\n * @augments Backbone.Model\n *\n * @memberof wp.media.controller\n *\n * @param {Object} [attributes] The attributes hash passed to the state.\n * @param {string} [attributes.id=gallery-library] Unique identifier.\n * @param {string} [attributes.title=Add to Gallery] Title for the state. Displays in the frame's title region.\n * @param {boolean} [attributes.multiple=add] Whether multi-select is enabled. @todo 'add' doesn't seem do anything special, and gets used as a boolean.\n * @param {wp.media.model.Attachments} [attributes.library] The attachments collection to browse.\n * If one is not supplied, a collection of all images will be created.\n * @param {boolean|string} [attributes.filterable=uploaded] Whether the library is filterable, and if so what filters should be shown.\n * Accepts 'all', 'uploaded', or 'unattached'.\n * @param {string} [attributes.menu=gallery] Initial mode for the menu region.\n * @param {string} [attributes.content=upload] Initial mode for the content region.\n * Overridden by persistent user setting if 'contentUserSetting' is true.\n * @param {string} [attributes.router=browse] Initial mode for the router region.\n * @param {string} [attributes.toolbar=gallery-add] Initial mode for the toolbar region.\n * @param {boolean} [attributes.searchable=true] Whether the library is searchable.\n * @param {boolean} [attributes.sortable=true] Whether the Attachments should be sortable. Depends on the orderby property being set to menuOrder on the attachments collection.\n * @param {boolean} [attributes.autoSelect=true] Whether an uploaded attachment should be automatically added to the selection.\n * @param {boolean} [attributes.contentUserSetting=true] Whether the content region's mode should be set and persisted per user.\n * @param {number} [attributes.priority=100] The priority for the state link in the media menu.\n * @param {boolean} [attributes.syncSelection=false] Whether the Attachments selection should be persisted from the last state.\n * Defaults to false because for this state, because the library of the Edit Gallery state is the selection.\n */\nGalleryAdd = Library.extend(/** @lends wp.media.controller.GalleryAdd.prototype */{\n\tdefaults: _.defaults({\n\t\tid: 'gallery-library',\n\t\ttitle: l10n.addToGalleryTitle,\n\t\tmultiple: 'add',\n\t\tfilterable: 'uploaded',\n\t\tmenu: 'gallery',\n\t\ttoolbar: 'gallery-add',\n\t\tpriority: 100,\n\t\tsyncSelection: false\n\t}, Library.prototype.defaults ),\n\n\t/**\n\t * Initializes the library. Creates a library of images if a library isn't supplied.\n\t *\n\t * @since 3.5.0\n\t *\n\t * @returns {void}\n\t */\n\tinitialize: function() {\n\t\tif ( ! this.get('library') ) {\n\t\t\tthis.set( 'library', wp.media.query({ type: 'image' }) );\n\t\t}\n\n\t\tLibrary.prototype.initialize.apply( this, arguments );\n\t},\n\n\t/**\n\t * Activates the library.\n\t *\n\t * Removes all event listeners if in edit mode. Creates a validator to check an attachment.\n\t * Resets library and re-enables event listeners. Activates edit mode. Calls the parent's activate method.\n\t *\n\t * @since 3.5.0\n\t *\n\t * @returns {void}\n\t */\n\tactivate: function() {\n\t\tvar library = this.get('library'),\n\t\t\tedit = this.frame.state('gallery-edit').get('library');\n\n\t\tif ( this.editLibrary && this.editLibrary !== edit ) {\n\t\t\tlibrary.unobserve( this.editLibrary );\n\t\t}\n\n\t\t/*\n\t\t * Accept attachments that exist in the original library but\n\t\t * that do not exist in gallery's library yet.\n\t\t */\n\t\tlibrary.validator = function( attachment ) {\n\t\t\treturn !! this.mirroring.get( attachment.cid ) && ! edit.get( attachment.cid ) && Selection.prototype.validator.apply( this, arguments );\n\t\t};\n\n\t\t/*\n\t\t * Reset the library to ensure that all attachments are re-added\n\t\t * to the collection. Do so silently, as calling `observe` will\n\t\t * trigger the `reset` event.\n\t\t */\n\t\tlibrary.reset( library.mirroring.models, { silent: true });\n\t\tlibrary.observe( edit );\n\t\tthis.editLibrary = edit;\n\n\t\tLibrary.prototype.activate.apply( this, arguments );\n\t}\n});\n\nmodule.exports = GalleryAdd;\n\n\n//# sourceURL=webpack:///./src/js/media/controllers/gallery-add.js?"); - -/***/ }), - -/***/ "./src/js/media/controllers/gallery-edit.js": -/*!**************************************************!*\ - !*** ./src/js/media/controllers/gallery-edit.js ***! - \**************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("var Library = wp.media.controller.Library,\n\tl10n = wp.media.view.l10n,\n\tGalleryEdit;\n\n/**\n * wp.media.controller.GalleryEdit\n *\n * A state for editing a gallery's images and settings.\n *\n * @since 3.5.0\n *\n * @class\n * @augments wp.media.controller.Library\n * @augments wp.media.controller.State\n * @augments Backbone.Model\n *\n * @memberOf wp.media.controller\n *\n * @param {Object} [attributes] The attributes hash passed to the state.\n * @param {string} [attributes.id=gallery-edit] Unique identifier.\n * @param {string} [attributes.title=Edit Gallery] Title for the state. Displays in the frame's title region.\n * @param {wp.media.model.Attachments} [attributes.library] The collection of attachments in the gallery.\n * If one is not supplied, an empty media.model.Selection collection is created.\n * @param {boolean} [attributes.multiple=false] Whether multi-select is enabled.\n * @param {boolean} [attributes.searchable=false] Whether the library is searchable.\n * @param {boolean} [attributes.sortable=true] Whether the Attachments should be sortable. Depends on the orderby property being set to menuOrder on the attachments collection.\n * @param {boolean} [attributes.date=true] Whether to show the date filter in the browser's toolbar.\n * @param {string|false} [attributes.content=browse] Initial mode for the content region.\n * @param {string|false} [attributes.toolbar=image-details] Initial mode for the toolbar region.\n * @param {boolean} [attributes.describe=true] Whether to offer UI to describe attachments - e.g. captioning images in a gallery.\n * @param {boolean} [attributes.displaySettings=true] Whether to show the attachment display settings interface.\n * @param {boolean} [attributes.dragInfo=true] Whether to show instructional text about the attachments being sortable.\n * @param {number} [attributes.idealColumnWidth=170] The ideal column width in pixels for attachments.\n * @param {boolean} [attributes.editing=false] Whether the gallery is being created, or editing an existing instance.\n * @param {number} [attributes.priority=60] The priority for the state link in the media menu.\n * @param {boolean} [attributes.syncSelection=false] Whether the Attachments selection should be persisted from the last state.\n * Defaults to false for this state, because the library passed in *is* the selection.\n * @param {view} [attributes.AttachmentView] The single `Attachment` view to be used in the `Attachments`.\n * If none supplied, defaults to wp.media.view.Attachment.EditLibrary.\n */\nGalleryEdit = Library.extend(/** @lends wp.media.controller.GalleryEdit.prototype */{\n\tdefaults: {\n\t\tid: 'gallery-edit',\n\t\ttitle: l10n.editGalleryTitle,\n\t\tmultiple: false,\n\t\tsearchable: false,\n\t\tsortable: true,\n\t\tdate: false,\n\t\tdisplay: false,\n\t\tcontent: 'browse',\n\t\ttoolbar: 'gallery-edit',\n\t\tdescribe: true,\n\t\tdisplaySettings: true,\n\t\tdragInfo: true,\n\t\tidealColumnWidth: 170,\n\t\tediting: false,\n\t\tpriority: 60,\n\t\tsyncSelection: false\n\t},\n\n\t/**\n\t * Initializes the library.\n\t *\n\t * Creates a selection if a library isn't supplied and creates an attachment\n\t * view if no attachment view is supplied.\n\t *\n\t * @since 3.5.0\n\t *\n\t * @return {void}\n\t */\n\tinitialize: function() {\n\t\t// If we haven't been provided a `library`, create a `Selection`.\n\t\tif ( ! this.get('library') ) {\n\t\t\tthis.set( 'library', new wp.media.model.Selection() );\n\t\t}\n\n\t\t// The single `Attachment` view to be used in the `Attachments` view.\n\t\tif ( ! this.get('AttachmentView') ) {\n\t\t\tthis.set( 'AttachmentView', wp.media.view.Attachment.EditLibrary );\n\t\t}\n\n\t\tLibrary.prototype.initialize.apply( this, arguments );\n\t},\n\n\t/**\n\t * Activates the library.\n\t *\n\t * Limits the library to images, watches for uploaded attachments. Watches for\n\t * the browse event on the frame and binds it to gallerySettings.\n\t *\n\t * @since 3.5.0\n\t *\n\t * @return {void}\n\t */\n\tactivate: function() {\n\t\tvar library = this.get('library');\n\n\t\t// Limit the library to images only.\n\t\tlibrary.props.set( 'type', 'image' );\n\n\t\t// Watch for uploaded attachments.\n\t\tthis.get('library').observe( wp.Uploader.queue );\n\n\t\tthis.frame.on( 'content:render:browse', this.gallerySettings, this );\n\n\t\tLibrary.prototype.activate.apply( this, arguments );\n\t},\n\n\t/**\n\t * Deactivates the library.\n\t *\n\t * Stops watching for uploaded attachments and browse events.\n\t *\n\t * @since 3.5.0\n\t *\n\t * @return {void}\n\t */\n\tdeactivate: function() {\n\t\t// Stop watching for uploaded attachments.\n\t\tthis.get('library').unobserve( wp.Uploader.queue );\n\n\t\tthis.frame.off( 'content:render:browse', this.gallerySettings, this );\n\n\t\tLibrary.prototype.deactivate.apply( this, arguments );\n\t},\n\n\t/**\n\t * Adds the gallery settings to the sidebar and adds a reverse button to the\n\t * toolbar.\n\t *\n\t * @since 3.5.0\n\t *\n\t * @param {wp.media.view.Frame} browser The file browser.\n\t *\n\t * @return {void}\n\t */\n\tgallerySettings: function( browser ) {\n\t\tif ( ! this.get('displaySettings') ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar library = this.get('library');\n\n\t\tif ( ! library || ! browser ) {\n\t\t\treturn;\n\t\t}\n\n\t\tlibrary.gallery = library.gallery || new Backbone.Model();\n\n\t\tbrowser.sidebar.set({\n\t\t\tgallery: new wp.media.view.Settings.Gallery({\n\t\t\t\tcontroller: this,\n\t\t\t\tmodel: library.gallery,\n\t\t\t\tpriority: 40\n\t\t\t})\n\t\t});\n\n\t\tbrowser.toolbar.set( 'reverse', {\n\t\t\ttext: l10n.reverseOrder,\n\t\t\tpriority: 80,\n\n\t\t\tclick: function() {\n\t\t\t\tlibrary.reset( library.toArray().reverse() );\n\t\t\t}\n\t\t});\n\t}\n});\n\nmodule.exports = GalleryEdit;\n\n\n//# sourceURL=webpack:///./src/js/media/controllers/gallery-edit.js?"); - -/***/ }), - -/***/ "./src/js/media/controllers/image-details.js": -/*!***************************************************!*\ - !*** ./src/js/media/controllers/image-details.js ***! - \***************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("var State = wp.media.controller.State,\n\tLibrary = wp.media.controller.Library,\n\tl10n = wp.media.view.l10n,\n\tImageDetails;\n\n/**\n * wp.media.controller.ImageDetails\n *\n * A state for editing the attachment display settings of an image that's been\n * inserted into the editor.\n *\n * @memberOf wp.media.controller\n *\n * @class\n * @augments wp.media.controller.State\n * @augments Backbone.Model\n *\n * @param {object} [attributes] The attributes hash passed to the state.\n * @param {string} [attributes.id=image-details] Unique identifier.\n * @param {string} [attributes.title=Image Details] Title for the state. Displays in the frame's title region.\n * @param {wp.media.model.Attachment} attributes.image The image's model.\n * @param {string|false} [attributes.content=image-details] Initial mode for the content region.\n * @param {string|false} [attributes.menu=false] Initial mode for the menu region.\n * @param {string|false} [attributes.router=false] Initial mode for the router region.\n * @param {string|false} [attributes.toolbar=image-details] Initial mode for the toolbar region.\n * @param {boolean} [attributes.editing=false] Unused.\n * @param {int} [attributes.priority=60] Unused.\n *\n * @todo This state inherits some defaults from media.controller.Library.prototype.defaults,\n * however this may not do anything.\n */\nImageDetails = State.extend(/** @lends wp.media.controller.ImageDetails.prototype */{\n\tdefaults: _.defaults({\n\t\tid: 'image-details',\n\t\ttitle: l10n.imageDetailsTitle,\n\t\tcontent: 'image-details',\n\t\tmenu: false,\n\t\trouter: false,\n\t\ttoolbar: 'image-details',\n\t\tediting: false,\n\t\tpriority: 60\n\t}, Library.prototype.defaults ),\n\n\t/**\n\t * @since 3.9.0\n\t *\n\t * @param options Attributes\n\t */\n\tinitialize: function( options ) {\n\t\tthis.image = options.image;\n\t\tState.prototype.initialize.apply( this, arguments );\n\t},\n\n\t/**\n\t * @since 3.9.0\n\t */\n\tactivate: function() {\n\t\tthis.frame.modal.$el.addClass('image-details');\n\t}\n});\n\nmodule.exports = ImageDetails;\n\n\n//# sourceURL=webpack:///./src/js/media/controllers/image-details.js?"); - -/***/ }), - -/***/ "./src/js/media/controllers/library.js": -/*!*********************************************!*\ - !*** ./src/js/media/controllers/library.js ***! - \*********************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("var l10n = wp.media.view.l10n,\n\tgetUserSetting = window.getUserSetting,\n\tsetUserSetting = window.setUserSetting,\n\tLibrary;\n\n/**\n * wp.media.controller.Library\n *\n * A state for choosing an attachment or group of attachments from the media library.\n *\n * @memberOf wp.media.controller\n *\n * @class\n * @augments wp.media.controller.State\n * @augments Backbone.Model\n * @mixes media.selectionSync\n *\n * @param {object} [attributes] The attributes hash passed to the state.\n * @param {string} [attributes.id=library] Unique identifier.\n * @param {string} [attributes.title=Media library] Title for the state. Displays in the media menu and the frame's title region.\n * @param {wp.media.model.Attachments} [attributes.library] The attachments collection to browse.\n * If one is not supplied, a collection of all attachments will be created.\n * @param {wp.media.model.Selection|object} [attributes.selection] A collection to contain attachment selections within the state.\n * If the 'selection' attribute is a plain JS object,\n * a Selection will be created using its values as the selection instance's `props` model.\n * Otherwise, it will copy the library's `props` model.\n * @param {boolean} [attributes.multiple=false] Whether multi-select is enabled.\n * @param {string} [attributes.content=upload] Initial mode for the content region.\n * Overridden by persistent user setting if 'contentUserSetting' is true.\n * @param {string} [attributes.menu=default] Initial mode for the menu region.\n * @param {string} [attributes.router=browse] Initial mode for the router region.\n * @param {string} [attributes.toolbar=select] Initial mode for the toolbar region.\n * @param {boolean} [attributes.searchable=true] Whether the library is searchable.\n * @param {boolean|string} [attributes.filterable=false] Whether the library is filterable, and if so what filters should be shown.\n * Accepts 'all', 'uploaded', or 'unattached'.\n * @param {boolean} [attributes.sortable=true] Whether the Attachments should be sortable. Depends on the orderby property being set to menuOrder on the attachments collection.\n * @param {boolean} [attributes.autoSelect=true] Whether an uploaded attachment should be automatically added to the selection.\n * @param {boolean} [attributes.describe=false] Whether to offer UI to describe attachments - e.g. captioning images in a gallery.\n * @param {boolean} [attributes.contentUserSetting=true] Whether the content region's mode should be set and persisted per user.\n * @param {boolean} [attributes.syncSelection=true] Whether the Attachments selection should be persisted from the last state.\n */\nLibrary = wp.media.controller.State.extend(/** @lends wp.media.controller.Library.prototype */{\n\tdefaults: {\n\t\tid: 'library',\n\t\ttitle: l10n.mediaLibraryTitle,\n\t\tmultiple: false,\n\t\tcontent: 'upload',\n\t\tmenu: 'default',\n\t\trouter: 'browse',\n\t\ttoolbar: 'select',\n\t\tsearchable: true,\n\t\tfilterable: false,\n\t\tsortable: true,\n\t\tautoSelect: true,\n\t\tdescribe: false,\n\t\tcontentUserSetting: true,\n\t\tsyncSelection: true\n\t},\n\n\t/**\n\t * If a library isn't provided, query all media items.\n\t * If a selection instance isn't provided, create one.\n\t *\n\t * @since 3.5.0\n\t */\n\tinitialize: function() {\n\t\tvar selection = this.get('selection'),\n\t\t\tprops;\n\n\t\tif ( ! this.get('library') ) {\n\t\t\tthis.set( 'library', wp.media.query() );\n\t\t}\n\n\t\tif ( ! ( selection instanceof wp.media.model.Selection ) ) {\n\t\t\tprops = selection;\n\n\t\t\tif ( ! props ) {\n\t\t\t\tprops = this.get('library').props.toJSON();\n\t\t\t\tprops = _.omit( props, 'orderby', 'query' );\n\t\t\t}\n\n\t\t\tthis.set( 'selection', new wp.media.model.Selection( null, {\n\t\t\t\tmultiple: this.get('multiple'),\n\t\t\t\tprops: props\n\t\t\t}) );\n\t\t}\n\n\t\tthis.resetDisplays();\n\t},\n\n\t/**\n\t * @since 3.5.0\n\t */\n\tactivate: function() {\n\t\tthis.syncSelection();\n\n\t\twp.Uploader.queue.on( 'add', this.uploading, this );\n\n\t\tthis.get('selection').on( 'add remove reset', this.refreshContent, this );\n\n\t\tif ( this.get( 'router' ) && this.get('contentUserSetting') ) {\n\t\t\tthis.frame.on( 'content:activate', this.saveContentMode, this );\n\t\t\tthis.set( 'content', getUserSetting( 'libraryContent', this.get('content') ) );\n\t\t}\n\t},\n\n\t/**\n\t * @since 3.5.0\n\t */\n\tdeactivate: function() {\n\t\tthis.recordSelection();\n\n\t\tthis.frame.off( 'content:activate', this.saveContentMode, this );\n\n\t\t// Unbind all event handlers that use this state as the context\n\t\t// from the selection.\n\t\tthis.get('selection').off( null, null, this );\n\n\t\twp.Uploader.queue.off( null, null, this );\n\t},\n\n\t/**\n\t * Reset the library to its initial state.\n\t *\n\t * @since 3.5.0\n\t */\n\treset: function() {\n\t\tthis.get('selection').reset();\n\t\tthis.resetDisplays();\n\t\tthis.refreshContent();\n\t},\n\n\t/**\n\t * Reset the attachment display settings defaults to the site options.\n\t *\n\t * If site options don't define them, fall back to a persistent user setting.\n\t *\n\t * @since 3.5.0\n\t */\n\tresetDisplays: function() {\n\t\tvar defaultProps = wp.media.view.settings.defaultProps;\n\t\tthis._displays = [];\n\t\tthis._defaultDisplaySettings = {\n\t\t\talign: getUserSetting( 'align', defaultProps.align ) || 'none',\n\t\t\tsize: getUserSetting( 'imgsize', defaultProps.size ) || 'medium',\n\t\t\tlink: getUserSetting( 'urlbutton', defaultProps.link ) || 'none'\n\t\t};\n\t},\n\n\t/**\n\t * Create a model to represent display settings (alignment, etc.) for an attachment.\n\t *\n\t * @since 3.5.0\n\t *\n\t * @param {wp.media.model.Attachment} attachment\n\t * @returns {Backbone.Model}\n\t */\n\tdisplay: function( attachment ) {\n\t\tvar displays = this._displays;\n\n\t\tif ( ! displays[ attachment.cid ] ) {\n\t\t\tdisplays[ attachment.cid ] = new Backbone.Model( this.defaultDisplaySettings( attachment ) );\n\t\t}\n\t\treturn displays[ attachment.cid ];\n\t},\n\n\t/**\n\t * Given an attachment, create attachment display settings properties.\n\t *\n\t * @since 3.6.0\n\t *\n\t * @param {wp.media.model.Attachment} attachment\n\t * @returns {Object}\n\t */\n\tdefaultDisplaySettings: function( attachment ) {\n\t\tvar settings = _.clone( this._defaultDisplaySettings );\n\n\t\tif ( settings.canEmbed = this.canEmbed( attachment ) ) {\n\t\t\tsettings.link = 'embed';\n\t\t} else if ( ! this.isImageAttachment( attachment ) && settings.link === 'none' ) {\n\t\t\tsettings.link = 'file';\n\t\t}\n\n\t\treturn settings;\n\t},\n\n\t/**\n\t * Whether an attachment is image.\n\t *\n\t * @since 4.4.1\n\t *\n\t * @param {wp.media.model.Attachment} attachment\n\t * @returns {Boolean}\n\t */\n\tisImageAttachment: function( attachment ) {\n\t\t// If uploading, we know the filename but not the mime type.\n\t\tif ( attachment.get('uploading') ) {\n\t\t\treturn /\\.(jpe?g|png|gif)$/i.test( attachment.get('filename') );\n\t\t}\n\n\t\treturn attachment.get('type') === 'image';\n\t},\n\n\t/**\n\t * Whether an attachment can be embedded (audio or video).\n\t *\n\t * @since 3.6.0\n\t *\n\t * @param {wp.media.model.Attachment} attachment\n\t * @returns {Boolean}\n\t */\n\tcanEmbed: function( attachment ) {\n\t\t// If uploading, we know the filename but not the mime type.\n\t\tif ( ! attachment.get('uploading') ) {\n\t\t\tvar type = attachment.get('type');\n\t\t\tif ( type !== 'audio' && type !== 'video' ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\treturn _.contains( wp.media.view.settings.embedExts, attachment.get('filename').split('.').pop() );\n\t},\n\n\n\t/**\n\t * If the state is active, no items are selected, and the current\n\t * content mode is not an option in the state's router (provided\n\t * the state has a router), reset the content mode to the default.\n\t *\n\t * @since 3.5.0\n\t */\n\trefreshContent: function() {\n\t\tvar selection = this.get('selection'),\n\t\t\tframe = this.frame,\n\t\t\trouter = frame.router.get(),\n\t\t\tmode = frame.content.mode();\n\n\t\tif ( this.active && ! selection.length && router && ! router.get( mode ) ) {\n\t\t\tthis.frame.content.render( this.get('content') );\n\t\t}\n\t},\n\n\t/**\n\t * Callback handler when an attachment is uploaded.\n\t *\n\t * Switch to the Media Library if uploaded from the 'Upload Files' tab.\n\t *\n\t * Adds any uploading attachments to the selection.\n\t *\n\t * If the state only supports one attachment to be selected and multiple\n\t * attachments are uploaded, the last attachment in the upload queue will\n\t * be selected.\n\t *\n\t * @since 3.5.0\n\t *\n\t * @param {wp.media.model.Attachment} attachment\n\t */\n\tuploading: function( attachment ) {\n\t\tvar content = this.frame.content;\n\n\t\tif ( 'upload' === content.mode() ) {\n\t\t\tthis.frame.content.mode('browse');\n\t\t}\n\n\t\tif ( this.get( 'autoSelect' ) ) {\n\t\t\tthis.get('selection').add( attachment );\n\t\t\tthis.frame.trigger( 'library:selection:add' );\n\t\t}\n\t},\n\n\t/**\n\t * Persist the mode of the content region as a user setting.\n\t *\n\t * @since 3.5.0\n\t */\n\tsaveContentMode: function() {\n\t\tif ( 'browse' !== this.get('router') ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar mode = this.frame.content.mode(),\n\t\t\tview = this.frame.router.get();\n\n\t\tif ( view && view.get( mode ) ) {\n\t\t\tsetUserSetting( 'libraryContent', mode );\n\t\t}\n\t}\n\n});\n\n// Make selectionSync available on any Media Library state.\n_.extend( Library.prototype, wp.media.selectionSync );\n\nmodule.exports = Library;\n\n\n//# sourceURL=webpack:///./src/js/media/controllers/library.js?"); - -/***/ }), - -/***/ "./src/js/media/controllers/media-library.js": -/*!***************************************************!*\ - !*** ./src/js/media/controllers/media-library.js ***! - \***************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("/**\n * wp.media.controller.MediaLibrary\n *\n * @memberOf wp.media.controller\n *\n * @class\n * @augments wp.media.controller.Library\n * @augments wp.media.controller.State\n * @augments Backbone.Model\n */\nvar Library = wp.media.controller.Library,\n\tMediaLibrary;\n\nMediaLibrary = Library.extend(/** @lends wp.media.controller.MediaLibrary.prototype */{\n\tdefaults: _.defaults({\n\t\t// Attachments browser defaults. @see media.view.AttachmentsBrowser\n\t\tfilterable: 'uploaded',\n\n\t\tdisplaySettings: false,\n\t\tpriority: 80,\n\t\tsyncSelection: false\n\t}, Library.prototype.defaults ),\n\n\t/**\n\t * @since 3.9.0\n\t *\n\t * @param options\n\t */\n\tinitialize: function( options ) {\n\t\tthis.media = options.media;\n\t\tthis.type = options.type;\n\t\tthis.set( 'library', wp.media.query({ type: this.type }) );\n\n\t\tLibrary.prototype.initialize.apply( this, arguments );\n\t},\n\n\t/**\n\t * @since 3.9.0\n\t */\n\tactivate: function() {\n\t\t// @todo this should use this.frame.\n\t\tif ( wp.media.frame.lastMime ) {\n\t\t\tthis.set( 'library', wp.media.query({ type: wp.media.frame.lastMime }) );\n\t\t\tdelete wp.media.frame.lastMime;\n\t\t}\n\t\tLibrary.prototype.activate.apply( this, arguments );\n\t}\n});\n\nmodule.exports = MediaLibrary;\n\n\n//# sourceURL=webpack:///./src/js/media/controllers/media-library.js?"); - -/***/ }), - -/***/ "./src/js/media/controllers/region.js": -/*!********************************************!*\ - !*** ./src/js/media/controllers/region.js ***! - \********************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("/**\n * wp.media.controller.Region\n *\n * A region is a persistent application layout area.\n *\n * A region assumes one mode at any time, and can be switched to another.\n *\n * When mode changes, events are triggered on the region's parent view.\n * The parent view will listen to specific events and fill the region with an\n * appropriate view depending on mode. For example, a frame listens for the\n * 'browse' mode t be activated on the 'content' view and then fills the region\n * with an AttachmentsBrowser view.\n *\n * @memberOf wp.media.controller\n *\n * @class\n *\n * @param {object} options Options hash for the region.\n * @param {string} options.id Unique identifier for the region.\n * @param {Backbone.View} options.view A parent view the region exists within.\n * @param {string} options.selector jQuery selector for the region within the parent view.\n */\nvar Region = function( options ) {\n\t_.extend( this, _.pick( options || {}, 'id', 'view', 'selector' ) );\n};\n\n// Use Backbone's self-propagating `extend` inheritance method.\nRegion.extend = Backbone.Model.extend;\n\n_.extend( Region.prototype,/** @lends wp.media.controller.Region.prototype */{\n\t/**\n\t * Activate a mode.\n\t *\n\t * @since 3.5.0\n\t *\n\t * @param {string} mode\n\t *\n\t * @fires Region#activate\n\t * @fires Region#deactivate\n\t *\n\t * @returns {wp.media.controller.Region} Returns itself to allow chaining.\n\t */\n\tmode: function( mode ) {\n\t\tif ( ! mode ) {\n\t\t\treturn this._mode;\n\t\t}\n\t\t// Bail if we're trying to change to the current mode.\n\t\tif ( mode === this._mode ) {\n\t\t\treturn this;\n\t\t}\n\n\t\t/**\n\t\t * Region mode deactivation event.\n\t\t *\n\t\t * @event wp.media.controller.Region#deactivate\n\t\t */\n\t\tthis.trigger('deactivate');\n\n\t\tthis._mode = mode;\n\t\tthis.render( mode );\n\n\t\t/**\n\t\t * Region mode activation event.\n\t\t *\n\t\t * @event wp.media.controller.Region#activate\n\t\t */\n\t\tthis.trigger('activate');\n\t\treturn this;\n\t},\n\t/**\n\t * Render a mode.\n\t *\n\t * @since 3.5.0\n\t *\n\t * @param {string} mode\n\t *\n\t * @fires Region#create\n\t * @fires Region#render\n\t *\n\t * @returns {wp.media.controller.Region} Returns itself to allow chaining\n\t */\n\trender: function( mode ) {\n\t\t// If the mode isn't active, activate it.\n\t\tif ( mode && mode !== this._mode ) {\n\t\t\treturn this.mode( mode );\n\t\t}\n\n\t\tvar set = { view: null },\n\t\t\tview;\n\n\t\t/**\n\t\t * Create region view event.\n\t\t *\n\t\t * Region view creation takes place in an event callback on the frame.\n\t\t *\n\t\t * @event wp.media.controller.Region#create\n\t\t * @type {object}\n\t\t * @property {object} view\n\t\t */\n\t\tthis.trigger( 'create', set );\n\t\tview = set.view;\n\n\t\t/**\n\t\t * Render region view event.\n\t\t *\n\t\t * Region view creation takes place in an event callback on the frame.\n\t\t *\n\t\t * @event wp.media.controller.Region#render\n\t\t * @type {object}\n\t\t */\n\t\tthis.trigger( 'render', view );\n\t\tif ( view ) {\n\t\t\tthis.set( view );\n\t\t}\n\t\treturn this;\n\t},\n\n\t/**\n\t * Get the region's view.\n\t *\n\t * @since 3.5.0\n\t *\n\t * @returns {wp.media.View}\n\t */\n\tget: function() {\n\t\treturn this.view.views.first( this.selector );\n\t},\n\n\t/**\n\t * Set the region's view as a subview of the frame.\n\t *\n\t * @since 3.5.0\n\t *\n\t * @param {Array|Object} views\n\t * @param {Object} [options={}]\n\t * @returns {wp.Backbone.Subviews} Subviews is returned to allow chaining\n\t */\n\tset: function( views, options ) {\n\t\tif ( options ) {\n\t\t\toptions.add = false;\n\t\t}\n\t\treturn this.view.views.set( this.selector, views, options );\n\t},\n\n\t/**\n\t * Trigger regional view events on the frame.\n\t *\n\t * @since 3.5.0\n\t *\n\t * @param {string} event\n\t * @returns {undefined|wp.media.controller.Region} Returns itself to allow chaining.\n\t */\n\ttrigger: function( event ) {\n\t\tvar base, args;\n\n\t\tif ( ! this._mode ) {\n\t\t\treturn;\n\t\t}\n\n\t\targs = _.toArray( arguments );\n\t\tbase = this.id + ':' + event;\n\n\t\t// Trigger `{this.id}:{event}:{this._mode}` event on the frame.\n\t\targs[0] = base + ':' + this._mode;\n\t\tthis.view.trigger.apply( this.view, args );\n\n\t\t// Trigger `{this.id}:{event}` event on the frame.\n\t\targs[0] = base;\n\t\tthis.view.trigger.apply( this.view, args );\n\t\treturn this;\n\t}\n});\n\nmodule.exports = Region;\n\n\n//# sourceURL=webpack:///./src/js/media/controllers/region.js?"); - -/***/ }), - -/***/ "./src/js/media/controllers/replace-image.js": -/*!***************************************************!*\ - !*** ./src/js/media/controllers/replace-image.js ***! - \***************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("var Library = wp.media.controller.Library,\n\tl10n = wp.media.view.l10n,\n\tReplaceImage;\n\n/**\n * wp.media.controller.ReplaceImage\n *\n * A state for replacing an image.\n *\n * @memberOf wp.media.controller\n *\n * @class\n * @augments wp.media.controller.Library\n * @augments wp.media.controller.State\n * @augments Backbone.Model\n *\n * @param {object} [attributes] The attributes hash passed to the state.\n * @param {string} [attributes.id=replace-image] Unique identifier.\n * @param {string} [attributes.title=Replace Image] Title for the state. Displays in the media menu and the frame's title region.\n * @param {wp.media.model.Attachments} [attributes.library] The attachments collection to browse.\n * If one is not supplied, a collection of all images will be created.\n * @param {boolean} [attributes.multiple=false] Whether multi-select is enabled.\n * @param {string} [attributes.content=upload] Initial mode for the content region.\n * Overridden by persistent user setting if 'contentUserSetting' is true.\n * @param {string} [attributes.menu=default] Initial mode for the menu region.\n * @param {string} [attributes.router=browse] Initial mode for the router region.\n * @param {string} [attributes.toolbar=replace] Initial mode for the toolbar region.\n * @param {int} [attributes.priority=60] The priority for the state link in the media menu.\n * @param {boolean} [attributes.searchable=true] Whether the library is searchable.\n * @param {boolean|string} [attributes.filterable=uploaded] Whether the library is filterable, and if so what filters should be shown.\n * Accepts 'all', 'uploaded', or 'unattached'.\n * @param {boolean} [attributes.sortable=true] Whether the Attachments should be sortable. Depends on the orderby property being set to menuOrder on the attachments collection.\n * @param {boolean} [attributes.autoSelect=true] Whether an uploaded attachment should be automatically added to the selection.\n * @param {boolean} [attributes.describe=false] Whether to offer UI to describe attachments - e.g. captioning images in a gallery.\n * @param {boolean} [attributes.contentUserSetting=true] Whether the content region's mode should be set and persisted per user.\n * @param {boolean} [attributes.syncSelection=true] Whether the Attachments selection should be persisted from the last state.\n */\nReplaceImage = Library.extend(/** @lends wp.media.controller.ReplaceImage.prototype */{\n\tdefaults: _.defaults({\n\t\tid: 'replace-image',\n\t\ttitle: l10n.replaceImageTitle,\n\t\tmultiple: false,\n\t\tfilterable: 'uploaded',\n\t\ttoolbar: 'replace',\n\t\tmenu: false,\n\t\tpriority: 60,\n\t\tsyncSelection: true\n\t}, Library.prototype.defaults ),\n\n\t/**\n\t * @since 3.9.0\n\t *\n\t * @param options\n\t */\n\tinitialize: function( options ) {\n\t\tvar library, comparator;\n\n\t\tthis.image = options.image;\n\t\t// If we haven't been provided a `library`, create a `Selection`.\n\t\tif ( ! this.get('library') ) {\n\t\t\tthis.set( 'library', wp.media.query({ type: 'image' }) );\n\t\t}\n\n\t\tLibrary.prototype.initialize.apply( this, arguments );\n\n\t\tlibrary = this.get('library');\n\t\tcomparator = library.comparator;\n\n\t\t// Overload the library's comparator to push items that are not in\n\t\t// the mirrored query to the front of the aggregate collection.\n\t\tlibrary.comparator = function( a, b ) {\n\t\t\tvar aInQuery = !! this.mirroring.get( a.cid ),\n\t\t\t\tbInQuery = !! this.mirroring.get( b.cid );\n\n\t\t\tif ( ! aInQuery && bInQuery ) {\n\t\t\t\treturn -1;\n\t\t\t} else if ( aInQuery && ! bInQuery ) {\n\t\t\t\treturn 1;\n\t\t\t} else {\n\t\t\t\treturn comparator.apply( this, arguments );\n\t\t\t}\n\t\t};\n\n\t\t// Add all items in the selection to the library, so any featured\n\t\t// images that are not initially loaded still appear.\n\t\tlibrary.observe( this.get('selection') );\n\t},\n\n\t/**\n\t * @since 3.9.0\n\t */\n\tactivate: function() {\n\t\tthis.updateSelection();\n\t\tLibrary.prototype.activate.apply( this, arguments );\n\t},\n\n\t/**\n\t * @since 3.9.0\n\t */\n\tupdateSelection: function() {\n\t\tvar selection = this.get('selection'),\n\t\t\tattachment = this.image.attachment;\n\n\t\tselection.reset( attachment ? [ attachment ] : [] );\n\t}\n});\n\nmodule.exports = ReplaceImage;\n\n\n//# sourceURL=webpack:///./src/js/media/controllers/replace-image.js?"); - -/***/ }), - -/***/ "./src/js/media/controllers/site-icon-cropper.js": -/*!*******************************************************!*\ - !*** ./src/js/media/controllers/site-icon-cropper.js ***! - \*******************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("var Controller = wp.media.controller,\n\tSiteIconCropper;\n\n/**\n * wp.media.controller.SiteIconCropper\n *\n * A state for cropping a Site Icon.\n *\n * @memberOf wp.media.controller\n *\n * @class\n * @augments wp.media.controller.Cropper\n * @augments wp.media.controller.State\n * @augments Backbone.Model\n */\nSiteIconCropper = Controller.Cropper.extend(/** @lends wp.media.controller.SiteIconCropper.prototype */{\n\tactivate: function() {\n\t\tthis.frame.on( 'content:create:crop', this.createCropContent, this );\n\t\tthis.frame.on( 'close', this.removeCropper, this );\n\t\tthis.set('selection', new Backbone.Collection(this.frame._selection.single));\n\t},\n\n\tcreateCropContent: function() {\n\t\tthis.cropperView = new wp.media.view.SiteIconCropper({\n\t\t\tcontroller: this,\n\t\t\tattachment: this.get('selection').first()\n\t\t});\n\t\tthis.cropperView.on('image-loaded', this.createCropToolbar, this);\n\t\tthis.frame.content.set(this.cropperView);\n\n\t},\n\n\tdoCrop: function( attachment ) {\n\t\tvar cropDetails = attachment.get( 'cropDetails' ),\n\t\t\tcontrol = this.get( 'control' );\n\n\t\tcropDetails.dst_width = control.params.width;\n\t\tcropDetails.dst_height = control.params.height;\n\n\t\treturn wp.ajax.post( 'crop-image', {\n\t\t\tnonce: attachment.get( 'nonces' ).edit,\n\t\t\tid: attachment.get( 'id' ),\n\t\t\tcontext: 'site-icon',\n\t\t\tcropDetails: cropDetails\n\t\t} );\n\t}\n});\n\nmodule.exports = SiteIconCropper;\n\n\n//# sourceURL=webpack:///./src/js/media/controllers/site-icon-cropper.js?"); - -/***/ }), - -/***/ "./src/js/media/controllers/state-machine.js": -/*!***************************************************!*\ - !*** ./src/js/media/controllers/state-machine.js ***! - \***************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("/**\n * wp.media.controller.StateMachine\n *\n * A state machine keeps track of state. It is in one state at a time,\n * and can change from one state to another.\n *\n * States are stored as models in a Backbone collection.\n *\n * @memberOf wp.media.controller\n *\n * @since 3.5.0\n *\n * @class\n * @augments Backbone.Model\n * @mixin\n * @mixes Backbone.Events\n *\n * @param {Array} states\n */\nvar StateMachine = function( states ) {\n\t// @todo This is dead code. The states collection gets created in media.view.Frame._createStates.\n\tthis.states = new Backbone.Collection( states );\n};\n\n// Use Backbone's self-propagating `extend` inheritance method.\nStateMachine.extend = Backbone.Model.extend;\n\n_.extend( StateMachine.prototype, Backbone.Events,/** @lends wp.media.controller.StateMachine.prototype */{\n\t/**\n\t * Fetch a state.\n\t *\n\t * If no `id` is provided, returns the active state.\n\t *\n\t * Implicitly creates states.\n\t *\n\t * Ensure that the `states` collection exists so the `StateMachine`\n\t * can be used as a mixin.\n\t *\n\t * @since 3.5.0\n\t *\n\t * @param {string} id\n\t * @returns {wp.media.controller.State} Returns a State model\n\t * from the StateMachine collection\n\t */\n\tstate: function( id ) {\n\t\tthis.states = this.states || new Backbone.Collection();\n\n\t\t// Default to the active state.\n\t\tid = id || this._state;\n\n\t\tif ( id && ! this.states.get( id ) ) {\n\t\t\tthis.states.add({ id: id });\n\t\t}\n\t\treturn this.states.get( id );\n\t},\n\n\t/**\n\t * Sets the active state.\n\t *\n\t * Bail if we're trying to select the current state, if we haven't\n\t * created the `states` collection, or are trying to select a state\n\t * that does not exist.\n\t *\n\t * @since 3.5.0\n\t *\n\t * @param {string} id\n\t *\n\t * @fires wp.media.controller.State#deactivate\n\t * @fires wp.media.controller.State#activate\n\t *\n\t * @returns {wp.media.controller.StateMachine} Returns itself to allow chaining\n\t */\n\tsetState: function( id ) {\n\t\tvar previous = this.state();\n\n\t\tif ( ( previous && id === previous.id ) || ! this.states || ! this.states.get( id ) ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( previous ) {\n\t\t\tprevious.trigger('deactivate');\n\t\t\tthis._lastState = previous.id;\n\t\t}\n\n\t\tthis._state = id;\n\t\tthis.state().trigger('activate');\n\n\t\treturn this;\n\t},\n\n\t/**\n\t * Returns the previous active state.\n\t *\n\t * Call the `state()` method with no parameters to retrieve the current\n\t * active state.\n\t *\n\t * @since 3.5.0\n\t *\n\t * @returns {wp.media.controller.State} Returns a State model\n\t * from the StateMachine collection\n\t */\n\tlastState: function() {\n\t\tif ( this._lastState ) {\n\t\t\treturn this.state( this._lastState );\n\t\t}\n\t}\n});\n\n// Map all event binding and triggering on a StateMachine to its `states` collection.\n_.each([ 'on', 'off', 'trigger' ], function( method ) {\n\t/**\n\t * @function on\n\t * @memberOf wp.media.controller.StateMachine\n\t * @instance\n\t * @returns {wp.media.controller.StateMachine} Returns itself to allow chaining.\n\t */\n\t/**\n\t * @function off\n\t * @memberOf wp.media.controller.StateMachine\n\t * @instance\n\t * @returns {wp.media.controller.StateMachine} Returns itself to allow chaining.\n\t */\n\t/**\n\t * @function trigger\n\t * @memberOf wp.media.controller.StateMachine\n\t * @instance\n\t * @returns {wp.media.controller.StateMachine} Returns itself to allow chaining.\n\t */\n\tStateMachine.prototype[ method ] = function() {\n\t\t// Ensure that the `states` collection exists so the `StateMachine`\n\t\t// can be used as a mixin.\n\t\tthis.states = this.states || new Backbone.Collection();\n\t\t// Forward the method to the `states` collection.\n\t\tthis.states[ method ].apply( this.states, arguments );\n\t\treturn this;\n\t};\n});\n\nmodule.exports = StateMachine;\n\n\n//# sourceURL=webpack:///./src/js/media/controllers/state-machine.js?"); - -/***/ }), - -/***/ "./src/js/media/controllers/state.js": -/*!*******************************************!*\ - !*** ./src/js/media/controllers/state.js ***! - \*******************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("/**\n * wp.media.controller.State\n *\n * A state is a step in a workflow that when set will trigger the controllers\n * for the regions to be updated as specified in the frame.\n *\n * A state has an event-driven lifecycle:\n *\n * 'ready' triggers when a state is added to a state machine's collection.\n * 'activate' triggers when a state is activated by a state machine.\n * 'deactivate' triggers when a state is deactivated by a state machine.\n * 'reset' is not triggered automatically. It should be invoked by the\n * proper controller to reset the state to its default.\n *\n * @memberOf wp.media.controller\n *\n * @class\n * @augments Backbone.Model\n */\nvar State = Backbone.Model.extend(/** @lends wp.media.controller.State.prototype */{\n\t/**\n\t * Constructor.\n\t *\n\t * @since 3.5.0\n\t */\n\tconstructor: function() {\n\t\tthis.on( 'activate', this._preActivate, this );\n\t\tthis.on( 'activate', this.activate, this );\n\t\tthis.on( 'activate', this._postActivate, this );\n\t\tthis.on( 'deactivate', this._deactivate, this );\n\t\tthis.on( 'deactivate', this.deactivate, this );\n\t\tthis.on( 'reset', this.reset, this );\n\t\tthis.on( 'ready', this._ready, this );\n\t\tthis.on( 'ready', this.ready, this );\n\t\t/**\n\t\t * Call parent constructor with passed arguments\n\t\t */\n\t\tBackbone.Model.apply( this, arguments );\n\t\tthis.on( 'change:menu', this._updateMenu, this );\n\t},\n\t/**\n\t * Ready event callback.\n\t *\n\t * @abstract\n\t * @since 3.5.0\n\t */\n\tready: function() {},\n\n\t/**\n\t * Activate event callback.\n\t *\n\t * @abstract\n\t * @since 3.5.0\n\t */\n\tactivate: function() {},\n\n\t/**\n\t * Deactivate event callback.\n\t *\n\t * @abstract\n\t * @since 3.5.0\n\t */\n\tdeactivate: function() {},\n\n\t/**\n\t * Reset event callback.\n\t *\n\t * @abstract\n\t * @since 3.5.0\n\t */\n\treset: function() {},\n\n\t/**\n\t * @access private\n\t * @since 3.5.0\n\t */\n\t_ready: function() {\n\t\tthis._updateMenu();\n\t},\n\n\t/**\n\t * @access private\n\t * @since 3.5.0\n\t*/\n\t_preActivate: function() {\n\t\tthis.active = true;\n\t},\n\n\t/**\n\t * @access private\n\t * @since 3.5.0\n\t */\n\t_postActivate: function() {\n\t\tthis.on( 'change:menu', this._menu, this );\n\t\tthis.on( 'change:titleMode', this._title, this );\n\t\tthis.on( 'change:content', this._content, this );\n\t\tthis.on( 'change:toolbar', this._toolbar, this );\n\n\t\tthis.frame.on( 'title:render:default', this._renderTitle, this );\n\n\t\tthis._title();\n\t\tthis._menu();\n\t\tthis._toolbar();\n\t\tthis._content();\n\t\tthis._router();\n\t},\n\n\t/**\n\t * @access private\n\t * @since 3.5.0\n\t */\n\t_deactivate: function() {\n\t\tthis.active = false;\n\n\t\tthis.frame.off( 'title:render:default', this._renderTitle, this );\n\n\t\tthis.off( 'change:menu', this._menu, this );\n\t\tthis.off( 'change:titleMode', this._title, this );\n\t\tthis.off( 'change:content', this._content, this );\n\t\tthis.off( 'change:toolbar', this._toolbar, this );\n\t},\n\n\t/**\n\t * @access private\n\t * @since 3.5.0\n\t */\n\t_title: function() {\n\t\tthis.frame.title.render( this.get('titleMode') || 'default' );\n\t},\n\n\t/**\n\t * @access private\n\t * @since 3.5.0\n\t */\n\t_renderTitle: function( view ) {\n\t\tview.$el.text( this.get('title') || '' );\n\t},\n\n\t/**\n\t * @access private\n\t * @since 3.5.0\n\t */\n\t_router: function() {\n\t\tvar router = this.frame.router,\n\t\t\tmode = this.get('router'),\n\t\t\tview;\n\n\t\tthis.frame.$el.toggleClass( 'hide-router', ! mode );\n\t\tif ( ! mode ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.frame.router.render( mode );\n\n\t\tview = router.get();\n\t\tif ( view && view.select ) {\n\t\t\tview.select( this.frame.content.mode() );\n\t\t}\n\t},\n\n\t/**\n\t * @access private\n\t * @since 3.5.0\n\t */\n\t_menu: function() {\n\t\tvar menu = this.frame.menu,\n\t\t\tmode = this.get('menu'),\n\t\t\tview;\n\n\t\tthis.frame.$el.toggleClass( 'hide-menu', ! mode );\n\t\tif ( ! mode ) {\n\t\t\treturn;\n\t\t}\n\n\t\tmenu.mode( mode );\n\n\t\tview = menu.get();\n\t\tif ( view && view.select ) {\n\t\t\tview.select( this.id );\n\t\t}\n\t},\n\n\t/**\n\t * @access private\n\t * @since 3.5.0\n\t */\n\t_updateMenu: function() {\n\t\tvar previous = this.previous('menu'),\n\t\t\tmenu = this.get('menu');\n\n\t\tif ( previous ) {\n\t\t\tthis.frame.off( 'menu:render:' + previous, this._renderMenu, this );\n\t\t}\n\n\t\tif ( menu ) {\n\t\t\tthis.frame.on( 'menu:render:' + menu, this._renderMenu, this );\n\t\t}\n\t},\n\n\t/**\n\t * Create a view in the media menu for the state.\n\t *\n\t * @access private\n\t * @since 3.5.0\n\t *\n\t * @param {media.view.Menu} view The menu view.\n\t */\n\t_renderMenu: function( view ) {\n\t\tvar menuItem = this.get('menuItem'),\n\t\t\ttitle = this.get('title'),\n\t\t\tpriority = this.get('priority');\n\n\t\tif ( ! menuItem && title ) {\n\t\t\tmenuItem = { text: title };\n\n\t\t\tif ( priority ) {\n\t\t\t\tmenuItem.priority = priority;\n\t\t\t}\n\t\t}\n\n\t\tif ( ! menuItem ) {\n\t\t\treturn;\n\t\t}\n\n\t\tview.set( this.id, menuItem );\n\t}\n});\n\n_.each(['toolbar','content'], function( region ) {\n\t/**\n\t * @access private\n\t */\n\tState.prototype[ '_' + region ] = function() {\n\t\tvar mode = this.get( region );\n\t\tif ( mode ) {\n\t\t\tthis.frame[ region ].render( mode );\n\t\t}\n\t};\n});\n\nmodule.exports = State;\n\n\n//# sourceURL=webpack:///./src/js/media/controllers/state.js?"); - -/***/ }), - -/***/ "./src/js/media/utils/selection-sync.js": -/*!**********************************************!*\ - !*** ./src/js/media/utils/selection-sync.js ***! - \**********************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("/**\n * wp.media.selectionSync\n *\n * Sync an attachments selection in a state with another state.\n *\n * Allows for selecting multiple images in the Add Media workflow, and then\n * switching to the Insert Gallery workflow while preserving the attachments selection.\n *\n * @memberOf wp.media\n *\n * @mixin\n */\nvar selectionSync = {\n\t/**\n\t * @since 3.5.0\n\t */\n\tsyncSelection: function() {\n\t\tvar selection = this.get('selection'),\n\t\t\tmanager = this.frame._selection;\n\n\t\tif ( ! this.get('syncSelection') || ! manager || ! selection ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If the selection supports multiple items, validate the stored\n\t\t// attachments based on the new selection's conditions. Record\n\t\t// the attachments that are not included; we'll maintain a\n\t\t// reference to those. Other attachments are considered in flux.\n\t\tif ( selection.multiple ) {\n\t\t\tselection.reset( [], { silent: true });\n\t\t\tselection.validateAll( manager.attachments );\n\t\t\tmanager.difference = _.difference( manager.attachments.models, selection.models );\n\t\t}\n\n\t\t// Sync the selection's single item with the master.\n\t\tselection.single( manager.single );\n\t},\n\n\t/**\n\t * Record the currently active attachments, which is a combination\n\t * of the selection's attachments and the set of selected\n\t * attachments that this specific selection considered invalid.\n\t * Reset the difference and record the single attachment.\n\t *\n\t * @since 3.5.0\n\t */\n\trecordSelection: function() {\n\t\tvar selection = this.get('selection'),\n\t\t\tmanager = this.frame._selection;\n\n\t\tif ( ! this.get('syncSelection') || ! manager || ! selection ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( selection.multiple ) {\n\t\t\tmanager.attachments.reset( selection.toArray().concat( manager.difference ) );\n\t\t\tmanager.difference = [];\n\t\t} else {\n\t\t\tmanager.attachments.add( selection.toArray() );\n\t\t}\n\n\t\tmanager.single = selection._single;\n\t}\n};\n\nmodule.exports = selectionSync;\n\n\n//# sourceURL=webpack:///./src/js/media/utils/selection-sync.js?"); - -/***/ }), - -/***/ "./src/js/media/views/attachment-compat.js": -/*!*************************************************!*\ - !*** ./src/js/media/views/attachment-compat.js ***! - \*************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("var View = wp.media.View,\n\tAttachmentCompat;\n\n/**\n * wp.media.view.AttachmentCompat\n *\n * A view to display fields added via the `attachment_fields_to_edit` filter.\n *\n * @memberOf wp.media.view\n *\n * @class\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n */\nAttachmentCompat = View.extend(/** @lends wp.media.view.AttachmentCompat.prototype */{\n\ttagName: 'form',\n\tclassName: 'compat-item',\n\n\tevents: {\n\t\t'submit': 'preventDefault',\n\t\t'change input': 'save',\n\t\t'change select': 'save',\n\t\t'change textarea': 'save'\n\t},\n\n\tinitialize: function() {\n\t\tthis.listenTo( this.model, 'change:compat', this.render );\n\t},\n\t/**\n\t * @returns {wp.media.view.AttachmentCompat} Returns itself to allow chaining\n\t */\n\tdispose: function() {\n\t\tif ( this.$(':focus').length ) {\n\t\t\tthis.save();\n\t\t}\n\t\t/**\n\t\t * call 'dispose' directly on the parent class\n\t\t */\n\t\treturn View.prototype.dispose.apply( this, arguments );\n\t},\n\t/**\n\t * @returns {wp.media.view.AttachmentCompat} Returns itself to allow chaining\n\t */\n\trender: function() {\n\t\tvar compat = this.model.get('compat');\n\t\tif ( ! compat || ! compat.item ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.views.detach();\n\t\tthis.$el.html( compat.item );\n\t\tthis.views.render();\n\t\treturn this;\n\t},\n\t/**\n\t * @param {Object} event\n\t */\n\tpreventDefault: function( event ) {\n\t\tevent.preventDefault();\n\t},\n\t/**\n\t * @param {Object} event\n\t */\n\tsave: function( event ) {\n\t\tvar data = {};\n\n\t\tif ( event ) {\n\t\t\tevent.preventDefault();\n\t\t}\n\n\t\t_.each( this.$el.serializeArray(), function( pair ) {\n\t\t\tdata[ pair.name ] = pair.value;\n\t\t});\n\n\t\tthis.controller.trigger( 'attachment:compat:waiting', ['waiting'] );\n\t\tthis.model.saveCompat( data ).always( _.bind( this.postSave, this ) );\n\t},\n\n\tpostSave: function() {\n\t\tthis.controller.trigger( 'attachment:compat:ready', ['ready'] );\n\t}\n});\n\nmodule.exports = AttachmentCompat;\n\n\n//# sourceURL=webpack:///./src/js/media/views/attachment-compat.js?"); - -/***/ }), - -/***/ "./src/js/media/views/attachment-filters.js": -/*!**************************************************!*\ - !*** ./src/js/media/views/attachment-filters.js ***! - \**************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("var $ = jQuery,\n\tAttachmentFilters;\n\n/**\n * wp.media.view.AttachmentFilters\n *\n * @memberOf wp.media.view\n *\n * @class\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n */\nAttachmentFilters = wp.media.View.extend(/** @lends wp.media.view.AttachmentFilters.prototype */{\n\ttagName: 'select',\n\tclassName: 'attachment-filters',\n\tid: 'media-attachment-filters',\n\n\tevents: {\n\t\tchange: 'change'\n\t},\n\n\tkeys: [],\n\n\tinitialize: function() {\n\t\tthis.createFilters();\n\t\t_.extend( this.filters, this.options.filters );\n\n\t\t// Build `' ).val( value ).html( filter.text )[0],\n\t\t\t\tpriority: filter.priority || 50\n\t\t\t};\n\t\t}, this ).sortBy('priority').pluck('el').value() );\n\n\t\tthis.listenTo( this.model, 'change', this.select );\n\t\tthis.select();\n\t},\n\n\t/**\n\t * @abstract\n\t */\n\tcreateFilters: function() {\n\t\tthis.filters = {};\n\t},\n\n\t/**\n\t * When the selected filter changes, update the Attachment Query properties to match.\n\t */\n\tchange: function() {\n\t\tvar filter = this.filters[ this.el.value ];\n\t\tif ( filter ) {\n\t\t\tthis.model.set( filter.props );\n\t\t}\n\t},\n\n\tselect: function() {\n\t\tvar model = this.model,\n\t\t\tvalue = 'all',\n\t\t\tprops = model.toJSON();\n\n\t\t_.find( this.filters, function( filter, id ) {\n\t\t\tvar equal = _.all( filter.props, function( prop, key ) {\n\t\t\t\treturn prop === ( _.isUndefined( props[ key ] ) ? null : props[ key ] );\n\t\t\t});\n\n\t\t\tif ( equal ) {\n\t\t\t\treturn value = id;\n\t\t\t}\n\t\t});\n\n\t\tthis.$el.val( value );\n\t}\n});\n\nmodule.exports = AttachmentFilters;\n\n\n//# sourceURL=webpack:///./src/js/media/views/attachment-filters.js?"); - -/***/ }), - -/***/ "./src/js/media/views/attachment-filters/all.js": -/*!******************************************************!*\ - !*** ./src/js/media/views/attachment-filters/all.js ***! - \******************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("var l10n = wp.media.view.l10n,\n\tAll;\n\n/**\n * wp.media.view.AttachmentFilters.All\n *\n * @memberOf wp.media.view.AttachmentFilters\n *\n * @class\n * @augments wp.media.view.AttachmentFilters\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n */\nAll = wp.media.view.AttachmentFilters.extend(/** @lends wp.media.view.AttachmentFilters.All.prototype */{\n\tcreateFilters: function() {\n\t\tvar filters = {},\n\t\t\tuid = window.userSettings ? parseInt( window.userSettings.uid, 10 ) : 0;\n\n\t\t_.each( wp.media.view.settings.mimeTypes || {}, function( text, key ) {\n\t\t\tfilters[ key ] = {\n\t\t\t\ttext: text,\n\t\t\t\tprops: {\n\t\t\t\t\tstatus: null,\n\t\t\t\t\ttype: key,\n\t\t\t\t\tuploadedTo: null,\n\t\t\t\t\torderby: 'date',\n\t\t\t\t\torder: 'DESC',\n\t\t\t\t\tauthor: null\n\t\t\t\t}\n\t\t\t};\n\t\t});\n\n\t\tfilters.all = {\n\t\t\ttext: l10n.allMediaItems,\n\t\t\tprops: {\n\t\t\t\tstatus: null,\n\t\t\t\ttype: null,\n\t\t\t\tuploadedTo: null,\n\t\t\t\torderby: 'date',\n\t\t\t\torder: 'DESC',\n\t\t\t\tauthor: null\n\t\t\t},\n\t\t\tpriority: 10\n\t\t};\n\n\t\tif ( wp.media.view.settings.post.id ) {\n\t\t\tfilters.uploaded = {\n\t\t\t\ttext: l10n.uploadedToThisPost,\n\t\t\t\tprops: {\n\t\t\t\t\tstatus: null,\n\t\t\t\t\ttype: null,\n\t\t\t\t\tuploadedTo: wp.media.view.settings.post.id,\n\t\t\t\t\torderby: 'menuOrder',\n\t\t\t\t\torder: 'ASC',\n\t\t\t\t\tauthor: null\n\t\t\t\t},\n\t\t\t\tpriority: 20\n\t\t\t};\n\t\t}\n\n\t\tfilters.unattached = {\n\t\t\ttext: l10n.unattached,\n\t\t\tprops: {\n\t\t\t\tstatus: null,\n\t\t\t\tuploadedTo: 0,\n\t\t\t\ttype: null,\n\t\t\t\torderby: 'menuOrder',\n\t\t\t\torder: 'ASC',\n\t\t\t\tauthor: null\n\t\t\t},\n\t\t\tpriority: 50\n\t\t};\n\n\t\tif ( uid ) {\n\t\t\tfilters.mine = {\n\t\t\t\ttext: l10n.mine,\n\t\t\t\tprops: {\n\t\t\t\t\tstatus:\t\tnull,\n\t\t\t\t\ttype:\t\tnull,\n\t\t\t\t\tuploadedTo:\tnull,\n\t\t\t\t\torderby:\t'date',\n\t\t\t\t\torder:\t\t'DESC',\n\t\t\t\t\tauthor:\t\tuid\n\t\t\t\t},\n\t\t\t\tpriority: 50\n\t\t\t};\n\t\t}\n\n\t\tif ( wp.media.view.settings.mediaTrash &&\n\t\t\tthis.controller.isModeActive( 'grid' ) ) {\n\n\t\t\tfilters.trash = {\n\t\t\t\ttext: l10n.trash,\n\t\t\t\tprops: {\n\t\t\t\t\tuploadedTo: null,\n\t\t\t\t\tstatus: 'trash',\n\t\t\t\t\ttype: null,\n\t\t\t\t\torderby: 'date',\n\t\t\t\t\torder: 'DESC',\n\t\t\t\t\tauthor: null\n\t\t\t\t},\n\t\t\t\tpriority: 50\n\t\t\t};\n\t\t}\n\n\t\tthis.filters = filters;\n\t}\n});\n\nmodule.exports = All;\n\n\n//# sourceURL=webpack:///./src/js/media/views/attachment-filters/all.js?"); - -/***/ }), - -/***/ "./src/js/media/views/attachment-filters/date.js": -/*!*******************************************************!*\ - !*** ./src/js/media/views/attachment-filters/date.js ***! - \*******************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("var l10n = wp.media.view.l10n,\n\tDateFilter;\n\n/**\n * A filter dropdown for month/dates.\n *\n * @memberOf wp.media.view.AttachmentFilters\n *\n * @class\n * @augments wp.media.view.AttachmentFilters\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n */\nDateFilter = wp.media.view.AttachmentFilters.extend(/** @lends wp.media.view.AttachmentFilters.Date.prototype */{\n\tid: 'media-attachment-date-filters',\n\n\tcreateFilters: function() {\n\t\tvar filters = {};\n\t\t_.each( wp.media.view.settings.months || {}, function( value, index ) {\n\t\t\tfilters[ index ] = {\n\t\t\t\ttext: value.text,\n\t\t\t\tprops: {\n\t\t\t\t\tyear: value.year,\n\t\t\t\t\tmonthnum: value.month\n\t\t\t\t}\n\t\t\t};\n\t\t});\n\t\tfilters.all = {\n\t\t\ttext: l10n.allDates,\n\t\t\tprops: {\n\t\t\t\tmonthnum: false,\n\t\t\t\tyear: false\n\t\t\t},\n\t\t\tpriority: 10\n\t\t};\n\t\tthis.filters = filters;\n\t}\n});\n\nmodule.exports = DateFilter;\n\n\n//# sourceURL=webpack:///./src/js/media/views/attachment-filters/date.js?"); - -/***/ }), - -/***/ "./src/js/media/views/attachment-filters/uploaded.js": -/*!***********************************************************!*\ - !*** ./src/js/media/views/attachment-filters/uploaded.js ***! - \***********************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("var l10n = wp.media.view.l10n,\n\tUploaded;\n\n/**\n * wp.media.view.AttachmentFilters.Uploaded\n *\n * @memberOf wp.media.view.AttachmentFilters\n *\n * @class\n * @augments wp.media.view.AttachmentFilters\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n */\nUploaded = wp.media.view.AttachmentFilters.extend(/** @lends wp.media.view.AttachmentFilters.Uploaded.prototype */{\n\tcreateFilters: function() {\n\t\tvar type = this.model.get('type'),\n\t\t\ttypes = wp.media.view.settings.mimeTypes,\n\t\t\tuid = window.userSettings ? parseInt( window.userSettings.uid, 10 ) : 0,\n\t\t\ttext;\n\n\t\tif ( types && type ) {\n\t\t\ttext = types[ type ];\n\t\t}\n\n\t\tthis.filters = {\n\t\t\tall: {\n\t\t\t\ttext: text || l10n.allMediaItems,\n\t\t\t\tprops: {\n\t\t\t\t\tuploadedTo: null,\n\t\t\t\t\torderby: 'date',\n\t\t\t\t\torder: 'DESC',\n\t\t\t\t\tauthor:\t null\n\t\t\t\t},\n\t\t\t\tpriority: 10\n\t\t\t},\n\n\t\t\tuploaded: {\n\t\t\t\ttext: l10n.uploadedToThisPost,\n\t\t\t\tprops: {\n\t\t\t\t\tuploadedTo: wp.media.view.settings.post.id,\n\t\t\t\t\torderby: 'menuOrder',\n\t\t\t\t\torder: 'ASC',\n\t\t\t\t\tauthor:\t null\n\t\t\t\t},\n\t\t\t\tpriority: 20\n\t\t\t},\n\n\t\t\tunattached: {\n\t\t\t\ttext: l10n.unattached,\n\t\t\t\tprops: {\n\t\t\t\t\tuploadedTo: 0,\n\t\t\t\t\torderby: 'menuOrder',\n\t\t\t\t\torder: 'ASC',\n\t\t\t\t\tauthor:\t null\n\t\t\t\t},\n\t\t\t\tpriority: 50\n\t\t\t}\n\t\t};\n\n\t\tif ( uid ) {\n\t\t\tthis.filters.mine = {\n\t\t\t\ttext: l10n.mine,\n\t\t\t\tprops: {\n\t\t\t\t\torderby: 'date',\n\t\t\t\t\torder: 'DESC',\n\t\t\t\t\tauthor: uid\n\t\t\t\t},\n\t\t\t\tpriority: 50\n\t\t\t};\n\t\t}\n\t}\n});\n\nmodule.exports = Uploaded;\n\n\n//# sourceURL=webpack:///./src/js/media/views/attachment-filters/uploaded.js?"); - -/***/ }), - -/***/ "./src/js/media/views/attachment.js": -/*!******************************************!*\ - !*** ./src/js/media/views/attachment.js ***! - \******************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("var View = wp.media.View,\n\t$ = jQuery,\n\tAttachment;\n\n/**\n * wp.media.view.Attachment\n *\n * @memberOf wp.media.view\n *\n * @class\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n */\nAttachment = View.extend(/** @lends wp.media.view.Attachment.prototype */{\n\ttagName: 'li',\n\tclassName: 'attachment',\n\ttemplate: wp.template('attachment'),\n\n\tattributes: function() {\n\t\treturn {\n\t\t\t'tabIndex': 0,\n\t\t\t'role': 'checkbox',\n\t\t\t'aria-label': this.model.get( 'title' ),\n\t\t\t'aria-checked': false,\n\t\t\t'data-id': this.model.get( 'id' )\n\t\t};\n\t},\n\n\tevents: {\n\t\t'click': 'toggleSelectionHandler',\n\t\t'change [data-setting]': 'updateSetting',\n\t\t'change [data-setting] input': 'updateSetting',\n\t\t'change [data-setting] select': 'updateSetting',\n\t\t'change [data-setting] textarea': 'updateSetting',\n\t\t'click .attachment-close': 'removeFromLibrary',\n\t\t'click .check': 'checkClickHandler',\n\t\t'keydown': 'toggleSelectionHandler'\n\t},\n\n\tbuttons: {},\n\n\tinitialize: function() {\n\t\tvar selection = this.options.selection,\n\t\t\toptions = _.defaults( this.options, {\n\t\t\t\trerenderOnModelChange: true\n\t\t\t} );\n\n\t\tif ( options.rerenderOnModelChange ) {\n\t\t\tthis.listenTo( this.model, 'change', this.render );\n\t\t} else {\n\t\t\tthis.listenTo( this.model, 'change:percent', this.progress );\n\t\t}\n\t\tthis.listenTo( this.model, 'change:title', this._syncTitle );\n\t\tthis.listenTo( this.model, 'change:caption', this._syncCaption );\n\t\tthis.listenTo( this.model, 'change:artist', this._syncArtist );\n\t\tthis.listenTo( this.model, 'change:album', this._syncAlbum );\n\n\t\t// Update the selection.\n\t\tthis.listenTo( this.model, 'add', this.select );\n\t\tthis.listenTo( this.model, 'remove', this.deselect );\n\t\tif ( selection ) {\n\t\t\tselection.on( 'reset', this.updateSelect, this );\n\t\t\t// Update the model's details view.\n\t\t\tthis.listenTo( this.model, 'selection:single selection:unsingle', this.details );\n\t\t\tthis.details( this.model, this.controller.state().get('selection') );\n\t\t}\n\n\t\tthis.listenTo( this.controller, 'attachment:compat:waiting attachment:compat:ready', this.updateSave );\n\t},\n\t/**\n\t * @returns {wp.media.view.Attachment} Returns itself to allow chaining\n\t */\n\tdispose: function() {\n\t\tvar selection = this.options.selection;\n\n\t\t// Make sure all settings are saved before removing the view.\n\t\tthis.updateAll();\n\n\t\tif ( selection ) {\n\t\t\tselection.off( null, null, this );\n\t\t}\n\t\t/**\n\t\t * call 'dispose' directly on the parent class\n\t\t */\n\t\tView.prototype.dispose.apply( this, arguments );\n\t\treturn this;\n\t},\n\t/**\n\t * @returns {wp.media.view.Attachment} Returns itself to allow chaining\n\t */\n\trender: function() {\n\t\tvar options = _.defaults( this.model.toJSON(), {\n\t\t\t\torientation: 'landscape',\n\t\t\t\tuploading: false,\n\t\t\t\ttype: '',\n\t\t\t\tsubtype: '',\n\t\t\t\ticon: '',\n\t\t\t\tfilename: '',\n\t\t\t\tcaption: '',\n\t\t\t\ttitle: '',\n\t\t\t\tdateFormatted: '',\n\t\t\t\twidth: '',\n\t\t\t\theight: '',\n\t\t\t\tcompat: false,\n\t\t\t\talt: '',\n\t\t\t\tdescription: ''\n\t\t\t}, this.options );\n\n\t\toptions.buttons = this.buttons;\n\t\toptions.describe = this.controller.state().get('describe');\n\n\t\tif ( 'image' === options.type ) {\n\t\t\toptions.size = this.imageSize();\n\t\t}\n\n\t\toptions.can = {};\n\t\tif ( options.nonces ) {\n\t\t\toptions.can.remove = !! options.nonces['delete'];\n\t\t\toptions.can.save = !! options.nonces.update;\n\t\t}\n\n\t\tif ( this.controller.state().get('allowLocalEdits') ) {\n\t\t\toptions.allowLocalEdits = true;\n\t\t}\n\n\t\tif ( options.uploading && ! options.percent ) {\n\t\t\toptions.percent = 0;\n\t\t}\n\n\t\tthis.views.detach();\n\t\tthis.$el.html( this.template( options ) );\n\n\t\tthis.$el.toggleClass( 'uploading', options.uploading );\n\n\t\tif ( options.uploading ) {\n\t\t\tthis.$bar = this.$('.media-progress-bar div');\n\t\t} else {\n\t\t\tdelete this.$bar;\n\t\t}\n\n\t\t// Check if the model is selected.\n\t\tthis.updateSelect();\n\n\t\t// Update the save status.\n\t\tthis.updateSave();\n\n\t\tthis.views.render();\n\n\t\treturn this;\n\t},\n\n\tprogress: function() {\n\t\tif ( this.$bar && this.$bar.length ) {\n\t\t\tthis.$bar.width( this.model.get('percent') + '%' );\n\t\t}\n\t},\n\n\t/**\n\t * @param {Object} event\n\t */\n\ttoggleSelectionHandler: function( event ) {\n\t\tvar method;\n\n\t\t// Don't do anything inside inputs and on the attachment check and remove buttons.\n\t\tif ( 'INPUT' === event.target.nodeName || 'BUTTON' === event.target.nodeName ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Catch arrow events\n\t\tif ( 37 === event.keyCode || 38 === event.keyCode || 39 === event.keyCode || 40 === event.keyCode ) {\n\t\t\tthis.controller.trigger( 'attachment:keydown:arrow', event );\n\t\t\treturn;\n\t\t}\n\n\t\t// Catch enter and space events\n\t\tif ( 'keydown' === event.type && 13 !== event.keyCode && 32 !== event.keyCode ) {\n\t\t\treturn;\n\t\t}\n\n\t\tevent.preventDefault();\n\n\t\t// In the grid view, bubble up an edit:attachment event to the controller.\n\t\tif ( this.controller.isModeActive( 'grid' ) ) {\n\t\t\tif ( this.controller.isModeActive( 'edit' ) ) {\n\t\t\t\t// Pass the current target to restore focus when closing\n\t\t\t\tthis.controller.trigger( 'edit:attachment', this.model, event.currentTarget );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( this.controller.isModeActive( 'select' ) ) {\n\t\t\t\tmethod = 'toggle';\n\t\t\t}\n\t\t}\n\n\t\tif ( event.shiftKey ) {\n\t\t\tmethod = 'between';\n\t\t} else if ( event.ctrlKey || event.metaKey ) {\n\t\t\tmethod = 'toggle';\n\t\t}\n\n\t\tthis.toggleSelection({\n\t\t\tmethod: method\n\t\t});\n\n\t\tthis.controller.trigger( 'selection:toggle' );\n\t},\n\t/**\n\t * @param {Object} options\n\t */\n\ttoggleSelection: function( options ) {\n\t\tvar collection = this.collection,\n\t\t\tselection = this.options.selection,\n\t\t\tmodel = this.model,\n\t\t\tmethod = options && options.method,\n\t\t\tsingle, models, singleIndex, modelIndex;\n\n\t\tif ( ! selection ) {\n\t\t\treturn;\n\t\t}\n\n\t\tsingle = selection.single();\n\t\tmethod = _.isUndefined( method ) ? selection.multiple : method;\n\n\t\t// If the `method` is set to `between`, select all models that\n\t\t// exist between the current and the selected model.\n\t\tif ( 'between' === method && single && selection.multiple ) {\n\t\t\t// If the models are the same, short-circuit.\n\t\t\tif ( single === model ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tsingleIndex = collection.indexOf( single );\n\t\t\tmodelIndex = collection.indexOf( this.model );\n\n\t\t\tif ( singleIndex < modelIndex ) {\n\t\t\t\tmodels = collection.models.slice( singleIndex, modelIndex + 1 );\n\t\t\t} else {\n\t\t\t\tmodels = collection.models.slice( modelIndex, singleIndex + 1 );\n\t\t\t}\n\n\t\t\tselection.add( models );\n\t\t\tselection.single( model );\n\t\t\treturn;\n\n\t\t// If the `method` is set to `toggle`, just flip the selection\n\t\t// status, regardless of whether the model is the single model.\n\t\t} else if ( 'toggle' === method ) {\n\t\t\tselection[ this.selected() ? 'remove' : 'add' ]( model );\n\t\t\tselection.single( model );\n\t\t\treturn;\n\t\t} else if ( 'add' === method ) {\n\t\t\tselection.add( model );\n\t\t\tselection.single( model );\n\t\t\treturn;\n\t\t}\n\n\t\t// Fixes bug that loses focus when selecting a featured image\n\t\tif ( ! method ) {\n\t\t\tmethod = 'add';\n\t\t}\n\n\t\tif ( method !== 'add' ) {\n\t\t\tmethod = 'reset';\n\t\t}\n\n\t\tif ( this.selected() ) {\n\t\t\t// If the model is the single model, remove it.\n\t\t\t// If it is not the same as the single model,\n\t\t\t// it now becomes the single model.\n\t\t\tselection[ single === model ? 'remove' : 'single' ]( model );\n\t\t} else {\n\t\t\t// If the model is not selected, run the `method` on the\n\t\t\t// selection. By default, we `reset` the selection, but the\n\t\t\t// `method` can be set to `add` the model to the selection.\n\t\t\tselection[ method ]( model );\n\t\t\tselection.single( model );\n\t\t}\n\t},\n\n\tupdateSelect: function() {\n\t\tthis[ this.selected() ? 'select' : 'deselect' ]();\n\t},\n\t/**\n\t * @returns {unresolved|Boolean}\n\t */\n\tselected: function() {\n\t\tvar selection = this.options.selection;\n\t\tif ( selection ) {\n\t\t\treturn !! selection.get( this.model.cid );\n\t\t}\n\t},\n\t/**\n\t * @param {Backbone.Model} model\n\t * @param {Backbone.Collection} collection\n\t */\n\tselect: function( model, collection ) {\n\t\tvar selection = this.options.selection,\n\t\t\tcontroller = this.controller;\n\n\t\t// Check if a selection exists and if it's the collection provided.\n\t\t// If they're not the same collection, bail; we're in another\n\t\t// selection's event loop.\n\t\tif ( ! selection || ( collection && collection !== selection ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Bail if the model is already selected.\n\t\tif ( this.$el.hasClass( 'selected' ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Add 'selected' class to model, set aria-checked to true.\n\t\tthis.$el.addClass( 'selected' ).attr( 'aria-checked', true );\n\t\t// Make the checkbox tabable, except in media grid (bulk select mode).\n\t\tif ( ! ( controller.isModeActive( 'grid' ) && controller.isModeActive( 'select' ) ) ) {\n\t\t\tthis.$( '.check' ).attr( 'tabindex', '0' );\n\t\t}\n\t},\n\t/**\n\t * @param {Backbone.Model} model\n\t * @param {Backbone.Collection} collection\n\t */\n\tdeselect: function( model, collection ) {\n\t\tvar selection = this.options.selection;\n\n\t\t// Check if a selection exists and if it's the collection provided.\n\t\t// If they're not the same collection, bail; we're in another\n\t\t// selection's event loop.\n\t\tif ( ! selection || ( collection && collection !== selection ) ) {\n\t\t\treturn;\n\t\t}\n\t\tthis.$el.removeClass( 'selected' ).attr( 'aria-checked', false )\n\t\t\t.find( '.check' ).attr( 'tabindex', '-1' );\n\t},\n\t/**\n\t * @param {Backbone.Model} model\n\t * @param {Backbone.Collection} collection\n\t */\n\tdetails: function( model, collection ) {\n\t\tvar selection = this.options.selection,\n\t\t\tdetails;\n\n\t\tif ( selection !== collection ) {\n\t\t\treturn;\n\t\t}\n\n\t\tdetails = selection.single();\n\t\tthis.$el.toggleClass( 'details', details === this.model );\n\t},\n\t/**\n\t * @param {string} size\n\t * @returns {Object}\n\t */\n\timageSize: function( size ) {\n\t\tvar sizes = this.model.get('sizes'), matched = false;\n\n\t\tsize = size || 'medium';\n\n\t\t// Use the provided image size if possible.\n\t\tif ( sizes ) {\n\t\t\tif ( sizes[ size ] ) {\n\t\t\t\tmatched = sizes[ size ];\n\t\t\t} else if ( sizes.large ) {\n\t\t\t\tmatched = sizes.large;\n\t\t\t} else if ( sizes.thumbnail ) {\n\t\t\t\tmatched = sizes.thumbnail;\n\t\t\t} else if ( sizes.full ) {\n\t\t\t\tmatched = sizes.full;\n\t\t\t}\n\n\t\t\tif ( matched ) {\n\t\t\t\treturn _.clone( matched );\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\turl: this.model.get('url'),\n\t\t\twidth: this.model.get('width'),\n\t\t\theight: this.model.get('height'),\n\t\t\torientation: this.model.get('orientation')\n\t\t};\n\t},\n\t/**\n\t * @param {Object} event\n\t */\n\tupdateSetting: function( event ) {\n\t\tvar $setting = $( event.target ).closest('[data-setting]'),\n\t\t\tsetting, value;\n\n\t\tif ( ! $setting.length ) {\n\t\t\treturn;\n\t\t}\n\n\t\tsetting = $setting.data('setting');\n\t\tvalue = event.target.value;\n\n\t\tif ( this.model.get( setting ) !== value ) {\n\t\t\tthis.save( setting, value );\n\t\t}\n\t},\n\n\t/**\n\t * Pass all the arguments to the model's save method.\n\t *\n\t * Records the aggregate status of all save requests and updates the\n\t * view's classes accordingly.\n\t */\n\tsave: function() {\n\t\tvar view = this,\n\t\t\tsave = this._save = this._save || { status: 'ready' },\n\t\t\trequest = this.model.save.apply( this.model, arguments ),\n\t\t\trequests = save.requests ? $.when( request, save.requests ) : request;\n\n\t\t// If we're waiting to remove 'Saved.', stop.\n\t\tif ( save.savedTimer ) {\n\t\t\tclearTimeout( save.savedTimer );\n\t\t}\n\n\t\tthis.updateSave('waiting');\n\t\tsave.requests = requests;\n\t\trequests.always( function() {\n\t\t\t// If we've performed another request since this one, bail.\n\t\t\tif ( save.requests !== requests ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tview.updateSave( requests.state() === 'resolved' ? 'complete' : 'error' );\n\t\t\tsave.savedTimer = setTimeout( function() {\n\t\t\t\tview.updateSave('ready');\n\t\t\t\tdelete save.savedTimer;\n\t\t\t}, 2000 );\n\t\t});\n\t},\n\t/**\n\t * @param {string} status\n\t * @returns {wp.media.view.Attachment} Returns itself to allow chaining\n\t */\n\tupdateSave: function( status ) {\n\t\tvar save = this._save = this._save || { status: 'ready' };\n\n\t\tif ( status && status !== save.status ) {\n\t\t\tthis.$el.removeClass( 'save-' + save.status );\n\t\t\tsave.status = status;\n\t\t}\n\n\t\tthis.$el.addClass( 'save-' + save.status );\n\t\treturn this;\n\t},\n\n\tupdateAll: function() {\n\t\tvar $settings = this.$('[data-setting]'),\n\t\t\tmodel = this.model,\n\t\t\tchanged;\n\n\t\tchanged = _.chain( $settings ).map( function( el ) {\n\t\t\tvar $input = $('input, textarea, select, [value]', el ),\n\t\t\t\tsetting, value;\n\n\t\t\tif ( ! $input.length ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tsetting = $(el).data('setting');\n\t\t\tvalue = $input.val();\n\n\t\t\t// Record the value if it changed.\n\t\t\tif ( model.get( setting ) !== value ) {\n\t\t\t\treturn [ setting, value ];\n\t\t\t}\n\t\t}).compact().object().value();\n\n\t\tif ( ! _.isEmpty( changed ) ) {\n\t\t\tmodel.save( changed );\n\t\t}\n\t},\n\t/**\n\t * @param {Object} event\n\t */\n\tremoveFromLibrary: function( event ) {\n\t\t// Catch enter and space events\n\t\tif ( 'keydown' === event.type && 13 !== event.keyCode && 32 !== event.keyCode ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Stop propagation so the model isn't selected.\n\t\tevent.stopPropagation();\n\n\t\tthis.collection.remove( this.model );\n\t},\n\n\t/**\n\t * Add the model if it isn't in the selection, if it is in the selection,\n\t * remove it.\n\t *\n\t * @param {[type]} event [description]\n\t * @return {[type]} [description]\n\t */\n\tcheckClickHandler: function ( event ) {\n\t\tvar selection = this.options.selection;\n\t\tif ( ! selection ) {\n\t\t\treturn;\n\t\t}\n\t\tevent.stopPropagation();\n\t\tif ( selection.where( { id: this.model.get( 'id' ) } ).length ) {\n\t\t\tselection.remove( this.model );\n\t\t\t// Move focus back to the attachment tile (from the check).\n\t\t\tthis.$el.focus();\n\t\t} else {\n\t\t\tselection.add( this.model );\n\t\t}\n\t}\n});\n\n// Ensure settings remain in sync between attachment views.\n_.each({\n\tcaption: '_syncCaption',\n\ttitle: '_syncTitle',\n\tartist: '_syncArtist',\n\talbum: '_syncAlbum'\n}, function( method, setting ) {\n\t/**\n\t * @function _syncCaption\n\t * @memberOf wp.media.view.Attachment\n\t * @instance\n\t *\n\t * @param {Backbone.Model} model\n\t * @param {string} value\n\t * @returns {wp.media.view.Attachment} Returns itself to allow chaining\n\t */\n\t/**\n\t * @function _syncTitle\n\t * @memberOf wp.media.view.Attachment\n\t * @instance\n\t *\n\t * @param {Backbone.Model} model\n\t * @param {string} value\n\t * @returns {wp.media.view.Attachment} Returns itself to allow chaining\n\t */\n\t/**\n\t * @function _syncArtist\n\t * @memberOf wp.media.view.Attachment\n\t * @instance\n\t *\n\t * @param {Backbone.Model} model\n\t * @param {string} value\n\t * @returns {wp.media.view.Attachment} Returns itself to allow chaining\n\t */\n\t/**\n\t * @function _syncAlbum\n\t * @memberOf wp.media.view.Attachment\n\t * @instance\n\t *\n\t * @param {Backbone.Model} model\n\t * @param {string} value\n\t * @returns {wp.media.view.Attachment} Returns itself to allow chaining\n\t */\n\tAttachment.prototype[ method ] = function( model, value ) {\n\t\tvar $setting = this.$('[data-setting=\"' + setting + '\"]');\n\n\t\tif ( ! $setting.length ) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// If the updated value is in sync with the value in the DOM, there\n\t\t// is no need to re-render. If we're currently editing the value,\n\t\t// it will automatically be in sync, suppressing the re-render for\n\t\t// the view we're editing, while updating any others.\n\t\tif ( value === $setting.find('input, textarea, select, [value]').val() ) {\n\t\t\treturn this;\n\t\t}\n\n\t\treturn this.render();\n\t};\n});\n\nmodule.exports = Attachment;\n\n\n//# sourceURL=webpack:///./src/js/media/views/attachment.js?"); - -/***/ }), - -/***/ "./src/js/media/views/attachment/details.js": -/*!**************************************************!*\ - !*** ./src/js/media/views/attachment/details.js ***! - \**************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("var Attachment = wp.media.view.Attachment,\n\tl10n = wp.media.view.l10n,\n\tDetails;\n\n/**\n * wp.media.view.Attachment.Details\n *\n * @memberOf wp.media.view.Attachment\n *\n * @class\n * @augments wp.media.view.Attachment\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n */\nDetails = Attachment.extend(/** @lends wp.media.view.Attachment.Details.prototype */{\n\ttagName: 'div',\n\tclassName: 'attachment-details',\n\ttemplate: wp.template('attachment-details'),\n\n\tattributes: function() {\n\t\treturn {\n\t\t\t'tabIndex': 0,\n\t\t\t'data-id': this.model.get( 'id' )\n\t\t};\n\t},\n\n\tevents: {\n\t\t'change [data-setting]': 'updateSetting',\n\t\t'change [data-setting] input': 'updateSetting',\n\t\t'change [data-setting] select': 'updateSetting',\n\t\t'change [data-setting] textarea': 'updateSetting',\n\t\t'click .delete-attachment': 'deleteAttachment',\n\t\t'click .trash-attachment': 'trashAttachment',\n\t\t'click .untrash-attachment': 'untrashAttachment',\n\t\t'click .edit-attachment': 'editAttachment',\n\t\t'keydown': 'toggleSelectionHandler'\n\t},\n\n\tinitialize: function() {\n\t\tthis.options = _.defaults( this.options, {\n\t\t\trerenderOnModelChange: false\n\t\t});\n\n\t\tthis.on( 'ready', this.initialFocus );\n\t\t// Call 'initialize' directly on the parent class.\n\t\tAttachment.prototype.initialize.apply( this, arguments );\n\t},\n\n\tinitialFocus: function() {\n\t\tif ( ! wp.media.isTouchDevice ) {\n\t\t\t/*\n\t\t\tPreviously focused the first ':input' (the readonly URL text field).\n\t\t\tSince the first ':input' is now a button (delete/trash): when pressing\n\t\t\tspacebar on an attachment, Firefox fires deleteAttachment/trashAttachment\n\t\t\tas soon as focus is moved. Explicitly target the first text field for now.\n\t\t\t@todo change initial focus logic, also for accessibility.\n\t\t\t*/\n\t\t\tthis.$( 'input[type=\"text\"]' ).eq( 0 ).focus();\n\t\t}\n\t},\n\t/**\n\t * @param {Object} event\n\t */\n\tdeleteAttachment: function( event ) {\n\t\tevent.preventDefault();\n\n\t\tif ( window.confirm( l10n.warnDelete ) ) {\n\t\t\tthis.model.destroy();\n\t\t\t// Keep focus inside media modal\n\t\t\t// after image is deleted\n\t\t\tthis.controller.modal.focusManager.focus();\n\t\t}\n\t},\n\t/**\n\t * @param {Object} event\n\t */\n\ttrashAttachment: function( event ) {\n\t\tvar library = this.controller.library;\n\t\tevent.preventDefault();\n\n\t\tif ( wp.media.view.settings.mediaTrash &&\n\t\t\t'edit-metadata' === this.controller.content.mode() ) {\n\n\t\t\tthis.model.set( 'status', 'trash' );\n\t\t\tthis.model.save().done( function() {\n\t\t\t\tlibrary._requery( true );\n\t\t\t} );\n\t\t} else {\n\t\t\tthis.model.destroy();\n\t\t}\n\t},\n\t/**\n\t * @param {Object} event\n\t */\n\tuntrashAttachment: function( event ) {\n\t\tvar library = this.controller.library;\n\t\tevent.preventDefault();\n\n\t\tthis.model.set( 'status', 'inherit' );\n\t\tthis.model.save().done( function() {\n\t\t\tlibrary._requery( true );\n\t\t} );\n\t},\n\t/**\n\t * @param {Object} event\n\t */\n\teditAttachment: function( event ) {\n\t\tvar editState = this.controller.states.get( 'edit-image' );\n\t\tif ( window.imageEdit && editState ) {\n\t\t\tevent.preventDefault();\n\n\t\t\teditState.set( 'image', this.model );\n\t\t\tthis.controller.setState( 'edit-image' );\n\t\t} else {\n\t\t\tthis.$el.addClass('needs-refresh');\n\t\t}\n\t},\n\t/**\n\t * When reverse tabbing(shift+tab) out of the right details panel, deliver\n\t * the focus to the item in the list that was being edited.\n\t *\n\t * @param {Object} event\n\t */\n\ttoggleSelectionHandler: function( event ) {\n\t\tif ( 'keydown' === event.type && 9 === event.keyCode && event.shiftKey && event.target === this.$( ':tabbable' ).get( 0 ) ) {\n\t\t\tthis.controller.trigger( 'attachment:details:shift-tab', event );\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( 37 === event.keyCode || 38 === event.keyCode || 39 === event.keyCode || 40 === event.keyCode ) {\n\t\t\tthis.controller.trigger( 'attachment:keydown:arrow', event );\n\t\t\treturn;\n\t\t}\n\t}\n});\n\nmodule.exports = Details;\n\n\n//# sourceURL=webpack:///./src/js/media/views/attachment/details.js?"); - -/***/ }), - -/***/ "./src/js/media/views/attachment/edit-library.js": -/*!*******************************************************!*\ - !*** ./src/js/media/views/attachment/edit-library.js ***! - \*******************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("/**\n * wp.media.view.Attachment.EditLibrary\n *\n * @memberOf wp.media.view.Attachment\n *\n * @class\n * @augments wp.media.view.Attachment\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n */\nvar EditLibrary = wp.media.view.Attachment.extend(/** @lends wp.media.view.Attachment.EditLibrary.prototype */{\n\tbuttons: {\n\t\tclose: true\n\t}\n});\n\nmodule.exports = EditLibrary;\n\n\n//# sourceURL=webpack:///./src/js/media/views/attachment/edit-library.js?"); - -/***/ }), - -/***/ "./src/js/media/views/attachment/edit-selection.js": -/*!*********************************************************!*\ - !*** ./src/js/media/views/attachment/edit-selection.js ***! - \*********************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("/**\n * wp.media.view.Attachment.EditSelection\n *\n * @memberOf wp.media.view.Attachment\n *\n * @class\n * @augments wp.media.view.Attachment.Selection\n * @augments wp.media.view.Attachment\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n */\nvar EditSelection = wp.media.view.Attachment.Selection.extend(/** @lends wp.media.view.Attachment.EditSelection.prototype */{\n\tbuttons: {\n\t\tclose: true\n\t}\n});\n\nmodule.exports = EditSelection;\n\n\n//# sourceURL=webpack:///./src/js/media/views/attachment/edit-selection.js?"); - -/***/ }), - -/***/ "./src/js/media/views/attachment/library.js": -/*!**************************************************!*\ - !*** ./src/js/media/views/attachment/library.js ***! - \**************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("/**\n * wp.media.view.Attachment.Library\n *\n * @memberOf wp.media.view.Attachment\n *\n * @class\n * @augments wp.media.view.Attachment\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n */\nvar Library = wp.media.view.Attachment.extend(/** @lends wp.media.view.Attachment.Library.prototype */{\n\tbuttons: {\n\t\tcheck: true\n\t}\n});\n\nmodule.exports = Library;\n\n\n//# sourceURL=webpack:///./src/js/media/views/attachment/library.js?"); - -/***/ }), - -/***/ "./src/js/media/views/attachment/selection.js": -/*!****************************************************!*\ - !*** ./src/js/media/views/attachment/selection.js ***! - \****************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("/**\n * wp.media.view.Attachment.Selection\n *\n * @memberOf wp.media.view.Attachment\n *\n * @class\n * @augments wp.media.view.Attachment\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n */\nvar Selection = wp.media.view.Attachment.extend(/** @lends wp.media.view.Attachment.Selection.prototype */{\n\tclassName: 'attachment selection',\n\n\t// On click, just select the model, instead of removing the model from\n\t// the selection.\n\ttoggleSelection: function() {\n\t\tthis.options.selection.single( this.model );\n\t}\n});\n\nmodule.exports = Selection;\n\n\n//# sourceURL=webpack:///./src/js/media/views/attachment/selection.js?"); - -/***/ }), - -/***/ "./src/js/media/views/attachments.js": -/*!*******************************************!*\ - !*** ./src/js/media/views/attachments.js ***! - \*******************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("var View = wp.media.View,\n\t$ = jQuery,\n\tAttachments;\n\nAttachments = View.extend(/** @lends wp.media.view.Attachments.prototype */{\n\ttagName: 'ul',\n\tclassName: 'attachments',\n\n\tattributes: {\n\t\ttabIndex: -1\n\t},\n\n\t/**\n\t * Represents the overview of attachments in the Media Library.\n\t *\n\t * The constructor binds events to the collection this view represents when\n\t * adding or removing attachments or resetting the entire collection.\n\t *\n\t * @since 3.5.0\n\t *\n\t * @constructs\n\t * @memberof wp.media.view\n\t *\n\t * @augments wp.media.View\n\t *\n\t * @listens collection:add\n\t * @listens collection:remove\n\t * @listens collection:reset\n\t * @listens controller:library:selection:add\n\t * @listens scrollElement:scroll\n\t * @listens this:ready\n\t * @listens controller:open\n\t */\n\tinitialize: function() {\n\t\tthis.el.id = _.uniqueId('__attachments-view-');\n\n\t\t/**\n\t\t * @param refreshSensitivity The time in milliseconds to throttle the scroll\n\t\t * handler.\n\t\t * @param refreshThreshold The amount of pixels that should be scrolled before\n\t\t * loading more attachments from the server.\n\t\t * @param AttachmentView The view class to be used for models in the\n\t\t * collection.\n\t\t * @param sortable A jQuery sortable options object\n\t\t * ( http://api.jqueryui.com/sortable/ ).\n\t\t * @param resize A boolean indicating whether or not to listen to\n\t\t * resize events.\n\t\t * @param idealColumnWidth The width in pixels which a column should have when\n\t\t * calculating the total number of columns.\n\t\t */\n\t\t_.defaults( this.options, {\n\t\t\trefreshSensitivity: wp.media.isTouchDevice ? 300 : 200,\n\t\t\trefreshThreshold: 3,\n\t\t\tAttachmentView: wp.media.view.Attachment,\n\t\t\tsortable: false,\n\t\t\tresize: true,\n\t\t\tidealColumnWidth: $( window ).width() < 640 ? 135 : 150\n\t\t});\n\n\t\tthis._viewsByCid = {};\n\t\tthis.$window = $( window );\n\t\tthis.resizeEvent = 'resize.media-modal-columns';\n\n\t\tthis.collection.on( 'add', function( attachment ) {\n\t\t\tthis.views.add( this.createAttachmentView( attachment ), {\n\t\t\t\tat: this.collection.indexOf( attachment )\n\t\t\t});\n\t\t}, this );\n\n\t\t/*\n\t\t * Find the view to be removed, delete it and call the remove function to clear\n\t\t * any set event handlers.\n\t\t */\n\t\tthis.collection.on( 'remove', function( attachment ) {\n\t\t\tvar view = this._viewsByCid[ attachment.cid ];\n\t\t\tdelete this._viewsByCid[ attachment.cid ];\n\n\t\t\tif ( view ) {\n\t\t\t\tview.remove();\n\t\t\t}\n\t\t}, this );\n\n\t\tthis.collection.on( 'reset', this.render, this );\n\n\t\tthis.listenTo( this.controller, 'library:selection:add', this.attachmentFocus );\n\n\t\t// Throttle the scroll handler and bind this.\n\t\tthis.scroll = _.chain( this.scroll ).bind( this ).throttle( this.options.refreshSensitivity ).value();\n\n\t\tthis.options.scrollElement = this.options.scrollElement || this.el;\n\t\t$( this.options.scrollElement ).on( 'scroll', this.scroll );\n\n\t\tthis.initSortable();\n\n\t\t_.bindAll( this, 'setColumns' );\n\n\t\tif ( this.options.resize ) {\n\t\t\tthis.on( 'ready', this.bindEvents );\n\t\t\tthis.controller.on( 'open', this.setColumns );\n\n\t\t\t/*\n\t\t\t * Call this.setColumns() after this view has been rendered in the\n\t\t\t * DOM so attachments get proper width applied.\n\t\t\t */\n\t\t\t_.defer( this.setColumns, this );\n\t\t}\n\t},\n\n\t/**\n\t * Listens to the resizeEvent on the window.\n\t *\n\t * Adjusts the amount of columns accordingly. First removes any existing event\n\t * handlers to prevent duplicate listeners.\n\t *\n\t * @since 4.0.0\n\t *\n\t * @listens window:resize\n\t *\n\t * @returns {void}\n\t */\n\tbindEvents: function() {\n\t\tthis.$window.off( this.resizeEvent ).on( this.resizeEvent, _.debounce( this.setColumns, 50 ) );\n\t},\n\n\t/**\n\t * Focuses the first item in the collection.\n\t *\n\t * @since 4.0.0\n\t *\n\t * @returns {void}\n\t */\n\tattachmentFocus: function() {\n\t\tthis.$( 'li:first' ).focus();\n\t},\n\n\t/**\n\t * Restores focus to the selected item in the collection.\n\t *\n\t * @since 4.0.0\n\t *\n\t * @returns {void}\n\t */\n\trestoreFocus: function() {\n\t\tthis.$( 'li.selected:first' ).focus();\n\t},\n\n\t/**\n\t * Handles events for arrow key presses.\n\t *\n\t * Focuses the attachment in the direction of the used arrow key if it exists.\n\t *\n\t * @since 4.0.0\n\t *\n\t * @param {KeyboardEvent} event The keyboard event that triggered this function.\n\t *\n\t * @returns {void}\n\t */\n\tarrowEvent: function( event ) {\n\t\tvar attachments = this.$el.children( 'li' ),\n\t\t\tperRow = this.columns,\n\t\t\tindex = attachments.filter( ':focus' ).index(),\n\t\t\trow = ( index + 1 ) <= perRow ? 1 : Math.ceil( ( index + 1 ) / perRow );\n\n\t\tif ( index === -1 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Left arrow = 37.\n\t\tif ( 37 === event.keyCode ) {\n\t\t\tif ( 0 === index ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tattachments.eq( index - 1 ).focus();\n\t\t}\n\n\t\t// Up arrow = 38.\n\t\tif ( 38 === event.keyCode ) {\n\t\t\tif ( 1 === row ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tattachments.eq( index - perRow ).focus();\n\t\t}\n\n\t\t// Right arrow = 39.\n\t\tif ( 39 === event.keyCode ) {\n\t\t\tif ( attachments.length === index ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tattachments.eq( index + 1 ).focus();\n\t\t}\n\n\t\t// Down arrow = 40.\n\t\tif ( 40 === event.keyCode ) {\n\t\t\tif ( Math.ceil( attachments.length / perRow ) === row ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tattachments.eq( index + perRow ).focus();\n\t\t}\n\t},\n\n\t/**\n\t * Clears any set event handlers.\n\t *\n\t * @since 3.5.0\n\t *\n\t * @returns {void}\n\t */\n\tdispose: function() {\n\t\tthis.collection.props.off( null, null, this );\n\t\tif ( this.options.resize ) {\n\t\t\tthis.$window.off( this.resizeEvent );\n\t\t}\n\n\t\t// Call 'dispose' directly on the parent class.\n\t\tView.prototype.dispose.apply( this, arguments );\n\t},\n\n\t/**\n\t * Calculates the amount of columns.\n\t *\n\t * Calculates the amount of columns and sets it on the data-columns attribute\n\t * of .media-frame-content.\n\t *\n\t * @since 4.0.0\n\t *\n\t * @returns {void}\n\t */\n\tsetColumns: function() {\n\t\tvar prev = this.columns,\n\t\t\twidth = this.$el.width();\n\n\t\tif ( width ) {\n\t\t\tthis.columns = Math.min( Math.round( width / this.options.idealColumnWidth ), 12 ) || 1;\n\n\t\t\tif ( ! prev || prev !== this.columns ) {\n\t\t\t\tthis.$el.closest( '.media-frame-content' ).attr( 'data-columns', this.columns );\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Initializes jQuery sortable on the attachment list.\n\t *\n\t * Fails gracefully if jQuery sortable doesn't exist or isn't passed in the\n\t * options.\n\t *\n\t * @since 3.5.0\n\t *\n\t * @fires collection:reset\n\t *\n\t * @returns {void}\n\t */\n\tinitSortable: function() {\n\t\tvar collection = this.collection;\n\n\t\tif ( ! this.options.sortable || ! $.fn.sortable ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.$el.sortable( _.extend({\n\t\t\t// If the `collection` has a `comparator`, disable sorting.\n\t\t\tdisabled: !! collection.comparator,\n\n\t\t\t/*\n\t\t\t * Change the position of the attachment as soon as the mouse pointer overlaps a\n\t\t\t * thumbnail.\n\t\t\t */\n\t\t\ttolerance: 'pointer',\n\n\t\t\t// Record the initial `index` of the dragged model.\n\t\t\tstart: function( event, ui ) {\n\t\t\t\tui.item.data('sortableIndexStart', ui.item.index());\n\t\t\t},\n\n\t\t\t/*\n\t\t\t * Update the model's index in the collection. Do so silently, as the view\n\t\t\t * is already accurate.\n\t\t\t */\n\t\t\tupdate: function( event, ui ) {\n\t\t\t\tvar model = collection.at( ui.item.data('sortableIndexStart') ),\n\t\t\t\t\tcomparator = collection.comparator;\n\n\t\t\t\t// Temporarily disable the comparator to prevent `add`\n\t\t\t\t// from re-sorting.\n\t\t\t\tdelete collection.comparator;\n\n\t\t\t\t// Silently shift the model to its new index.\n\t\t\t\tcollection.remove( model, {\n\t\t\t\t\tsilent: true\n\t\t\t\t});\n\t\t\t\tcollection.add( model, {\n\t\t\t\t\tsilent: true,\n\t\t\t\t\tat: ui.item.index()\n\t\t\t\t});\n\n\t\t\t\t// Restore the comparator.\n\t\t\t\tcollection.comparator = comparator;\n\n\t\t\t\t// Fire the `reset` event to ensure other collections sync.\n\t\t\t\tcollection.trigger( 'reset', collection );\n\n\t\t\t\t// If the collection is sorted by menu order, update the menu order.\n\t\t\t\tcollection.saveMenuOrder();\n\t\t\t}\n\t\t}, this.options.sortable ) );\n\n\t\t/*\n\t\t * If the `orderby` property is changed on the `collection`, check to see if we\n\t\t * have a `comparator`. If so, disable sorting.\n\t\t */\n\t\tcollection.props.on( 'change:orderby', function() {\n\t\t\tthis.$el.sortable( 'option', 'disabled', !! collection.comparator );\n\t\t}, this );\n\n\t\tthis.collection.props.on( 'change:orderby', this.refreshSortable, this );\n\t\tthis.refreshSortable();\n\t},\n\n\t/**\n\t * Disables jQuery sortable if collection has a comparator or collection.orderby\n\t * equals menuOrder.\n\t *\n\t * @since 3.5.0\n\t *\n\t * @returns {void}\n\t */\n\trefreshSortable: function() {\n\t\tif ( ! this.options.sortable || ! $.fn.sortable ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar collection = this.collection,\n\t\t\torderby = collection.props.get('orderby'),\n\t\t\tenabled = 'menuOrder' === orderby || ! collection.comparator;\n\n\t\tthis.$el.sortable( 'option', 'disabled', ! enabled );\n\t},\n\n\t/**\n\t * Creates a new view for an attachment and adds it to _viewsByCid.\n\t *\n\t * @since 3.5.0\n\t *\n\t * @param {wp.media.model.Attachment} attachment\n\t *\n\t * @returns {wp.media.View} The created view.\n\t */\n\tcreateAttachmentView: function( attachment ) {\n\t\tvar view = new this.options.AttachmentView({\n\t\t\tcontroller: this.controller,\n\t\t\tmodel: attachment,\n\t\t\tcollection: this.collection,\n\t\t\tselection: this.options.selection\n\t\t});\n\n\t\treturn this._viewsByCid[ attachment.cid ] = view;\n\t},\n\n\t/**\n\t * Prepares view for display.\n\t *\n\t * Creates views for every attachment in collection if the collection is not\n\t * empty, otherwise clears all views and loads more attachments.\n\t *\n\t * @since 3.5.0\n\t *\n\t * @returns {void}\n\t */\n\tprepare: function() {\n\t\tif ( this.collection.length ) {\n\t\t\tthis.views.set( this.collection.map( this.createAttachmentView, this ) );\n\t\t} else {\n\t\t\tthis.views.unset();\n\t\t\tthis.collection.more().done( this.scroll );\n\t\t}\n\t},\n\n\t/**\n\t * Triggers the scroll function to check if we should query for additional\n\t * attachments right away.\n\t *\n\t * @since 3.5.0\n\t *\n\t * @returns {void}\n\t */\n\tready: function() {\n\t\tthis.scroll();\n\t},\n\n\t/**\n\t * Handles scroll events.\n\t *\n\t * Shows the spinner if we're close to the bottom. Loads more attachments from\n\t * server if we're {refreshThreshold} times away from the bottom.\n\t *\n\t * @since 3.5.0\n\t *\n\t * @returns {void}\n\t */\n\tscroll: function() {\n\t\tvar view = this,\n\t\t\tel = this.options.scrollElement,\n\t\t\tscrollTop = el.scrollTop,\n\t\t\ttoolbar;\n\n\t\t/*\n\t\t * The scroll event occurs on the document, but the element that should be\n\t\t * checked is the document body.\n\t\t */\n\t\tif ( el === document ) {\n\t\t\tel = document.body;\n\t\t\tscrollTop = $(document).scrollTop();\n\t\t}\n\n\t\tif ( ! $(el).is(':visible') || ! this.collection.hasMore() ) {\n\t\t\treturn;\n\t\t}\n\n\t\ttoolbar = this.views.parent.toolbar;\n\n\t\t// Show the spinner only if we are close to the bottom.\n\t\tif ( el.scrollHeight - ( scrollTop + el.clientHeight ) < el.clientHeight / 3 ) {\n\t\t\ttoolbar.get('spinner').show();\n\t\t}\n\n\t\tif ( el.scrollHeight < scrollTop + ( el.clientHeight * this.options.refreshThreshold ) ) {\n\t\t\tthis.collection.more().done(function() {\n\t\t\t\tview.scroll();\n\t\t\t\ttoolbar.get('spinner').hide();\n\t\t\t});\n\t\t}\n\t}\n});\n\nmodule.exports = Attachments;\n\n\n//# sourceURL=webpack:///./src/js/media/views/attachments.js?"); - -/***/ }), - -/***/ "./src/js/media/views/attachments/browser.js": -/*!***************************************************!*\ - !*** ./src/js/media/views/attachments/browser.js ***! - \***************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("var View = wp.media.View,\n\tmediaTrash = wp.media.view.settings.mediaTrash,\n\tl10n = wp.media.view.l10n,\n\t$ = jQuery,\n\tAttachmentsBrowser;\n\n/**\n * wp.media.view.AttachmentsBrowser\n *\n * @memberOf wp.media.view\n *\n * @class\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n *\n * @param {object} [options] The options hash passed to the view.\n * @param {boolean|string} [options.filters=false] Which filters to show in the browser's toolbar.\n * Accepts 'uploaded' and 'all'.\n * @param {boolean} [options.search=true] Whether to show the search interface in the\n * browser's toolbar.\n * @param {boolean} [options.date=true] Whether to show the date filter in the\n * browser's toolbar.\n * @param {boolean} [options.display=false] Whether to show the attachments display settings\n * view in the sidebar.\n * @param {boolean|string} [options.sidebar=true] Whether to create a sidebar for the browser.\n * Accepts true, false, and 'errors'.\n */\nAttachmentsBrowser = View.extend(/** @lends wp.media.view.AttachmentsBrowser.prototype */{\n\ttagName: 'div',\n\tclassName: 'attachments-browser',\n\n\tinitialize: function() {\n\t\t_.defaults( this.options, {\n\t\t\tfilters: false,\n\t\t\tsearch: true,\n\t\t\tdate: true,\n\t\t\tdisplay: false,\n\t\t\tsidebar: true,\n\t\t\tAttachmentView: wp.media.view.Attachment.Library\n\t\t});\n\n\t\tthis.controller.on( 'toggle:upload:attachment', this.toggleUploader, this );\n\t\tthis.controller.on( 'edit:selection', this.editSelection );\n\n\t\t// In the Media Library, the sidebar is used to display errors before the attachments grid.\n\t\tif ( this.options.sidebar && 'errors' === this.options.sidebar ) {\n\t\t\tthis.createSidebar();\n\t\t}\n\n\t\t/*\n\t\t * For accessibility reasons, place the Inline Uploader before other sections.\n\t\t * This way, in the Media Library, it's right after the Add New button, see ticket #37188.\n\t\t */\n\t\tthis.createUploader();\n\n\t\t/*\n\t\t * Create a multi-purpose toolbar. Used as main toolbar in the Media Library\n\t\t * and also for other things, for example the \"Drag and drop to reorder\" and\n\t\t * \"Suggested dimensions\" info in the media modal.\n\t\t */\n\t\tthis.createToolbar();\n\n\t\t// Create the list of attachments.\n\t\tthis.createAttachments();\n\n\t\t// For accessibility reasons, place the normal sidebar after the attachments, see ticket #36909.\n\t\tif ( this.options.sidebar && 'errors' !== this.options.sidebar ) {\n\t\t\tthis.createSidebar();\n\t\t}\n\n\t\tthis.updateContent();\n\n\t\tif ( ! this.options.sidebar || 'errors' === this.options.sidebar ) {\n\t\t\tthis.$el.addClass( 'hide-sidebar' );\n\n\t\t\tif ( 'errors' === this.options.sidebar ) {\n\t\t\t\tthis.$el.addClass( 'sidebar-for-errors' );\n\t\t\t}\n\t\t}\n\n\t\tthis.collection.on( 'add remove reset', this.updateContent, this );\n\t},\n\n\teditSelection: function( modal ) {\n\t\tmodal.$( '.media-button-backToLibrary' ).focus();\n\t},\n\n\t/**\n\t * @returns {wp.media.view.AttachmentsBrowser} Returns itself to allow chaining\n\t */\n\tdispose: function() {\n\t\tthis.options.selection.off( null, null, this );\n\t\tView.prototype.dispose.apply( this, arguments );\n\t\treturn this;\n\t},\n\n\tcreateToolbar: function() {\n\t\tvar LibraryViewSwitcher, Filters, toolbarOptions;\n\n\t\ttoolbarOptions = {\n\t\t\tcontroller: this.controller\n\t\t};\n\n\t\tif ( this.controller.isModeActive( 'grid' ) ) {\n\t\t\ttoolbarOptions.className = 'media-toolbar wp-filter';\n\t\t}\n\n\t\t/**\n\t\t* @member {wp.media.view.Toolbar}\n\t\t*/\n\t\tthis.toolbar = new wp.media.view.Toolbar( toolbarOptions );\n\n\t\tthis.views.add( this.toolbar );\n\n\t\tthis.toolbar.set( 'spinner', new wp.media.view.Spinner({\n\t\t\tpriority: -60\n\t\t}) );\n\n\t\tif ( -1 !== $.inArray( this.options.filters, [ 'uploaded', 'all' ] ) ) {\n\t\t\t// \"Filters\" will return a , screen reader text needs to be rendered before\n\t\t\tthis.toolbar.set( 'dateFilterLabel', new wp.media.view.Label({\n\t\t\t\tvalue: l10n.filterByDate,\n\t\t\t\tattributes: {\n\t\t\t\t\t'for': 'media-attachment-date-filters'\n\t\t\t\t},\n\t\t\t\tpriority: -75\n\t\t\t}).render() );\n\t\t\tthis.toolbar.set( 'dateFilter', new wp.media.view.DateFilter({\n\t\t\t\tcontroller: this.controller,\n\t\t\t\tmodel: this.collection.props,\n\t\t\t\tpriority: -75\n\t\t\t}).render() );\n\n\t\t\t// BulkSelection is a
with subviews, including screen reader text\n\t\t\tthis.toolbar.set( 'selectModeToggleButton', new wp.media.view.SelectModeToggleButton({\n\t\t\t\ttext: l10n.bulkSelect,\n\t\t\t\tcontroller: this.controller,\n\t\t\t\tpriority: -70\n\t\t\t}).render() );\n\n\t\t\tthis.toolbar.set( 'deleteSelectedButton', new wp.media.view.DeleteSelectedButton({\n\t\t\t\tfilters: Filters,\n\t\t\t\tstyle: 'primary',\n\t\t\t\tdisabled: true,\n\t\t\t\ttext: mediaTrash ? l10n.trashSelected : l10n.deleteSelected,\n\t\t\t\tcontroller: this.controller,\n\t\t\t\tpriority: -60,\n\t\t\t\tclick: function() {\n\t\t\t\t\tvar changed = [], removed = [],\n\t\t\t\t\t\tselection = this.controller.state().get( 'selection' ),\n\t\t\t\t\t\tlibrary = this.controller.state().get( 'library' );\n\n\t\t\t\t\tif ( ! selection.length ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( ! mediaTrash && ! window.confirm( l10n.warnBulkDelete ) ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( mediaTrash &&\n\t\t\t\t\t\t'trash' !== selection.at( 0 ).get( 'status' ) &&\n\t\t\t\t\t\t! window.confirm( l10n.warnBulkTrash ) ) {\n\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tselection.each( function( model ) {\n\t\t\t\t\t\tif ( ! model.get( 'nonces' )['delete'] ) {\n\t\t\t\t\t\t\tremoved.push( model );\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif ( mediaTrash && 'trash' === model.get( 'status' ) ) {\n\t\t\t\t\t\t\tmodel.set( 'status', 'inherit' );\n\t\t\t\t\t\t\tchanged.push( model.save() );\n\t\t\t\t\t\t\tremoved.push( model );\n\t\t\t\t\t\t} else if ( mediaTrash ) {\n\t\t\t\t\t\t\tmodel.set( 'status', 'trash' );\n\t\t\t\t\t\t\tchanged.push( model.save() );\n\t\t\t\t\t\t\tremoved.push( model );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tmodel.destroy({wait: true});\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\n\t\t\t\t\tif ( changed.length ) {\n\t\t\t\t\t\tselection.remove( removed );\n\n\t\t\t\t\t\t$.when.apply( null, changed ).then( _.bind( function() {\n\t\t\t\t\t\t\tlibrary._requery( true );\n\t\t\t\t\t\t\tthis.controller.trigger( 'selection:action:done' );\n\t\t\t\t\t\t}, this ) );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.controller.trigger( 'selection:action:done' );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}).render() );\n\n\t\t\tif ( mediaTrash ) {\n\t\t\t\tthis.toolbar.set( 'deleteSelectedPermanentlyButton', new wp.media.view.DeleteSelectedPermanentlyButton({\n\t\t\t\t\tfilters: Filters,\n\t\t\t\t\tstyle: 'primary',\n\t\t\t\t\tdisabled: true,\n\t\t\t\t\ttext: l10n.deleteSelected,\n\t\t\t\t\tcontroller: this.controller,\n\t\t\t\t\tpriority: -55,\n\t\t\t\t\tclick: function() {\n\t\t\t\t\t\tvar removed = [],\n\t\t\t\t\t\t\tdestroy = [],\n\t\t\t\t\t\t\tselection = this.controller.state().get( 'selection' );\n\n\t\t\t\t\t\tif ( ! selection.length || ! window.confirm( l10n.warnBulkDelete ) ) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tselection.each( function( model ) {\n\t\t\t\t\t\t\tif ( ! model.get( 'nonces' )['delete'] ) {\n\t\t\t\t\t\t\t\tremoved.push( model );\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tdestroy.push( model );\n\t\t\t\t\t\t} );\n\n\t\t\t\t\t\tif ( removed.length ) {\n\t\t\t\t\t\t\tselection.remove( removed );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif ( destroy.length ) {\n\t\t\t\t\t\t\t$.when.apply( null, destroy.map( function (item) {\n\t\t\t\t\t\t\t\treturn item.destroy();\n\t\t\t\t\t\t\t} ) ).then( _.bind( function() {\n\t\t\t\t\t\t\t\tthis.controller.trigger( 'selection:action:done' );\n\t\t\t\t\t\t\t}, this ) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}).render() );\n\t\t\t}\n\n\t\t} else if ( this.options.date ) {\n\t\t\t// DateFilter is a ').val( this.model.get('url') );\n\t\tthis.input = this.$input[0];\n\n\t\tthis.spinner = $('')[0];\n\t\tthis.$el.append([ this.input, this.spinner ]);\n\n\t\tthis.listenTo( this.model, 'change:url', this.render );\n\n\t\tif ( this.model.get( 'url' ) ) {\n\t\t\t_.delay( _.bind( function () {\n\t\t\t\tthis.model.trigger( 'change:url' );\n\t\t\t}, this ), 500 );\n\t\t}\n\t},\n\t/**\n\t * @returns {wp.media.view.EmbedUrl} Returns itself to allow chaining\n\t */\n\trender: function() {\n\t\tvar $input = this.$input;\n\n\t\tif ( $input.is(':focus') ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.input.value = this.model.get('url') || 'http://';\n\t\t/**\n\t\t * Call `render` directly on parent class with passed arguments\n\t\t */\n\t\tView.prototype.render.apply( this, arguments );\n\t\treturn this;\n\t},\n\n\tready: function() {\n\t\tif ( ! wp.media.isTouchDevice ) {\n\t\t\tthis.focus();\n\t\t}\n\t},\n\n\turl: function( event ) {\n\t\tthis.model.set( 'url', $.trim( event.target.value ) );\n\t},\n\n\t/**\n\t * If the input is visible, focus and select its contents.\n\t */\n\tfocus: function() {\n\t\tvar $input = this.$input;\n\t\tif ( $input.is(':visible') ) {\n\t\t\t$input.focus()[0].select();\n\t\t}\n\t}\n});\n\nmodule.exports = EmbedUrl;\n\n\n//# sourceURL=webpack:///./src/js/media/views/embed/url.js?"); - -/***/ }), - -/***/ "./src/js/media/views/focus-manager.js": -/*!*********************************************!*\ - !*** ./src/js/media/views/focus-manager.js ***! - \*********************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("/**\n * wp.media.view.FocusManager\n *\n * @memberOf wp.media.view\n *\n * @class\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n */\nvar FocusManager = wp.media.View.extend(/** @lends wp.media.view.FocusManager.prototype */{\n\n\tevents: {\n\t\t'keydown': 'constrainTabbing'\n\t},\n\n\tfocus: function() { // Reset focus on first left menu item\n\t\tthis.$('.media-menu-item').first().focus();\n\t},\n\t/**\n\t * @param {Object} event\n\t */\n\tconstrainTabbing: function( event ) {\n\t\tvar tabbables;\n\n\t\t// Look for the tab key.\n\t\tif ( 9 !== event.keyCode ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Skip the file input added by Plupload.\n\t\ttabbables = this.$( ':tabbable' ).not( '.moxie-shim input[type=\"file\"]' );\n\n\t\t// Keep tab focus within media modal while it's open\n\t\tif ( tabbables.last()[0] === event.target && ! event.shiftKey ) {\n\t\t\ttabbables.first().focus();\n\t\t\treturn false;\n\t\t} else if ( tabbables.first()[0] === event.target && event.shiftKey ) {\n\t\t\ttabbables.last().focus();\n\t\t\treturn false;\n\t\t}\n\t}\n\n});\n\nmodule.exports = FocusManager;\n\n\n//# sourceURL=webpack:///./src/js/media/views/focus-manager.js?"); - -/***/ }), - -/***/ "./src/js/media/views/frame.js": -/*!*************************************!*\ - !*** ./src/js/media/views/frame.js ***! - \*************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("/**\n * wp.media.view.Frame\n *\n * A frame is a composite view consisting of one or more regions and one or more\n * states.\n *\n * @memberOf wp.media.view\n *\n * @see wp.media.controller.State\n * @see wp.media.controller.Region\n *\n * @class\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n * @mixes wp.media.controller.StateMachine\n */\nvar Frame = wp.media.View.extend(/** @lends wp.media.view.Frame.prototype */{\n\tinitialize: function() {\n\t\t_.defaults( this.options, {\n\t\t\tmode: [ 'select' ]\n\t\t});\n\t\tthis._createRegions();\n\t\tthis._createStates();\n\t\tthis._createModes();\n\t},\n\n\t_createRegions: function() {\n\t\t// Clone the regions array.\n\t\tthis.regions = this.regions ? this.regions.slice() : [];\n\n\t\t// Initialize regions.\n\t\t_.each( this.regions, function( region ) {\n\t\t\tthis[ region ] = new wp.media.controller.Region({\n\t\t\t\tview: this,\n\t\t\t\tid: region,\n\t\t\t\tselector: '.media-frame-' + region\n\t\t\t});\n\t\t}, this );\n\t},\n\t/**\n\t * Create the frame's states.\n\t *\n\t * @see wp.media.controller.State\n\t * @see wp.media.controller.StateMachine\n\t *\n\t * @fires wp.media.controller.State#ready\n\t */\n\t_createStates: function() {\n\t\t// Create the default `states` collection.\n\t\tthis.states = new Backbone.Collection( null, {\n\t\t\tmodel: wp.media.controller.State\n\t\t});\n\n\t\t// Ensure states have a reference to the frame.\n\t\tthis.states.on( 'add', function( model ) {\n\t\t\tmodel.frame = this;\n\t\t\tmodel.trigger('ready');\n\t\t}, this );\n\n\t\tif ( this.options.states ) {\n\t\t\tthis.states.add( this.options.states );\n\t\t}\n\t},\n\n\t/**\n\t * A frame can be in a mode or multiple modes at one time.\n\t *\n\t * For example, the manage media frame can be in the `Bulk Select` or `Edit` mode.\n\t */\n\t_createModes: function() {\n\t\t// Store active \"modes\" that the frame is in. Unrelated to region modes.\n\t\tthis.activeModes = new Backbone.Collection();\n\t\tthis.activeModes.on( 'add remove reset', _.bind( this.triggerModeEvents, this ) );\n\n\t\t_.each( this.options.mode, function( mode ) {\n\t\t\tthis.activateMode( mode );\n\t\t}, this );\n\t},\n\t/**\n\t * Reset all states on the frame to their defaults.\n\t *\n\t * @returns {wp.media.view.Frame} Returns itself to allow chaining\n\t */\n\treset: function() {\n\t\tthis.states.invoke( 'trigger', 'reset' );\n\t\treturn this;\n\t},\n\t/**\n\t * Map activeMode collection events to the frame.\n\t */\n\ttriggerModeEvents: function( model, collection, options ) {\n\t\tvar collectionEvent,\n\t\t\tmodeEventMap = {\n\t\t\t\tadd: 'activate',\n\t\t\t\tremove: 'deactivate'\n\t\t\t},\n\t\t\teventToTrigger;\n\t\t// Probably a better way to do this.\n\t\t_.each( options, function( value, key ) {\n\t\t\tif ( value ) {\n\t\t\t\tcollectionEvent = key;\n\t\t\t}\n\t\t} );\n\n\t\tif ( ! _.has( modeEventMap, collectionEvent ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\teventToTrigger = model.get('id') + ':' + modeEventMap[collectionEvent];\n\t\tthis.trigger( eventToTrigger );\n\t},\n\t/**\n\t * Activate a mode on the frame.\n\t *\n\t * @param string mode Mode ID.\n\t * @returns {this} Returns itself to allow chaining.\n\t */\n\tactivateMode: function( mode ) {\n\t\t// Bail if the mode is already active.\n\t\tif ( this.isModeActive( mode ) ) {\n\t\t\treturn;\n\t\t}\n\t\tthis.activeModes.add( [ { id: mode } ] );\n\t\t// Add a CSS class to the frame so elements can be styled for the mode.\n\t\tthis.$el.addClass( 'mode-' + mode );\n\n\t\treturn this;\n\t},\n\t/**\n\t * Deactivate a mode on the frame.\n\t *\n\t * @param string mode Mode ID.\n\t * @returns {this} Returns itself to allow chaining.\n\t */\n\tdeactivateMode: function( mode ) {\n\t\t// Bail if the mode isn't active.\n\t\tif ( ! this.isModeActive( mode ) ) {\n\t\t\treturn this;\n\t\t}\n\t\tthis.activeModes.remove( this.activeModes.where( { id: mode } ) );\n\t\tthis.$el.removeClass( 'mode-' + mode );\n\t\t/**\n\t\t * Frame mode deactivation event.\n\t\t *\n\t\t * @event wp.media.view.Frame#{mode}:deactivate\n\t\t */\n\t\tthis.trigger( mode + ':deactivate' );\n\n\t\treturn this;\n\t},\n\t/**\n\t * Check if a mode is enabled on the frame.\n\t *\n\t * @param string mode Mode ID.\n\t * @return bool\n\t */\n\tisModeActive: function( mode ) {\n\t\treturn Boolean( this.activeModes.where( { id: mode } ).length );\n\t}\n});\n\n// Make the `Frame` a `StateMachine`.\n_.extend( Frame.prototype, wp.media.controller.StateMachine.prototype );\n\nmodule.exports = Frame;\n\n\n//# sourceURL=webpack:///./src/js/media/views/frame.js?"); - -/***/ }), - -/***/ "./src/js/media/views/frame/image-details.js": -/*!***************************************************!*\ - !*** ./src/js/media/views/frame/image-details.js ***! - \***************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("var Select = wp.media.view.MediaFrame.Select,\n\tl10n = wp.media.view.l10n,\n\tImageDetails;\n\n/**\n * wp.media.view.MediaFrame.ImageDetails\n *\n * A media frame for manipulating an image that's already been inserted\n * into a post.\n *\n * @memberOf wp.media.view.MediaFrame\n *\n * @class\n * @augments wp.media.view.MediaFrame.Select\n * @augments wp.media.view.MediaFrame\n * @augments wp.media.view.Frame\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n * @mixes wp.media.controller.StateMachine\n */\nImageDetails = Select.extend(/** @lends wp.media.view.MediaFrame.ImageDetails.prototype */{\n\tdefaults: {\n\t\tid: 'image',\n\t\turl: '',\n\t\tmenu: 'image-details',\n\t\tcontent: 'image-details',\n\t\ttoolbar: 'image-details',\n\t\ttype: 'link',\n\t\ttitle: l10n.imageDetailsTitle,\n\t\tpriority: 120\n\t},\n\n\tinitialize: function( options ) {\n\t\tthis.image = new wp.media.model.PostImage( options.metadata );\n\t\tthis.options.selection = new wp.media.model.Selection( this.image.attachment, { multiple: false } );\n\t\tSelect.prototype.initialize.apply( this, arguments );\n\t},\n\n\tbindHandlers: function() {\n\t\tSelect.prototype.bindHandlers.apply( this, arguments );\n\t\tthis.on( 'menu:create:image-details', this.createMenu, this );\n\t\tthis.on( 'content:create:image-details', this.imageDetailsContent, this );\n\t\tthis.on( 'content:render:edit-image', this.editImageContent, this );\n\t\tthis.on( 'toolbar:render:image-details', this.renderImageDetailsToolbar, this );\n\t\t// override the select toolbar\n\t\tthis.on( 'toolbar:render:replace', this.renderReplaceImageToolbar, this );\n\t},\n\n\tcreateStates: function() {\n\t\tthis.states.add([\n\t\t\tnew wp.media.controller.ImageDetails({\n\t\t\t\timage: this.image,\n\t\t\t\teditable: false\n\t\t\t}),\n\t\t\tnew wp.media.controller.ReplaceImage({\n\t\t\t\tid: 'replace-image',\n\t\t\t\tlibrary: wp.media.query( { type: 'image' } ),\n\t\t\t\timage: this.image,\n\t\t\t\tmultiple: false,\n\t\t\t\ttitle: l10n.imageReplaceTitle,\n\t\t\t\ttoolbar: 'replace',\n\t\t\t\tpriority: 80,\n\t\t\t\tdisplaySettings: true\n\t\t\t}),\n\t\t\tnew wp.media.controller.EditImage( {\n\t\t\t\timage: this.image,\n\t\t\t\tselection: this.options.selection\n\t\t\t} )\n\t\t]);\n\t},\n\n\timageDetailsContent: function( options ) {\n\t\toptions.view = new wp.media.view.ImageDetails({\n\t\t\tcontroller: this,\n\t\t\tmodel: this.state().image,\n\t\t\tattachment: this.state().image.attachment\n\t\t});\n\t},\n\n\teditImageContent: function() {\n\t\tvar state = this.state(),\n\t\t\tmodel = state.get('image'),\n\t\t\tview;\n\n\t\tif ( ! model ) {\n\t\t\treturn;\n\t\t}\n\n\t\tview = new wp.media.view.EditImage( { model: model, controller: this } ).render();\n\n\t\tthis.content.set( view );\n\n\t\t// after bringing in the frame, load the actual editor via an ajax call\n\t\tview.loadEditor();\n\n\t},\n\n\trenderImageDetailsToolbar: function() {\n\t\tthis.toolbar.set( new wp.media.view.Toolbar({\n\t\t\tcontroller: this,\n\t\t\titems: {\n\t\t\t\tselect: {\n\t\t\t\t\tstyle: 'primary',\n\t\t\t\t\ttext: l10n.update,\n\t\t\t\t\tpriority: 80,\n\n\t\t\t\t\tclick: function() {\n\t\t\t\t\t\tvar controller = this.controller,\n\t\t\t\t\t\t\tstate = controller.state();\n\n\t\t\t\t\t\tcontroller.close();\n\n\t\t\t\t\t\t// not sure if we want to use wp.media.string.image which will create a shortcode or\n\t\t\t\t\t\t// perhaps wp.html.string to at least to build the \n\t\t\t\t\t\tstate.trigger( 'update', controller.image.toJSON() );\n\n\t\t\t\t\t\t// Restore and reset the default state.\n\t\t\t\t\t\tcontroller.setState( controller.options.state );\n\t\t\t\t\t\tcontroller.reset();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}) );\n\t},\n\n\trenderReplaceImageToolbar: function() {\n\t\tvar frame = this,\n\t\t\tlastState = frame.lastState(),\n\t\t\tprevious = lastState && lastState.id;\n\n\t\tthis.toolbar.set( new wp.media.view.Toolbar({\n\t\t\tcontroller: this,\n\t\t\titems: {\n\t\t\t\tback: {\n\t\t\t\t\ttext: l10n.back,\n\t\t\t\t\tpriority: 20,\n\t\t\t\t\tclick: function() {\n\t\t\t\t\t\tif ( previous ) {\n\t\t\t\t\t\t\tframe.setState( previous );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tframe.close();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\treplace: {\n\t\t\t\t\tstyle: 'primary',\n\t\t\t\t\ttext: l10n.replace,\n\t\t\t\t\tpriority: 80,\n\t\t\t\t\trequires: { selection: true },\n\n\t\t\t\t\tclick: function() {\n\t\t\t\t\t\tvar controller = this.controller,\n\t\t\t\t\t\t\tstate = controller.state(),\n\t\t\t\t\t\t\tselection = state.get( 'selection' ),\n\t\t\t\t\t\t\tattachment = selection.single();\n\n\t\t\t\t\t\tcontroller.close();\n\n\t\t\t\t\t\tcontroller.image.changeAttachment( attachment, state.display( attachment ) );\n\n\t\t\t\t\t\t// not sure if we want to use wp.media.string.image which will create a shortcode or\n\t\t\t\t\t\t// perhaps wp.html.string to at least to build the \n\t\t\t\t\t\tstate.trigger( 'replace', controller.image.toJSON() );\n\n\t\t\t\t\t\t// Restore and reset the default state.\n\t\t\t\t\t\tcontroller.setState( controller.options.state );\n\t\t\t\t\t\tcontroller.reset();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}) );\n\t}\n\n});\n\nmodule.exports = ImageDetails;\n\n\n//# sourceURL=webpack:///./src/js/media/views/frame/image-details.js?"); - -/***/ }), - -/***/ "./src/js/media/views/frame/post.js": -/*!******************************************!*\ - !*** ./src/js/media/views/frame/post.js ***! - \******************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("var Select = wp.media.view.MediaFrame.Select,\n\tLibrary = wp.media.controller.Library,\n\tl10n = wp.media.view.l10n,\n\tPost;\n\n/**\n * wp.media.view.MediaFrame.Post\n *\n * The frame for manipulating media on the Edit Post page.\n *\n * @memberOf wp.media.view.MediaFrame\n *\n * @class\n * @augments wp.media.view.MediaFrame.Select\n * @augments wp.media.view.MediaFrame\n * @augments wp.media.view.Frame\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n * @mixes wp.media.controller.StateMachine\n */\nPost = Select.extend(/** @lends wp.media.view.MediaFrame.Post.prototype */{\n\tinitialize: function() {\n\t\tthis.counts = {\n\t\t\taudio: {\n\t\t\t\tcount: wp.media.view.settings.attachmentCounts.audio,\n\t\t\t\tstate: 'playlist'\n\t\t\t},\n\t\t\tvideo: {\n\t\t\t\tcount: wp.media.view.settings.attachmentCounts.video,\n\t\t\t\tstate: 'video-playlist'\n\t\t\t}\n\t\t};\n\n\t\t_.defaults( this.options, {\n\t\t\tmultiple: true,\n\t\t\tediting: false,\n\t\t\tstate: 'insert',\n\t\t\tmetadata: {}\n\t\t});\n\n\t\t// Call 'initialize' directly on the parent class.\n\t\tSelect.prototype.initialize.apply( this, arguments );\n\t\tthis.createIframeStates();\n\n\t},\n\n\t/**\n\t * Create the default states.\n\t */\n\tcreateStates: function() {\n\t\tvar options = this.options;\n\n\t\tthis.states.add([\n\t\t\t// Main states.\n\t\t\tnew Library({\n\t\t\t\tid: 'insert',\n\t\t\t\ttitle: l10n.insertMediaTitle,\n\t\t\t\tpriority: 20,\n\t\t\t\ttoolbar: 'main-insert',\n\t\t\t\tfilterable: 'all',\n\t\t\t\tlibrary: wp.media.query( options.library ),\n\t\t\t\tmultiple: options.multiple ? 'reset' : false,\n\t\t\t\teditable: true,\n\n\t\t\t\t// If the user isn't allowed to edit fields,\n\t\t\t\t// can they still edit it locally?\n\t\t\t\tallowLocalEdits: true,\n\n\t\t\t\t// Show the attachment display settings.\n\t\t\t\tdisplaySettings: true,\n\t\t\t\t// Update user settings when users adjust the\n\t\t\t\t// attachment display settings.\n\t\t\t\tdisplayUserSettings: true\n\t\t\t}),\n\n\t\t\tnew Library({\n\t\t\t\tid: 'gallery',\n\t\t\t\ttitle: l10n.createGalleryTitle,\n\t\t\t\tpriority: 40,\n\t\t\t\ttoolbar: 'main-gallery',\n\t\t\t\tfilterable: 'uploaded',\n\t\t\t\tmultiple: 'add',\n\t\t\t\teditable: false,\n\n\t\t\t\tlibrary: wp.media.query( _.defaults({\n\t\t\t\t\ttype: 'image'\n\t\t\t\t}, options.library ) )\n\t\t\t}),\n\n\t\t\t// Embed states.\n\t\t\tnew wp.media.controller.Embed( { metadata: options.metadata } ),\n\n\t\t\tnew wp.media.controller.EditImage( { model: options.editImage } ),\n\n\t\t\t// Gallery states.\n\t\t\tnew wp.media.controller.GalleryEdit({\n\t\t\t\tlibrary: options.selection,\n\t\t\t\tediting: options.editing,\n\t\t\t\tmenu: 'gallery'\n\t\t\t}),\n\n\t\t\tnew wp.media.controller.GalleryAdd(),\n\n\t\t\tnew Library({\n\t\t\t\tid: 'playlist',\n\t\t\t\ttitle: l10n.createPlaylistTitle,\n\t\t\t\tpriority: 60,\n\t\t\t\ttoolbar: 'main-playlist',\n\t\t\t\tfilterable: 'uploaded',\n\t\t\t\tmultiple: 'add',\n\t\t\t\teditable: false,\n\n\t\t\t\tlibrary: wp.media.query( _.defaults({\n\t\t\t\t\ttype: 'audio'\n\t\t\t\t}, options.library ) )\n\t\t\t}),\n\n\t\t\t// Playlist states.\n\t\t\tnew wp.media.controller.CollectionEdit({\n\t\t\t\ttype: 'audio',\n\t\t\t\tcollectionType: 'playlist',\n\t\t\t\ttitle: l10n.editPlaylistTitle,\n\t\t\t\tSettingsView: wp.media.view.Settings.Playlist,\n\t\t\t\tlibrary: options.selection,\n\t\t\t\tediting: options.editing,\n\t\t\t\tmenu: 'playlist',\n\t\t\t\tdragInfoText: l10n.playlistDragInfo,\n\t\t\t\tdragInfo: false\n\t\t\t}),\n\n\t\t\tnew wp.media.controller.CollectionAdd({\n\t\t\t\ttype: 'audio',\n\t\t\t\tcollectionType: 'playlist',\n\t\t\t\ttitle: l10n.addToPlaylistTitle\n\t\t\t}),\n\n\t\t\tnew Library({\n\t\t\t\tid: 'video-playlist',\n\t\t\t\ttitle: l10n.createVideoPlaylistTitle,\n\t\t\t\tpriority: 60,\n\t\t\t\ttoolbar: 'main-video-playlist',\n\t\t\t\tfilterable: 'uploaded',\n\t\t\t\tmultiple: 'add',\n\t\t\t\teditable: false,\n\n\t\t\t\tlibrary: wp.media.query( _.defaults({\n\t\t\t\t\ttype: 'video'\n\t\t\t\t}, options.library ) )\n\t\t\t}),\n\n\t\t\tnew wp.media.controller.CollectionEdit({\n\t\t\t\ttype: 'video',\n\t\t\t\tcollectionType: 'playlist',\n\t\t\t\ttitle: l10n.editVideoPlaylistTitle,\n\t\t\t\tSettingsView: wp.media.view.Settings.Playlist,\n\t\t\t\tlibrary: options.selection,\n\t\t\t\tediting: options.editing,\n\t\t\t\tmenu: 'video-playlist',\n\t\t\t\tdragInfoText: l10n.videoPlaylistDragInfo,\n\t\t\t\tdragInfo: false\n\t\t\t}),\n\n\t\t\tnew wp.media.controller.CollectionAdd({\n\t\t\t\ttype: 'video',\n\t\t\t\tcollectionType: 'playlist',\n\t\t\t\ttitle: l10n.addToVideoPlaylistTitle\n\t\t\t})\n\t\t]);\n\n\t\tif ( wp.media.view.settings.post.featuredImageId ) {\n\t\t\tthis.states.add( new wp.media.controller.FeaturedImage() );\n\t\t}\n\t},\n\n\tbindHandlers: function() {\n\t\tvar handlers, checkCounts;\n\n\t\tSelect.prototype.bindHandlers.apply( this, arguments );\n\n\t\tthis.on( 'activate', this.activate, this );\n\n\t\t// Only bother checking media type counts if one of the counts is zero\n\t\tcheckCounts = _.find( this.counts, function( type ) {\n\t\t\treturn type.count === 0;\n\t\t} );\n\n\t\tif ( typeof checkCounts !== 'undefined' ) {\n\t\t\tthis.listenTo( wp.media.model.Attachments.all, 'change:type', this.mediaTypeCounts );\n\t\t}\n\n\t\tthis.on( 'menu:create:gallery', this.createMenu, this );\n\t\tthis.on( 'menu:create:playlist', this.createMenu, this );\n\t\tthis.on( 'menu:create:video-playlist', this.createMenu, this );\n\t\tthis.on( 'toolbar:create:main-insert', this.createToolbar, this );\n\t\tthis.on( 'toolbar:create:main-gallery', this.createToolbar, this );\n\t\tthis.on( 'toolbar:create:main-playlist', this.createToolbar, this );\n\t\tthis.on( 'toolbar:create:main-video-playlist', this.createToolbar, this );\n\t\tthis.on( 'toolbar:create:featured-image', this.featuredImageToolbar, this );\n\t\tthis.on( 'toolbar:create:main-embed', this.mainEmbedToolbar, this );\n\n\t\thandlers = {\n\t\t\tmenu: {\n\t\t\t\t'default': 'mainMenu',\n\t\t\t\t'gallery': 'galleryMenu',\n\t\t\t\t'playlist': 'playlistMenu',\n\t\t\t\t'video-playlist': 'videoPlaylistMenu'\n\t\t\t},\n\n\t\t\tcontent: {\n\t\t\t\t'embed': 'embedContent',\n\t\t\t\t'edit-image': 'editImageContent',\n\t\t\t\t'edit-selection': 'editSelectionContent'\n\t\t\t},\n\n\t\t\ttoolbar: {\n\t\t\t\t'main-insert': 'mainInsertToolbar',\n\t\t\t\t'main-gallery': 'mainGalleryToolbar',\n\t\t\t\t'gallery-edit': 'galleryEditToolbar',\n\t\t\t\t'gallery-add': 'galleryAddToolbar',\n\t\t\t\t'main-playlist':\t'mainPlaylistToolbar',\n\t\t\t\t'playlist-edit':\t'playlistEditToolbar',\n\t\t\t\t'playlist-add':\t\t'playlistAddToolbar',\n\t\t\t\t'main-video-playlist': 'mainVideoPlaylistToolbar',\n\t\t\t\t'video-playlist-edit': 'videoPlaylistEditToolbar',\n\t\t\t\t'video-playlist-add': 'videoPlaylistAddToolbar'\n\t\t\t}\n\t\t};\n\n\t\t_.each( handlers, function( regionHandlers, region ) {\n\t\t\t_.each( regionHandlers, function( callback, handler ) {\n\t\t\t\tthis.on( region + ':render:' + handler, this[ callback ], this );\n\t\t\t}, this );\n\t\t}, this );\n\t},\n\n\tactivate: function() {\n\t\t// Hide menu items for states tied to particular media types if there are no items\n\t\t_.each( this.counts, function( type ) {\n\t\t\tif ( type.count < 1 ) {\n\t\t\t\tthis.menuItemVisibility( type.state, 'hide' );\n\t\t\t}\n\t\t}, this );\n\t},\n\n\tmediaTypeCounts: function( model, attr ) {\n\t\tif ( typeof this.counts[ attr ] !== 'undefined' && this.counts[ attr ].count < 1 ) {\n\t\t\tthis.counts[ attr ].count++;\n\t\t\tthis.menuItemVisibility( this.counts[ attr ].state, 'show' );\n\t\t}\n\t},\n\n\t// Menus\n\t/**\n\t * @param {wp.Backbone.View} view\n\t */\n\tmainMenu: function( view ) {\n\t\tview.set({\n\t\t\t'library-separator': new wp.media.View({\n\t\t\t\tclassName: 'separator',\n\t\t\t\tpriority: 100\n\t\t\t})\n\t\t});\n\t},\n\n\tmenuItemVisibility: function( state, visibility ) {\n\t\tvar menu = this.menu.get();\n\t\tif ( visibility === 'hide' ) {\n\t\t\tmenu.hide( state );\n\t\t} else if ( visibility === 'show' ) {\n\t\t\tmenu.show( state );\n\t\t}\n\t},\n\t/**\n\t * @param {wp.Backbone.View} view\n\t */\n\tgalleryMenu: function( view ) {\n\t\tvar lastState = this.lastState(),\n\t\t\tprevious = lastState && lastState.id,\n\t\t\tframe = this;\n\n\t\tview.set({\n\t\t\tcancel: {\n\t\t\t\ttext: l10n.cancelGalleryTitle,\n\t\t\t\tpriority: 20,\n\t\t\t\tclick: function() {\n\t\t\t\t\tif ( previous ) {\n\t\t\t\t\t\tframe.setState( previous );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tframe.close();\n\t\t\t\t\t}\n\n\t\t\t\t\t// Keep focus inside media modal\n\t\t\t\t\t// after canceling a gallery\n\t\t\t\t\tthis.controller.modal.focusManager.focus();\n\t\t\t\t}\n\t\t\t},\n\t\t\tseparateCancel: new wp.media.View({\n\t\t\t\tclassName: 'separator',\n\t\t\t\tpriority: 40\n\t\t\t})\n\t\t});\n\t},\n\n\tplaylistMenu: function( view ) {\n\t\tvar lastState = this.lastState(),\n\t\t\tprevious = lastState && lastState.id,\n\t\t\tframe = this;\n\n\t\tview.set({\n\t\t\tcancel: {\n\t\t\t\ttext: l10n.cancelPlaylistTitle,\n\t\t\t\tpriority: 20,\n\t\t\t\tclick: function() {\n\t\t\t\t\tif ( previous ) {\n\t\t\t\t\t\tframe.setState( previous );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tframe.close();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\tseparateCancel: new wp.media.View({\n\t\t\t\tclassName: 'separator',\n\t\t\t\tpriority: 40\n\t\t\t})\n\t\t});\n\t},\n\n\tvideoPlaylistMenu: function( view ) {\n\t\tvar lastState = this.lastState(),\n\t\t\tprevious = lastState && lastState.id,\n\t\t\tframe = this;\n\n\t\tview.set({\n\t\t\tcancel: {\n\t\t\t\ttext: l10n.cancelVideoPlaylistTitle,\n\t\t\t\tpriority: 20,\n\t\t\t\tclick: function() {\n\t\t\t\t\tif ( previous ) {\n\t\t\t\t\t\tframe.setState( previous );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tframe.close();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\tseparateCancel: new wp.media.View({\n\t\t\t\tclassName: 'separator',\n\t\t\t\tpriority: 40\n\t\t\t})\n\t\t});\n\t},\n\n\t// Content\n\tembedContent: function() {\n\t\tvar view = new wp.media.view.Embed({\n\t\t\tcontroller: this,\n\t\t\tmodel: this.state()\n\t\t}).render();\n\n\t\tthis.content.set( view );\n\n\t\tif ( ! wp.media.isTouchDevice ) {\n\t\t\tview.url.focus();\n\t\t}\n\t},\n\n\teditSelectionContent: function() {\n\t\tvar state = this.state(),\n\t\t\tselection = state.get('selection'),\n\t\t\tview;\n\n\t\tview = new wp.media.view.AttachmentsBrowser({\n\t\t\tcontroller: this,\n\t\t\tcollection: selection,\n\t\t\tselection: selection,\n\t\t\tmodel: state,\n\t\t\tsortable: true,\n\t\t\tsearch: false,\n\t\t\tdate: false,\n\t\t\tdragInfo: true,\n\n\t\t\tAttachmentView: wp.media.view.Attachments.EditSelection\n\t\t}).render();\n\n\t\tview.toolbar.set( 'backToLibrary', {\n\t\t\ttext: l10n.returnToLibrary,\n\t\t\tpriority: -100,\n\n\t\t\tclick: function() {\n\t\t\t\tthis.controller.content.mode('browse');\n\t\t\t}\n\t\t});\n\n\t\t// Browse our library of attachments.\n\t\tthis.content.set( view );\n\n\t\t// Trigger the controller to set focus\n\t\tthis.trigger( 'edit:selection', this );\n\t},\n\n\teditImageContent: function() {\n\t\tvar image = this.state().get('image'),\n\t\t\tview = new wp.media.view.EditImage( { model: image, controller: this } ).render();\n\n\t\tthis.content.set( view );\n\n\t\t// after creating the wrapper view, load the actual editor via an ajax call\n\t\tview.loadEditor();\n\n\t},\n\n\t// Toolbars\n\n\t/**\n\t * @param {wp.Backbone.View} view\n\t */\n\tselectionStatusToolbar: function( view ) {\n\t\tvar editable = this.state().get('editable');\n\n\t\tview.set( 'selection', new wp.media.view.Selection({\n\t\t\tcontroller: this,\n\t\t\tcollection: this.state().get('selection'),\n\t\t\tpriority: -40,\n\n\t\t\t// If the selection is editable, pass the callback to\n\t\t\t// switch the content mode.\n\t\t\teditable: editable && function() {\n\t\t\t\tthis.controller.content.mode('edit-selection');\n\t\t\t}\n\t\t}).render() );\n\t},\n\n\t/**\n\t * @param {wp.Backbone.View} view\n\t */\n\tmainInsertToolbar: function( view ) {\n\t\tvar controller = this;\n\n\t\tthis.selectionStatusToolbar( view );\n\n\t\tview.set( 'insert', {\n\t\t\tstyle: 'primary',\n\t\t\tpriority: 80,\n\t\t\ttext: l10n.insertIntoPost,\n\t\t\trequires: { selection: true },\n\n\t\t\t/**\n\t\t\t * @ignore\n\t\t\t *\n\t\t\t * @fires wp.media.controller.State#insert\n\t\t\t */\n\t\t\tclick: function() {\n\t\t\t\tvar state = controller.state(),\n\t\t\t\t\tselection = state.get('selection');\n\n\t\t\t\tcontroller.close();\n\t\t\t\tstate.trigger( 'insert', selection ).reset();\n\t\t\t}\n\t\t});\n\t},\n\n\t/**\n\t * @param {wp.Backbone.View} view\n\t */\n\tmainGalleryToolbar: function( view ) {\n\t\tvar controller = this;\n\n\t\tthis.selectionStatusToolbar( view );\n\n\t\tview.set( 'gallery', {\n\t\t\tstyle: 'primary',\n\t\t\ttext: l10n.createNewGallery,\n\t\t\tpriority: 60,\n\t\t\trequires: { selection: true },\n\n\t\t\tclick: function() {\n\t\t\t\tvar selection = controller.state().get('selection'),\n\t\t\t\t\tedit = controller.state('gallery-edit'),\n\t\t\t\t\tmodels = selection.where({ type: 'image' });\n\n\t\t\t\tedit.set( 'library', new wp.media.model.Selection( models, {\n\t\t\t\t\tprops: selection.props.toJSON(),\n\t\t\t\t\tmultiple: true\n\t\t\t\t}) );\n\n\t\t\t\tthis.controller.setState('gallery-edit');\n\n\t\t\t\t// Keep focus inside media modal\n\t\t\t\t// after jumping to gallery view\n\t\t\t\tthis.controller.modal.focusManager.focus();\n\t\t\t}\n\t\t});\n\t},\n\n\tmainPlaylistToolbar: function( view ) {\n\t\tvar controller = this;\n\n\t\tthis.selectionStatusToolbar( view );\n\n\t\tview.set( 'playlist', {\n\t\t\tstyle: 'primary',\n\t\t\ttext: l10n.createNewPlaylist,\n\t\t\tpriority: 100,\n\t\t\trequires: { selection: true },\n\n\t\t\tclick: function() {\n\t\t\t\tvar selection = controller.state().get('selection'),\n\t\t\t\t\tedit = controller.state('playlist-edit'),\n\t\t\t\t\tmodels = selection.where({ type: 'audio' });\n\n\t\t\t\tedit.set( 'library', new wp.media.model.Selection( models, {\n\t\t\t\t\tprops: selection.props.toJSON(),\n\t\t\t\t\tmultiple: true\n\t\t\t\t}) );\n\n\t\t\t\tthis.controller.setState('playlist-edit');\n\n\t\t\t\t// Keep focus inside media modal\n\t\t\t\t// after jumping to playlist view\n\t\t\t\tthis.controller.modal.focusManager.focus();\n\t\t\t}\n\t\t});\n\t},\n\n\tmainVideoPlaylistToolbar: function( view ) {\n\t\tvar controller = this;\n\n\t\tthis.selectionStatusToolbar( view );\n\n\t\tview.set( 'video-playlist', {\n\t\t\tstyle: 'primary',\n\t\t\ttext: l10n.createNewVideoPlaylist,\n\t\t\tpriority: 100,\n\t\t\trequires: { selection: true },\n\n\t\t\tclick: function() {\n\t\t\t\tvar selection = controller.state().get('selection'),\n\t\t\t\t\tedit = controller.state('video-playlist-edit'),\n\t\t\t\t\tmodels = selection.where({ type: 'video' });\n\n\t\t\t\tedit.set( 'library', new wp.media.model.Selection( models, {\n\t\t\t\t\tprops: selection.props.toJSON(),\n\t\t\t\t\tmultiple: true\n\t\t\t\t}) );\n\n\t\t\t\tthis.controller.setState('video-playlist-edit');\n\n\t\t\t\t// Keep focus inside media modal\n\t\t\t\t// after jumping to video playlist view\n\t\t\t\tthis.controller.modal.focusManager.focus();\n\t\t\t}\n\t\t});\n\t},\n\n\tfeaturedImageToolbar: function( toolbar ) {\n\t\tthis.createSelectToolbar( toolbar, {\n\t\t\ttext: l10n.setFeaturedImage,\n\t\t\tstate: this.options.state\n\t\t});\n\t},\n\n\tmainEmbedToolbar: function( toolbar ) {\n\t\ttoolbar.view = new wp.media.view.Toolbar.Embed({\n\t\t\tcontroller: this\n\t\t});\n\t},\n\n\tgalleryEditToolbar: function() {\n\t\tvar editing = this.state().get('editing');\n\t\tthis.toolbar.set( new wp.media.view.Toolbar({\n\t\t\tcontroller: this,\n\t\t\titems: {\n\t\t\t\tinsert: {\n\t\t\t\t\tstyle: 'primary',\n\t\t\t\t\ttext: editing ? l10n.updateGallery : l10n.insertGallery,\n\t\t\t\t\tpriority: 80,\n\t\t\t\t\trequires: { library: true },\n\n\t\t\t\t\t/**\n\t\t\t\t\t * @fires wp.media.controller.State#update\n\t\t\t\t\t */\n\t\t\t\t\tclick: function() {\n\t\t\t\t\t\tvar controller = this.controller,\n\t\t\t\t\t\t\tstate = controller.state();\n\n\t\t\t\t\t\tcontroller.close();\n\t\t\t\t\t\tstate.trigger( 'update', state.get('library') );\n\n\t\t\t\t\t\t// Restore and reset the default state.\n\t\t\t\t\t\tcontroller.setState( controller.options.state );\n\t\t\t\t\t\tcontroller.reset();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}) );\n\t},\n\n\tgalleryAddToolbar: function() {\n\t\tthis.toolbar.set( new wp.media.view.Toolbar({\n\t\t\tcontroller: this,\n\t\t\titems: {\n\t\t\t\tinsert: {\n\t\t\t\t\tstyle: 'primary',\n\t\t\t\t\ttext: l10n.addToGallery,\n\t\t\t\t\tpriority: 80,\n\t\t\t\t\trequires: { selection: true },\n\n\t\t\t\t\t/**\n\t\t\t\t\t * @fires wp.media.controller.State#reset\n\t\t\t\t\t */\n\t\t\t\t\tclick: function() {\n\t\t\t\t\t\tvar controller = this.controller,\n\t\t\t\t\t\t\tstate = controller.state(),\n\t\t\t\t\t\t\tedit = controller.state('gallery-edit');\n\n\t\t\t\t\t\tedit.get('library').add( state.get('selection').models );\n\t\t\t\t\t\tstate.trigger('reset');\n\t\t\t\t\t\tcontroller.setState('gallery-edit');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}) );\n\t},\n\n\tplaylistEditToolbar: function() {\n\t\tvar editing = this.state().get('editing');\n\t\tthis.toolbar.set( new wp.media.view.Toolbar({\n\t\t\tcontroller: this,\n\t\t\titems: {\n\t\t\t\tinsert: {\n\t\t\t\t\tstyle: 'primary',\n\t\t\t\t\ttext: editing ? l10n.updatePlaylist : l10n.insertPlaylist,\n\t\t\t\t\tpriority: 80,\n\t\t\t\t\trequires: { library: true },\n\n\t\t\t\t\t/**\n\t\t\t\t\t * @fires wp.media.controller.State#update\n\t\t\t\t\t */\n\t\t\t\t\tclick: function() {\n\t\t\t\t\t\tvar controller = this.controller,\n\t\t\t\t\t\t\tstate = controller.state();\n\n\t\t\t\t\t\tcontroller.close();\n\t\t\t\t\t\tstate.trigger( 'update', state.get('library') );\n\n\t\t\t\t\t\t// Restore and reset the default state.\n\t\t\t\t\t\tcontroller.setState( controller.options.state );\n\t\t\t\t\t\tcontroller.reset();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}) );\n\t},\n\n\tplaylistAddToolbar: function() {\n\t\tthis.toolbar.set( new wp.media.view.Toolbar({\n\t\t\tcontroller: this,\n\t\t\titems: {\n\t\t\t\tinsert: {\n\t\t\t\t\tstyle: 'primary',\n\t\t\t\t\ttext: l10n.addToPlaylist,\n\t\t\t\t\tpriority: 80,\n\t\t\t\t\trequires: { selection: true },\n\n\t\t\t\t\t/**\n\t\t\t\t\t * @fires wp.media.controller.State#reset\n\t\t\t\t\t */\n\t\t\t\t\tclick: function() {\n\t\t\t\t\t\tvar controller = this.controller,\n\t\t\t\t\t\t\tstate = controller.state(),\n\t\t\t\t\t\t\tedit = controller.state('playlist-edit');\n\n\t\t\t\t\t\tedit.get('library').add( state.get('selection').models );\n\t\t\t\t\t\tstate.trigger('reset');\n\t\t\t\t\t\tcontroller.setState('playlist-edit');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}) );\n\t},\n\n\tvideoPlaylistEditToolbar: function() {\n\t\tvar editing = this.state().get('editing');\n\t\tthis.toolbar.set( new wp.media.view.Toolbar({\n\t\t\tcontroller: this,\n\t\t\titems: {\n\t\t\t\tinsert: {\n\t\t\t\t\tstyle: 'primary',\n\t\t\t\t\ttext: editing ? l10n.updateVideoPlaylist : l10n.insertVideoPlaylist,\n\t\t\t\t\tpriority: 140,\n\t\t\t\t\trequires: { library: true },\n\n\t\t\t\t\tclick: function() {\n\t\t\t\t\t\tvar controller = this.controller,\n\t\t\t\t\t\t\tstate = controller.state(),\n\t\t\t\t\t\t\tlibrary = state.get('library');\n\n\t\t\t\t\t\tlibrary.type = 'video';\n\n\t\t\t\t\t\tcontroller.close();\n\t\t\t\t\t\tstate.trigger( 'update', library );\n\n\t\t\t\t\t\t// Restore and reset the default state.\n\t\t\t\t\t\tcontroller.setState( controller.options.state );\n\t\t\t\t\t\tcontroller.reset();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}) );\n\t},\n\n\tvideoPlaylistAddToolbar: function() {\n\t\tthis.toolbar.set( new wp.media.view.Toolbar({\n\t\t\tcontroller: this,\n\t\t\titems: {\n\t\t\t\tinsert: {\n\t\t\t\t\tstyle: 'primary',\n\t\t\t\t\ttext: l10n.addToVideoPlaylist,\n\t\t\t\t\tpriority: 140,\n\t\t\t\t\trequires: { selection: true },\n\n\t\t\t\t\tclick: function() {\n\t\t\t\t\t\tvar controller = this.controller,\n\t\t\t\t\t\t\tstate = controller.state(),\n\t\t\t\t\t\t\tedit = controller.state('video-playlist-edit');\n\n\t\t\t\t\t\tedit.get('library').add( state.get('selection').models );\n\t\t\t\t\t\tstate.trigger('reset');\n\t\t\t\t\t\tcontroller.setState('video-playlist-edit');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}) );\n\t}\n});\n\nmodule.exports = Post;\n\n\n//# sourceURL=webpack:///./src/js/media/views/frame/post.js?"); - -/***/ }), - -/***/ "./src/js/media/views/frame/select.js": -/*!********************************************!*\ - !*** ./src/js/media/views/frame/select.js ***! - \********************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("var MediaFrame = wp.media.view.MediaFrame,\n\tl10n = wp.media.view.l10n,\n\tSelect;\n\n/**\n * wp.media.view.MediaFrame.Select\n *\n * A frame for selecting an item or items from the media library.\n *\n * @memberOf wp.media.view.MediaFrame\n *\n * @class\n * @augments wp.media.view.MediaFrame\n * @augments wp.media.view.Frame\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n * @mixes wp.media.controller.StateMachine\n */\nSelect = MediaFrame.extend(/** @lends wp.media.view.MediaFrame.Select.prototype */{\n\tinitialize: function() {\n\t\t// Call 'initialize' directly on the parent class.\n\t\tMediaFrame.prototype.initialize.apply( this, arguments );\n\n\t\t_.defaults( this.options, {\n\t\t\tselection: [],\n\t\t\tlibrary: {},\n\t\t\tmultiple: false,\n\t\t\tstate: 'library'\n\t\t});\n\n\t\tthis.createSelection();\n\t\tthis.createStates();\n\t\tthis.bindHandlers();\n\t},\n\n\t/**\n\t * Attach a selection collection to the frame.\n\t *\n\t * A selection is a collection of attachments used for a specific purpose\n\t * by a media frame. e.g. Selecting an attachment (or many) to insert into\n\t * post content.\n\t *\n\t * @see media.model.Selection\n\t */\n\tcreateSelection: function() {\n\t\tvar selection = this.options.selection;\n\n\t\tif ( ! (selection instanceof wp.media.model.Selection) ) {\n\t\t\tthis.options.selection = new wp.media.model.Selection( selection, {\n\t\t\t\tmultiple: this.options.multiple\n\t\t\t});\n\t\t}\n\n\t\tthis._selection = {\n\t\t\tattachments: new wp.media.model.Attachments(),\n\t\t\tdifference: []\n\t\t};\n\t},\n\n\t/**\n\t * Create the default states on the frame.\n\t */\n\tcreateStates: function() {\n\t\tvar options = this.options;\n\n\t\tif ( this.options.states ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Add the default states.\n\t\tthis.states.add([\n\t\t\t// Main states.\n\t\t\tnew wp.media.controller.Library({\n\t\t\t\tlibrary: wp.media.query( options.library ),\n\t\t\t\tmultiple: options.multiple,\n\t\t\t\ttitle: options.title,\n\t\t\t\tpriority: 20\n\t\t\t})\n\t\t]);\n\t},\n\n\t/**\n\t * Bind region mode event callbacks.\n\t *\n\t * @see media.controller.Region.render\n\t */\n\tbindHandlers: function() {\n\t\tthis.on( 'router:create:browse', this.createRouter, this );\n\t\tthis.on( 'router:render:browse', this.browseRouter, this );\n\t\tthis.on( 'content:create:browse', this.browseContent, this );\n\t\tthis.on( 'content:render:upload', this.uploadContent, this );\n\t\tthis.on( 'toolbar:create:select', this.createSelectToolbar, this );\n\t},\n\n\t/**\n\t * Render callback for the router region in the `browse` mode.\n\t *\n\t * @param {wp.media.view.Router} routerView\n\t */\n\tbrowseRouter: function( routerView ) {\n\t\trouterView.set({\n\t\t\tupload: {\n\t\t\t\ttext: l10n.uploadFilesTitle,\n\t\t\t\tpriority: 20\n\t\t\t},\n\t\t\tbrowse: {\n\t\t\t\ttext: l10n.mediaLibraryTitle,\n\t\t\t\tpriority: 40\n\t\t\t}\n\t\t});\n\t},\n\n\t/**\n\t * Render callback for the content region in the `browse` mode.\n\t *\n\t * @param {wp.media.controller.Region} contentRegion\n\t */\n\tbrowseContent: function( contentRegion ) {\n\t\tvar state = this.state();\n\n\t\tthis.$el.removeClass('hide-toolbar');\n\n\t\t// Browse our library of attachments.\n\t\tcontentRegion.view = new wp.media.view.AttachmentsBrowser({\n\t\t\tcontroller: this,\n\t\t\tcollection: state.get('library'),\n\t\t\tselection: state.get('selection'),\n\t\t\tmodel: state,\n\t\t\tsortable: state.get('sortable'),\n\t\t\tsearch: state.get('searchable'),\n\t\t\tfilters: state.get('filterable'),\n\t\t\tdate: state.get('date'),\n\t\t\tdisplay: state.has('display') ? state.get('display') : state.get('displaySettings'),\n\t\t\tdragInfo: state.get('dragInfo'),\n\n\t\t\tidealColumnWidth: state.get('idealColumnWidth'),\n\t\t\tsuggestedWidth: state.get('suggestedWidth'),\n\t\t\tsuggestedHeight: state.get('suggestedHeight'),\n\n\t\t\tAttachmentView: state.get('AttachmentView')\n\t\t});\n\t},\n\n\t/**\n\t * Render callback for the content region in the `upload` mode.\n\t */\n\tuploadContent: function() {\n\t\tthis.$el.removeClass( 'hide-toolbar' );\n\t\tthis.content.set( new wp.media.view.UploaderInline({\n\t\t\tcontroller: this\n\t\t}) );\n\t},\n\n\t/**\n\t * Toolbars\n\t *\n\t * @param {Object} toolbar\n\t * @param {Object} [options={}]\n\t * @this wp.media.controller.Region\n\t */\n\tcreateSelectToolbar: function( toolbar, options ) {\n\t\toptions = options || this.options.button || {};\n\t\toptions.controller = this;\n\n\t\ttoolbar.view = new wp.media.view.Toolbar.Select( options );\n\t}\n});\n\nmodule.exports = Select;\n\n\n//# sourceURL=webpack:///./src/js/media/views/frame/select.js?"); - -/***/ }), - -/***/ "./src/js/media/views/iframe.js": -/*!**************************************!*\ - !*** ./src/js/media/views/iframe.js ***! - \**************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("/**\n * wp.media.view.Iframe\n *\n * @memberOf wp.media.view\n *\n * @class\n * @augments wp.media.View\n * @augments wp.Backbone.View\n * @augments Backbone.View\n */\nvar Iframe = wp.media.View.extend(/** @lends wp.media.view.Iframe.prototype */{\n\tclassName: 'media-iframe',\n\t/**\n\t * @returns {wp.media.view.Iframe} Returns itself to allow chaining\n\t */\n\trender: function() {\n\t\tthis.views.detach();\n\t\tthis.$el.html( '