Make WordPress Core

Changeset 32856


Ignore:
Timestamp:
06/19/2015 10:34:59 AM (9 years ago)
Author:
iseulde
Message:

Editor: restructure word count

  • The WordCounter should only do one thing: count words. This makes it also easier to test.
  • Add some really basic unit tests.
  • Instead of only refreshing the count on enter and delete, refresh the count when the user stops typing. Also look at paste and content changes in TinyMCE.
  • Use match instead of replace when it is appropriate.
  • More readable code.

See #30966. Fixes #26620.

Location:
trunk
Files:
1 added
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/js/post.js

    r32680 r32856  
    204204    var stamp, visibility, $submitButtons, updateVisibility, updateText,
    205205        sticky = '',
    206         last = 0,
    207206        $textarea = $('#content'),
    208207        $document = $(document),
     
    789788    }
    790789
    791     // word count
    792     if ( typeof(wpWordCount) != 'undefined' ) {
    793         $document.triggerHandler('wpcountwords', [ $textarea.val() ]);
    794 
    795         $textarea.keyup( function(e) {
    796             var k = e.keyCode || e.charCode;
    797 
    798             if ( k == last )
    799                 return true;
    800 
    801             if ( 13 == k || 8 == last || 46 == last )
    802                 $document.triggerHandler('wpcountwords', [ $textarea.val() ]);
    803 
    804             last = k;
    805             return true;
    806         });
    807     }
    808 
    809790    wptitlehint = function(id) {
    810791        id = id || 'title';
     
    936917    });
    937918});
     919
     920( function( $, counter ) {
     921    $( function() {
     922        var $content = $( '#content' ),
     923            $count = $( '#wp-word-count' ).find( '.word-count' ),
     924            prevCount = 0,
     925            contentEditor;
     926
     927        function update() {
     928            var text, count;
     929
     930            if ( ! contentEditor || contentEditor.isHidden() ) {
     931                text = $content.val();
     932            } else {
     933                text = contentEditor.getContent( { format: 'raw' } );
     934            }
     935
     936            count = counter.count( text );
     937
     938            if ( count !== prevCount ) {
     939                $count.text( count );
     940            }
     941
     942            prevCount = count;
     943        }
     944
     945        $( document ).on( 'tinymce-editor-init', function( event, editor ) {
     946            if ( editor.id !== 'content' ) {
     947                return;
     948            }
     949
     950            contentEditor = editor;
     951
     952            editor.on( 'nodechange keyup', _.debounce( update, 2000 ) );
     953        } );
     954
     955        $content.on( 'input keyup', _.debounce( update, 2000 ) );
     956
     957        update();
     958    } );
     959} )( jQuery, new wp.utils.WordCounter() );
  • trunk/src/wp-admin/js/word-count.js

    r26209 r32856  
    1 /* global wordCountL10n */
    2 var wpWordCount;
    3 (function($,undefined) {
    4     wpWordCount = {
     1( function() {
     2    function WordCounter( settings ) {
     3        var key;
    54
    6         settings : {
    7             strip : /<[a-zA-Z\/][^<>]*>/g, // strip HTML tags
    8             clean : /[0-9.(),;:!?%#$¿'"_+=\\/-]+/g, // regexp to remove punctuation, etc.
    9             w : /\S\s+/g, // word-counting regexp
    10             c : /\S/g // char-counting regexp for asian languages
    11         },
     5        if ( settings ) {
     6            for ( key in settings ) {
     7                if ( settings.hasOwnProperty( key ) ) {
     8                    this.settings[ key ] = settings[ key ];
     9                }
     10            }
     11        }
     12    }
    1213
    13         block : 0,
    14 
    15         wc : function(tx, type) {
    16             var t = this, w = $('.word-count'), tc = 0;
    17 
    18             if ( type === undefined )
    19                 type = wordCountL10n.type;
    20             if ( type !== 'w' && type !== 'c' )
    21                 type = 'w';
    22 
    23             if ( t.block )
    24                 return;
    25 
    26             t.block = 1;
    27 
    28             setTimeout( function() {
    29                 if ( tx ) {
    30                     tx = tx.replace( t.settings.strip, ' ' ).replace( /&nbsp;|&#160;/gi, ' ' );
    31                     tx = tx.replace( t.settings.clean, '' );
    32                     tx.replace( t.settings[type], function(){tc++;} );
    33                 }
    34                 w.html(tc.toString());
    35 
    36                 setTimeout( function() { t.block = 0; }, 2000 );
    37             }, 1 );
    38         }
     14    WordCounter.prototype.settings = {
     15        HTMLRegExp: /<\/?[a-z][^>]*?>/gi,
     16        spaceRegExp: /&nbsp;|&#160;/gi,
     17        removeRegExp: /[0-9.(),;:!?%#$¿'"_+=\\\/-]+/g,
     18        wordsRegExp: /\S\s+/g,
     19        charactersRegExp: /\S/g,
     20        l10n: window.wordCountL10n || {}
    3921    };
    4022
    41     $(document).bind( 'wpcountwords', function(e, txt) {
    42         wpWordCount.wc(txt);
    43     });
    44 }(jQuery));
     23    WordCounter.prototype.count = function( text, type ) {
     24        var count = 0;
     25
     26        type = type || this.settings.l10n.type || 'words';
     27
     28        if ( text ) {
     29            text = ' ' + text + ' ';
     30
     31            text = text.replace( this.settings.HTMLRegExp, ' ' );
     32            text = text.replace( this.settings.spaceRegExp, ' ' );
     33            text = text.replace( this.settings.removeRegExp, '' );
     34
     35            text = text.match( this.settings[ type + 'RegExp' ] );
     36
     37            if ( text ) {
     38                count = text.length;
     39            }
     40        }
     41
     42        return count;
     43    };
     44
     45    window.wp = window.wp || {};
     46    window.wp.utils = window.wp.utils || {};
     47    window.wp.utils.WordCounter = WordCounter;
     48} )();
  • trunk/src/wp-includes/js/tinymce/plugins/wordpress/plugin.js

    r32831 r32856  
    88        each = tinymce.each,
    99        __ = editor.editorManager.i18n.translate,
    10         wpAdvButton, style,
    11         last = 0;
     10        wpAdvButton, style;
    1211
    1312    if ( typeof window.jQuery !== 'undefined' ) {
     
    363362        }
    364363    });
    365 
    366     // Word count
    367     if ( typeof window.jQuery !== 'undefined' ) {
    368         editor.on( 'keyup', function( e ) {
    369             var key = e.keyCode || e.charCode;
    370 
    371             if ( key === last ) {
    372                 return;
    373             }
    374 
    375             if ( 13 === key || 8 === last || 46 === last ) {
    376                 window.jQuery( document ).triggerHandler( 'wpcountwords', [ editor.getContent({ format : 'raw' }) ] );
    377             }
    378 
    379             last = key;
    380         });
    381     }
    382364
    383365    editor.on( 'SaveContent', function( e ) {
  • trunk/src/wp-includes/script-loader.php

    r32843 r32856  
    372372    $scripts->add( 'wpdialogs', "/wp-includes/js/wpdialog$suffix.js", array( 'jquery-ui-dialog' ), false, 1 );
    373373
    374     $scripts->add( 'word-count', "/wp-admin/js/word-count$suffix.js", array( 'jquery' ), false, 1 );
     374    $scripts->add( 'word-count', "/wp-admin/js/word-count$suffix.js", array(), false, 1 );
    375375    did_action( 'init' ) && $scripts->localize( 'word-count', 'wordCountL10n', array(
    376376        /* translators: If your word count is based on single characters (East Asian characters),
    377377           enter 'characters'. Otherwise, enter 'words'. Do not translate into your own language. */
    378         'type' => 'characters' == _x( 'words', 'word count: words or characters?' ) ? 'c' : 'w',
     378        'type' => _x( 'words', 'word count: words or characters?' )
    379379    ) );
    380380
     
    452452        ) );
    453453
    454         $scripts->add( 'post', "/wp-admin/js/post$suffix.js", array( 'suggest', 'wp-lists', 'postbox', 'tags-box' ), false, 1 );
     454        $scripts->add( 'post', "/wp-admin/js/post$suffix.js", array( 'suggest', 'wp-lists', 'postbox', 'tags-box', 'underscore', 'word-count' ), false, 1 );
    455455        did_action( 'init' ) && $scripts->localize( 'post', 'postL10n', array(
    456456            'ok' => __('OK'),
  • trunk/tests/qunit/index.html

    r32699 r32856  
    3333        <script src="../../src/wp-includes/js/shortcode.js"></script>
    3434        <script src="../../src/wp-admin/js/customize-controls.js"></script>
     35        <script src="../../src/wp-admin/js/word-count.js"></script>
    3536
    3637        <!-- Unit tests -->
     
    4142        <script src="wp-admin/js/customize-controls.js"></script>
    4243        <script src="wp-admin/js/customize-controls-utils.js"></script>
     44        <script src="wp-admin/js/word-count.js"></script>
    4345
    4446        <!-- Customizer templates for sections -->
Note: See TracChangeset for help on using the changeset viewer.