diff --git a/src/wp-admin/css/list-tables.css b/src/wp-admin/css/list-tables.css index cc6aa97cc5..ec22cd7a1c 100644 --- a/src/wp-admin/css/list-tables.css +++ b/src/wp-admin/css/list-tables.css @@ -428,6 +428,60 @@ th.asc a:focus span.sorting-indicator:before { content: '\f140'; } +.wp-list-table .toggle-row { + position: absolute; + right: 8px; + top: 10px; + display: none; + padding: 0; + width: 40px; + height: 40px; + border: none; + outline: none; + background: transparent; +} + +.wp-list-table .toggle-row:hover { + cursor: pointer; +} + +.wp-list-table .toggle-row:focus { + -webkit-box-shadow: + 0 0 0 1px #5b9dd9, + 0 0 2px 1px rgba(30, 140, 190, .8); + box-shadow: + 0 0 0 1px #5b9dd9, + 0 0 2px 1px rgba(30, 140, 190, .8); +} + +.ie8 .wp-list-table .toggle-row:focus { + outline: #5b9dd9 solid 1px; +} + +.wp-list-table .toggle-row:active { + -webkit-box-shadow: none; + box-shadow: none; +} + +.wp-list-table .toggle-row:before { + position: absolute; + top: 0; + left: 10px; + display: block; + padding: 0; + color: #666; + content: '\f140'; + font: normal 20px/1 'dashicons'; + line-height: 10px; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + speak: none; +} + +.wp-list-table .is-expanded .toggle-row:before { + content: '\f142'; +} + tr.wp-locked .locked-indicator { margin-left: 6px; height: 20px; @@ -1303,7 +1357,8 @@ tr.active.update + tr.plugin-update-tr .plugin-update { content: '\f147'; } -.plugins .plugin-update-tr .plugin-update { +.wp-list-table.plugins tbody tr.plugin-update-tr td.plugin-update { + overflow: hidden; /* clearfix */ padding: 0; -webkit-box-shadow: inset 0 -1px 0 rgba(0,0,0,0.1); box-shadow: inset 0 -1px 0 rgba(0,0,0,0.1); @@ -1676,32 +1731,75 @@ div.action-links, font-size: 14px; } - /* Columns to hide */ - .fixed .column-date, - .fixed .column-author, - .column-categories, - .column-tags, - .tags .column-description, - .media .column-parent, - .media .column-comments, - .users .column-email, - .users .column-name, - .sites .column-registered, - .sites .column-users { + .wp-list-table th:not(.column-primary), + .wp-list-table th:not(.column-primary), + .wp-list-table tr:not(.inline-edit-row) td:not(.column-primary):not(.check-column) { display: none; } + /* Checkboxes need to show */ + .wp-list-table tr th.check-column { + display: table-cell; + width: 35px; + } + + .wp-list-table .toggle-row { + display: block; + } + + .wp-list-table tr:not(.inline-edit-row) td:not(.check-column) { + position: relative; + clear: both; + display: block; + width: auto !important; /* needs to override some columns that are more specifically targeted */ + } + + .wp-list-table td.column-primary { + padding-right: 50px; /* space for toggle button */ + } + + .wp-list-table tr:not(.inline-edit-row) td:not(.column-primary):not(.check-column) { + padding: 3px 8px 3px 35%; + } + + .wp-list-table tr:not(.inline-edit-row) td:not(.column-primary)::before { + position: absolute; + left: 10px; /* match padding of regular table cell */ + display: block; + overflow: hidden; + width: 32%; /* leave a little space for a gutter */ + content: attr(data-colname); + white-space: nowrap; + text-overflow: ellipsis; + } + + .wp-list-table .is-expanded td:not(.hidden) { + display: block !important; + overflow: hidden; /* clearfix */ + } + + /* Special cases */ + .widefat .num, + .column-posts { + text-align: left; + } + + #comments-form .fixed .column-author { + display: none !important; + } + .fixed .column-comment .comment-author { display: block; } - /* Posts */ - .column-title { - width: 85%; + #the-comment-list .is-expanded td { + -webkit-box-shadow: none; + box-shadow: none; } - .fixed .column-comments, .widefat .check-column { - width: 35px + #the-comment-list .is-expanded td:last-child { + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.1); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.1); } .widefat thead .check-column, .widefat tfoot .check-column { @@ -1712,11 +1810,6 @@ div.action-links, word-wrap: normal; } - /* Media */ - .media .column-title { - width: auto; - } - /* Quick Edit and Bulk Edit */ #wpbody-content .quick-edit-row-post .inline-edit-col-left, #wpbody-content .quick-edit-row-post .inline-edit-col-right, @@ -1792,30 +1885,6 @@ div.action-links, height: 22px; } - /* Taxonomies */ - .tags .column-posts { - width: 74px; - } - - .tags .column-slug { - width: 30%; - } - - /* Comments */ - .comments .column-response { - width: 35%; - } - - /* Users */ - .users .column-role { - width: 35%; - } - - /* Network admin sites */ - .sites .column-blogname { - width: 55%; - } - /* Updates */ #wpbody-content #update-themes-table .plugin-title { width: auto; @@ -1831,32 +1900,18 @@ div.action-links, } /* Plugin/Theme Management Page */ - .wp-list-table.plugins { - position: relative; - margin-bottom: 15px; - } - - #wpbody-content .wp-list-table.plugins thead .column-description, - #wpbody-content .wp-list-table.plugins tfoot .column-description, - .wp-list-table.plugins th#description { + .wp-list-table.plugins .toggle-row { display: none; } - #wpbody-content .wp-list-table.plugins, - #wpbody-content .wp-list-table.plugins thead, - #wpbody-content .wp-list-table.plugins tbody, - #wpbody-content .wp-list-table.plugins tr, - #wpbody-content .wp-list-table.plugins .column-description, - #wpbody-content .wp-list-table.plugins .plugin-title, - #wpbody-content .wp-list-table.plugins .theme-title, - #wpbody-content .wp-list-table.plugins .plugin-update, - #wpbody-content .wp-list-table.plugins .manage-column.column-name { + #wpbody-content .wp-list-table.plugins td { display: block; width: auto; + padding: 10px 9px; /* reset from other list tables that have a label at this width */ } - .active, .inactive { - padding-top: 0; + #wpbody-content .wp-list-table.plugins .column-description { + padding-top: 2px; } .wp-list-table.plugins .plugin-title, @@ -1865,11 +1920,9 @@ div.action-links, padding-bottom: 4px; } - .plugins tr.active + tr.inactive th.check-column, .plugins tr.active + tr.inactive td, .wp-list-table.plugins .plugin-title, - .wp-list-table.plugins .theme-title, - .wp-list-table.plugins tbody th { + .wp-list-table.plugins .theme-title { -webkit-box-shadow: none; box-shadow: none; } @@ -1878,7 +1931,9 @@ div.action-links, padding: 1px 0 0; } - .plugins tr.active + tr.inactive td.column-description { + .plugins tr.active + tr.inactive th.check-column, + .plugins tr.active + tr.inactive td.column-description, + .plugins .plugin-update-tr:before { -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.1); box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.1); } @@ -1888,69 +1943,23 @@ div.action-links, border-top: none; } - .wp-list-table.plugins .column-description { - padding-top: 0; + /* mimic the checkbox th */ + .plugins .plugin-update-tr:before { + content: ''; + display: table-cell; } - .wp-list-table.plugins .manage-column.column-name, - .wp-list-table.plugins .column-description, - .wp-list-table.plugins .plugin-title, - .wp-list-table.plugins .theme-title { - padding-right: 12px; - padding-left: 46px; + .plugins .active.update + .plugin-update-tr:before { + border-left: 4px solid #d54e21; + background-color: #fef7f1; } - .wp-list-table.plugins .manage-column.column-name { - padding-top: 11px; - padding-bottom: 12px; + .plugins .plugin-update-tr .plugin-update { + border-left: none; } - .wp-list-table.plugins .manage-column.column-name.sortable { - padding: 4px 12px 4px 36px; - } - - .wp-list-table.plugins tr { - position: relative; - } - - .wp-list-table.plugins th.check-column, - .wp-list-table.plugins thead td.check-column, - .wp-list-table.plugins tfoot td.check-column, - .wp-list-table.plugins tr.update th.check-column { - position: absolute; - height: auto; - top: 0; - bottom: 0; - left: 0; - padding-left: 2px; - padding-top: 18px; - } - - .wp-list-table.plugins thead td.check-column, - .wp-list-table.plugins tfoot td.check-column { - padding-left: 3px; - padding-top: 11px; - background: none; - } - - .plugins tbody th.check-column input[type="checkbox"] { - margin-top: -3px; - margin-left: 9px; - } - - .plugins tbody .active th.check-column input[type="checkbox"], - .plugins tbody .active.update th.check-column input[type="checkbox"] { - margin-left: 5px; - } - - .wp-list-table.plugins thead .check-column input, - .wp-list-table.plugins tfoot .check-column input { - margin-top: -2px; - margin-left: 8px; - } - - .wp-list-table.plugins .active th.check-column { - background: none; + .plugin-update-tr .update-message { + margin-left: 0; } .wp-list-table.plugins .plugin-title strong, @@ -1991,13 +2000,3 @@ div.action-links, box-shadow: inset 0 -1px 0 rgba(0,0,0,0.1); } } - -/* Smartphone */ -@media screen and (max-width: 600px) { - /* Remove slug column from taxonomy list page - and role column from users list page */ - .tags .column-slug, - .users .column-role { - display: none; - } -} diff --git a/src/wp-admin/includes/class-wp-comments-list-table.php b/src/wp-admin/includes/class-wp-comments-list-table.php index bee725ec02..86db55f85d 100644 --- a/src/wp-admin/includes/class-wp-comments-list-table.php +++ b/src/wp-admin/includes/class-wp-comments-list-table.php @@ -395,7 +395,7 @@ class WP_Comments_List_Table extends WP_List_Table { $this->display_tablenav( 'top' ); ?> - +
print_column_headers(); ?> @@ -466,98 +466,102 @@ class WP_Comments_List_Table extends WP_List_Table { return; } + if ( $primary !== $column_name ) { + return ''; + } + $post = get_post(); $the_comment_status = wp_get_comment_status( $comment->comment_ID ); $out = ''; - if ( $primary === $column_name ) { - $del_nonce = esc_html( '_wpnonce=' . wp_create_nonce( "delete-comment_$comment->comment_ID" ) ); - $approve_nonce = esc_html( '_wpnonce=' . wp_create_nonce( "approve-comment_$comment->comment_ID" ) ); + $del_nonce = esc_html( '_wpnonce=' . wp_create_nonce( "delete-comment_$comment->comment_ID" ) ); + $approve_nonce = esc_html( '_wpnonce=' . wp_create_nonce( "approve-comment_$comment->comment_ID" ) ); - $url = "comment.php?c=$comment->comment_ID"; + $url = "comment.php?c=$comment->comment_ID"; - $approve_url = esc_url( $url . "&action=approvecomment&$approve_nonce" ); - $unapprove_url = esc_url( $url . "&action=unapprovecomment&$approve_nonce" ); - $spam_url = esc_url( $url . "&action=spamcomment&$del_nonce" ); - $unspam_url = esc_url( $url . "&action=unspamcomment&$del_nonce" ); - $trash_url = esc_url( $url . "&action=trashcomment&$del_nonce" ); - $untrash_url = esc_url( $url . "&action=untrashcomment&$del_nonce" ); - $delete_url = esc_url( $url . "&action=deletecomment&$del_nonce" ); + $approve_url = esc_url( $url . "&action=approvecomment&$approve_nonce" ); + $unapprove_url = esc_url( $url . "&action=unapprovecomment&$approve_nonce" ); + $spam_url = esc_url( $url . "&action=spamcomment&$del_nonce" ); + $unspam_url = esc_url( $url . "&action=unspamcomment&$del_nonce" ); + $trash_url = esc_url( $url . "&action=trashcomment&$del_nonce" ); + $untrash_url = esc_url( $url . "&action=untrashcomment&$del_nonce" ); + $delete_url = esc_url( $url . "&action=deletecomment&$del_nonce" ); - // Preorder it: Approve | Reply | Quick Edit | Edit | Spam | Trash. - $actions = array( - 'approve' => '', 'unapprove' => '', - 'reply' => '', - 'quickedit' => '', - 'edit' => '', - 'spam' => '', 'unspam' => '', - 'trash' => '', 'untrash' => '', 'delete' => '' - ); + // Preorder it: Approve | Reply | Quick Edit | Edit | Spam | Trash. + $actions = array( + 'approve' => '', 'unapprove' => '', + 'reply' => '', + 'quickedit' => '', + 'edit' => '', + 'spam' => '', 'unspam' => '', + 'trash' => '', 'untrash' => '', 'delete' => '' + ); - // Not looking at all comments. - if ( $comment_status && 'all' != $comment_status ) { - if ( 'approved' == $the_comment_status ) { - $actions['unapprove'] = "" . __( 'Unapprove' ) . ''; - } elseif ( 'unapproved' == $the_comment_status ) { - $actions['approve'] = "" . __( 'Approve' ) . ''; - } - } else { - $actions['approve'] = "" . __( 'Approve' ) . ''; - $actions['unapprove'] = "" . __( 'Unapprove' ) . ''; + // Not looking at all comments. + if ( $comment_status && 'all' != $comment_status ) { + if ( 'approved' == $the_comment_status ) { + $actions['unapprove'] = "" . __( 'Unapprove' ) . ''; + } elseif ( 'unapproved' == $the_comment_status ) { + $actions['approve'] = "" . __( 'Approve' ) . ''; } - - if ( 'spam' != $the_comment_status ) { - $actions['spam'] = "" . /* translators: mark as spam link */ _x( 'Spam', 'verb' ) . ''; - } elseif ( 'spam' == $the_comment_status ) { - $actions['unspam'] = "" . _x( 'Not Spam', 'comment' ) . ''; - } - - if ( 'trash' == $the_comment_status ) { - $actions['untrash'] = "" . __( 'Restore' ) . ''; - } - - if ( 'spam' == $the_comment_status || 'trash' == $the_comment_status || !EMPTY_TRASH_DAYS ) { - $actions['delete'] = "" . __( 'Delete Permanently' ) . ''; - } else { - $actions['trash'] = "" . _x( 'Trash', 'verb' ) . ''; - } - - if ( 'spam' != $the_comment_status && 'trash' != $the_comment_status ) { - $actions['edit'] = "". __( 'Edit' ) . ''; - - $format = '%s'; - - $actions['quickedit'] = sprintf( $format, $comment->comment_ID, $post->ID, 'edit', 'vim-q comment-inline',esc_attr__( 'Edit this item inline' ), __( 'Quick Edit' ) ); - - $actions['reply'] = sprintf( $format, $comment->comment_ID, $post->ID, 'replyto', 'vim-r comment-inline', esc_attr__( 'Reply to this comment' ), __( 'Reply' ) ); - } - - /** This filter is documented in wp-admin/includes/dashboard.php */ - $actions = apply_filters( 'comment_row_actions', array_filter( $actions ), $comment ); - - $i = 0; - $out .= '
'; - foreach ( $actions as $action => $link ) { - ++$i; - ( ( ( 'approve' == $action || 'unapprove' == $action ) && 2 === $i ) || 1 === $i ) ? $sep = '' : $sep = ' | '; - - // Reply and quickedit need a hide-if-no-js span when not added with ajax - if ( ( 'reply' == $action || 'quickedit' == $action ) && ! defined('DOING_AJAX') ) - $action .= ' hide-if-no-js'; - elseif ( ( $action == 'untrash' && $the_comment_status == 'trash' ) || ( $action == 'unspam' && $the_comment_status == 'spam' ) ) { - if ( '1' == get_comment_meta( $comment->comment_ID, '_wp_trash_meta_status', true ) ) - $action .= ' approve'; - else - $action .= ' unapprove'; - } - - $out .= "$sep$link"; - } - $out .= '
'; + } else { + $actions['approve'] = "" . __( 'Approve' ) . ''; + $actions['unapprove'] = "" . __( 'Unapprove' ) . ''; } + if ( 'spam' != $the_comment_status ) { + $actions['spam'] = "" . /* translators: mark as spam link */ _x( 'Spam', 'verb' ) . ''; + } elseif ( 'spam' == $the_comment_status ) { + $actions['unspam'] = "" . _x( 'Not Spam', 'comment' ) . ''; + } + + if ( 'trash' == $the_comment_status ) { + $actions['untrash'] = "" . __( 'Restore' ) . ''; + } + + if ( 'spam' == $the_comment_status || 'trash' == $the_comment_status || !EMPTY_TRASH_DAYS ) { + $actions['delete'] = "" . __( 'Delete Permanently' ) . ''; + } else { + $actions['trash'] = "" . _x( 'Trash', 'verb' ) . ''; + } + + if ( 'spam' != $the_comment_status && 'trash' != $the_comment_status ) { + $actions['edit'] = "". __( 'Edit' ) . ''; + + $format = '%s'; + + $actions['quickedit'] = sprintf( $format, $comment->comment_ID, $post->ID, 'edit', 'vim-q comment-inline',esc_attr__( 'Edit this item inline' ), __( 'Quick Edit' ) ); + + $actions['reply'] = sprintf( $format, $comment->comment_ID, $post->ID, 'replyto', 'vim-r comment-inline', esc_attr__( 'Reply to this comment' ), __( 'Reply' ) ); + } + + /** This filter is documented in wp-admin/includes/dashboard.php */ + $actions = apply_filters( 'comment_row_actions', array_filter( $actions ), $comment ); + + $i = 0; + $out .= '
'; + foreach ( $actions as $action => $link ) { + ++$i; + ( ( ( 'approve' == $action || 'unapprove' == $action ) && 2 === $i ) || 1 === $i ) ? $sep = '' : $sep = ' | '; + + // Reply and quickedit need a hide-if-no-js span when not added with ajax + if ( ( 'reply' == $action || 'quickedit' == $action ) && ! defined('DOING_AJAX') ) + $action .= ' hide-if-no-js'; + elseif ( ( $action == 'untrash' && $the_comment_status == 'trash' ) || ( $action == 'unspam' && $the_comment_status == 'spam' ) ) { + if ( '1' == get_comment_meta( $comment->comment_ID, '_wp_trash_meta_status', true ) ) + $action .= ' approve'; + else + $action .= ' unapprove'; + } + + $out .= "$sep$link"; + } + $out .= '
'; + + $out .= ''; + return $out; } diff --git a/src/wp-admin/includes/class-wp-list-table.php b/src/wp-admin/includes/class-wp-list-table.php index 18836b8b23..76fea0096c 100644 --- a/src/wp-admin/includes/class-wp-list-table.php +++ b/src/wp-admin/includes/class-wp-list-table.php @@ -497,6 +497,8 @@ class WP_List_Table { } $out .= ''; + $out .= ''; + return $out; } @@ -943,7 +945,7 @@ class WP_List_Table { * @param bool $with_id Whether to set the id attribute or not */ public function print_column_headers( $with_id = true ) { - list( $columns, $hidden, $sortable ) = $this->get_column_info(); + list( $columns, $hidden, $sortable, $primary ) = $this->get_column_info(); $current_url = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] ); $current_url = remove_query_arg( 'paged', $current_url ); @@ -977,6 +979,10 @@ class WP_List_Table { elseif ( in_array( $column_key, array( 'posts', 'comments', 'links' ) ) ) $class[] = 'num'; + if ( $column_key === $primary ) { + $class[] = 'column-primary'; + } + if ( isset( $sortable[$column_key] ) ) { list( $orderby, $desc_first ) = $sortable[$column_key]; @@ -1163,7 +1169,11 @@ class WP_List_Table { $classes .= ' hidden'; } - $attributes = "class='$classes'"; + // Comments column uses HTML in the display name with screen reader text. + // Instead of using esc_attr(), we strip tags to get closer to a user-friendly string. + $data = 'data-colname="' . wp_strip_all_tags( $column_display_name ) . '"'; + + $attributes = "class='$classes' $data"; if ( 'cb' == $column_name ) { echo '"; diff --git a/src/wp-admin/js/common.js b/src/wp-admin/js/common.js index 6366fdc8d3..10c2d14885 100644 --- a/src/wp-admin/js/common.js +++ b/src/wp-admin/js/common.js @@ -487,6 +487,11 @@ $(document).ready( function() { } }, 'td.has-row-actions' ); + // Toggle list table rows on small screens + $( 'tbody' ).on( 'click', '.toggle-row', function() { + $( this ).closest( 'tr' ).toggleClass( 'is-expanded' ); + }); + $('#default-password-nag-no').click( function() { setUserSetting('default_password_nag', 'hide'); $('div.default-password-nag').hide(); diff --git a/src/wp-admin/js/inline-edit-post.js b/src/wp-admin/js/inline-edit-post.js index ad83d7e20c..02f5c76ea2 100644 --- a/src/wp-admin/js/inline-edit-post.js +++ b/src/wp-admin/js/inline-edit-post.js @@ -133,7 +133,7 @@ inlineEditPost = { editRow = $('#inline-edit').clone(true); $( 'td', editRow ).attr( 'colspan', $( 'th:visible, td:visible', '.widefat:first thead' ).length ); - $(t.what+id).hide().after(editRow).after(''); + $(t.what+id).removeClass('is-expanded').hide().after(editRow).after(''); // populate the data rowData = $('#inline_'+id);
'; diff --git a/src/wp-admin/includes/class-wp-ms-sites-list-table.php b/src/wp-admin/includes/class-wp-ms-sites-list-table.php index f47c671e71..3db96518bb 100644 --- a/src/wp-admin/includes/class-wp-ms-sites-list-table.php +++ b/src/wp-admin/includes/class-wp-ms-sites-list-table.php @@ -403,7 +403,9 @@ class WP_MS_Sites_List_Table extends WP_List_Table { $classes .= ' hidden'; } - $attributes = "class='$classes'"; + $data = 'data-colname="' . wp_strip_all_tags( $column_display_name ) . '"'; + + $attributes = "class='$classes' $data"; if ( 'cb' === $column_name ) { echo ''; diff --git a/src/wp-admin/includes/class-wp-ms-users-list-table.php b/src/wp-admin/includes/class-wp-ms-users-list-table.php index df5fb66b6a..a73bf9c2bf 100644 --- a/src/wp-admin/includes/class-wp-ms-users-list-table.php +++ b/src/wp-admin/includes/class-wp-ms-users-list-table.php @@ -336,7 +336,9 @@ class WP_MS_Users_List_Table extends WP_List_Table { $classes .= ' hidden'; } - $attributes = "class='$classes'"; + $data = 'data-colname="' . wp_strip_all_tags( $column_display_name ) . '"'; + + $attributes = "class='$classes' $data"; if ( 'cb' === $column_name ) { echo ''; diff --git a/src/wp-admin/includes/class-wp-posts-list-table.php b/src/wp-admin/includes/class-wp-posts-list-table.php index 57ecdd78ca..a4f2ff2153 100644 --- a/src/wp-admin/includes/class-wp-posts-list-table.php +++ b/src/wp-admin/includes/class-wp-posts-list-table.php @@ -973,7 +973,11 @@ class WP_Posts_List_Table extends WP_List_Table { $classes .= ' hidden'; } - $attributes = "class='$classes'"; + // Comments column uses HTML in the display name with screen reader text. + // Instead of using esc_attr(), we strip tags to get closer to a user-friendly string. + $data = 'data-colname="' . wp_strip_all_tags( $column_display_name ) . '"'; + + $attributes = "class='$classes' $data"; if ( 'cb' === $column_name ) { echo ''; diff --git a/src/wp-admin/includes/class-wp-users-list-table.php b/src/wp-admin/includes/class-wp-users-list-table.php index 7dbc866f19..719007691d 100644 --- a/src/wp-admin/includes/class-wp-users-list-table.php +++ b/src/wp-admin/includes/class-wp-users-list-table.php @@ -419,7 +419,9 @@ class WP_Users_List_Table extends WP_List_Table { $classes .= ' hidden'; } - $attributes = "class='$classes'"; + $data = 'data-colname="' . wp_strip_all_tags( $column_display_name ) . '"'; + + $attributes = "class='$classes' $data"; if ( 'cb' === $column_name ) { $r .= "$checkbox