WordPress.org

Make WordPress Core

Changeset 32883


Ignore:
Timestamp:
06/20/2015 02:15:04 AM (4 years ago)
Author:
azaozz
Message:

Editor: add ARIA labels to the Quicktags buttons to improve accessibility.
Props afercia, azaozz. Fixes #31522.

Location:
trunk/src/wp-includes
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/js/quicktags.js

    r32677 r32883  
    236236        }
    237237    };
     238
     239    function _escape( text ) {
     240        text = text || '';
     241        text = text.replace( /&([^#])(?![a-z1-4]{1,8};)/gi, '&$1' );
     242        return text.replace( /</g, '&lt;' ).replace( />/g, '&gt;' ).replace( /"/g, '&quot;' ).replace( /'/g, '&#039;' );
     243    }
    238244
    239245    qt.instances = {};
     
    328334     * @param int priority Optional. Number representing the desired position of the button in the toolbar. 1 - 9 = first, 11 - 19 = second, 21 - 29 = third, etc.
    329335     * @param string instance Optional. Limit the button to a specific instance of Quicktags, add to all instances if not present.
     336     * @param attr object Optional. Used to pass additional attributes. Currently supports `ariaLabel` and `ariaLabelClose` (for "close tag" state)
    330337     * @return mixed null or the button object that is needed for back-compat.
    331338     */
    332     qt.addButton = function( id, display, arg1, arg2, access_key, title, priority, instance ) {
     339    qt.addButton = function( id, display, arg1, arg2, access_key, title, priority, instance, attr ) {
    333340        var btn;
    334341
     
    339346        priority = priority || 0;
    340347        arg2 = arg2 || '';
     348        attr = attr || {};
    341349
    342350        if ( typeof(arg1) === 'function' ) {
    343             btn = new qt.Button(id, display, access_key, title, instance);
     351            btn = new qt.Button( id, display, access_key, title, instance, attr );
    344352            btn.callback = arg1;
    345353        } else if ( typeof(arg1) === 'string' ) {
    346             btn = new qt.TagButton(id, display, arg1, arg2, access_key, title, instance);
     354            btn = new qt.TagButton( id, display, arg1, arg2, access_key, title, instance, attr );
    347355        } else {
    348356            return;
     
    400408
    401409    // a plain, dumb button
    402     qt.Button = function(id, display, access, title, instance) {
    403         var t = this;
    404         t.id = id;
    405         t.display = display;
    406         t.access = '';
    407         t.title = title || '';
    408         t.instance = instance || '';
     410    qt.Button = function( id, display, access, title, instance, attr ) {
     411        this.id = id;
     412        this.display = display;
     413        this.access = '';
     414        this.title = title || '';
     415        this.instance = instance || '';
     416        this.attr = attr || {};
    409417    };
    410418    qt.Button.prototype.html = function(idPrefix) {
    411         var title = this.title ? ' title="' + this.title + '"' : '',
    412             active, on, wp,
     419        var active, on, wp,
     420            title = this.title ? ' title="' + _escape( this.title ) + '"' : '',
     421            ariaLabel = this.attr && this.attr.ariaLabel ? ' aria-label="' + _escape( this.attr.ariaLabel ) + '"' : '',
     422            val = this.display ? ' value="' + _escape( this.display ) + '"' : '',
     423            id = this.id ? ' id="' + _escape( idPrefix + this.id ) + '"' : '',
    413424            dfw = ( wp = window.wp ) && wp.editor && wp.editor.dfw;
    414425
    415426        if ( this.id === 'fullscreen' ) {
    416             return '<button type="button" id="' + idPrefix + this.id + '" class="ed_button qt-dfw qt-fullscreen"' + title + '></button>';
     427            return '<button type="button"' + id + ' class="ed_button qt-dfw qt-fullscreen"' + title + ariaLabel + '></button>';
    417428        } else if ( this.id === 'dfw' ) {
    418429            active = dfw && dfw.isActive() ? '' : ' disabled="disabled"';
    419430            on = dfw && dfw.isOn() ? ' active' : '';
    420431
    421             return '<button type="button" id="' + idPrefix + this.id + '" class="ed_button qt-dfw' + on + '"' + title + active + '></button>';
    422         }
    423 
    424         return '<input type="button" id="' + idPrefix + this.id + '" class="ed_button button button-small"' + title + ' value="' + this.display + '" />';
     432            return '<button type="button"' + id + ' class="ed_button qt-dfw' + on + '"' + title + ariaLabel + active + '></button>';
     433        }
     434
     435        return '<input type="button"' + id + ' class="ed_button button button-small"' + title + ariaLabel + val + ' />';
    425436    };
    426437    qt.Button.prototype.callback = function(){};
    427438
    428439    // a button that inserts HTML tag
    429     qt.TagButton = function(id, display, tagStart, tagEnd, access, title, instance) {
     440    qt.TagButton = function( id, display, tagStart, tagEnd, access, title, instance, attr ) {
    430441        var t = this;
    431         qt.Button.call(t, id, display, access, title, instance);
     442        qt.Button.call( t, id, display, access, title, instance, attr );
    432443        t.tagStart = tagStart;
    433444        t.tagEnd = tagEnd;
    434445    };
    435446    qt.TagButton.prototype = new qt.Button();
    436     qt.TagButton.prototype.openTag = function(e, ed) {
    437         var t = this;
    438 
     447    qt.TagButton.prototype.openTag = function( element, ed ) {
    439448        if ( ! ed.openTags ) {
    440449            ed.openTags = [];
    441450        }
    442         if ( t.tagEnd ) {
    443             ed.openTags.push(t.id);
    444             e.value = '/' + e.value;
    445         }
    446     };
    447     qt.TagButton.prototype.closeTag = function(e, ed) {
    448         var t = this, i = t.isOpen(ed);
     451
     452        if ( this.tagEnd ) {
     453            ed.openTags.push( this.id );
     454            element.value = '/' + element.value;
     455
     456            if ( this.attr.ariaLabelClose ) {
     457                element.setAttribute( 'aria-label', this.attr.ariaLabelClose );
     458            }
     459        }
     460    };
     461    qt.TagButton.prototype.closeTag = function( element, ed ) {
     462        var i = this.isOpen(ed);
    449463
    450464        if ( i !== false ) {
    451             ed.openTags.splice(i, 1);
    452         }
    453 
    454         e.value = t.display;
     465            ed.openTags.splice( i, 1 );
     466        }
     467
     468        element.value = this.display;
     469
     470        if ( this.attr.ariaLabel ) {
     471            element.setAttribute( 'aria-label', this.attr.ariaLabel );
     472        }
    455473    };
    456474    // whether a tag is open or not. Returns false if not open, or current open depth of the tag
     
    545563    // the close tags button
    546564    qt.CloseButton = function() {
    547         qt.Button.call(this, 'close', quicktagsL10n.closeTags, '', quicktagsL10n.closeAllOpenTags);
     565        qt.Button.call( this, 'close', quicktagsL10n.closeTags, '', quicktagsL10n.closeAllOpenTags );
    548566    };
    549567
     
    576594    // the link button
    577595    qt.LinkButton = function() {
    578         qt.TagButton.call(this, 'link', 'link', '', '</a>');
     596        var attr = {
     597            ariaLabel: quicktagsL10n.link
     598        };
     599
     600        qt.TagButton.call( this, 'link', 'link', '', '</a>', '', '', '', attr );
    579601    };
    580602    qt.LinkButton.prototype = new qt.TagButton();
     
    592614
    593615        if ( t.isOpen(ed) === false ) {
    594             URL = prompt(quicktagsL10n.enterURL, defaultValue);
     616            URL = prompt( quicktagsL10n.enterURL, defaultValue );
    595617            if ( URL ) {
    596618                t.tagStart = '<a href="' + URL + '">';
     
    604626    // the img button
    605627    qt.ImgButton = function() {
    606         qt.TagButton.call(this, 'img', 'img', '', '');
     628        var attr = {
     629            ariaLabel: quicktagsL10n.image
     630        };
     631
     632        qt.TagButton.call( this, 'img', 'img', '', '', '', '', '', attr );
    607633    };
    608634    qt.ImgButton.prototype = new qt.TagButton();
     
    634660
    635661    qt.TextDirectionButton = function() {
    636         qt.Button.call(this, 'textdirection', quicktagsL10n.textdirection, '', quicktagsL10n.toggleTextdirection);
     662        qt.Button.call( this, 'textdirection', quicktagsL10n.textdirection, '', quicktagsL10n.toggleTextdirection );
    637663    };
    638664    qt.TextDirectionButton.prototype = new qt.Button();
     
    650676
    651677    // ensure backward compatibility
    652     edButtons[10] = new qt.TagButton('strong','b','<strong>','</strong>');
    653     edButtons[20] = new qt.TagButton('em','i','<em>','</em>'),
    654     edButtons[30] = new qt.LinkButton(), // special case
    655     edButtons[40] = new qt.TagButton('block','b-quote','\n\n<blockquote>','</blockquote>\n\n'),
    656     edButtons[50] = new qt.TagButton('del','del','<del datetime="' + _datetime + '">','</del>'),
    657     edButtons[60] = new qt.TagButton('ins','ins','<ins datetime="' + _datetime + '">','</ins>'),
    658     edButtons[70] = new qt.ImgButton(), // special case
    659     edButtons[80] = new qt.TagButton('ul','ul','<ul>\n','</ul>\n\n'),
    660     edButtons[90] = new qt.TagButton('ol','ol','<ol>\n','</ol>\n\n'),
    661     edButtons[100] = new qt.TagButton('li','li','\t<li>','</li>\n'),
    662     edButtons[110] = new qt.TagButton('code','code','<code>','</code>'),
    663     edButtons[120] = new qt.TagButton('more','more','<!--more-->\n\n',''),
     678    edButtons[10]  = new qt.TagButton( 'strong', 'b', '<strong>', '</strong>', '', '', '', { ariaLabel: quicktagsL10n.strong, ariaLabelClose: quicktagsL10n.strongClose } );
     679    edButtons[20]  = new qt.TagButton( 'em', 'i', '<em>', '</em>', '', '', '', { ariaLabel: quicktagsL10n.em, ariaLabelClose: quicktagsL10n.emClose } );
     680    edButtons[30]  = new qt.LinkButton(); // special case
     681    edButtons[40]  = new qt.TagButton( 'block', 'b-quote', '\n\n<blockquote>', '</blockquote>\n\n', '', '', '', { ariaLabel: quicktagsL10n.blockquote, ariaLabelClose: quicktagsL10n.blockquoteClose } );
     682    edButtons[50]  = new qt.TagButton( 'del', 'del', '<del datetime="' + _datetime + '">', '</del>', '', '', '', { ariaLabel: quicktagsL10n.del, ariaLabelClose: quicktagsL10n.delClose } );
     683    edButtons[60]  = new qt.TagButton( 'ins', 'ins', '<ins datetime="' + _datetime + '">', '</ins>', '', '', '', { ariaLabel: quicktagsL10n.ins, ariaLabelClose: quicktagsL10n.insClose } );
     684    edButtons[70]  = new qt.ImgButton(); // special case
     685    edButtons[80]  = new qt.TagButton( 'ul', 'ul', '<ul>\n', '</ul>\n\n', '', '', '', { ariaLabel: quicktagsL10n.ul, ariaLabelClose: quicktagsL10n.ulClose } );
     686    edButtons[90]  = new qt.TagButton( 'ol', 'ol', '<ol>\n', '</ol>\n\n', '', '', '', { ariaLabel: quicktagsL10n.ol, ariaLabelClose: quicktagsL10n.olClose } );
     687    edButtons[100] = new qt.TagButton( 'li', 'li', '\t<li>', '</li>\n', '', '', '', { ariaLabel: quicktagsL10n.li, ariaLabelClose: quicktagsL10n.liClose } );
     688    edButtons[110] = new qt.TagButton( 'code', 'code', '<code>', '</code>', '', '', '', { ariaLabel: quicktagsL10n.code, ariaLabelClose: quicktagsL10n.codeClose } );
     689    edButtons[120] = new qt.TagButton( 'more', 'more', '<!--more-->\n\n', '', '', '', '', { ariaLabel: quicktagsL10n.more } );
    664690    edButtons[140] = new qt.CloseButton();
    665691
  • trunk/src/wp-includes/script-loader.php

    r32864 r32883  
    9090    $scripts->add( 'quicktags', "/wp-includes/js/quicktags$suffix.js", array(), false, 1 );
    9191    did_action( 'init' ) && $scripts->localize( 'quicktags', 'quicktagsL10n', array(
    92         'closeAllOpenTags'      => esc_attr__( 'Close all open tags' ),
    93         'closeTags'             => esc_attr__( 'close tags' ),
     92        'closeAllOpenTags'      => __( 'Close all open tags' ),
     93        'closeTags'             => __( 'close tags' ),
    9494        'enterURL'              => __( 'Enter the URL' ),
    9595        'enterImageURL'         => __( 'Enter the URL of the image' ),
    9696        'enterImageDescription' => __( 'Enter a description of the image' ),
    97         'textdirection'         => esc_attr__( 'text direction' ),
    98         'toggleTextdirection'   => esc_attr__( 'Toggle Editor Text Direction' ),
    99         'dfw'                   => esc_attr__( 'Distraction-free writing mode' )
     97        'textdirection'         => __( 'text direction' ),
     98        'toggleTextdirection'   => __( 'Toggle Editor Text Direction' ),
     99        'dfw'                   => __( 'Distraction-free writing mode' ),
     100        'strong'          => __( 'Bold' ),
     101        'strongClose'     => __( 'Close bold tag' ),
     102        'em'              => __( 'Italic' ),
     103        'emClose'         => __( 'Close italic tag' ),
     104        'link'            => __( 'Insert link' ),
     105        'blockquote'      => __( 'Blockquote' ),
     106        'blockquoteClose' => __( 'Close blockquote tag' ),
     107        'del'             => __( 'Deleted text (strikethrough)' ),
     108        'delClose'        => __( 'Close deleted text tag' ),
     109        'ins'             => __( 'Inserted text' ),
     110        'insClose'        => __( 'Close inserted text tag' ),
     111        'image'           => __( 'Insert image' ),
     112        'ul'              => __( 'Bulleted list' ),
     113        'ulClose'         => __( 'Close bulleted list tag' ),
     114        'ol'              => __( 'Numbered list' ),
     115        'olClose'         => __( 'Close numbered list tag' ),
     116        'li'              => __( 'List item' ),
     117        'liClose'         => __( 'Close list item tag' ),
     118        'code'            => __( 'Code' ),
     119        'codeClose'       => __( 'Close code tag' ),
     120        'more'            => __( 'Insert Read More tag' ),
    100121    ) );
    101122
Note: See TracChangeset for help on using the changeset viewer.