Make WordPress Core

Changeset 40640


Ignore:
Timestamp:
05/11/2017 09:10:54 PM (6 years ago)
Author:
westonruter
Message:

Widgets: Introduce media widgets for images, audio, and video with extensible base for additional media widgets in the future.

The last time a new widget was introduced, Vuvuzelas were a thing, Angry Birds started taking over phones, and WordPress stopped shipping with Kubrick. Seven years and 17 releases without new widgets have been enough, time to spice up your sidebar!

Props westonruter, melchoyce, obenland, timmydcrawford, adamsilverstein, gonom9, wonderboymusic, Fab1en, DrewAPicture, sirbrillig, joen, matias, samikeijonen, afercia, celloexpressions, designsimply, michelleweber, ranh, kjellr, karmatosed.
Fixes #32417, #39993, #39994, #39995.

Location:
trunk
Files:
20 added
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/css/widgets.css

    r40480 r40640  
    5656}
    5757
     58/* Media Widgets */
     59.wp-core-ui .media-widget-control.selected .placeholder,
     60.wp-core-ui .media-widget-control.selected .not-selected,
     61.wp-core-ui .media-widget-control .selected {
     62    display: none;
     63}
     64
     65.media-widget-control.selected .selected {
     66    display: inline-block;
     67}
     68
     69.media-widget-buttons {
     70    text-align: left;
     71    margin-bottom: 10px;
     72}
     73
     74.media-widget-control .media-widget-buttons .button {
     75    margin-left: 8px;
     76    width: auto;
     77}
     78.media-widget-control:not(.selected) .media-widget-buttons .button,
     79.media-widget-buttons .button:first-child {
     80    margin-left: 0;
     81}
     82
     83.media-widget-control .placeholder {
     84    border: 1px dashed #b4b9be;
     85    -webkit-box-sizing: border-box;
     86    -moz-box-sizing: border-box;
     87    box-sizing: border-box;
     88    cursor: default;
     89    line-height: 20px;
     90    padding: 9px 0;
     91    position: relative;
     92    text-align: center;
     93    width: 100%;
     94}
     95
     96.media-widget-control .media-widget-preview {
     97    text-align: center;
     98}
     99.media-widget-control .media-widget-preview .notice {
     100    text-align: initial;
     101}
     102.media-frame .media-widget-embed-notice p code,
     103.media-widget-control .notice p code {
     104    padding: 0 3px 0 0;
     105}
     106.media-frame .media-widget-embed-notice {
     107    margin-top: 16px;
     108}
     109.media-widget-control .media-widget-preview img {
     110    max-width: 100%;
     111}
     112.media-widget-control .media-widget-preview .wp-video-shortcode {
     113    background: #000;
     114}
     115
     116.media-frame.media-widget .media-toolbar-secondary {
     117    min-width: 300px;
     118}
     119
     120.media-frame.media-widget .image-details .embed-media-settings .setting.align,
     121.media-frame.media-widget .attachment-display-settings .setting.align,
     122.media-frame.media-widget .embed-media-settings .setting.align,
     123.media-frame.media-widget .embed-link-settings .setting.link-text,
     124.media-frame.media-widget .replace-attachment,
     125.media-frame.media-widget .checkbox-setting.autoplay {
     126    display: none;
     127}
     128
     129.media-widget-video-preview {
     130    width: 100%;
     131}
     132
     133.media-widget-video-link {
     134    display: inline-block;
     135    min-height: 132px;
     136    width: 100%;
     137    background: black;
     138}
     139
     140.media-widget-video-link .dashicons {
     141    font: normal 60px/1 'dashicons';
     142    position: relative;
     143    width: 100%;
     144    top: -90px;
     145    color: white;
     146    text-decoration: none;
     147}
     148
     149.media-widget-video-link.no-poster .dashicons {
     150    top: 30px;
     151}
     152
     153.media-frame #embed-url-field.invalid {
     154    border: 1px solid #f00;
     155}
     156
     157.wp-customizer .mejs-controls a:focus > .mejs-offscreen,
     158.widgets-php .mejs-controls a:focus > .mejs-offscreen {
     159    z-index: 2;
     160}
     161
    58162/* Widget Dragging Helpers */
    59163.widget.ui-draggable-dragging {
  • trunk/src/wp-content/themes/twentyten/style.css

    r38171 r40640  
    842842    text-align: center;
    843843}
     844.widget-container .wp-caption {
     845    max-width: 100% !important;
     846}
    844847.wp-caption img {
    845848    margin: 5px 5px 0;
  • trunk/src/wp-includes/default-widgets.php

    r34408 r40640  
    1919/** WP_Widget_Archives class */
    2020require_once( ABSPATH . WPINC . '/widgets/class-wp-widget-archives.php' );
     21
     22/** WP_Widget_Media class */
     23require_once( ABSPATH . WPINC . '/widgets/class-wp-widget-media.php' );
     24
     25/** WP_Widget_Media_Audio class */
     26require_once( ABSPATH . WPINC . '/widgets/class-wp-widget-media-audio.php' );
     27
     28/** WP_Widget_Media_Image class */
     29require_once( ABSPATH . WPINC . '/widgets/class-wp-widget-media-image.php' );
     30
     31/** WP_Widget_Media_Video class */
     32require_once( ABSPATH . WPINC . '/widgets/class-wp-widget-media-video.php' );
     33
     34/** WP_Widget_Meta class */
     35require_once( ABSPATH . WPINC . '/widgets/class-wp-widget-meta.php' );
    2136
    2237/** WP_Widget_Meta class */
  • trunk/src/wp-includes/js/customize-selective-refresh.js

    r40055 r40640  
    469469            // Prevent placement container from being being re-triggered as being rendered among nested partials.
    470470            placement.container.data( 'customize-partial-content-rendered', true );
     471
     472            /*
     473             * Note that the 'wp_audio_shortcode_library' and 'wp_video_shortcode_library' filters
     474             * will determine whether or not wp.mediaelement is loaded and whether it will
     475             * initialize audio and video respectively. See also https://core.trac.wordpress.org/ticket/40144
     476             */
     477            if ( wp.mediaelement ) {
     478                wp.mediaelement.initialize();
     479            }
    471480
    472481            /**
  • trunk/src/wp-includes/media-template.php

    r40573 r40640  
    609609
    610610        <# if ( 'image' === data.type ) { #>
    611             <label class="setting">
     611            <label class="setting align">
    612612                <span><?php _e('Alignment'); ?></span>
    613613                <select class="alignment"
     
    10881088                </div>
    10891089
    1090                 <label class="setting checkbox-setting">
     1090                <label class="setting checkbox-setting autoplay">
    10911091                    <input type="checkbox" data-setting="autoplay" />
    10921092                    <span><?php _e( 'Autoplay' ); ?></span>
     
    11771177                </div>
    11781178
    1179                 <label class="setting checkbox-setting">
     1179                <label class="setting checkbox-setting autoplay">
    11801180                    <input type="checkbox" data-setting="autoplay" />
    11811181                    <span><?php _e( 'Autoplay' ); ?></span>
  • trunk/src/wp-includes/script-loader.php

    r40631 r40640  
    603603
    604604        $scripts->add( 'admin-widgets', "/wp-admin/js/widgets$suffix.js", array( 'jquery-ui-sortable', 'jquery-ui-draggable', 'jquery-ui-droppable' ), false, 1 );
     605        $scripts->add( 'media-widgets', "/wp-admin/js/widgets/media-widgets$suffix.js", array( 'jquery', 'media-models', 'media-views' ) );
     606        $scripts->add_inline_script( 'media-widgets', 'wp.mediaWidgets.init();', 'after' );
     607
     608        $scripts->add( 'media-audio-widget', "/wp-admin/js/widgets/media-audio-widget$suffix.js", array( 'media-widgets', 'media-audiovideo' ) );
     609        $scripts->add( 'media-image-widget', "/wp-admin/js/widgets/media-image-widget$suffix.js", array( 'media-widgets' ) );
     610        $scripts->add( 'media-video-widget', "/wp-admin/js/widgets/media-video-widget$suffix.js", array( 'media-widgets', 'media-audiovideo' ) );
    605611        $scripts->add( 'text-widgets', "/wp-admin/js/widgets/text-widgets$suffix.js", array( 'jquery', 'backbone', 'editor', 'wp-util' ) );
    606612        $scripts->add_inline_script( 'text-widgets', 'wp.textWidgets.init();', 'after' );
  • trunk/src/wp-includes/widgets.php

    r40251 r40640  
    14371437 */
    14381438function wp_widgets_init() {
    1439     if ( !is_blog_installed() )
    1440         return;
    1441 
    1442     register_widget('WP_Widget_Pages');
    1443 
    1444     register_widget('WP_Widget_Calendar');
    1445 
    1446     register_widget('WP_Widget_Archives');
    1447 
    1448     if ( get_option( 'link_manager_enabled' ) )
    1449         register_widget('WP_Widget_Links');
    1450 
    1451     register_widget('WP_Widget_Meta');
    1452 
    1453     register_widget('WP_Widget_Search');
    1454 
    1455     register_widget('WP_Widget_Text');
    1456 
    1457     register_widget('WP_Widget_Categories');
    1458 
    1459     register_widget('WP_Widget_Recent_Posts');
    1460 
    1461     register_widget('WP_Widget_Recent_Comments');
    1462 
    1463     register_widget('WP_Widget_RSS');
    1464 
    1465     register_widget('WP_Widget_Tag_Cloud');
    1466 
    1467     register_widget('WP_Nav_Menu_Widget');
     1439    if ( ! is_blog_installed() ) {
     1440        return;
     1441    }
     1442
     1443    register_widget( 'WP_Widget_Pages' );
     1444
     1445    register_widget( 'WP_Widget_Calendar' );
     1446
     1447    register_widget( 'WP_Widget_Archives' );
     1448
     1449    if ( get_option( 'link_manager_enabled' ) ) {
     1450        register_widget( 'WP_Widget_Links' );
     1451    }
     1452
     1453    register_widget( 'WP_Widget_Media_Audio' );
     1454
     1455    register_widget( 'WP_Widget_Media_Image' );
     1456
     1457    register_widget( 'WP_Widget_Media_Video' );
     1458
     1459    register_widget( 'WP_Widget_Meta' );
     1460
     1461    register_widget( 'WP_Widget_Search' );
     1462
     1463    register_widget( 'WP_Widget_Text' );
     1464
     1465    register_widget( 'WP_Widget_Categories' );
     1466
     1467    register_widget( 'WP_Widget_Recent_Posts' );
     1468
     1469    register_widget( 'WP_Widget_Recent_Comments' );
     1470
     1471    register_widget( 'WP_Widget_RSS' );
     1472
     1473    register_widget( 'WP_Widget_Tag_Cloud' );
     1474
     1475    register_widget( 'WP_Nav_Menu_Widget' );
    14681476
    14691477    /**
  • trunk/tests/phpunit/tests/widgets/text-widget.php

    r40631 r40640  
    179179        $result = $widget->update( $instance, array() );
    180180        $this->assertEquals( $result, $expected );
    181 
    182181        remove_filter( 'map_meta_cap', array( $this, 'grant_unfiltered_html_cap' ) );
     182
    183183        add_filter( 'map_meta_cap', array( $this, 'revoke_unfiltered_html_cap' ), 10, 2 );
    184184        $this->assertFalse( current_user_can( 'unfiltered_html' ) );
     
    187187        $result = $widget->update( $instance, array() );
    188188        $this->assertEquals( $result, $expected );
    189         remove_filter( 'map_meta_cap', array( $this, 'revoke_unfiltered_html_cap' ), 10, 2 );
     189        remove_filter( 'map_meta_cap', array( $this, 'revoke_unfiltered_html_cap' ), 10 );
    190190    }
    191191
  • trunk/tests/qunit/index.html

    r40584 r40640  
    2525        <script src="../../src/wp-includes/js/wp-util.js"></script>
    2626        <script src="../../src/wp-includes/js/wp-a11y.js"></script>
     27        <script>
     28            window._wpMediaModelsL10n = {"settings":{"ajaxurl":"\/wp-admin\/admin-ajax.php","post":{"id":0}}};
     29        </script>
     30        <script src="../../src/wp-includes/js/media-models.js"></script>
     31        <script>
     32            window.userSettings = {"url":"\/","uid":"0","time":"1493325477","secure":""};
     33        </script>
     34        <script src="../../src/wp-includes/js/utils.js"></script>
     35        <script src="../../src/wp-includes/js/plupload/plupload.full.min.js"></script>
     36        <script>
     37            window.pluploadL10n = {"queue_limit_exceeded":"You have attempted to queue too many files.","file_exceeds_size_limit":"%s exceeds the maximum upload size for this site.","zero_byte_file":"This file is empty. Please try another.","invalid_filetype":"Sorry, this file type is not permitted for security reasons.","not_an_image":"This file is not an image. Please try another.","image_memory_exceeded":"Memory exceeded. Please try another smaller file.","image_dimensions_exceeded":"This is larger than the maximum size. Please try another.","default_error":"An error occurred in the upload. Please try again later.","missing_upload_url":"There was a configuration error. Please contact the server administrator.","upload_limit_exceeded":"You may only upload 1 file.","http_error":"HTTP error.","upload_failed":"Upload failed.","big_upload_failed":"Please try uploading this file with the %1$sbrowser uploader%2$s.","big_upload_queued":"%s exceeds the maximum upload size for the multi-file uploader when used in your browser.","io_error":"IO error.","security_error":"Security error.","file_cancelled":"File canceled.","upload_stopped":"Upload stopped.","dismiss":"Dismiss","crunching":"Crunching\u2026","deleted":"moved to the trash.","error_uploading":"\u201c%s\u201d has failed to upload."};
     38            window._wpPluploadSettings = {"defaults":{"runtimes":"html5,flash,silverlight,html4","file_data_name":"async-upload","url":"\/wp-admin\/async-upload.php","flash_swf_url":"http:\/\/src.wordpress-develop.dev\/wp-includes\/js\/plupload\/plupload.flash.swf","silverlight_xap_url":"http:\/\/src.wordpress-develop.dev\/wp-includes\/js\/plupload\/plupload.silverlight.xap","filters":{"max_file_size":"2097152b","mime_types":[{"extensions":"jpg,jpeg,jpe,gif,png,bmp,tiff,tif,ico,asf,asx,wmv,wmx,wm,avi,divx,flv,mov,qt,mpeg,mpg,mpe,mp4,m4v,ogv,webm,mkv,3gp,3gpp,3g2,3gp2,txt,asc,c,cc,h,srt,csv,tsv,ics,rtx,css,vtt,dfxp,mp3,m4a,m4b,ra,ram,wav,ogg,oga,mid,midi,wma,wax,mka,rtf,js,pdf,class,tar,zip,gz,gzip,rar,7z,psd,xcf,doc,pot,pps,ppt,wri,xla,xls,xlt,xlw,mdb,mpp,docx,docm,dotx,dotm,xlsx,xlsm,xlsb,xltx,xltm,xlam,pptx,pptm,ppsx,ppsm,potx,potm,ppam,sldx,sldm,onetoc,onetoc2,onetmp,onepkg,oxps,xps,odt,odp,ods,odg,odc,odb,odf,wp,wpd,key,numbers,pages"}]},"multipart_params":{"action":"upload-attachment","_wpnonce":"87fa5740b8"}},"browser":{"mobile":false,"supported":true},"limitExceeded":false};
     39        </script>
     40        <script src="../../src/wp-includes/js/plupload/wp-plupload.js"></script>
     41        <script>
     42            window.mejsL10n = {"language":"en-US","strings":{"Close":"Close","Fullscreen":"Fullscreen","Turn off Fullscreen":"Turn off Fullscreen","Go Fullscreen":"Go Fullscreen","Download File":"Download File","Download Video":"Download Video","Play":"Play","Pause":"Pause","Captions\/Subtitles":"Captions\/Subtitles","None":"None","Time Slider":"Time Slider","Skip back %1 seconds":"Skip back %1 seconds","Video Player":"Video Player","Audio Player":"Audio Player","Volume Slider":"Volume Slider","Mute Toggle":"Mute Toggle","Unmute":"Unmute","Mute":"Mute","Use Up\/Down Arrow keys to increase or decrease volume.":"Use Up\/Down Arrow keys to increase or decrease volume.","Use Left\/Right Arrow keys to advance one second, Up\/Down arrows to advance ten seconds.":"Use Left\/Right Arrow keys to advance one second, Up\/Down arrows to advance ten seconds."}};
     43            window._wpmejsSettings = {"pluginPath":"\/wp-includes\/js\/mediaelement\/"};
     44        </script>
     45        <script src="../../src/wp-includes/js/mediaelement/mediaelement-and-player.min.js"></script>
     46        <script src="../../src/wp-includes/js/mediaelement/wp-mediaelement.js"></script>
     47        <script>
     48            window._wpMediaViewsL10n = {"url":"URL","addMedia":"Add Media","search":"Search","select":"Select","cancel":"Cancel","update":"Update","replace":"Replace","remove":"Remove","back":"Back","selected":"%d selected","dragInfo":"Drag and drop to reorder media files.","uploadFilesTitle":"Upload Files","uploadImagesTitle":"Upload Images","mediaLibraryTitle":"Media Library","insertMediaTitle":"Insert Media","createNewGallery":"Create a new gallery","createNewPlaylist":"Create a new playlist","createNewVideoPlaylist":"Create a new video playlist","returnToLibrary":"\u2190 Return to library","allMediaItems":"All media items","allDates":"All dates","noItemsFound":"No items found.","insertIntoPost":"Insert into post","unattached":"Unattached","trash":"Trash","uploadedToThisPost":"Uploaded to this post","warnDelete":"You are about to permanently delete this item.\nThis will remove it from your site.\n 'Cancel' to stop, 'OK' to delete.","warnBulkDelete":"You are about to permanently delete these items.\nThis will remove them from your site.\n 'Cancel' to stop, 'OK' to delete.","warnBulkTrash":"You are about to trash these items.\n  'Cancel' to stop, 'OK' to delete.","bulkSelect":"Bulk Select","cancelSelection":"Cancel Selection","trashSelected":"Trash Selected","untrashSelected":"Untrash Selected","deleteSelected":"Delete Selected","deletePermanently":"Delete Permanently","apply":"Apply","filterByDate":"Filter by date","filterByType":"Filter by type","searchMediaLabel":"Search Media","searchMediaPlaceholder":"Search media items...","noMedia":"No media files found.","attachmentDetails":"Attachment Details","insertFromUrlTitle":"Insert from URL","setFeaturedImageTitle":"Featured Image","setFeaturedImage":"Set featured image","createGalleryTitle":"Create Gallery","editGalleryTitle":"Edit Gallery","cancelGalleryTitle":"\u2190 Cancel Gallery","insertGallery":"Insert gallery","updateGallery":"Update gallery","addToGallery":"Add to gallery","addToGalleryTitle":"Add to Gallery","reverseOrder":"Reverse order","imageDetailsTitle":"Image Details","imageReplaceTitle":"Replace Image","imageDetailsCancel":"Cancel Edit","editImage":"Edit Image","chooseImage":"Choose Image","selectAndCrop":"Select and Crop","skipCropping":"Skip Cropping","cropImage":"Crop Image","cropYourImage":"Crop your image","cropping":"Cropping\u2026","suggestedDimensions":"Suggested image dimensions:","cropError":"There has been an error cropping your image.","audioDetailsTitle":"Audio Details","audioReplaceTitle":"Replace Audio","audioAddSourceTitle":"Add Audio Source","audioDetailsCancel":"Cancel Edit","videoDetailsTitle":"Video Details","videoReplaceTitle":"Replace Video","videoAddSourceTitle":"Add Video Source","videoDetailsCancel":"Cancel Edit","videoSelectPosterImageTitle":"Select Poster Image","videoAddTrackTitle":"Add Subtitles","playlistDragInfo":"Drag and drop to reorder tracks.","createPlaylistTitle":"Create Audio Playlist","editPlaylistTitle":"Edit Audio Playlist","cancelPlaylistTitle":"\u2190 Cancel Audio Playlist","insertPlaylist":"Insert audio playlist","updatePlaylist":"Update audio playlist","addToPlaylist":"Add to audio playlist","addToPlaylistTitle":"Add to Audio Playlist","videoPlaylistDragInfo":"Drag and drop to reorder videos.","createVideoPlaylistTitle":"Create Video Playlist","editVideoPlaylistTitle":"Edit Video Playlist","cancelVideoPlaylistTitle":"\u2190 Cancel Video Playlist","insertVideoPlaylist":"Insert video playlist","updateVideoPlaylist":"Update video playlist","addToVideoPlaylist":"Add to video playlist","addToVideoPlaylistTitle":"Add to Video Playlist","settings":{"tabs":[],"tabUrl":"http:\/\/src.wordpress-develop.dev\/wp-admin\/media-upload.php?chromeless=1","mimeTypes":{"image":"Images","audio":"Audio","video":"Video"},"captions":true,"nonce":{"sendToEditor":"9585d11de6"},"post":{"id":0},"defaultProps":{"link":"none","align":"","size":""},"attachmentCounts":{"audio":1,"video":1},"embedExts":["mp3","ogg","wma","m4a","wav","mp4","m4v","webm","ogv","wmv","flv"],"embedMimes":{"mp3":"audio\/mpeg","ogg":"audio\/ogg","wma":"audio\/x-ms-wma","m4a":"audio\/mpeg","wav":"audio\/wav","mp4":"video\/mp4","m4v":"video\/mp4","webm":"video\/webm","ogv":"video\/ogg","wmv":"video\/x-ms-wmv","flv":"video\/x-flv"},"contentWidth":525,"months":[{"year":"2017","month":"4","text":"April 2017"}],"mediaTrash":0}};
     49        </script>
     50        <script src="../../src/wp-includes/js/media-views.js"></script>
     51        <script src="../../src/wp-includes/js/media-editor.js"></script>
     52        <script src="../../src/wp-includes/js/media-audiovideo.js"></script>
     53        <script src="../../src/wp-includes/js/mce-view.js"></script>
    2754
    2855        <!-- QUnit -->
     
    6592        <script src="../../src/wp-admin/js/word-count.js"></script>
    6693
     94        <script src="../../src/wp-admin/js/widgets/media-widgets.js"></script>
     95        <script>
     96            wp.mediaWidgets.init();
     97        </script>
     98        <script src="../../src/wp-admin/js/widgets/media-image-widget.js"></script>
     99        <script>
     100            wp.mediaWidgets.modelConstructors[ "media_image" ].prototype.schema = {"attachment_id":{"type":"integer","default":0,"minimum":0,"media_prop":"id"},"url":{"type":"string","default":"","format":"uri"},"title":{"type":"string","default":"","should_preview_update":false},"size":{"type":"string","default":"medium","enum":["thumbnail","medium","medium_large","large","twentyseventeen-featured-image","twentyseventeen-thumbnail-avatar","full","custom"]},"width":{"type":"integer","default":0,"minimum":0},"height":{"type":"integer","default":0,"minimum":0},"caption":{"type":"string","default":"","should_preview_update":false},"alt":{"type":"string","default":""},"link_type":{"type":"string","default":"none","enum":["none","file","post","custom"],"media_prop":"link","should_preview_update":false},"link_url":{"type":"string","default":"","format":"uri","media_prop":"linkUrl","should_preview_update":false},"image_classes":{"type":"string","default":"","media_prop":"extraClasses","should_preview_update":false},"link_classes":{"type":"string","default":"","media_prop":"linkClassName","should_preview_update":false},"link_rel":{"type":"string","default":"","media_prop":"linkRel","should_preview_update":false},"link_target_blank":{"type":"boolean","default":false,"media_prop":"linkTargetBlank","should_preview_update":false},"image_title":{"type":"string","default":"","media_prop":"title","should_preview_update":false}};
     101
     102            wp.mediaWidgets.controlConstructors[ "media_image" ].prototype.mime_type = "image";
     103            _.extend( wp.mediaWidgets.controlConstructors[ "media_image" ].prototype.l10n, {"no_media_selected":"No image selected","select_media":"Select Image","change_media":"Change Image","edit_media":"Edit Image","add_to_widget":"Add to Widget","missing_attachment":"We can&#8217;t find that image. Check your <a href=\"http:\/\/src.wordpress-develop.dev\/wp-admin\/upload.php\">media library<\/a> and make sure it wasn&#8217;t deleted.","media_library_state_multi":{"0":"Image Widget (%d)","1":"Image Widget (%d)","singular":"Image Widget (%d)","plural":"Image Widget (%d)","context":null,"domain":null},"media_library_state_single":"Image Widget"} );
     104        </script>
     105        <script src="../../src/wp-admin/js/widgets/media-video-widget.js"></script>
     106        <script>
     107            wp.mediaWidgets.modelConstructors[ "media_video" ].prototype.schema = {"attachment_id":{"type":"integer","default":0,"minimum":0,"media_prop":"id"},"url":{"type":"string","default":"","format":"uri"},"title":{"type":"string","default":""},"preload":{"type":"string","default":"metadata","enum":["none","auto","metadata"]},"loop":{"type":"boolean","default":false},"content":{"type":"string","default":""},"mp4":{"type":"string","default":"","format":"uri"},"m4v":{"type":"string","default":"","format":"uri"},"webm":{"type":"string","default":"","format":"uri"},"ogv":{"type":"string","default":"","format":"uri"},"wmv":{"type":"string","default":"","format":"uri"},"flv":{"type":"string","default":"","format":"uri"}};
     108
     109            wp.mediaWidgets.controlConstructors[ "media_video" ].prototype.mime_type = "video";
     110            _.extend( wp.mediaWidgets.controlConstructors[ "media_video" ].prototype.l10n, {"no_media_selected":"No video selected","select_media":"Select Video","change_media":"Change Video","edit_media":"Edit Video","add_to_widget":"Add to Widget","missing_attachment":"We can&#8217;t find that video. Check your <a href=\"http:\/\/src.wordpress-develop.dev\/wp-admin\/upload.php\">media library<\/a> and make sure it wasn&#8217;t deleted.","media_library_state_multi":{"0":"Video Widget (%d)","1":"Video Widget (%d)","singular":"Video Widget (%d)","plural":"Video Widget (%d)","context":null,"domain":null},"media_library_state_single":"Video Widget"} );
     111        </script>
     112        <script src="../../src/wp-admin/js/widgets/media-audio-widget.js"></script>
     113        <script>
     114            wp.mediaWidgets.modelConstructors[ "media_audio" ].prototype.schema = {"attachment_id":{"type":"integer","default":0,"minimum":0,"media_prop":"id"},"url":{"type":"string","default":"","format":"uri"},"title":{"type":"string","default":""},"preload":{"type":"string","default":"none","enum":["none","auto","metadata"]},"loop":{"type":"boolean","default":false},"mp3":{"type":"string","default":"","format":"uri"},"ogg":{"type":"string","default":"","format":"uri"},"wma":{"type":"string","default":"","format":"uri"},"m4a":{"type":"string","default":"","format":"uri"},"wav":{"type":"string","default":"","format":"uri"}};
     115
     116            wp.mediaWidgets.controlConstructors[ "media_audio" ].prototype.mime_type = "audio";
     117            _.extend( wp.mediaWidgets.controlConstructors[ "media_audio" ].prototype.l10n, {"no_media_selected":"No audio selected","select_media":"Select File","change_media":"Change Audio","edit_media":"Edit Audio","add_to_widget":"Add to Widget","missing_attachment":"We can&#8217;t find that audio file. Check your <a href=\"http:\/\/src.wordpress-develop.dev\/wp-admin\/upload.php\">media library<\/a> and make sure it wasn&#8217;t deleted.","media_library_state_multi":{"0":"Audio Widget (%d)","1":"Audio Widget (%d)","singular":"Audio Widget (%d)","plural":"Audio Widget (%d)","context":null,"domain":null},"media_library_state_single":"Audio Widget"} );
     118        </script>
     119
    67120        <!-- Unit tests -->
    68121        <script src="wp-admin/js/password-strength-meter.js"></script>
     
    77130        <script src="wp-admin/js/word-count.js"></script>
    78131        <script src="wp-admin/js/nav-menu.js"></script>
     132        <script src="wp-admin/js/widgets/test-media-widgets.js"></script>
     133        <script src="wp-admin/js/widgets/test-media-image-widget.js"></script>
     134        <script src="wp-admin/js/widgets/test-media-video-widget.js"></script>
    79135
    80136        <!-- Customizer templates for sections -->
     
    500556                </div><!-- #available-widgets -->
    501557            </div><!-- #widgets-left -->
     558           
     559            <script type="text/html" id="tmpl-widget-media-media_image-control">
     560            <# var elementIdPrefix = 'el' + String( Math.random() ) + '_' #>
     561            <p>
     562                <label for="{{ elementIdPrefix }}title">Title:</label>
     563                <input id="{{ elementIdPrefix }}title" type="text" class="widefat title">
     564            </p>
     565            <div class="media-widget-preview">
     566                <div class="attachment-media-view">
     567                    <div class="placeholder">No image selected</div>
     568                </div>
     569            </div>
     570            <p class="media-widget-buttons">
     571                <button type="button" class="button edit-media selected">
     572                    Edit Image              </button>
     573                <button type="button" class="button change-media select-media selected">
     574                    Replace Image               </button>
     575                <button type="button" class="button select-media not-selected">
     576                    Add Image               </button>
     577            </p>
     578        </script>
     579                <script type="text/html" id="tmpl-wp-media-widget-image-preview">
     580            <#
     581            var describedById = 'describedBy-' + String( Math.random() );
     582            #>
     583            <# if ( data.error && 'missing_attachment' === data.error ) { #>
     584                <div class="notice notice-error notice-alt notice-missing-attachment">
     585                    <p>We can&#8217;t find that image. Check your <a href="http://src.wordpress-develop.dev/wp-admin/upload.php">media library</a> and make sure it wasn&#8217;t deleted.</p>
     586                </div>
     587            <# } else if ( data.error ) { #>
     588                <div class="notice notice-error notice-alt">
     589                    <p>Unable to preview media due to an unknown error.</p>
     590                </div>
     591            <# } else if ( data.url ) { #>
     592                <img class="attachment-thumb" src="{{ data.url }}" draggable="false" alt="{{ data.alt }}" <# if ( ! data.alt && data.currentFilename ) { #> aria-describedby="{{ describedById }}" <# } #> />
     593                <# if ( ! data.alt && data.currentFilename ) { #>
     594                    <p class="hidden" id="{{ describedById }}">Current image: {{ data.currentFilename }}</p>
     595                <# } #>
     596            <# } #>
     597        </script>
     598                <script type="text/html" id="tmpl-widget-media-media_video-control">
     599            <# var elementIdPrefix = 'el' + String( Math.random() ) + '_' #>
     600            <p>
     601                <label for="{{ elementIdPrefix }}title">Title:</label>
     602                <input id="{{ elementIdPrefix }}title" type="text" class="widefat title">
     603            </p>
     604            <div class="media-widget-preview">
     605                <div class="attachment-media-view">
     606                    <div class="placeholder">No video selected</div>
     607                </div>
     608            </div>
     609            <p class="media-widget-buttons">
     610                <button type="button" class="button edit-media selected">
     611                    Edit Video              </button>
     612                <button type="button" class="button change-media select-media selected">
     613                    Replace Video               </button>
     614                <button type="button" class="button select-media not-selected">
     615                    Add Video               </button>
     616            </p>
     617        </script>
     618                <script type="text/html" id="tmpl-wp-media-widget-video-preview">
     619            <# if ( data.error && 'missing_attachment' === data.error ) { #>
     620                <div class="notice notice-error notice-alt notice-missing-attachment">
     621                    <p>We can&#8217;t find that video. Check your <a href="http://src.wordpress-develop.dev/wp-admin/upload.php">media library</a> and make sure it wasn&#8217;t deleted.</p>
     622                </div>
     623            <# } else if ( data.error && 'unsupported_file_type' === data.error ) { #>
     624                <div class="notice notice-error notice-alt notice-missing-attachment">
     625                    <p>Sorry, we can&#8217;t display the video file type selected. Please select a supported video file (<code>.mp4</code>, <code>.m4v</code>, <code>.webm</code>, <code>.ogv</code>, <code>.wmv</code>, <code>.flv</code>) or stream (YouTube or Vimeo) instead.</p>
     626                </div>
     627            <# } else if ( data.error ) { #>
     628                <div class="notice notice-error notice-alt">
     629                    <p>Unable to preview media due to an unknown error.</p>
     630                </div>
     631            <# } else if ( data.is_hosted_embed && data.model.poster ) { #>
     632                <a href="{{ data.model.src }}" target="_blank" class="media-widget-video-link">
     633                    <img src="{{ data.model.poster }}" />
     634                </a>
     635            <# } else if ( data.is_hosted_embed ) { #>
     636                <a href="{{ data.model.src }}" target="_blank" class="media-widget-video-link no-poster">
     637                    <span class="dashicons dashicons-format-video"></span>
     638                </a>
     639            <# } else if ( data.model.src ) { #>
     640                <#  var w_rule = '', classes = [],
     641        w, h, settings = wp.media.view.settings,
     642        isYouTube = isVimeo = false;
     643
     644    if ( ! _.isEmpty( data.model.src ) ) {
     645        isYouTube = data.model.src.match(/youtube|youtu\.be/);
     646        isVimeo = -1 !== data.model.src.indexOf('vimeo');
     647    }
     648
     649    if ( settings.contentWidth && data.model.width >= settings.contentWidth ) {
     650        w = settings.contentWidth;
     651    } else {
     652        w = data.model.width;
     653    }
     654
     655    if ( w !== data.model.width ) {
     656        h = Math.ceil( ( data.model.height * w ) / data.model.width );
     657    } else {
     658        h = data.model.height;
     659    }
     660
     661    if ( w ) {
     662        w_rule = 'width: ' + w + 'px; ';
     663    }
     664
     665    if ( isYouTube ) {
     666        classes.push( 'youtube-video' );
     667    }
     668
     669    if ( isVimeo ) {
     670        classes.push( 'vimeo-video' );
     671    }
     672
     673#>
     674<div style="{{ w_rule }}" class="wp-video">
     675<video controls
     676    class="wp-video-shortcode {{ classes.join( ' ' ) }}"
     677    <# if ( w ) { #>width="{{ w }}"<# } #>
     678    <# if ( h ) { #>height="{{ h }}"<# } #>
     679    <#
     680        if ( ! _.isUndefined( data.model.poster ) && data.model.poster ) {
     681            #> poster="{{ data.model.poster }}"<#
     682        } #>
     683        preload="{{ _.isUndefined( data.model.preload ) ? 'metadata' : data.model.preload }}"<#
     684     if ( ! _.isUndefined( data.model.autoplay ) && data.model.autoplay ) {
     685        #> autoplay<#
     686    }
     687     if ( ! _.isUndefined( data.model.loop ) && data.model.loop ) {
     688        #> loop<#
     689    }
     690    #>
     691>
     692    <# if ( ! _.isEmpty( data.model.src ) ) {
     693        if ( isYouTube ) { #>
     694        <source src="{{ data.model.src }}" type="video/youtube" />
     695        <# } else if ( isVimeo ) { #>
     696        <source src="{{ data.model.src }}" type="video/vimeo" />
     697        <# } else { #>
     698        <source src="{{ data.model.src }}" type="{{ settings.embedMimes[ data.model.src.split('.').pop() ] }}" />
     699        <# }
     700    } #>
     701
     702    <# if ( data.model.mp4 ) { #>
     703    <source src="{{ data.model.mp4 }}" type="{{ settings.embedMimes[ 'mp4' ] }}" />
     704    <# } #>
     705    <# if ( data.model.m4v ) { #>
     706    <source src="{{ data.model.m4v }}" type="{{ settings.embedMimes[ 'm4v' ] }}" />
     707    <# } #>
     708    <# if ( data.model.webm ) { #>
     709    <source src="{{ data.model.webm }}" type="{{ settings.embedMimes[ 'webm' ] }}" />
     710    <# } #>
     711    <# if ( data.model.ogv ) { #>
     712    <source src="{{ data.model.ogv }}" type="{{ settings.embedMimes[ 'ogv' ] }}" />
     713    <# } #>
     714    <# if ( data.model.wmv ) { #>
     715    <source src="{{ data.model.wmv }}" type="{{ settings.embedMimes[ 'wmv' ] }}" />
     716    <# } #>
     717    <# if ( data.model.flv ) { #>
     718    <source src="{{ data.model.flv }}" type="{{ settings.embedMimes[ 'flv' ] }}" />
     719    <# } #>
     720        {{{ data.model.content }}}
     721</video>
     722</div>
     723            <# } #>
     724        </script>
     725            <script type="text/html" id="tmpl-widget-media-media_audio-control">
     726                <# var elementIdPrefix = 'el' + String( Math.random() ) + '_' #>
     727                <p>
     728                    <label for="{{ elementIdPrefix }}title">Title:</label>
     729                    <input id="{{ elementIdPrefix }}title" type="text" class="widefat title">
     730                </p>
     731                <div class="media-widget-preview">
     732                    <div class="attachment-media-view">
     733                        <div class="placeholder">No audio selected</div>
     734                    </div>
     735                </div>
     736                <p class="media-widget-buttons">
     737                    <button type="button" class="button edit-media selected">
     738                        Edit Audio              </button>
     739                    <button type="button" class="button change-media select-media selected">
     740                        Replace Audio               </button>
     741                    <button type="button" class="button select-media not-selected">
     742                        Add File                </button>
     743                </p>
     744            </script>
     745            <script type="text/html" id="tmpl-wp-media-widget-audio-preview">
     746                <# if ( data.error && 'missing_attachment' === data.error ) { #>
     747                    <div class="notice notice-error notice-alt notice-missing-attachment">
     748                        <p>We can&#8217;t find that audio file. Check your <a href="http://src.wordpress-develop.dev/wp-admin/upload.php">media library</a> and make sure it wasn&#8217;t deleted.</p>
     749                    </div>
     750                <# } else if ( data.error ) { #>
     751                    <div class="notice notice-error notice-alt">
     752                        <p>Unable to preview media due to an unknown error.</p>
     753                    </div>
     754                <# } else if ( data.model && data.model.src ) { #>
     755                    <audio style="visibility: hidden"
     756                        controls
     757                        class="wp-audio-shortcode"
     758                        width="{{ _.isUndefined( data.model.width ) ? 400 : data.model.width }}"
     759                        preload="{{ _.isUndefined( data.model.preload ) ? 'none' : data.model.preload }}"
     760                        <#
     761                        if ( ! _.isUndefined( data.model.autoplay ) && data.model.autoplay ) {
     762                            #> autoplay<#
     763                        }
     764                        if ( ! _.isUndefined( data.model.loop ) && data.model.loop ) {
     765                            #> loop<#
     766                        }
     767                        #>
     768                    >
     769                    <# if ( ! _.isEmpty( data.model.src ) ) { #>
     770                        <source src="{{ data.model.src }}" type="{{ wp.media.view.settings.embedMimes[ data.model.src.split('.').pop() ] }}" />
     771                    <# } #>
     772
     773                    <# if ( ! _.isEmpty( data.model.mp3 ) ) { #>
     774                        <source src="{{ data.model.mp3 }}" type="{{ wp.media.view.settings.embedMimes[ 'mp3' ] }}" />
     775                    <# } #>
     776                    <# if ( ! _.isEmpty( data.model.ogg ) ) { #>
     777                        <source src="{{ data.model.ogg }}" type="{{ wp.media.view.settings.embedMimes[ 'ogg' ] }}" />
     778                    <# } #>
     779                    <# if ( ! _.isEmpty( data.model.wma ) ) { #>
     780                        <source src="{{ data.model.wma }}" type="{{ wp.media.view.settings.embedMimes[ 'wma' ] }}" />
     781                    <# } #>
     782                    <# if ( ! _.isEmpty( data.model.m4a ) ) { #>
     783                        <source src="{{ data.model.m4a }}" type="{{ wp.media.view.settings.embedMimes[ 'm4a' ] }}" />
     784                    <# } #>
     785                    <# if ( ! _.isEmpty( data.model.wav ) ) { #>
     786                        <source src="{{ data.model.wav }}" type="{{ wp.media.view.settings.embedMimes[ 'wav' ] }}" />
     787                    <# } #>
     788                    </audio>
     789                <# } #>
     790            </script>
     791            <script type="text/html" id="tmpl-media-frame">
     792        <div class="media-frame-menu"></div>
     793        <div class="media-frame-title"></div>
     794        <div class="media-frame-router"></div>
     795        <div class="media-frame-content"></div>
     796        <div class="media-frame-toolbar"></div>
     797        <div class="media-frame-uploader"></div>
     798    </script>
     799
     800    <script type="text/html" id="tmpl-media-modal">
     801        <div class="media-modal wp-core-ui">
     802            <button type="button" class="media-modal-close"><span class="media-modal-icon"><span class="screen-reader-text">Close media panel</span></span></button>
     803            <div class="media-modal-content"></div>
     804        </div>
     805        <div class="media-modal-backdrop"></div>
     806    </script>
     807
     808    <script type="text/html" id="tmpl-uploader-window">
     809        <div class="uploader-window-content">
     810            <h1>Drop files to upload</h1>
     811        </div>
     812    </script>
     813
     814    <script type="text/html" id="tmpl-uploader-editor">
     815        <div class="uploader-editor-content">
     816            <div class="uploader-editor-title">Drop files to upload</div>
     817        </div>
     818    </script>
     819
     820    <script type="text/html" id="tmpl-uploader-inline">
     821        <# var messageClass = data.message ? 'has-upload-message' : 'no-upload-message'; #>
     822        <# if ( data.canClose ) { #>
     823        <button class="close dashicons dashicons-no"><span class="screen-reader-text">Close uploader</span></button>
     824        <# } #>
     825        <div class="uploader-inline-content {{ messageClass }}">
     826        <# if ( data.message ) { #>
     827            <h2 class="upload-message">{{ data.message }}</h2>
     828        <# } #>
     829                    <div class="upload-ui">
     830                <h2 class="upload-instructions drop-instructions">Drop files anywhere to upload</h2>
     831                <p class="upload-instructions drop-instructions">or</p>
     832                <button type="button" class="browser button button-hero">Select Files</button>
     833            </div>
     834
     835            <div class="upload-inline-status"></div>
     836
     837            <div class="post-upload-ui">
     838
     839                <p class="max-upload-size">Maximum upload file size: 2 MB.</p>
     840
     841                <# if ( data.suggestedWidth && data.suggestedHeight ) { #>
     842                    <p class="suggested-dimensions">
     843                        Suggested image dimensions: {{data.suggestedWidth}} &times; {{data.suggestedHeight}}
     844                    </p>
     845                <# } #>
     846
     847                            </div>
     848                </div>
     849    </script>
     850
     851    <script type="text/html" id="tmpl-media-library-view-switcher">
     852        <a href="?mode=list" class="view-list">
     853            <span class="screen-reader-text">List View</span>
     854        </a>
     855        <a href="?mode=grid" class="view-grid current">
     856            <span class="screen-reader-text">Grid View</span>
     857        </a>
     858    </script>
     859
     860    <script type="text/html" id="tmpl-uploader-status">
     861        <h2>Uploading</h2>
     862        <button type="button" class="button-link upload-dismiss-errors"><span class="screen-reader-text">Dismiss Errors</span></button>
     863
     864        <div class="media-progress-bar"><div></div></div>
     865        <div class="upload-details">
     866            <span class="upload-count">
     867                <span class="upload-index"></span> / <span class="upload-total"></span>
     868            </span>
     869            <span class="upload-detail-separator">&ndash;</span>
     870            <span class="upload-filename"></span>
     871        </div>
     872        <div class="upload-errors"></div>
     873    </script>
     874
     875    <script type="text/html" id="tmpl-uploader-status-error">
     876        <span class="upload-error-filename">{{{ data.filename }}}</span>
     877        <span class="upload-error-message">{{ data.message }}</span>
     878    </script>
     879
     880    <script type="text/html" id="tmpl-edit-attachment-frame">
     881        <div class="edit-media-header">
     882            <button class="left dashicons <# if ( ! data.hasPrevious ) { #> disabled <# } #>"><span class="screen-reader-text">Edit previous media item</span></button>
     883            <button class="right dashicons <# if ( ! data.hasNext ) { #> disabled <# } #>"><span class="screen-reader-text">Edit next media item</span></button>
     884        </div>
     885        <div class="media-frame-title"></div>
     886        <div class="media-frame-content"></div>
     887    </script>
     888
     889    <script type="text/html" id="tmpl-attachment-details-two-column">
     890        <div class="attachment-media-view {{ data.orientation }}">
     891            <div class="thumbnail thumbnail-{{ data.type }}">
     892                <# if ( data.uploading ) { #>
     893                    <div class="media-progress-bar"><div></div></div>
     894                <# } else if ( data.sizes && data.sizes.large ) { #>
     895                    <img class="details-image" src="{{ data.sizes.large.url }}" draggable="false" alt="" />
     896                <# } else if ( data.sizes && data.sizes.full ) { #>
     897                    <img class="details-image" src="{{ data.sizes.full.url }}" draggable="false" alt="" />
     898                <# } else if ( -1 === jQuery.inArray( data.type, [ 'audio', 'video' ] ) ) { #>
     899                    <img class="details-image icon" src="{{ data.icon }}" draggable="false" alt="" />
     900                <# } #>
     901
     902                <# if ( 'audio' === data.type ) { #>
     903                <div class="wp-media-wrapper">
     904                    <audio style="visibility: hidden" controls class="wp-audio-shortcode" width="100%" preload="none">
     905                        <source type="{{ data.mime }}" src="{{ data.url }}"/>
     906                    </audio>
     907                </div>
     908                <# } else if ( 'video' === data.type ) {
     909                    var w_rule = '';
     910                    if ( data.width ) {
     911                        w_rule = 'width: ' + data.width + 'px;';
     912                    } else if ( wp.media.view.settings.contentWidth ) {
     913                        w_rule = 'width: ' + wp.media.view.settings.contentWidth + 'px;';
     914                    }
     915                #>
     916                <div style="{{ w_rule }}" class="wp-media-wrapper wp-video">
     917                    <video controls="controls" class="wp-video-shortcode" preload="metadata"
     918                        <# if ( data.width ) { #>width="{{ data.width }}"<# } #>
     919                        <# if ( data.height ) { #>height="{{ data.height }}"<# } #>
     920                        <# if ( data.image && data.image.src !== data.icon ) { #>poster="{{ data.image.src }}"<# } #>>
     921                        <source type="{{ data.mime }}" src="{{ data.url }}"/>
     922                    </video>
     923                </div>
     924                <# } #>
     925
     926                <div class="attachment-actions">
     927                    <# if ( 'image' === data.type && ! data.uploading && data.sizes && data.can.save ) { #>
     928                    <button type="button" class="button edit-attachment">Edit Image</button>
     929                    <# } else if ( 'pdf' === data.subtype && data.sizes ) { #>
     930                    Document Preview                    <# } #>
     931                </div>
     932            </div>
     933        </div>
     934        <div class="attachment-info">
     935            <span class="settings-save-status">
     936                <span class="spinner"></span>
     937                <span class="saved">Saved.</span>
     938            </span>
     939            <div class="details">
     940                <div class="filename"><strong>File name:</strong> {{ data.filename }}</div>
     941                <div class="filename"><strong>File type:</strong> {{ data.mime }}</div>
     942                <div class="uploaded"><strong>Uploaded on:</strong> {{ data.dateFormatted }}</div>
     943
     944                <div class="file-size"><strong>File size:</strong> {{ data.filesizeHumanReadable }}</div>
     945                <# if ( 'image' === data.type && ! data.uploading ) { #>
     946                    <# if ( data.width && data.height ) { #>
     947                        <div class="dimensions"><strong>Dimensions:</strong> {{ data.width }} &times; {{ data.height }}</div>
     948                    <# } #>
     949                <# } #>
     950
     951                <# if ( data.fileLength ) { #>
     952                    <div class="file-length"><strong>Length:</strong> {{ data.fileLength }}</div>
     953                <# } #>
     954
     955                <# if ( 'audio' === data.type && data.meta.bitrate ) { #>
     956                    <div class="bitrate">
     957                        <strong>Bitrate:</strong> {{ Math.round( data.meta.bitrate / 1000 ) }}kb/s
     958                        <# if ( data.meta.bitrate_mode ) { #>
     959                        {{ ' ' + data.meta.bitrate_mode.toUpperCase() }}
     960                        <# } #>
     961                    </div>
     962                <# } #>
     963
     964                <div class="compat-meta">
     965                    <# if ( data.compat && data.compat.meta ) { #>
     966                        {{{ data.compat.meta }}}
     967                    <# } #>
     968                </div>
     969            </div>
     970
     971            <div class="settings">
     972                <label class="setting" data-setting="url">
     973                    <span class="name">URL</span>
     974                    <input type="text" value="{{ data.url }}" readonly />
     975                </label>
     976                <# var maybeReadOnly = data.can.save || data.allowLocalEdits ? '' : 'readonly'; #>
     977                                <label class="setting" data-setting="title">
     978                    <span class="name">Title</span>
     979                    <input type="text" value="{{ data.title }}" {{ maybeReadOnly }} />
     980                </label>
     981                                <# if ( 'audio' === data.type ) { #>
     982                                <label class="setting" data-setting="artist">
     983                    <span class="name">Artist</span>
     984                    <input type="text" value="{{ data.artist || data.meta.artist || '' }}" />
     985                </label>
     986                                <label class="setting" data-setting="album">
     987                    <span class="name">Album</span>
     988                    <input type="text" value="{{ data.album || data.meta.album || '' }}" />
     989                </label>
     990                                <# } #>
     991                <label class="setting" data-setting="caption">
     992                    <span class="name">Caption</span>
     993                    <textarea {{ maybeReadOnly }}>{{ data.caption }}</textarea>
     994                </label>
     995                <# if ( 'image' === data.type ) { #>
     996                    <label class="setting" data-setting="alt">
     997                        <span class="name">Alt Text</span>
     998                        <input type="text" value="{{ data.alt }}" {{ maybeReadOnly }} />
     999                    </label>
     1000                <# } #>
     1001                <label class="setting" data-setting="description">
     1002                    <span class="name">Description</span>
     1003                    <textarea {{ maybeReadOnly }}>{{ data.description }}</textarea>
     1004                </label>
     1005                <label class="setting">
     1006                    <span class="name">Uploaded By</span>
     1007                    <span class="value">{{ data.authorName }}</span>
     1008                </label>
     1009                <# if ( data.uploadedToTitle ) { #>
     1010                    <label class="setting">
     1011                        <span class="name">Uploaded To</span>
     1012                        <# if ( data.uploadedToLink ) { #>
     1013                            <span class="value"><a href="{{ data.uploadedToLink }}">{{ data.uploadedToTitle }}</a></span>
     1014                        <# } else { #>
     1015                            <span class="value">{{ data.uploadedToTitle }}</span>
     1016                        <# } #>
     1017                    </label>
     1018                <# } #>
     1019                <div class="attachment-compat"></div>
     1020            </div>
     1021
     1022            <div class="actions">
     1023                <a class="view-attachment" href="{{ data.link }}">View attachment page</a>
     1024                <# if ( data.can.save ) { #> |
     1025                    <a href="post.php?post={{ data.id }}&action=edit">Edit more details</a>
     1026                <# } #>
     1027                <# if ( ! data.uploading && data.can.remove ) { #> |
     1028                                            <button type="button" class="button-link delete-attachment">Delete Permanently</button>
     1029                                    <# } #>
     1030            </div>
     1031
     1032        </div>
     1033    </script>
     1034
     1035    <script type="text/html" id="tmpl-attachment">
     1036        <div class="attachment-preview js--select-attachment type-{{ data.type }} subtype-{{ data.subtype }} {{ data.orientation }}">
     1037            <div class="thumbnail">
     1038                <# if ( data.uploading ) { #>
     1039                    <div class="media-progress-bar"><div style="width: {{ data.percent }}%"></div></div>
     1040                <# } else if ( 'image' === data.type && data.sizes ) { #>
     1041                    <div class="centered">
     1042                        <img src="{{ data.size.url }}" draggable="false" alt="" />
     1043                    </div>
     1044                <# } else { #>
     1045                    <div class="centered">
     1046                        <# if ( data.image && data.image.src && data.image.src !== data.icon ) { #>
     1047                            <img src="{{ data.image.src }}" class="thumbnail" draggable="false" alt="" />
     1048                        <# } else if ( data.sizes && data.sizes.medium ) { #>
     1049                            <img src="{{ data.sizes.medium.url }}" class="thumbnail" draggable="false" alt="" />
     1050                        <# } else { #>
     1051                            <img src="{{ data.icon }}" class="icon" draggable="false" alt="" />
     1052                        <# } #>
     1053                    </div>
     1054                    <div class="filename">
     1055                        <div>{{ data.filename }}</div>
     1056                    </div>
     1057                <# } #>
     1058            </div>
     1059            <# if ( data.buttons.close ) { #>
     1060                <button type="button" class="button-link attachment-close media-modal-icon"><span class="screen-reader-text">Remove</span></button>
     1061            <# } #>
     1062        </div>
     1063        <# if ( data.buttons.check ) { #>
     1064            <button type="button" class="check" tabindex="-1"><span class="media-modal-icon"></span><span class="screen-reader-text">Deselect</span></button>
     1065        <# } #>
     1066        <#
     1067        var maybeReadOnly = data.can.save || data.allowLocalEdits ? '' : 'readonly';
     1068        if ( data.describe ) {
     1069            if ( 'image' === data.type ) { #>
     1070                <input type="text" value="{{ data.caption }}" class="describe" data-setting="caption"
     1071                    placeholder="Caption this image&hellip;" {{ maybeReadOnly }} />
     1072            <# } else { #>
     1073                <input type="text" value="{{ data.title }}" class="describe" data-setting="title"
     1074                    <# if ( 'video' === data.type ) { #>
     1075                        placeholder="Describe this video&hellip;"
     1076                    <# } else if ( 'audio' === data.type ) { #>
     1077                        placeholder="Describe this audio file&hellip;"
     1078                    <# } else { #>
     1079                        placeholder="Describe this media file&hellip;"
     1080                    <# } #> {{ maybeReadOnly }} />
     1081            <# }
     1082        } #>
     1083    </script>
     1084
     1085    <script type="text/html" id="tmpl-attachment-details">
     1086        <h2>
     1087            Attachment Details          <span class="settings-save-status">
     1088                <span class="spinner"></span>
     1089                <span class="saved">Saved.</span>
     1090            </span>
     1091        </h2>
     1092        <div class="attachment-info">
     1093            <div class="thumbnail thumbnail-{{ data.type }}">
     1094                <# if ( data.uploading ) { #>
     1095                    <div class="media-progress-bar"><div></div></div>
     1096                <# } else if ( 'image' === data.type && data.sizes ) { #>
     1097                    <img src="{{ data.size.url }}" draggable="false" alt="" />
     1098                <# } else { #>
     1099                    <img src="{{ data.icon }}" class="icon" draggable="false" alt="" />
     1100                <# } #>
     1101            </div>
     1102            <div class="details">
     1103                <div class="filename">{{ data.filename }}</div>
     1104                <div class="uploaded">{{ data.dateFormatted }}</div>
     1105
     1106                <div class="file-size">{{ data.filesizeHumanReadable }}</div>
     1107                <# if ( 'image' === data.type && ! data.uploading ) { #>
     1108                    <# if ( data.width && data.height ) { #>
     1109                        <div class="dimensions">{{ data.width }} &times; {{ data.height }}</div>
     1110                    <# } #>
     1111
     1112                    <# if ( data.can.save && data.sizes ) { #>
     1113                        <a class="edit-attachment" href="{{ data.editLink }}&amp;image-editor" target="_blank">Edit Image</a>
     1114                    <# } #>
     1115                <# } #>
     1116
     1117                <# if ( data.fileLength ) { #>
     1118                    <div class="file-length">Length: {{ data.fileLength }}</div>
     1119                <# } #>
     1120
     1121                <# if ( ! data.uploading && data.can.remove ) { #>
     1122                                            <button type="button" class="button-link delete-attachment">Delete Permanently</button>
     1123                                    <# } #>
     1124
     1125                <div class="compat-meta">
     1126                    <# if ( data.compat && data.compat.meta ) { #>
     1127                        {{{ data.compat.meta }}}
     1128                    <# } #>
     1129                </div>
     1130            </div>
     1131        </div>
     1132
     1133        <label class="setting" data-setting="url">
     1134            <span class="name">URL</span>
     1135            <input type="text" value="{{ data.url }}" readonly />
     1136        </label>
     1137        <# var maybeReadOnly = data.can.save || data.allowLocalEdits ? '' : 'readonly'; #>
     1138                <label class="setting" data-setting="title">
     1139            <span class="name">Title</span>
     1140            <input type="text" value="{{ data.title }}" {{ maybeReadOnly }} />
     1141        </label>
     1142                <# if ( 'audio' === data.type ) { #>
     1143                <label class="setting" data-setting="artist">
     1144            <span class="name">Artist</span>
     1145            <input type="text" value="{{ data.artist || data.meta.artist || '' }}" />
     1146        </label>
     1147                <label class="setting" data-setting="album">
     1148            <span class="name">Album</span>
     1149            <input type="text" value="{{ data.album || data.meta.album || '' }}" />
     1150        </label>
     1151                <# } #>
     1152        <label class="setting" data-setting="caption">
     1153            <span class="name">Caption</span>
     1154            <textarea {{ maybeReadOnly }}>{{ data.caption }}</textarea>
     1155        </label>
     1156        <# if ( 'image' === data.type ) { #>
     1157            <label class="setting" data-setting="alt">
     1158                <span class="name">Alt Text</span>
     1159                <input type="text" value="{{ data.alt }}" {{ maybeReadOnly }} />
     1160            </label>
     1161        <# } #>
     1162        <label class="setting" data-setting="description">
     1163            <span class="name">Description</span>
     1164            <textarea {{ maybeReadOnly }}>{{ data.description }}</textarea>
     1165        </label>
     1166    </script>
     1167
     1168    <script type="text/html" id="tmpl-media-selection">
     1169        <div class="selection-info">
     1170            <span class="count"></span>
     1171            <# if ( data.editable ) { #>
     1172                <button type="button" class="button-link edit-selection">Edit Selection</button>
     1173            <# } #>
     1174            <# if ( data.clearable ) { #>
     1175                <button type="button" class="button-link clear-selection">Clear</button>
     1176            <# } #>
     1177        </div>
     1178        <div class="selection-view"></div>
     1179    </script>
     1180
     1181    <script type="text/html" id="tmpl-attachment-display-settings">
     1182        <h2>Attachment Display Settings</h2>
     1183
     1184        <# if ( 'image' === data.type ) { #>
     1185            <label class="setting">
     1186                <span>Alignment</span>
     1187                <select class="alignment"
     1188                    data-setting="align"
     1189                    <# if ( data.userSettings ) { #>
     1190                        data-user-setting="align"
     1191                    <# } #>>
     1192
     1193                    <option value="left">
     1194                        Left                    </option>
     1195                    <option value="center">
     1196                        Center                  </option>
     1197                    <option value="right">
     1198                        Right                   </option>
     1199                    <option value="none" selected>
     1200                        None                    </option>
     1201                </select>
     1202            </label>
     1203        <# } #>
     1204
     1205        <div class="setting">
     1206            <label>
     1207                <# if ( data.model.canEmbed ) { #>
     1208                    <span>Embed or Link</span>
     1209                <# } else { #>
     1210                    <span>Link To</span>
     1211                <# } #>
     1212
     1213                <select class="link-to"
     1214                    data-setting="link"
     1215                    <# if ( data.userSettings && ! data.model.canEmbed ) { #>
     1216                        data-user-setting="urlbutton"
     1217                    <# } #>>
     1218
     1219                <# if ( data.model.canEmbed ) { #>
     1220                    <option value="embed" selected>
     1221                        Embed Media Player                  </option>
     1222                    <option value="file">
     1223                <# } else { #>
     1224                    <option value="none" selected>
     1225                        None                    </option>
     1226                    <option value="file">
     1227                <# } #>
     1228                    <# if ( data.model.canEmbed ) { #>
     1229                        Link to Media File                  <# } else { #>
     1230                        Media File                  <# } #>
     1231                    </option>
     1232                    <option value="post">
     1233                    <# if ( data.model.canEmbed ) { #>
     1234                        Link to Attachment Page                 <# } else { #>
     1235                        Attachment Page                 <# } #>
     1236                    </option>
     1237                <# if ( 'image' === data.type ) { #>
     1238                    <option value="custom">
     1239                        Custom URL                  </option>
     1240                <# } #>
     1241                </select>
     1242            </label>
     1243            <input type="text" class="link-to-custom" data-setting="linkUrl" />
     1244        </div>
     1245
     1246        <# if ( 'undefined' !== typeof data.sizes ) { #>
     1247            <label class="setting">
     1248                <span>Size</span>
     1249                <select class="size" name="size"
     1250                    data-setting="size"
     1251                    <# if ( data.userSettings ) { #>
     1252                        data-user-setting="imgsize"
     1253                    <# } #>>
     1254                                            <#
     1255                        var size = data.sizes['thumbnail'];
     1256                        if ( size ) { #>
     1257                            <option value="thumbnail" >
     1258                                Thumbnail &ndash; {{ size.width }} &times; {{ size.height }}
     1259                            </option>
     1260                        <# } #>
     1261                                            <#
     1262                        var size = data.sizes['medium'];
     1263                        if ( size ) { #>
     1264                            <option value="medium" >
     1265                                Medium &ndash; {{ size.width }} &times; {{ size.height }}
     1266                            </option>
     1267                        <# } #>
     1268                                            <#
     1269                        var size = data.sizes['large'];
     1270                        if ( size ) { #>
     1271                            <option value="large" >
     1272                                Large &ndash; {{ size.width }} &times; {{ size.height }}
     1273                            </option>
     1274                        <# } #>
     1275                                            <#
     1276                        var size = data.sizes['full'];
     1277                        if ( size ) { #>
     1278                            <option value="full"  selected='selected'>
     1279                                Full Size &ndash; {{ size.width }} &times; {{ size.height }}
     1280                            </option>
     1281                        <# } #>
     1282                                    </select>
     1283            </label>
     1284        <# } #>
     1285    </script>
     1286
     1287    <script type="text/html" id="tmpl-gallery-settings">
     1288        <h2>Gallery Settings</h2>
     1289
     1290        <label class="setting">
     1291            <span>Link To</span>
     1292            <select class="link-to"
     1293                data-setting="link"
     1294                <# if ( data.userSettings ) { #>
     1295                    data-user-setting="urlbutton"
     1296                <# } #>>
     1297
     1298                <option value="post" <# if ( ! wp.media.galleryDefaults.link || 'post' == wp.media.galleryDefaults.link ) {
     1299                    #>selected="selected"<# }
     1300                #>>
     1301                    Attachment Page             </option>
     1302                <option value="file" <# if ( 'file' == wp.media.galleryDefaults.link ) { #>selected="selected"<# } #>>
     1303                    Media File              </option>
     1304                <option value="none" <# if ( 'none' == wp.media.galleryDefaults.link ) { #>selected="selected"<# } #>>
     1305                    None                </option>
     1306            </select>
     1307        </label>
     1308
     1309        <label class="setting">
     1310            <span>Columns</span>
     1311            <select class="columns" name="columns"
     1312                data-setting="columns">
     1313                                    <option value="1" <#
     1314                        if ( 1 == wp.media.galleryDefaults.columns ) { #>selected="selected"<# }
     1315                    #>>
     1316                        1                   </option>
     1317                                    <option value="2" <#
     1318                        if ( 2 == wp.media.galleryDefaults.columns ) { #>selected="selected"<# }
     1319                    #>>
     1320                        2                   </option>
     1321                                    <option value="3" <#
     1322                        if ( 3 == wp.media.galleryDefaults.columns ) { #>selected="selected"<# }
     1323                    #>>
     1324                        3                   </option>
     1325                                    <option value="4" <#
     1326                        if ( 4 == wp.media.galleryDefaults.columns ) { #>selected="selected"<# }
     1327                    #>>
     1328                        4                   </option>
     1329                                    <option value="5" <#
     1330                        if ( 5 == wp.media.galleryDefaults.columns ) { #>selected="selected"<# }
     1331                    #>>
     1332                        5                   </option>
     1333                                    <option value="6" <#
     1334                        if ( 6 == wp.media.galleryDefaults.columns ) { #>selected="selected"<# }
     1335                    #>>
     1336                        6                   </option>
     1337                                    <option value="7" <#
     1338                        if ( 7 == wp.media.galleryDefaults.columns ) { #>selected="selected"<# }
     1339                    #>>
     1340                        7                   </option>
     1341                                    <option value="8" <#
     1342                        if ( 8 == wp.media.galleryDefaults.columns ) { #>selected="selected"<# }
     1343                    #>>
     1344                        8                   </option>
     1345                                    <option value="9" <#
     1346                        if ( 9 == wp.media.galleryDefaults.columns ) { #>selected="selected"<# }
     1347                    #>>
     1348                        9                   </option>
     1349                            </select>
     1350        </label>
     1351
     1352        <label class="setting">
     1353            <span>Random Order</span>
     1354            <input type="checkbox" data-setting="_orderbyRandom" />
     1355        </label>
     1356
     1357        <label class="setting size">
     1358            <span>Size</span>
     1359            <select class="size" name="size"
     1360                data-setting="size"
     1361                <# if ( data.userSettings ) { #>
     1362                    data-user-setting="imgsize"
     1363                <# } #>
     1364                >
     1365                                    <option value="thumbnail">
     1366                        Thumbnail                   </option>
     1367                                    <option value="medium">
     1368                        Medium                  </option>
     1369                                    <option value="large">
     1370                        Large                   </option>
     1371                                    <option value="full">
     1372                        Full Size                   </option>
     1373                            </select>
     1374        </label>
     1375    </script>
     1376
     1377    <script type="text/html" id="tmpl-playlist-settings">
     1378        <h2>Playlist Settings</h2>
     1379
     1380        <# var emptyModel = _.isEmpty( data.model ),
     1381            isVideo = 'video' === data.controller.get('library').props.get('type'); #>
     1382
     1383        <label class="setting">
     1384            <input type="checkbox" data-setting="tracklist" <# if ( emptyModel ) { #>
     1385                checked="checked"
     1386            <# } #> />
     1387            <# if ( isVideo ) { #>
     1388            <span>Show Video List</span>
     1389            <# } else { #>
     1390            <span>Show Tracklist</span>
     1391            <# } #>
     1392        </label>
     1393
     1394        <# if ( ! isVideo ) { #>
     1395        <label class="setting">
     1396            <input type="checkbox" data-setting="artists" <# if ( emptyModel ) { #>
     1397                checked="checked"
     1398            <# } #> />
     1399            <span>Show Artist Name in Tracklist</span>
     1400        </label>
     1401        <# } #>
     1402
     1403        <label class="setting">
     1404            <input type="checkbox" data-setting="images" <# if ( emptyModel ) { #>
     1405                checked="checked"
     1406            <# } #> />
     1407            <span>Show Images</span>
     1408        </label>
     1409    </script>
     1410
     1411    <script type="text/html" id="tmpl-embed-link-settings">
     1412        <label class="setting link-text">
     1413            <span>Link Text</span>
     1414            <input type="text" class="alignment" data-setting="linkText" />
     1415        </label>
     1416        <div class="embed-container" style="display: none;">
     1417            <div class="embed-preview"></div>
     1418        </div>
     1419    </script>
     1420
     1421    <script type="text/html" id="tmpl-embed-image-settings">
     1422        <div class="thumbnail">
     1423            <img src="{{ data.model.url }}" draggable="false" alt="" />
     1424        </div>
     1425
     1426                    <label class="setting caption">
     1427                <span>Caption</span>
     1428                <textarea data-setting="caption" />
     1429            </label>
     1430
     1431        <label class="setting alt-text">
     1432            <span>Alt Text</span>
     1433            <input type="text" data-setting="alt" />
     1434        </label>
     1435
     1436        <div class="setting align">
     1437            <span>Align</span>
     1438            <div class="button-group button-large" data-setting="align">
     1439                <button class="button" value="left">
     1440                    Left                </button>
     1441                <button class="button" value="center">
     1442                    Center              </button>
     1443                <button class="button" value="right">
     1444                    Right               </button>
     1445                <button class="button active" value="none">
     1446                    None                </button>
     1447            </div>
     1448        </div>
     1449
     1450        <div class="setting link-to">
     1451            <span>Link To</span>
     1452            <div class="button-group button-large" data-setting="link">
     1453                <button class="button" value="file">
     1454                    Image URL               </button>
     1455                <button class="button" value="custom">
     1456                    Custom URL              </button>
     1457                <button class="button active" value="none">
     1458                    None                </button>
     1459            </div>
     1460            <input type="text" class="link-to-custom" data-setting="linkUrl" />
     1461        </div>
     1462    </script>
     1463
     1464    <script type="text/html" id="tmpl-image-details">
     1465        <div class="media-embed">
     1466            <div class="embed-media-settings">
     1467                <div class="column-image">
     1468                    <div class="image">
     1469                        <img src="{{ data.model.url }}" draggable="false" alt="" />
     1470
     1471                        <# if ( data.attachment && window.imageEdit ) { #>
     1472                            <div class="actions">
     1473                                <input type="button" class="edit-attachment button" value="Edit Original" />
     1474                                <input type="button" class="replace-attachment button" value="Replace" />
     1475                            </div>
     1476                        <# } #>
     1477                    </div>
     1478                </div>
     1479                <div class="column-settings">
     1480                                            <label class="setting caption">
     1481                            <span>Caption</span>
     1482                            <textarea data-setting="caption">{{ data.model.caption }}</textarea>
     1483                        </label>
     1484
     1485                    <label class="setting alt-text">
     1486                        <span>Alternative Text</span>
     1487                        <input type="text" data-setting="alt" value="{{ data.model.alt }}" />
     1488                    </label>
     1489
     1490                    <h2>Display Settings</h2>
     1491                    <div class="setting align">
     1492                        <span>Align</span>
     1493                        <div class="button-group button-large" data-setting="align">
     1494                            <button class="button" value="left">
     1495                                Left                            </button>
     1496                            <button class="button" value="center">
     1497                                Center                          </button>
     1498                            <button class="button" value="right">
     1499                                Right                           </button>
     1500                            <button class="button active" value="none">
     1501                                None                            </button>
     1502                        </div>
     1503                    </div>
     1504
     1505                    <# if ( data.attachment ) { #>
     1506                        <# if ( 'undefined' !== typeof data.attachment.sizes ) { #>
     1507                            <label class="setting size">
     1508                                <span>Size</span>
     1509                                <select class="size" name="size"
     1510                                    data-setting="size"
     1511                                    <# if ( data.userSettings ) { #>
     1512                                        data-user-setting="imgsize"
     1513                                    <# } #>>
     1514                                                                            <#
     1515                                        var size = data.sizes['thumbnail'];
     1516                                        if ( size ) { #>
     1517                                            <option value="thumbnail">
     1518                                                Thumbnail &ndash; {{ size.width }} &times; {{ size.height }}
     1519                                            </option>
     1520                                        <# } #>
     1521                                                                            <#
     1522                                        var size = data.sizes['medium'];
     1523                                        if ( size ) { #>
     1524                                            <option value="medium">
     1525                                                Medium &ndash; {{ size.width }} &times; {{ size.height }}
     1526                                            </option>
     1527                                        <# } #>
     1528                                                                            <#
     1529                                        var size = data.sizes['large'];
     1530                                        if ( size ) { #>
     1531                                            <option value="large">
     1532                                                Large &ndash; {{ size.width }} &times; {{ size.height }}
     1533                                            </option>
     1534                                        <# } #>
     1535                                                                            <#
     1536                                        var size = data.sizes['full'];
     1537                                        if ( size ) { #>
     1538                                            <option value="full">
     1539                                                Full Size &ndash; {{ size.width }} &times; {{ size.height }}
     1540                                            </option>
     1541                                        <# } #>
     1542                                                                        <option value="custom">
     1543                                        Custom Size                                 </option>
     1544                                </select>
     1545                            </label>
     1546                        <# } #>
     1547                            <div class="custom-size<# if ( data.model.size !== 'custom' ) { #> hidden<# } #>">
     1548                                <label><span>Width <small>(px)</small></span> <input data-setting="customWidth" type="number" step="1" value="{{ data.model.customWidth }}" /></label><span class="sep">&times;</span><label><span>Height <small>(px)</small></span><input data-setting="customHeight" type="number" step="1" value="{{ data.model.customHeight }}" /></label>
     1549                            </div>
     1550                    <# } #>
     1551
     1552                    <div class="setting link-to">
     1553                        <span>Link To</span>
     1554                        <select data-setting="link">
     1555                        <# if ( data.attachment ) { #>
     1556                            <option value="file">
     1557                                Media File                          </option>
     1558                            <option value="post">
     1559                                Attachment Page                         </option>
     1560                        <# } else { #>
     1561                            <option value="file">
     1562                                Image URL                           </option>
     1563                        <# } #>
     1564                            <option value="custom">
     1565                                Custom URL                          </option>
     1566                            <option value="none">
     1567                                None                            </option>
     1568                        </select>
     1569                        <input type="text" class="link-to-custom" data-setting="linkUrl" />
     1570                    </div>
     1571                    <div class="advanced-section">
     1572                        <h2><button type="button" class="button-link advanced-toggle">Advanced Options</button></h2>
     1573                        <div class="advanced-settings hidden">
     1574                            <div class="advanced-image">
     1575                                <label class="setting title-text">
     1576                                    <span>Image Title Attribute</span>
     1577                                    <input type="text" data-setting="title" value="{{ data.model.title }}" />
     1578                                </label>
     1579                                <label class="setting extra-classes">
     1580                                    <span>Image CSS Class</span>
     1581                                    <input type="text" data-setting="extraClasses" value="{{ data.model.extraClasses }}" />
     1582                                </label>
     1583                            </div>
     1584                            <div class="advanced-link">
     1585                                <div class="setting link-target">
     1586                                    <label><input type="checkbox" data-setting="linkTargetBlank" value="_blank" <# if ( data.model.linkTargetBlank ) { #>checked="checked"<# } #>>Open link in a new tab</label>
     1587                                </div>
     1588                                <label class="setting link-rel">
     1589                                    <span>Link Rel</span>
     1590                                    <input type="text" data-setting="linkRel" value="{{ data.model.linkClassName }}" />
     1591                                </label>
     1592                                <label class="setting link-class-name">
     1593                                    <span>Link CSS Class</span>
     1594                                    <input type="text" data-setting="linkClassName" value="{{ data.model.linkClassName }}" />
     1595                                </label>
     1596                            </div>
     1597                        </div>
     1598                    </div>
     1599                </div>
     1600            </div>
     1601        </div>
     1602    </script>
     1603
     1604    <script type="text/html" id="tmpl-image-editor">
     1605        <div id="media-head-{{ data.id }}"></div>
     1606        <div id="image-editor-{{ data.id }}"></div>
     1607    </script>
     1608
     1609    <script type="text/html" id="tmpl-audio-details">
     1610        <# var ext, html5types = {
     1611            mp3: wp.media.view.settings.embedMimes.mp3,
     1612            ogg: wp.media.view.settings.embedMimes.ogg
     1613        }; #>
     1614
     1615                <div class="media-embed media-embed-details">
     1616            <div class="embed-media-settings embed-audio-settings">
     1617                <audio style="visibility: hidden"
     1618    controls
     1619    class="wp-audio-shortcode"
     1620    width="{{ _.isUndefined( data.model.width ) ? 400 : data.model.width }}"
     1621    preload="{{ _.isUndefined( data.model.preload ) ? 'none' : data.model.preload }}"
     1622    <#
     1623    if ( ! _.isUndefined( data.model.autoplay ) && data.model.autoplay ) {
     1624        #> autoplay<#
     1625    }
     1626    if ( ! _.isUndefined( data.model.loop ) && data.model.loop ) {
     1627        #> loop<#
     1628    }
     1629    #>
     1630>
     1631    <# if ( ! _.isEmpty( data.model.src ) ) { #>
     1632    <source src="{{ data.model.src }}" type="{{ wp.media.view.settings.embedMimes[ data.model.src.split('.').pop() ] }}" />
     1633    <# } #>
     1634
     1635    <# if ( ! _.isEmpty( data.model.mp3 ) ) { #>
     1636    <source src="{{ data.model.mp3 }}" type="{{ wp.media.view.settings.embedMimes[ 'mp3' ] }}" />
     1637    <# } #>
     1638    <# if ( ! _.isEmpty( data.model.ogg ) ) { #>
     1639    <source src="{{ data.model.ogg }}" type="{{ wp.media.view.settings.embedMimes[ 'ogg' ] }}" />
     1640    <# } #>
     1641    <# if ( ! _.isEmpty( data.model.wma ) ) { #>
     1642    <source src="{{ data.model.wma }}" type="{{ wp.media.view.settings.embedMimes[ 'wma' ] }}" />
     1643    <# } #>
     1644    <# if ( ! _.isEmpty( data.model.m4a ) ) { #>
     1645    <source src="{{ data.model.m4a }}" type="{{ wp.media.view.settings.embedMimes[ 'm4a' ] }}" />
     1646    <# } #>
     1647    <# if ( ! _.isEmpty( data.model.wav ) ) { #>
     1648    <source src="{{ data.model.wav }}" type="{{ wp.media.view.settings.embedMimes[ 'wav' ] }}" />
     1649    <# } #>
     1650    </audio>
     1651
     1652                <# if ( ! _.isEmpty( data.model.src ) ) {
     1653                    ext = data.model.src.split('.').pop();
     1654                    if ( html5types[ ext ] ) {
     1655                        delete html5types[ ext ];
     1656                    }
     1657                #>
     1658                <label class="setting">
     1659                    <span>SRC</span>
     1660                    <input type="text" disabled="disabled" data-setting="src" value="{{ data.model.src }}" />
     1661                    <button type="button" class="button-link remove-setting">Remove audio source</button>
     1662                </label>
     1663                <# } #>
     1664                <# if ( ! _.isEmpty( data.model.mp3 ) ) {
     1665                    if ( ! _.isUndefined( html5types.mp3 ) ) {
     1666                        delete html5types.mp3;
     1667                    }
     1668                #>
     1669                <label class="setting">
     1670                    <span>MP3</span>
     1671                    <input type="text" disabled="disabled" data-setting="mp3" value="{{ data.model.mp3 }}" />
     1672                    <button type="button" class="button-link remove-setting">Remove audio source</button>
     1673                </label>
     1674                <# } #>
     1675                <# if ( ! _.isEmpty( data.model.ogg ) ) {
     1676                    if ( ! _.isUndefined( html5types.ogg ) ) {
     1677                        delete html5types.ogg;
     1678                    }
     1679                #>
     1680                <label class="setting">
     1681                    <span>OGG</span>
     1682                    <input type="text" disabled="disabled" data-setting="ogg" value="{{ data.model.ogg }}" />
     1683                    <button type="button" class="button-link remove-setting">Remove audio source</button>
     1684                </label>
     1685                <# } #>
     1686                <# if ( ! _.isEmpty( data.model.wma ) ) {
     1687                    if ( ! _.isUndefined( html5types.wma ) ) {
     1688                        delete html5types.wma;
     1689                    }
     1690                #>
     1691                <label class="setting">
     1692                    <span>WMA</span>
     1693                    <input type="text" disabled="disabled" data-setting="wma" value="{{ data.model.wma }}" />
     1694                    <button type="button" class="button-link remove-setting">Remove audio source</button>
     1695                </label>
     1696                <# } #>
     1697                <# if ( ! _.isEmpty( data.model.m4a ) ) {
     1698                    if ( ! _.isUndefined( html5types.m4a ) ) {
     1699                        delete html5types.m4a;
     1700                    }
     1701                #>
     1702                <label class="setting">
     1703                    <span>M4A</span>
     1704                    <input type="text" disabled="disabled" data-setting="m4a" value="{{ data.model.m4a }}" />
     1705                    <button type="button" class="button-link remove-setting">Remove audio source</button>
     1706                </label>
     1707                <# } #>
     1708                <# if ( ! _.isEmpty( data.model.wav ) ) {
     1709                    if ( ! _.isUndefined( html5types.wav ) ) {
     1710                        delete html5types.wav;
     1711                    }
     1712                #>
     1713                <label class="setting">
     1714                    <span>WAV</span>
     1715                    <input type="text" disabled="disabled" data-setting="wav" value="{{ data.model.wav }}" />
     1716                    <button type="button" class="button-link remove-setting">Remove audio source</button>
     1717                </label>
     1718                <# } #>
     1719
     1720                <# if ( ! _.isEmpty( html5types ) ) { #>
     1721                <div class="setting">
     1722                    <span>Add alternate sources for maximum HTML5 playback:</span>
     1723                    <div class="button-large">
     1724                    <# _.each( html5types, function (mime, type) { #>
     1725                    <button class="button add-media-source" data-mime="{{ mime }}">{{ type }}</button>
     1726                    <# } ) #>
     1727                    </div>
     1728                </div>
     1729                <# } #>
     1730
     1731                <div class="setting preload">
     1732                    <span>Preload</span>
     1733                    <div class="button-group button-large" data-setting="preload">
     1734                        <button class="button" value="auto">Auto</button>
     1735                        <button class="button" value="metadata">Metadata</button>
     1736                        <button class="button active" value="none">None</button>
     1737                    </div>
     1738                </div>
     1739
     1740                <label class="setting checkbox-setting">
     1741                    <input type="checkbox" data-setting="autoplay" />
     1742                    <span>Autoplay</span>
     1743                </label>
     1744
     1745                <label class="setting checkbox-setting">
     1746                    <input type="checkbox" data-setting="loop" />
     1747                    <span>Loop</span>
     1748                </label>
     1749            </div>
     1750        </div>
     1751    </script>
     1752
     1753    <script type="text/html" id="tmpl-video-details">
     1754        <# var ext, html5types = {
     1755            mp4: wp.media.view.settings.embedMimes.mp4,
     1756            ogv: wp.media.view.settings.embedMimes.ogv,
     1757            webm: wp.media.view.settings.embedMimes.webm
     1758        }; #>
     1759
     1760                <div class="media-embed media-embed-details">
     1761            <div class="embed-media-settings embed-video-settings">
     1762                <div class="wp-video-holder">
     1763                <#
     1764                var w = ! data.model.width || data.model.width > 640 ? 640 : data.model.width,
     1765                    h = ! data.model.height ? 360 : data.model.height;
     1766
     1767                if ( data.model.width && w !== data.model.width ) {
     1768                    h = Math.ceil( ( h * w ) / data.model.width );
     1769                }
     1770                #>
     1771
     1772                <#  var w_rule = '', classes = [],
     1773        w, h, settings = wp.media.view.settings,
     1774        isYouTube = isVimeo = false;
     1775
     1776    if ( ! _.isEmpty( data.model.src ) ) {
     1777        isYouTube = data.model.src.match(/youtube|youtu\.be/);
     1778        isVimeo = -1 !== data.model.src.indexOf('vimeo');
     1779    }
     1780
     1781    if ( settings.contentWidth && data.model.width >= settings.contentWidth ) {
     1782        w = settings.contentWidth;
     1783    } else {
     1784        w = data.model.width;
     1785    }
     1786
     1787    if ( w !== data.model.width ) {
     1788        h = Math.ceil( ( data.model.height * w ) / data.model.width );
     1789    } else {
     1790        h = data.model.height;
     1791    }
     1792
     1793    if ( w ) {
     1794        w_rule = 'width: ' + w + 'px; ';
     1795    }
     1796
     1797    if ( isYouTube ) {
     1798        classes.push( 'youtube-video' );
     1799    }
     1800
     1801    if ( isVimeo ) {
     1802        classes.push( 'vimeo-video' );
     1803    }
     1804
     1805#>
     1806<div style="{{ w_rule }}" class="wp-video">
     1807<video controls
     1808    class="wp-video-shortcode {{ classes.join( ' ' ) }}"
     1809    <# if ( w ) { #>width="{{ w }}"<# } #>
     1810    <# if ( h ) { #>height="{{ h }}"<# } #>
     1811    <#
     1812        if ( ! _.isUndefined( data.model.poster ) && data.model.poster ) {
     1813            #> poster="{{ data.model.poster }}"<#
     1814        } #>
     1815        preload="{{ _.isUndefined( data.model.preload ) ? 'metadata' : data.model.preload }}"<#
     1816     if ( ! _.isUndefined( data.model.autoplay ) && data.model.autoplay ) {
     1817        #> autoplay<#
     1818    }
     1819     if ( ! _.isUndefined( data.model.loop ) && data.model.loop ) {
     1820        #> loop<#
     1821    }
     1822    #>
     1823>
     1824    <# if ( ! _.isEmpty( data.model.src ) ) {
     1825        if ( isYouTube ) { #>
     1826        <source src="{{ data.model.src }}" type="video/youtube" />
     1827        <# } else if ( isVimeo ) { #>
     1828        <source src="{{ data.model.src }}" type="video/vimeo" />
     1829        <# } else { #>
     1830        <source src="{{ data.model.src }}" type="{{ settings.embedMimes[ data.model.src.split('.').pop() ] }}" />
     1831        <# }
     1832    } #>
     1833
     1834    <# if ( data.model.mp4 ) { #>
     1835    <source src="{{ data.model.mp4 }}" type="{{ settings.embedMimes[ 'mp4' ] }}" />
     1836    <# } #>
     1837    <# if ( data.model.m4v ) { #>
     1838    <source src="{{ data.model.m4v }}" type="{{ settings.embedMimes[ 'm4v' ] }}" />
     1839    <# } #>
     1840    <# if ( data.model.webm ) { #>
     1841    <source src="{{ data.model.webm }}" type="{{ settings.embedMimes[ 'webm' ] }}" />
     1842    <# } #>
     1843    <# if ( data.model.ogv ) { #>
     1844    <source src="{{ data.model.ogv }}" type="{{ settings.embedMimes[ 'ogv' ] }}" />
     1845    <# } #>
     1846    <# if ( data.model.wmv ) { #>
     1847    <source src="{{ data.model.wmv }}" type="{{ settings.embedMimes[ 'wmv' ] }}" />
     1848    <# } #>
     1849    <# if ( data.model.flv ) { #>
     1850    <source src="{{ data.model.flv }}" type="{{ settings.embedMimes[ 'flv' ] }}" />
     1851    <# } #>
     1852        {{{ data.model.content }}}
     1853</video>
     1854</div>
     1855
     1856                <# if ( ! _.isEmpty( data.model.src ) ) {
     1857                    ext = data.model.src.split('.').pop();
     1858                    if ( html5types[ ext ] ) {
     1859                        delete html5types[ ext ];
     1860                    }
     1861                #>
     1862                <label class="setting">
     1863                    <span>SRC</span>
     1864                    <input type="text" disabled="disabled" data-setting="src" value="{{ data.model.src }}" />
     1865                    <button type="button" class="button-link remove-setting">Remove video source</button>
     1866                </label>
     1867                <# } #>
     1868                <# if ( ! _.isEmpty( data.model.mp4 ) ) {
     1869                    if ( ! _.isUndefined( html5types.mp4 ) ) {
     1870                        delete html5types.mp4;
     1871                    }
     1872                #>
     1873                <label class="setting">
     1874                    <span>MP4</span>
     1875                    <input type="text" disabled="disabled" data-setting="mp4" value="{{ data.model.mp4 }}" />
     1876                    <button type="button" class="button-link remove-setting">Remove video source</button>
     1877                </label>
     1878                <# } #>
     1879                <# if ( ! _.isEmpty( data.model.m4v ) ) {
     1880                    if ( ! _.isUndefined( html5types.m4v ) ) {
     1881                        delete html5types.m4v;
     1882                    }
     1883                #>
     1884                <label class="setting">
     1885                    <span>M4V</span>
     1886                    <input type="text" disabled="disabled" data-setting="m4v" value="{{ data.model.m4v }}" />
     1887                    <button type="button" class="button-link remove-setting">Remove video source</button>
     1888                </label>
     1889                <# } #>
     1890                <# if ( ! _.isEmpty( data.model.webm ) ) {
     1891                    if ( ! _.isUndefined( html5types.webm ) ) {
     1892                        delete html5types.webm;
     1893                    }
     1894                #>
     1895                <label class="setting">
     1896                    <span>WEBM</span>
     1897                    <input type="text" disabled="disabled" data-setting="webm" value="{{ data.model.webm }}" />
     1898                    <button type="button" class="button-link remove-setting">Remove video source</button>
     1899                </label>
     1900                <# } #>
     1901                <# if ( ! _.isEmpty( data.model.ogv ) ) {
     1902                    if ( ! _.isUndefined( html5types.ogv ) ) {
     1903                        delete html5types.ogv;
     1904                    }
     1905                #>
     1906                <label class="setting">
     1907                    <span>OGV</span>
     1908                    <input type="text" disabled="disabled" data-setting="ogv" value="{{ data.model.ogv }}" />
     1909                    <button type="button" class="button-link remove-setting">Remove video source</button>
     1910                </label>
     1911                <# } #>
     1912                <# if ( ! _.isEmpty( data.model.wmv ) ) {
     1913                    if ( ! _.isUndefined( html5types.wmv ) ) {
     1914                        delete html5types.wmv;
     1915                    }
     1916                #>
     1917                <label class="setting">
     1918                    <span>WMV</span>
     1919                    <input type="text" disabled="disabled" data-setting="wmv" value="{{ data.model.wmv }}" />
     1920                    <button type="button" class="button-link remove-setting">Remove video source</button>
     1921                </label>
     1922                <# } #>
     1923                <# if ( ! _.isEmpty( data.model.flv ) ) {
     1924                    if ( ! _.isUndefined( html5types.flv ) ) {
     1925                        delete html5types.flv;
     1926                    }
     1927                #>
     1928                <label class="setting">
     1929                    <span>FLV</span>
     1930                    <input type="text" disabled="disabled" data-setting="flv" value="{{ data.model.flv }}" />
     1931                    <button type="button" class="button-link remove-setting">Remove video source</button>
     1932                </label>
     1933                <# } #>
     1934                                </div>
     1935
     1936                <# if ( ! _.isEmpty( html5types ) ) { #>
     1937                <div class="setting">
     1938                    <span>Add alternate sources for maximum HTML5 playback:</span>
     1939                    <div class="button-large">
     1940                    <# _.each( html5types, function (mime, type) { #>
     1941                    <button class="button add-media-source" data-mime="{{ mime }}">{{ type }}</button>
     1942                    <# } ) #>
     1943                    </div>
     1944                </div>
     1945                <# } #>
     1946
     1947                <# if ( ! _.isEmpty( data.model.poster ) ) { #>
     1948                <label class="setting">
     1949                    <span>Poster Image</span>
     1950                    <input type="text" disabled="disabled" data-setting="poster" value="{{ data.model.poster }}" />
     1951                    <button type="button" class="button-link remove-setting">Remove poster image</button>
     1952                </label>
     1953                <# } #>
     1954                <div class="setting preload">
     1955                    <span>Preload</span>
     1956                    <div class="button-group button-large" data-setting="preload">
     1957                        <button class="button" value="auto">Auto</button>
     1958                        <button class="button" value="metadata">Metadata</button>
     1959                        <button class="button active" value="none">None</button>
     1960                    </div>
     1961                </div>
     1962
     1963                <label class="setting checkbox-setting">
     1964                    <input type="checkbox" data-setting="autoplay" />
     1965                    <span>Autoplay</span>
     1966                </label>
     1967
     1968                <label class="setting checkbox-setting">
     1969                    <input type="checkbox" data-setting="loop" />
     1970                    <span>Loop</span>
     1971                </label>
     1972
     1973                <label class="setting" data-setting="content">
     1974                    <span>Tracks (subtitles, captions, descriptions, chapters, or metadata)</span>
     1975                    <#
     1976                    var content = '';
     1977                    if ( ! _.isEmpty( data.model.content ) ) {
     1978                        var tracks = jQuery( data.model.content ).filter( 'track' );
     1979                        _.each( tracks.toArray(), function (track) {
     1980                            content += track.outerHTML; #>
     1981                        <p>
     1982                            <input class="content-track" type="text" value="{{ track.outerHTML }}" />
     1983                            <button type="button" class="button-link remove-setting remove-track">Remove video track</button>
     1984                        </p>
     1985                        <# } ); #>
     1986                    <# } else { #>
     1987                    <em>There are no associated subtitles.</em>
     1988                    <# } #>
     1989                    <textarea class="hidden content-setting">{{ content }}</textarea>
     1990                </label>
     1991            </div>
     1992        </div>
     1993    </script>
     1994
     1995    <script type="text/html" id="tmpl-editor-gallery">
     1996        <# if ( data.attachments.length ) { #>
     1997            <div class="gallery gallery-columns-{{ data.columns }}">
     1998                <# _.each( data.attachments, function( attachment, index ) { #>
     1999                    <dl class="gallery-item">
     2000                        <dt class="gallery-icon">
     2001                            <# if ( attachment.thumbnail ) { #>
     2002                                <img src="{{ attachment.thumbnail.url }}" width="{{ attachment.thumbnail.width }}" height="{{ attachment.thumbnail.height }}" alt="" />
     2003                            <# } else { #>
     2004                                <img src="{{ attachment.url }}" alt="" />
     2005                            <# } #>
     2006                        </dt>
     2007                        <# if ( attachment.caption ) { #>
     2008                            <dd class="wp-caption-text gallery-caption">
     2009                                {{{ data.verifyHTML( attachment.caption ) }}}
     2010                            </dd>
     2011                        <# } #>
     2012                    </dl>
     2013                    <# if ( index % data.columns === data.columns - 1 ) { #>
     2014                        <br style="clear: both;">
     2015                    <# } #>
     2016                <# } ); #>
     2017            </div>
     2018        <# } else { #>
     2019            <div class="wpview-error">
     2020                <div class="dashicons dashicons-format-gallery"></div><p>No items found.</p>
     2021            </div>
     2022        <# } #>
     2023    </script>
     2024
     2025    <script type="text/html" id="tmpl-crop-content">
     2026        <img class="crop-image" src="{{ data.url }}" alt="Image crop area preview. Requires mouse interaction.">
     2027        <div class="upload-errors"></div>
     2028    </script>
     2029
     2030    <script type="text/html" id="tmpl-site-icon-preview">
     2031        <h2>Preview</h2>
     2032        <strong aria-hidden="true">As a browser icon</strong>
     2033        <div class="favicon-preview">
     2034            <img src="http://src.wordpress-develop.dev/wp-admin/images/browser.png" class="browser-preview" width="182" height="" alt="" />
     2035
     2036            <div class="favicon">
     2037                <img id="preview-favicon" src="{{ data.url }}" alt="Preview as a browser icon"/>
     2038            </div>
     2039            <span class="browser-title" aria-hidden="true">WordPress Develop</span>
     2040        </div>
     2041
     2042        <strong aria-hidden="true">As an app icon</strong>
     2043        <div class="app-icon-preview">
     2044            <img id="preview-app-icon" src="{{ data.url }}" alt="Preview as an app icon"/>
     2045        </div>
     2046    </script>
    5022047        </div><!-- end widget templates -->
    5032048        <script src="../../src/wp-includes/js/tinymce/tinymce.js"></script>
Note: See TracChangeset for help on using the changeset viewer.