WordPress.org

Make WordPress Core

Changeset 28682


Ignore:
Timestamp:
06/05/14 22:00:24 (3 years ago)
Author:
helen
Message:

Grid view for the media library, first pass. This is alpha; expect imperfection. We will be iterating further.

props ericlewis, shaunandrews, wonderboymusic.
see #24716.

Location:
trunk/src
Files:
10 edited

Legend:

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

    r27956 r28682  
    635635.view-switch > a:before { 
    636636    color: #bbb; 
    637     content: '\f163'; 
    638637    display: inline-block; 
    639638    float: left; 
     
    646645} 
    647646 
     647.view-switch > .view-list:before { 
     648    content: '\f163'; 
     649} 
     650 
    648651.view-switch a:hover:before { 
    649652    color: #727272; 
     
    654657} 
    655658 
    656 .view-switch > a + a:before { 
     659.view-switch > a + a { 
    657660    margin-left: 5px; 
     661} 
     662 
     663.view-switch > .view-excerpt:before { 
    658664    content: '\f164'; 
     665} 
     666 
     667.view-switch > .view-grid:before { 
     668    content: '\f180'; 
    659669} 
    660670 
  • trunk/src/wp-admin/includes/class-wp-list-table.php

    r28524 r28682  
    494494<?php 
    495495            foreach ( $modes as $mode => $title ) { 
    496                 $class = ( $current_mode == $mode ) ? 'class="current"' : ''; 
    497                 echo "<a href='" . esc_url( add_query_arg( 'mode', $mode, $_SERVER['REQUEST_URI'] ) ) . "' $class><img id='view-switch-$mode' src='" . esc_url( includes_url( 'images/blank.gif' ) ) . "' width='20' height='20' title='$title' alt='$title' /></a>\n"; 
     496                $classes = array( 'view-' . $mode ); 
     497                if ( $current_mode == $mode ) 
     498                    $classes[] = 'current'; 
     499                printf( 
     500                    "<a href='%s' class='%s'><img id='view-switch-$mode' src='%s' width='20' height='20' title='%s' alt='%s' /></a>\n", 
     501                    esc_url( add_query_arg( 'mode', $mode ) ), 
     502                    implode( ' ', $classes ), 
     503                    esc_url( includes_url( 'images/blank.gif' ) ), 
     504                    $title, 
     505                    $title 
     506                ); 
    498507            } 
    499508        ?> 
  • trunk/src/wp-admin/includes/class-wp-media-list-table.php

    r28553 r28682  
    2424 
    2525    public function prepare_items() { 
    26         global $lost, $wp_query, $post_mime_types, $avail_post_mime_types; 
     26        global $lost, $wp_query, $post_mime_types, $avail_post_mime_types, $mode; 
    2727 
    2828        $q = $_REQUEST; 
     
    3434 
    3535        $this->is_trash = isset( $_REQUEST['status'] ) && 'trash' == $_REQUEST['status']; 
     36 
     37        $mode = empty( $_REQUEST['mode'] ) ? 'list' : $_REQUEST['mode']; 
    3638 
    3739        $this->set_pagination_args( array( 
     
    124126    public function no_items() { 
    125127        _e( 'No media attachments found.' ); 
     128    } 
     129 
     130    protected function pagination( $which ) { 
     131        global $mode; 
     132 
     133        parent::pagination( $which ); 
     134 
     135        $this->view_switcher( $mode ); 
     136    } 
     137 
     138    /** 
     139     * Display a view switcher 
     140     * 
     141     * @since 3.1.0 
     142     * @access protected 
     143     */ 
     144    protected function view_switcher( $current_mode ) { 
     145        $modes = array( 
     146            'list'    => __( 'List View' ), 
     147            'grid' => __( 'Grid View' ) 
     148        ); 
     149 
     150?> 
     151        <input type="hidden" name="mode" value="<?php echo esc_attr( $current_mode ); ?>" /> 
     152        <div class="view-switch"> 
     153<?php 
     154            foreach ( $modes as $mode => $title ) { 
     155                $classes = array( 'view-' . $mode ); 
     156                if ( $current_mode == $mode ) 
     157                    $classes[] = 'current'; 
     158                printf( 
     159                    "<a href='%s' class='%s'><img id='view-switch-$mode' src='%s' width='20' height='20' title='%s' alt='%s' /></a>\n", 
     160                    esc_url( add_query_arg( 'mode', $mode ) ), 
     161                    implode( ' ', $classes ), 
     162                    esc_url( includes_url( 'images/blank.gif' ) ), 
     163                    $title, 
     164                    $title 
     165 
     166                ); 
     167            } 
     168        ?> 
     169        </div> 
     170<?php 
    126171    } 
    127172 
  • trunk/src/wp-admin/js/media.js

    r27403 r28682  
    7373 
    7474    $( document ).ready( function() { 
     75        // Open up a manage media frame into the grid. 
     76        wp.media && wp.media({ 
     77            frame: 'manage', 
     78            container: $('#wpbody-content') 
     79        }).open(); 
     80 
    7581        $( '#find-posts-submit' ).click( function( event ) { 
    7682            if ( ! $( '#find-posts-response input[type="radio"]:checked' ).length ) 
  • trunk/src/wp-admin/upload.php

    r27469 r28682  
    1212if ( !current_user_can('upload_files') ) 
    1313    wp_die( __( 'You do not have permission to upload files.' ) ); 
     14 
     15$mode = get_user_option( 'media_library_mode', get_current_user_id() ) ? get_user_option( 'media_library_mode', get_current_user_id() ) : 'grid'; 
     16$modes = array( 'grid', 'list' ); 
     17 
     18if ( isset( $_GET['mode'] ) && in_array( $_GET['mode'], $modes ) ) { 
     19    $mode = $_GET['mode']; 
     20    update_user_option( get_current_user_id(), 'media_library_mode', $mode ); 
     21} 
     22 
     23if ( 'grid' === $mode ) { 
     24    wp_enqueue_media(); 
     25    wp_enqueue_script( 'media' ); 
     26    require_once( ABSPATH . 'wp-admin/admin-header.php' ); 
     27    ?><div class="view-switch media-grid-view-switch"> 
     28        <a href="<?php echo esc_url( add_query_arg( 'mode', 'list', $_SERVER['REQUEST_URI'] ) ) ?>" class="view-list"> 
     29            <img id="view-switch-list" src="<?php echo includes_url( 'images/blank.gif' ) ?>" width="20" height="20" title="List View" alt="List View"/> 
     30        </a> 
     31        <a href="<?php echo esc_url( add_query_arg( 'mode', 'grid', $_SERVER['REQUEST_URI'] ) ) ?>" class="view-grid current"> 
     32            <img id="view-switch-excerpt" src="<?php echo includes_url( 'images/blank.gif' ) ?>" width="20" height="20" title="Grid View" alt="Grid View"/> 
     33        </a> 
     34    </div><?php 
     35    include( ABSPATH . 'wp-admin/admin-footer.php' ); 
     36    exit; 
     37} 
    1438 
    1539$wp_list_table = _get_list_table('WP_Media_List_Table'); 
     
    238262 
    239263<div id="ajax-response"></div> 
    240 <?php find_posts_div(); ?>  
     264<?php find_posts_div(); ?> 
    241265</form> 
    242266</div> 
  • trunk/src/wp-includes/css/media-views.css

    r28607 r28682  
    296296} 
    297297 
    298 .media-sidebar .setting span { 
     298.media-sidebar .setting .name { 
    299299    min-width: 30%; 
    300300    margin-right: 4%; 
    301301    font-size: 12px; 
     302    text-align: right; 
    302303} 
    303304 
     
    320321    padding-top: 8px; 
    321322    line-height: 16px; 
    322     text-align: right; 
    323323    font-weight: normal; 
    324324    color: #666; 
    325325} 
    326326 
     327.compat-item label span  { 
     328    text-align: right; 
     329} 
     330 
    327331.media-sidebar .setting input, 
    328 .media-sidebar .setting textarea { 
     332.media-sidebar .setting textarea, 
     333.media-sidebar .setting .value { 
    329334    margin: 1px; 
    330335    width: 65%; 
     
    18131818} 
    18141819 
    1815 .image-details .embed-media-settings .setting span { 
     1820.image-details .embed-media-settings .setting .name { 
    18161821    float: left; 
    18171822    width: 25%; 
     
    23692374    } 
    23702375} 
     2376 
     2377 
     2378/** 
     2379 * Media Grid 
     2380 */ 
     2381 
     2382.media-grid-view h1 { 
     2383    color: #222; 
     2384    font-size: 23px; 
     2385    font-weight: 400; 
     2386    margin: 10px 0 0; 
     2387    padding: 9px 15px 4px 22px; 
     2388    line-height: 29px; 
     2389} 
     2390 
     2391.media-grid-view-switch { 
     2392    position: fixed; 
     2393    right: 10px; 
     2394    top: 44px; 
     2395    z-index: 300; 
     2396} 
     2397 
     2398/** 
     2399 * Position both the frame and the uploader window into the content 
     2400 * area of the screen. 
     2401 */ 
     2402.media-grid-view { 
     2403    position: fixed; 
     2404    bottom: 0; 
     2405    left: 160px; 
     2406    right: 0; 
     2407    top: 32px; 
     2408} 
     2409@media screen and (max-width: 900px) { 
     2410    .auto-fold .media-grid-view { 
     2411        left: 36px; 
     2412    } 
     2413} 
     2414@media screen and (max-width: 782px) { 
     2415    .media-grid-view { 
     2416        top: 46px; 
     2417    } 
     2418    .auto-fold .media-grid-view { 
     2419        left: 0px; 
     2420        bottom: 0px; 
     2421    } 
     2422} 
     2423 
     2424/* Regions we don't use at all */ 
     2425.media-grid-view .media-frame-toolbar, 
     2426.media-grid-view .media-frame-menu { 
     2427    display: none; 
     2428} 
     2429 
     2430.media-grid-view .media-frame-content { 
     2431    bottom: 40px; 
     2432} 
     2433@media screen and (max-width: 782px) { 
     2434    .media-grid-view .media-frame-content { 
     2435        border-bottom: none; 
     2436        bottom: 0; 
     2437    } 
     2438} 
     2439 
     2440@media only screen and (max-width: 640px), screen and (max-height: 400px) { 
     2441    .media-grid-view .media-frame-title { 
     2442        display: block; 
     2443        width: auto; 
     2444        bottom: auto; 
     2445        right: 0; 
     2446        top: 0; 
     2447        height: 60px; 
     2448    } 
     2449} 
  • trunk/src/wp-includes/js/media-models.js

    r28095 r28682  
    3131        } else if ( 'post' === attributes.frame && MediaFrame.Post ) { 
    3232            frame = new MediaFrame.Post( attributes ); 
     33        } else if ( 'manage' === attributes.frame && MediaFrame.Manage ) { 
     34            frame = new MediaFrame.Manage( attributes );  
    3335        } else if ( 'image' === attributes.frame && MediaFrame.ImageDetails ) { 
    3436            frame = new MediaFrame.ImageDetails( attributes ); 
  • trunk/src/wp-includes/js/media-views.js

    r28675 r28682  
    616616            this.get('selection').on( 'add remove reset', this.refreshContent, this ); 
    617617 
    618             if ( this.get('contentUserSetting') ) { 
     618            if ( this.get( 'router' ) && this.get('contentUserSetting') ) { 
    619619                this.frame.on( 'content:activate', this.saveContentMode, this ); 
    620620                this.set( 'content', getUserSetting( 'libraryContent', this.get('content') ) ); 
     
    19191919            return this; 
    19201920        }; 
     1921    }); 
     1922 
     1923    /** 
     1924     * wp.media.view.MediaFrame.Manage 
     1925     * 
     1926     * A generic management frame workflow. 
     1927     * 
     1928     * Used in the media grid view. 
     1929     * 
     1930     * @constructor 
     1931     * @augments wp.media.view.MediaFrame 
     1932     * @augments wp.media.view.Frame 
     1933     * @augments wp.media.View 
     1934     * @augments wp.Backbone.View 
     1935     * @augments Backbone.View 
     1936     * @mixes wp.media.controller.StateMachine 
     1937     */ 
     1938    media.view.MediaFrame.Manage = media.view.MediaFrame.extend({ 
     1939        /** 
     1940         * @global wp.Uploader 
     1941         */ 
     1942        initialize: function() { 
     1943            _.defaults( this.options, { 
     1944                title:     l10n.mediaLibraryTitle, 
     1945                modal:     false, 
     1946                selection: [], 
     1947                library:   {}, 
     1948                multiple:  false, 
     1949                state:     'library', 
     1950                uploader:  true 
     1951            }); 
     1952 
     1953            // Ensure core and media grid view UI is enabled. 
     1954            this.$el.addClass('wp-core-ui media-grid-view'); 
     1955 
     1956            // Force the uploader off if the upload limit has been exceeded or 
     1957            // if the browser isn't supported. 
     1958            if ( wp.Uploader.limitExceeded || ! wp.Uploader.browser.supported ) { 
     1959                this.options.uploader = false; 
     1960            } 
     1961 
     1962            // Initialize a window-wide uploader. 
     1963            if ( this.options.uploader ) { 
     1964                this.uploader = new media.view.UploaderWindow({ 
     1965                    controller: this, 
     1966                    uploader: { 
     1967                        dropzone:  $('body'), 
     1968                        container: $('body') 
     1969                    } 
     1970                }).render(); 
     1971                this.uploader.ready(); 
     1972                $('body').append( this.uploader.el ); 
     1973 
     1974                this.options.uploader = false; 
     1975            } 
     1976 
     1977            /** 
     1978             * call 'initialize' directly on the parent class 
     1979             */ 
     1980            media.view.MediaFrame.prototype.initialize.apply( this, arguments ); 
     1981 
     1982            // Since we're not using the default modal built into 
     1983            // a media frame, append our $element to the supplied container. 
     1984            this.$el.appendTo( this.options.container ); 
     1985 
     1986            this.createSelection(); 
     1987            this.createStates(); 
     1988            this.bindHandlers(); 
     1989            this.render(); 
     1990        }, 
     1991 
     1992        createSelection: function() { 
     1993            var selection = this.options.selection; 
     1994 
     1995            if ( ! (selection instanceof media.model.Selection) ) { 
     1996                this.options.selection = new media.model.Selection( selection, { 
     1997                    multiple: this.options.multiple 
     1998                }); 
     1999            } 
     2000 
     2001            this._selection = { 
     2002                attachments: new media.model.Attachments(), 
     2003                difference: [] 
     2004            }; 
     2005        }, 
     2006 
     2007        createStates: function() { 
     2008            var options = this.options; 
     2009 
     2010            if ( this.options.states ) { 
     2011                return; 
     2012            } 
     2013 
     2014            // Add the default states. 
     2015            this.states.add([ 
     2016                new media.controller.Library({ 
     2017                    library:    media.query( options.library ), 
     2018                    multiple:   options.multiple, 
     2019                    title:      options.title, 
     2020                    priority:   20, 
     2021                    toolbar:    false, 
     2022                    router:     false, 
     2023                    content:    'browse', 
     2024                    filterable: 'mime-types' 
     2025                }), 
     2026 
     2027                new media.controller.EditImage( { model: options.editImage } ) 
     2028            ]); 
     2029        }, 
     2030 
     2031        bindHandlers: function() { 
     2032            this.on( 'content:create:browse', this.browseContent, this ); 
     2033            this.on( 'content:render:edit-image', this.editImageContent, this ); 
     2034        }, 
     2035 
     2036        /** 
     2037         * Content 
     2038         * 
     2039         * @param {Object} content 
     2040         * @this wp.media.controller.Region 
     2041         */ 
     2042        browseContent: function( content ) { 
     2043            var state = this.state(); 
     2044 
     2045            // Browse our library of attachments. 
     2046            content.view = new media.view.AttachmentsBrowser({ 
     2047                controller: this, 
     2048                collection: state.get('library'), 
     2049                selection:  state.get('selection'), 
     2050                model:      state, 
     2051                sortable:   state.get('sortable'), 
     2052                search:     state.get('searchable'), 
     2053                filters:    state.get('filterable'), 
     2054                display:    state.get('displaySettings'), 
     2055                dragInfo:   state.get('dragInfo'), 
     2056                bulkEdit:   true, 
     2057 
     2058                suggestedWidth:  state.get('suggestedWidth'), 
     2059                suggestedHeight: state.get('suggestedHeight'), 
     2060 
     2061                AttachmentView: state.get('AttachmentView') 
     2062            }); 
     2063        }, 
     2064 
     2065        editImageContent: function() { 
     2066            var image = this.state().get('image'), 
     2067                view = new media.view.EditImage( { model: image, controller: this } ).render(); 
     2068 
     2069            this.content.set( view ); 
     2070 
     2071            // after creating the wrapper view, load the actual editor via an ajax call 
     2072            view.loadEditor(); 
     2073 
     2074        }, 
    19212075    }); 
    19222076 
     
    53645518    }); 
    53655519 
     5520    /** 
     5521     * wp.media.view.AttachmentFilters.FileTypes 
     5522     * 
     5523     * @constructor 
     5524     * @augments wp.media.view.AttachmentFilters 
     5525     * @augments wp.media.View 
     5526     * @augments wp.Backbone.View 
     5527     * @augments Backbone.View 
     5528     */ 
     5529    media.view.AttachmentFilters.mimeTypes = media.view.AttachmentFilters.extend({ 
     5530        createFilters: function() { 
     5531            var filters = {}; 
     5532 
     5533            _.each( media.view.settings.mimeTypes || {}, function( text, key ) { 
     5534                filters[ key ] = { 
     5535                    text: text, 
     5536                    props: { 
     5537                        type:    key, 
     5538                        uploadedTo: null, 
     5539                        orderby: 'date', 
     5540                        order:   'DESC' 
     5541                    } 
     5542                }; 
     5543            }); 
     5544            filters.all = { 
     5545                text:  l10n.allMediaTypes, 
     5546                props: { 
     5547                    type:    null, 
     5548                    uploadedTo: null, 
     5549                    orderby: 'date', 
     5550                    order:   'DESC' 
     5551                }, 
     5552                priority: 10 
     5553            }; 
     5554 
     5555            this.filters = filters; 
     5556        } 
     5557    }); 
     5558 
    53665559 
    53675560    /** 
     
    54185611            } else if ( 'all' === filters ) { 
    54195612                FiltersConstructor = media.view.AttachmentFilters.All; 
     5613            } else if ( 'mime-types' === filters ) { 
     5614                FiltersConstructor = media.view.AttachmentFilters.mimeTypes; 
    54205615            } 
    54215616 
  • trunk/src/wp-includes/media-template.php

    r28607 r28682  
    309309                <div class="uploaded">{{ data.dateFormatted }}</div> 
    310310 
     311                <div class="file-size">{{ data.filesizeHumanReadable }}</div> 
    311312                <# if ( 'image' === data.type && ! data.uploading ) { #> 
    312313                    <# if ( data.width && data.height ) { #> 
     
    340341        </div> 
    341342 
     343        <label class="setting" data-setting="url"> 
     344            <span class="name"><?php _e('URL'); ?></span> 
     345            <input type="text" value="{{ data.url }}" readonly /> 
     346        </label> 
    342347        <# var maybeReadOnly = data.can.save || data.allowLocalEdits ? '' : 'readonly'; #> 
    343             <label class="setting" data-setting="title"> 
    344                 <span><?php _e('Title'); ?></span> 
    345                 <input type="text" value="{{ data.title }}" {{ maybeReadOnly }} /> 
    346             </label> 
    347             <label class="setting" data-setting="caption"> 
    348                 <span><?php _e('Caption'); ?></span> 
    349                 <textarea {{ maybeReadOnly }}>{{ data.caption }}</textarea> 
    350             </label> 
     348        <label class="setting" data-setting="title"> 
     349            <span class="name"><?php _e('Title'); ?></span> 
     350            <input type="text" value="{{ data.title }}" {{ maybeReadOnly }} /> 
     351        </label> 
     352        <label class="setting" data-setting="caption"> 
     353            <span class="name"><?php _e('Caption'); ?></span> 
     354            <textarea {{ maybeReadOnly }}>{{ data.caption }}</textarea> 
     355        </label> 
    351356        <# if ( 'image' === data.type ) { #> 
    352357            <label class="setting" data-setting="alt"> 
    353                 <span><?php _e('Alt Text'); ?></span> 
     358                <span class="name"><?php _e('Alt Text'); ?></span> 
    354359                <input type="text" value="{{ data.alt }}" {{ maybeReadOnly }} /> 
    355360            </label> 
    356361        <# } #> 
    357             <label class="setting" data-setting="description"> 
    358                 <span><?php _e('Description'); ?></span> 
    359                 <textarea {{ maybeReadOnly }}>{{ data.description }}</textarea> 
     362        <label class="setting" data-setting="description"> 
     363            <span class="name"><?php _e('Description'); ?></span> 
     364            <textarea {{ maybeReadOnly }}>{{ data.description }}</textarea> 
     365        </label> 
     366        <label class="setting"> 
     367                <span class="name"><?php _e( 'Uploaded By' ); ?></span> 
     368                <span class="value">{{ data.authorName }}</span> 
    360369            </label> 
     370        <# if ( data.uploadedTo ) { #> 
     371            <label class="setting"> 
     372                <span class="name"><?php _e('Uploaded To'); ?></span> 
     373                <span class="value"><a href="{{ data.uploadedToLink }}">{{ data.uploadedToTitle }}</a></span> 
     374            </label> 
     375        <# } #> 
    361376    </script> 
    362377 
  • trunk/src/wp-includes/media.php

    r28653 r28682  
    25932593    ); 
    25942594 
     2595    $author = new WP_User( $attachment->post_author ); 
     2596    $response['authorName'] = $author->display_name; 
     2597 
     2598    if ( $attachment->post_parent ) { 
     2599        $post_parent = get_post( $attachment->post_parent ); 
     2600        $response['uploadedToLink'] = get_edit_post_link( $attachment->post_parent, 'raw' ); 
     2601        $response['uploadedToTitle'] = $post_parent->post_title ? $post_parent->post_title : __( '(No title)' ); 
     2602    } 
     2603 
     2604    $bytes = filesize( get_attached_file( $attachment->ID ) ); 
     2605    $response['filesizeInBytes'] = $bytes; 
     2606    $response['filesizeHumanReadable'] = size_format( $bytes ); 
     2607 
    25952608    if ( current_user_can( 'edit_post', $attachment->ID ) ) { 
    25962609        $response['nonces']['update'] = wp_create_nonce( 'update-post_' . $attachment->ID ); 
     
    28502863        'returnToLibrary'    => __( '&#8592; Return to library' ), 
    28512864        'allMediaItems'      => __( 'All media items' ), 
     2865        'allMediaTypes'      => __( 'All media types' ), 
    28522866        'noItemsFound'       => __( 'No items found.' ), 
    28532867        'insertIntoPost'     => $hier ? __( 'Insert into page' ) : __( 'Insert into post' ), 
Note: See TracChangeset for help on using the changeset viewer.