Make WordPress Core

Changeset 23727


Ignore:
Timestamp:
03/16/2013 04:47:19 AM (14 years ago)
Author:
markjaquith
Message:

Accessibility revamp for nav menus.

props lessbloat. fixes #14045

Location:
trunk/wp-admin
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/wp-admin/css/colors-fresh.css

    r23638 r23727  
    17881788        border: 1px solid #eeeeee;
    17891789        background: #fbfbfb;
    1790 }
    1791 
    1792 .menu-settings {
    1793         border-top: 1px solid #eeeeee;
    17941790}
    17951791
  • trunk/wp-admin/css/wp-admin.css

    r23725 r23727  
    73067306}
    73077307
     7308.menu-edit #post-body-content h3 {
     7309        margin: 0 0 10px;
     7310}
     7311
    73087312.menu-settings {
    73097313        margin-top: 2em;
    7310         padding-top: 16px;
    73117314        overflow: hidden;
    73127315}
    … …  
    78007803        border-bottom-left-radius: 3px;
    78017804        border-bottom-right-radius: 3px;
     7805}
     7806
     7807.menu-item-settings .field-move a {
     7808        display: none;
     7809        margin: 0 2px;
    78027810}
    78037811
  • trunk/wp-admin/includes/nav-menu.php

    r23712 r23727  
    9090                        <dl class="menu-item-bar">
    9191                                <dt class="menu-item-handle">
    92                                         <span class="item-title"><?php echo esc_html( $title ); ?> <span class="is-submenu" <?php echo $submenu_text; ?>><?php _e( 'sub item' ); ?></span></span>
     92                                        <span class="item-title"><span class="menu-item-title"><?php echo esc_html( $title ); ?></span> <span class="is-submenu" <?php echo $submenu_text; ?>><?php _e( 'sub item' ); ?></span></span>
    9393                                        <span class="item-controls">
    9494                                                <span class="item-type"><?php echo esc_html( $item->type_label ); ?></span>
    … …  
    171171                                                <textarea id="edit-menu-item-description-<?php echo $item_id; ?>" class="widefat edit-menu-item-description" rows="3" cols="20" name="menu-item-description[<?php echo $item_id; ?>]"><?php echo esc_html( $item->description ); // textarea_escaped ?></textarea>
    172172                                                <span class="description"><?php _e('The description will be displayed in the menu if the current theme supports it.'); ?></span>
     173                                        </label>
     174                                </p>
     175
     176                                <p class="field-move description description-wide">
     177                                        <label>
     178                                                <?php _e( 'Move' ); ?>
     179                                                <a href="#" class="menus-move-up"><?php _e( 'Up one' ); ?></a>
     180                                                <a href="#" class="menus-move-down"><?php _e( 'Down one' ); ?></a>
     181                                                <a href="#" class="menus-move-left"></a>
     182                                                <a href="#" class="menus-move-right"></a>
     183                                                <a href="#" class="menus-move-top"><?php _e( 'To the top' ); ?></a>
    173184                                        </label>
    174185                                </p>
  • trunk/wp-admin/js/nav-menu.js

    r23707 r23727  
    4646                                this.initSortables();
    4747
    48                         if( oneThemeLocationNoMenus )
     48                        if( menu.oneThemeLocationNoMenus )
    4949                                $( '#posttype-page' ).addSelectedToMenu( api.addMenuItemToBottom );
    5050
    … …  
    163163                                        return this.each(function() {
    164164                                                var t = $(this), menuItems = {},
    165                                                         checkboxes = ( oneThemeLocationNoMenus && 0 == t.find('.tabs-panel-active .categorychecklist li input:checked').length ) ? t.find('#page-all li input[type="checkbox"]') : t.find('.tabs-panel-active .categorychecklist li input:checked'),
     165                                                        checkboxes = ( menu.oneThemeLocationNoMenus && 0 == t.find('.tabs-panel-active .categorychecklist li input:checked').length ) ? t.find('#page-all li input[type="checkbox"]') : t.find('.tabs-panel-active .categorychecklist li input:checked'),
    166166                                                        re = new RegExp('menu-item\\[(\[^\\]\]*)');
    167167
    … …  
    272272                },
    273273
     274                countMenuItems : function( depth ) {
     275                        return $( '.menu-item-depth-' + depth ).length;
     276                },
     277
     278                moveMenuItem : function( $this, dir ) {
     279
     280                        var menuItems = $('#menu-to-edit li');
     281                                menuItemsCount = menuItems.length,
     282                                thisItem = $this.parents( 'li.menu-item' ),
     283                                thisItemChildren = thisItem.childMenuItems(),
     284                                thisItemData = thisItem.getItemData(),
     285                                thisItemDepth = parseInt( thisItem.menuItemDepth() ),
     286                                thisItemPosition = parseInt( thisItem.index() ),
     287                                nextItem = thisItem.next(),
     288                                nextItemChildren = nextItem.childMenuItems(),
     289                                nextItemDepth = parseInt( nextItem.menuItemDepth() ) + 1,
     290                                prevItem = thisItem.prev(),
     291                                prevItemDepth = parseInt( prevItem.menuItemDepth() ),
     292                                prevItemId = prevItem.getItemData()['menu-item-db-id'];
     293
     294                        switch ( dir ) {
     295                        case 'up':
     296                                var newItemPosition = thisItemPosition - 1;
     297
     298                                // Already at top
     299                                if ( 0 === thisItemPosition )
     300                                        break;
     301
     302                                // If a sub item is moved to top, shift it to 0 depth
     303                                if ( 0 === newItemPosition && 0 !== thisItemDepth )
     304                                        thisItem.moveHorizontally( 0, thisItemDepth );
     305
     306                                // If prev item is sub item, shift to match depth
     307                                if ( 0 !== prevItemDepth )
     308                                        thisItem.moveHorizontally( prevItemDepth, thisItemDepth );
     309
     310                                // Does this item have sub items?
     311                                if ( thisItemChildren ) {
     312                                        var items = thisItem.add( thisItemChildren );
     313                                        // Move the entire block
     314                                        items.detach().insertBefore( menuItems.eq( newItemPosition ) ).updateParentMenuItemDBId();
     315                                } else {
     316                                        thisItem.detach().insertBefore( menuItems.eq( newItemPosition ) ).updateParentMenuItemDBId();
     317                                }
     318                                break;
     319                        case 'down':
     320                                // Does this item have sub items?
     321                                if ( thisItemChildren ) {
     322                                        var items = thisItem.add( thisItemChildren ),
     323                                                nextItem = menuItems.eq( items.length + thisItemPosition ),
     324                                                nextItemChildren = 0 !== nextItem.childMenuItems().length;
     325
     326                                        if ( nextItemChildren ) {
     327                                                var newDepth = parseInt( nextItem.menuItemDepth() ) + 1;
     328                                                thisItem.moveHorizontally( newDepth, thisItemDepth );
     329                                        }
     330
     331                                        // Have we reached the bottom?
     332                                        if ( menuItemsCount === thisItemPosition + items.length )
     333                                                break;
     334
     335                                        items.detach().insertAfter( menuItems.eq( thisItemPosition + items.length ) ).updateParentMenuItemDBId();
     336                                } else {
     337                                        // If next item has sub items, shift depth
     338                                        if ( 0 !== nextItemChildren.length )
     339                                                thisItem.moveHorizontally( nextItemDepth, thisItemDepth );
     340
     341                                        // Have we reached the bottom
     342                                        if ( menuItemsCount === thisItemPosition + 1 )
     343                                                break;
     344                                        thisItem.detach().insertAfter( menuItems.eq( thisItemPosition + 1 ) ).updateParentMenuItemDBId();
     345                                }
     346                                break;
     347                        case 'top':
     348                                // Already at top
     349                                if ( 0 === thisItemPosition )
     350                                        break;
     351                                // Does this item have sub items?
     352                                if ( thisItemChildren ) {
     353                                        var items = thisItem.add( thisItemChildren );
     354                                        // Move the entire block
     355                                        items.detach().insertBefore( menuItems.eq( 0 ) ).updateParentMenuItemDBId();
     356                                } else {
     357                                        thisItem.detach().insertBefore( menuItems.eq( 0 ) ).updateParentMenuItemDBId();
     358                                }
     359                                break;
     360                        case 'left':
     361                                // As far left as possible
     362                                if ( 0 === thisItemDepth )
     363                                        break;
     364                                thisItem.shiftHorizontally( -1 );
     365                                break;
     366                        case 'right':
     367                                // Can't be sub item at top
     368                                if ( 0 === thisItemPosition )
     369                                        break;
     370                                // Already sub item of prevItem
     371                                if ( thisItemData['menu-item-parent-id'] === prevItemId )
     372                                        break;
     373                                thisItem.shiftHorizontally( 1 );
     374                                break;
     375                        }
     376                        $this.focus();
     377                        api.registerChange();
     378                        api.refreshKeyboardAccessibility();
     379                        api.refreshAdvancedAccessibility();
     380                },
     381
    274382                initAccessibility : function() {
     383                        api.refreshKeyboardAccessibility();
     384                        api.refreshAdvancedAccessibility();
     385
     386                        // Events
     387                        $( '.menus-move-up' ).on( 'click', function ( e ) {
     388                                api.moveMenuItem( $( this ).parents( 'li.menu-item' ).find( 'a.item-edit' ), 'up' );
     389                                e.preventDefault();
     390                        });
     391                        $( '.menus-move-down' ).on( 'click', function ( e ) {
     392                                api.moveMenuItem( $( this ).parents( 'li.menu-item' ).find( 'a.item-edit' ), 'down' );
     393                                e.preventDefault();
     394                        });
     395                        $( '.menus-move-top' ).on( 'click', function ( e ) {
     396                                api.moveMenuItem( $( this ).parents( 'li.menu-item' ).find( 'a.item-edit' ), 'top' );
     397                                e.preventDefault();
     398                        });
     399                        $( '.menus-move-left' ).on( 'click', function ( e ) {
     400                                api.moveMenuItem( $( this ).parents( 'li.menu-item' ).find( 'a.item-edit' ), 'left' );
     401                                e.preventDefault();
     402                        });
     403                        $( '.menus-move-right' ).on( 'click', function ( e ) {
     404                                api.moveMenuItem( $( this ).parents( 'li.menu-item' ).find( 'a.item-edit' ), 'right' );
     405                                e.preventDefault();
     406                        });
     407                },
     408
     409                refreshAdvancedAccessibility : function() {
     410
     411                        // Hide all links by default
     412                        $( '.menu-item-settings .field-move a' ).hide();
     413
     414                        $( '.item-edit' ).each( function() {
     415                                var $this = $(this),
     416                                        movement = [],
     417                                        availableMovement = '',
     418                                        menuItem = $this.parents( 'li.menu-item' ).first(),
     419                                        depth = menuItem.menuItemDepth(),
     420                                        isPrimaryMenuItem = ( 0 === depth ),
     421                                        itemName = $this.parents( '.menu-item-handle' ).find( '.menu-item-title' ).text(),
     422                                        position = parseInt( menuItem.index() ),
     423                                        prevItemDepth = ( isPrimaryMenuItem ) ? depth : parseInt( depth - 1 ),
     424                                        prevItemNameLeft = menuItem.prevAll('.menu-item-depth-' + prevItemDepth).first().find( '.menu-item-title' ).text(),
     425                                        prevItemNameRight = menuItem.prevAll('.menu-item-depth-' + depth).first().find( '.menu-item-title' ).text(),
     426                                        totalMenuItems = $('#menu-to-edit li').length,
     427                                        hasSameDepthSibling = menuItem.nextAll( '.menu-item-depth-' + depth ).length;
     428
     429                                // Where can they move this menu item?
     430                                if ( 0 !== position ) {
     431                                        var thisLink = menuItem.find( '.menus-move-up' ),
     432                                                thisLinkText = thisLink.text();
     433                                        thisLink.prop('title', menus.move + ' ' + thisLinkText).show();
     434                                }
     435
     436                                if ( 0 !== position && isPrimaryMenuItem ) {
     437                                        var thisLink = menuItem.find( '.menus-move-top' ),
     438                                                thisLinkText = thisLink.text();
     439                                        thisLink.prop('title', menus.move + ' ' + thisLinkText).show();
     440                                }
     441
     442                                if ( position + 1 !== totalMenuItems && 0 !== position ) {
     443                                        var thisLink = menuItem.find( '.menus-move-down' ),
     444                                                thisLinkText = thisLink.text();
     445                                        thisLink.prop('title', menus.move + ' ' + thisLinkText).show();
     446                                }
     447
     448                                if ( 0 === position && 0 !== hasSameDepthSibling ) {
     449                                        var thisLink = menuItem.find( '.menus-move-down' ),
     450                                                thisLinkText = thisLink.text();
     451                                        thisLink.prop('title', menus.move + ' ' + thisLinkText).show();
     452                                }
     453
     454                                if ( ! isPrimaryMenuItem ) {
     455                                        var thisLink = menuItem.find( '.menus-move-left' ),
     456                                                thisLinkText = menus.outFrom + ' ' + prevItemNameLeft;
     457                                        thisLink.prop('title', menus.move + ' ' + thisLinkText).html(thisLinkText).show();
     458                                }
     459
     460                                if ( 0 !== position ) {
     461                                        if ( menuItem.find( '.menu-item-data-parent-id' ).val() !== menuItem.prev().find( '.menu-item-data-db-id' ).val() ) {
     462                                                var thisLink = menuItem.find( '.menus-move-right' ),
     463                                                        thisLinkText = menus.under + ' ' + prevItemNameRight;
     464                                                thisLink.prop('title', menus.move + ' ' + thisLinkText).html(thisLinkText).show();
     465                                        }
     466                                }
     467
     468                                if ( isPrimaryMenuItem ) {
     469                                        var primaryItems = $( '.menu-item-depth-0' ),
     470                                                itemPosition = primaryItems.index( menuItem ) + 1,
     471                                                totalMenuItems = primaryItems.length,
     472
     473                                                // String together help text for primary menu items
     474                                                title = itemName + '. ' + menus.menuFocus.replace('%d', itemPosition).replace('%d', totalMenuItems) + '.';
     475                                } else {
     476                                        var parentItem = menuItem.prevAll( '.menu-item-depth-' + parseInt( depth - 1 ) ).first(),
     477                                                parentItemId = parentItem.find( '.menu-item-data-db-id' ).val(),
     478                                                parentItemName = parentItem.find( '.menu-item-title' ).text(),
     479                                                subItems = $( '.menu-item .menu-item-data-parent-id[value="' + parentItemId + '"]' ),
     480                                                itemPosition = $(subItems.parents('.menu-item').get().reverse()).index( menuItem ) + 1;
     481
     482                                                // String together help text for sub menu items
     483
     484                                                title = itemName + '. ' + menus.subMenuFocus.replace('%d', itemPosition) + parentItemName + '.';
     485                                }
     486
     487                                $this.prop('title', title).html( title );
     488                        });
     489                },
     490
     491                refreshKeyboardAccessibility : function() {
    275492                        $( '.item-edit' ).off( 'focus' ).on( 'focus', function(){
    276                                 $(this).on( 'keydown', function(e){
     493                                $(this).off( 'keydown' ).on( 'keydown', function(e){
    277494
    278495                                        var $this = $(this);
    … …  
    285502                                        $this.off('keydown');
    286503
    287                                         var menuItems = $('#menu-to-edit li');
    288                                                 menuItemsCount = menuItems.length,
    289                                                 thisItem = $this.parents( 'li.menu-item' ),
    290                                                 thisItemChildren = thisItem.childMenuItems(),
    291                                                 thisItemData = thisItem.getItemData(),
    292                                                 thisItemDepth = parseInt( thisItem.menuItemDepth() ),
    293                                                 thisItemPosition = parseInt( thisItem.index() ),
    294                                                 nextItem = thisItem.next(),
    295                                                 nextItemChildren = nextItem.childMenuItems(),
    296                                                 nextItemDepth = parseInt( nextItem.menuItemDepth() ) + 1,
    297                                                 prevItem = thisItem.prev(),
    298                                                 prevItemDepth = parseInt( prevItem.menuItemDepth() ),
    299                                                 prevItemId = prevItem.getItemData()['menu-item-db-id'];
    300 
    301504                                        // Bail if there is only one menu item
    302                                         if ( 1 === menuItemsCount )
     505                                        if ( 1 === $('#menu-to-edit li').length )
    303506                                                return;
    304507
    … …  
    310513                                        switch ( arrows[e.which] ) {
    311514                                        case 'up':
    312                                                 var newItemPosition = thisItemPosition - 1;
    313 
    314                                                 // Already at top
    315                                                 if ( 0 === thisItemPosition )
    316                                                         break;
    317 
    318                                                 // If a sub item is moved to top, shift it to 0 depth
    319                                                 if ( 0 === newItemPosition && 0 !== thisItemDepth )
    320                                                         thisItem.moveHorizontally( 0, thisItemDepth );
    321 
    322                                                 // If prev item is sub item, shift to match depth
    323                                                 if ( 0 !== prevItemDepth )
    324                                                         thisItem.moveHorizontally( prevItemDepth, thisItemDepth );
    325 
    326                                                 // Does this item have sub items?
    327                                                 if ( thisItemChildren ) {
    328                                                         var items = thisItem.add( thisItemChildren );
    329                                                         // Move the entire block
    330                                                         items.detach().insertBefore( menuItems.eq( newItemPosition ) );
    331                                                 } else {
    332                                                         thisItem.detach().insertBefore( menuItems.eq( newItemPosition ) );
    333                                                 }
     515                                                api.moveMenuItem( $this, 'up' );
    334516                                                break;
    335517                                        case 'down':
    336                                                 // Does this item have sub items?
    337                                                 if ( thisItemChildren ) {
    338                                                         var items = thisItem.add( thisItemChildren ),
    339                                                                 nextItem = menuItems.eq( items.length + thisItemPosition ),
    340                                                                 nextItemChildren = 0 !== nextItem.childMenuItems().length;
    341 
    342                                                         if ( nextItemChildren ) {
    343                                                                 var newDepth = parseInt( nextItem.menuItemDepth() ) + 1;
    344                                                                 thisItem.moveHorizontally( newDepth, thisItemDepth );
    345                                                         }
    346 
    347                                                         // Have we reached the bottom?
    348                                                         if ( menuItemsCount === thisItemPosition + items.length )
    349                                                                 break;
    350 
    351                                                         items.detach().insertAfter( menuItems.eq( thisItemPosition + items.length ) );
    352                                                 } else {
    353                                                         // If next item has sub items, shift depth
    354                                                         if ( 0 !== nextItemChildren.length )
    355                                                                 thisItem.moveHorizontally( nextItemDepth, thisItemDepth );
    356 
    357                                                         // Have we reached the bottom
    358                                                         if ( menuItemsCount === thisItemPosition + 1 )
    359                                                                 break;
    360                                                         thisItem.detach().insertAfter( menuItems.eq( thisItemPosition + 1 ) );
    361                                                 }
     518                                                api.moveMenuItem( $this, 'down' );
    362519                                                break;
    363520                                        case 'left':
    364                                                 // As far left as possible
    365                                                 if ( 0 === thisItemDepth )
    366                                                         break;
    367                                                 thisItem.shiftHorizontally( -1 );
     521                                                api.moveMenuItem( $this, 'left' );
    368522                                                break;
    369523                                        case 'right':
    370                                                 // Can't be sub item at top
    371                                                 if ( 0 === thisItemPosition )
    372                                                         break;
    373                                                 // Already sub item of prevItem
    374                                                 if ( thisItemData['menu-item-parent-id'] === prevItemId )
    375                                                         break;
    376                                                 thisItem.shiftHorizontally( 1 );
     524                                                api.moveMenuItem( $this, 'right' );
    377525                                                break;
    378526                                        }
    379                                         api.registerChange();
    380527                                        // Put focus back on same menu item
    381528                                        $( '#edit-' + thisItemData['menu-item-db-id'] ).focus();
    382529                                        return false;
    383530                                });
    384                         }).blur(function () {
    385                                 $(this).off( 'keydown' );
    386531                        });
    387532                },
    … …  
    513658                                                ui.item[0].style.right = 0;
    514659                                        }
     660
     661                                        api.refreshKeyboardAccessibility();
     662                                        api.refreshAdvancedAccessibility();
    515663                                },
    516664                                change: function(e, ui) {
    … …  
    774922                addMenuItemToBottom : function( menuMarkup, req ) {
    775923                        $(menuMarkup).hideAdvancedMenuItemFields().appendTo( api.targetList );
    776                         api.initAccessibility();
     924                        api.refreshKeyboardAccessibility();
     925                        api.refreshAdvancedAccessibility();
    777926                },
    778927
    779928                addMenuItemToTop : function( menuMarkup, req ) {
    780929                        $(menuMarkup).hideAdvancedMenuItemFields().prependTo( api.targetList );
    781                         api.initAccessibility();
     930                        api.refreshKeyboardAccessibility();
     931                        api.refreshAdvancedAccessibility();
    782932                },
    783933
  • trunk/wp-admin/nav-menus.php

    r23707 r23727  
    354354$page_count = wp_count_posts( 'page' );
    355355$one_theme_location_no_menus = ( 1 == count( get_registered_nav_menus() ) && ! $add_new_screen && empty( $nav_menus ) && ! empty( $page_count->publish ) ) ? true : false;
     356
     357$l10n = array(
     358        "oneThemeLocationNoMenus" => ( $one_theme_location_no_menus ) ? 'true' : 'false',
     359        "move" => __( 'Move' ),
     360        "menuFocus" => __( 'Menu item %d of %d' ),
     361        "subMenuFocus" => __( 'Sub item number %d under' ),
     362        "under" => __( 'Under' ),
     363        "outFrom" => __( 'Out from under' )
     364);
     365wp_localize_script( 'nav-menu', 'menus', $l10n );
    356366
    357367// Redirect to add screen if there are no menus and this users has either zero, or more than 1 theme locations
    … …  
    544554                                                <div id="post-body-content">
    545555                                                        <?php if ( ! $add_new_screen ) : ?>
     556                                                        <h3><?php _e( 'Menu Structure' ); ?></h3>
    546557                                                        <?php $starter_copy = ( $one_theme_location_no_menus ) ? __( 'Edit your default menu by adding or removing items. Drag each item into the order you prefer. Click Create Menu to save your changes.' ) : __( 'Drag each item into the order you prefer. Click an item to reveal additional configuration options.' ); ?>
    547558                                                        <div class="drag-instructions post-body-plain" <?php if ( isset( $menu_items ) && 0 == count( $menu_items ) ) { ?>style="display: none;"<?php } ?>>
    … …  
    560571                                                        <?php endif; ?>
    561572                                                        <div class="menu-settings" <?php if ( $one_theme_location_no_menus ) { ?>style="display: none;"<?php } ?>>
     573                                                                <h3><?php _e( 'Menu Settings' ); ?></h3>
    562574                                                                <?php
    563575                                                                if ( ! isset( $auto_add ) ) {
    … …  
    613625        </div><!-- /#nav-menus-frame -->
    614626</div><!-- /.wrap-->
    615 <script type="text/javascript">var oneThemeLocationNoMenus = <?php if ( $one_theme_location_no_menus ) echo 'true'; else echo 'false'; ?>;</script>
    616627<?php include( './admin-footer.php' ); ?>
Note: See TracChangeset for help on using the changeset viewer.