WordPress.org

Make WordPress Core

Changeset 38637


Ignore:
Timestamp:
09/21/2016 08:56:28 AM (4 years ago)
Author:
SergeyBiryukov
Message:

Editor: Improve post.js documentation.

Props jipmoors, boblinthorst.
Fixes #38118.

File:
1 edited

Legend:

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

    r38425 r38637  
    22/* global theList:true, theExtraList:true, getUserSetting, setUserSetting, commentReply */
    33
     4/**
     5 * Contains all dynamic functionality needed on post and term pages.
     6 *
     7 * @summary Control page and term functionality.
     8 */
     9
    410var commentsBox, WPSetThumbnailHTML, WPSetThumbnailID, WPRemoveThumbnail, wptitlehint, makeSlugeditClickable, editPermalink;
    5 // Back-compat: prevent fatal errors
     11// Backwards compatibility: prevent fatal errors.
    612makeSlugeditClickable = editPermalink = function(){};
    713
     14// Make sure the wp object exists.
    815window.wp = window.wp || {};
    916
     
    1118    var titleHasFocus = false;
    1219
    13 commentsBox = {
    14     st : 0,
    15 
    16     get : function(total, num) {
    17         var st = this.st, data;
    18         if ( ! num )
    19             num = 20;
    20 
    21         this.st += num;
    22         this.total = total;
    23         $( '#commentsdiv .spinner' ).addClass( 'is-active' );
    24 
    25         data = {
    26             'action' : 'get-comments',
    27             'mode' : 'single',
    28             '_ajax_nonce' : $('#add_comment_nonce').val(),
    29             'p' : $('#post_ID').val(),
    30             'start' : st,
    31             'number' : num
    32         };
    33 
    34         $.post(ajaxurl, data,
    35             function(r) {
    36                 r = wpAjax.parseAjaxResponse(r);
    37                 $('#commentsdiv .widefat').show();
    38                 $( '#commentsdiv .spinner' ).removeClass( 'is-active' );
    39 
    40                 if ( 'object' == typeof r && r.responses[0] ) {
    41                     $('#the-comment-list').append( r.responses[0].data );
    42 
    43                     theList = theExtraList = null;
    44                     $( 'a[className*=\':\']' ).unbind();
    45 
    46                     if ( commentsBox.st > commentsBox.total )
    47                         $('#show-comments').hide();
    48                     else
    49                         $('#show-comments').show().children('a').html(postL10n.showcomm);
    50 
    51                     return;
    52                 } else if ( 1 == r ) {
    53                     $('#show-comments').html(postL10n.endcomm);
    54                     return;
     20    /**
     21     * Control loading of comments on the post and term edit pages.
     22     *
     23     * @type {{st: number, get: commentsBox.get, load: commentsBox.load}}
     24     *
     25     * @namespace commentsBox
     26     */
     27    commentsBox = {
     28        // Comment offset to use when fetching new comments.
     29        st : 0,
     30
     31        /**
     32         * Fetch comments using AJAX and display them in the box.
     33         *
     34         * @param {int} total Total number of comments for this post.
     35         * @param {int} num   Optional. Number of comments to fetch, defaults to 20.
     36         * @returns {boolean} Always returns false.
     37         *
     38         * @memberof commentsBox
     39         */
     40        get : function(total, num) {
     41            var st = this.st, data;
     42            if ( ! num )
     43                num = 20;
     44
     45            this.st += num;
     46            this.total = total;
     47            $( '#commentsdiv .spinner' ).addClass( 'is-active' );
     48
     49            data = {
     50                'action' : 'get-comments',
     51                'mode' : 'single',
     52                '_ajax_nonce' : $('#add_comment_nonce').val(),
     53                'p' : $('#post_ID').val(),
     54                'start' : st,
     55                'number' : num
     56            };
     57
     58            $.post(
     59                ajaxurl,
     60                data,
     61                function(r) {
     62                    r = wpAjax.parseAjaxResponse(r);
     63                    $('#commentsdiv .widefat').show();
     64                    $( '#commentsdiv .spinner' ).removeClass( 'is-active' );
     65
     66                    if ( 'object' == typeof r && r.responses[0] ) {
     67                        $('#the-comment-list').append( r.responses[0].data );
     68
     69                        theList = theExtraList = null;
     70                        $( 'a[className*=\':\']' ).unbind();
     71
     72                        // If the offset is over the total number of comments we cannot fetch any more, so hide the button.
     73                        if ( commentsBox.st > commentsBox.total )
     74                            $('#show-comments').hide();
     75                        else
     76                            $('#show-comments').show().children('a').html(postL10n.showcomm);
     77
     78                        return;
     79                    } else if ( 1 == r ) {
     80                        $('#show-comments').html(postL10n.endcomm);
     81                        return;
     82                    }
     83
     84                    $('#the-comment-list').append('<tr><td colspan="2">'+wpAjax.broken+'</td></tr>');
    5585                }
    56 
    57                 $('#the-comment-list').append('<tr><td colspan="2">'+wpAjax.broken+'</td></tr>');
    58             }
     86            );
     87
     88            return false;
     89        },
     90
     91        /**
     92         * Load the next batch of comments.
     93         *
     94         * @param {int} total Total number of comments to load.
     95         *
     96         * @memberof commentsBox
     97         */
     98        load: function(total){
     99            this.st = jQuery('#the-comment-list tr.comment:visible').length;
     100            this.get(total);
     101        }
     102    };
     103
     104    /**
     105     * Overwrite the content of the Featured Image postbox
     106     *
     107     * @param {string} html New HTML to be displayed in the content area of the postbox.
     108     *
     109     * @global
     110     */
     111    WPSetThumbnailHTML = function(html){
     112        $('.inside', '#postimagediv').html(html);
     113    };
     114
     115    /**
     116     * Set the Image ID of the Featured Image
     117     *
     118     * @param {int} id The post_id of the image to use as Featured Image.
     119     *
     120     * @global
     121     */
     122    WPSetThumbnailID = function(id){
     123        var field = $('input[value="_thumbnail_id"]', '#list-table');
     124        if ( field.length > 0 ) {
     125            $('#meta\\[' + field.attr('id').match(/[0-9]+/) + '\\]\\[value\\]').text(id);
     126        }
     127    };
     128
     129    /**
     130     * Remove the Featured Image
     131     *
     132     * @param {string} nonce Nonce to use in the request.
     133     *
     134     * @global
     135     */
     136    WPRemoveThumbnail = function(nonce){
     137        $.post(ajaxurl, {
     138            action: 'set-post-thumbnail', post_id: $( '#post_ID' ).val(), thumbnail_id: -1, _ajax_nonce: nonce, cookie: encodeURIComponent( document.cookie )
     139        },
     140            /**
     141             * Handle server response
     142             *
     143             * @param {string} str Response, will be '0' when an error occured otherwise contains link to add Featured Image.
     144             */
     145            function(str){
     146            if ( str == '0' ) {
     147                alert( setPostThumbnailL10n.error );
     148            } else {
     149                WPSetThumbnailHTML(str);
     150            }
     151        }
    59152        );
    60 
    61         return false;
    62     },
    63 
    64     load: function(total){
    65         this.st = jQuery('#the-comment-list tr.comment:visible').length;
    66         this.get(total);
    67     }
    68 };
    69 
    70 WPSetThumbnailHTML = function(html){
    71     $('.inside', '#postimagediv').html(html);
    72 };
    73 
    74 WPSetThumbnailID = function(id){
    75     var field = $('input[value="_thumbnail_id"]', '#list-table');
    76     if ( field.length > 0 ) {
    77         $('#meta\\[' + field.attr('id').match(/[0-9]+/) + '\\]\\[value\\]').text(id);
    78     }
    79 };
    80 
    81 WPRemoveThumbnail = function(nonce){
    82     $.post(ajaxurl, {
    83         action: 'set-post-thumbnail', post_id: $( '#post_ID' ).val(), thumbnail_id: -1, _ajax_nonce: nonce, cookie: encodeURIComponent( document.cookie )
    84     }, function(str){
    85         if ( str == '0' ) {
    86             alert( setPostThumbnailL10n.error );
    87         } else {
    88             WPSetThumbnailHTML(str);
    89         }
    90     }
    91     );
    92 };
    93 
    94 $(document).on( 'heartbeat-send.refresh-lock', function( e, data ) {
    95     var lock = $('#active_post_lock').val(),
    96         post_id = $('#post_ID').val(),
    97         send = {};
    98 
    99     if ( ! post_id || ! $('#post-lock-dialog').length )
    100         return;
    101 
    102     send.post_id = post_id;
    103 
    104     if ( lock )
    105         send.lock = lock;
    106 
    107     data['wp-refresh-post-lock'] = send;
    108 
    109 }).on( 'heartbeat-tick.refresh-lock', function( e, data ) {
    110     // Post locks: update the lock string or show the dialog if somebody has taken over editing
    111     var received, wrap, avatar;
    112 
    113     if ( data['wp-refresh-post-lock'] ) {
    114         received = data['wp-refresh-post-lock'];
    115 
    116         if ( received.lock_error ) {
    117             // show "editing taken over" message
    118             wrap = $('#post-lock-dialog');
    119 
    120             if ( wrap.length && ! wrap.is(':visible') ) {
    121                 if ( wp.autosave ) {
    122                     // Save the latest changes and disable
    123                     $(document).one( 'heartbeat-tick', function() {
    124                         wp.autosave.server.suspend();
    125                         wrap.removeClass('saving').addClass('saved');
    126                         $(window).off( 'beforeunload.edit-post' );
    127                     });
    128 
    129                     wrap.addClass('saving');
    130                     wp.autosave.server.triggerSave();
     153    };
     154
     155    /**
     156     * Heartbeat locks.
     157     *
     158     * Used to lock editing of an object by only one user at a time.
     159     *
     160     * When the user does not send a heartbeat in a heartbeat-time
     161     * the user is no longer editing and another user can start editing.
     162     */
     163    $(document).on( 'heartbeat-send.refresh-lock', function( e, data ) {
     164        var lock = $('#active_post_lock').val(),
     165            post_id = $('#post_ID').val(),
     166            send = {};
     167
     168        if ( ! post_id || ! $('#post-lock-dialog').length )
     169            return;
     170
     171        send.post_id = post_id;
     172
     173        if ( lock )
     174            send.lock = lock;
     175
     176        data['wp-refresh-post-lock'] = send;
     177
     178    }).on( 'heartbeat-tick.refresh-lock', function( e, data ) {
     179        // Post locks: update the lock string or show the dialog if somebody has taken over editing.
     180        var received, wrap, avatar;
     181
     182        if ( data['wp-refresh-post-lock'] ) {
     183            received = data['wp-refresh-post-lock'];
     184
     185            if ( received.lock_error ) {
     186                // Show "editing taken over" message.
     187                wrap = $('#post-lock-dialog');
     188
     189                if ( wrap.length && ! wrap.is(':visible') ) {
     190                    if ( wp.autosave ) {
     191                        // Save the latest changes and disable.
     192                        $(document).one( 'heartbeat-tick', function() {
     193                            wp.autosave.server.suspend();
     194                            wrap.removeClass('saving').addClass('saved');
     195                            $(window).off( 'beforeunload.edit-post' );
     196                        });
     197
     198                        wrap.addClass('saving');
     199                        wp.autosave.server.triggerSave();
     200                    }
     201
     202                    if ( received.lock_error.avatar_src ) {
     203                        avatar = $( '<img class="avatar avatar-64 photo" width="64" height="64" alt="" />' ).attr( 'src', received.lock_error.avatar_src.replace( /&amp;/g, '&' ) );
     204                        wrap.find('div.post-locked-avatar').empty().append( avatar );
     205                    }
     206
     207                    wrap.show().find('.currently-editing').text( received.lock_error.text );
     208                    wrap.find('.wp-tab-first').focus();
    131209                }
    132 
    133                 if ( received.lock_error.avatar_src ) {
    134                     avatar = $( '<img class="avatar avatar-64 photo" width="64" height="64" alt="" />' ).attr( 'src', received.lock_error.avatar_src.replace( /&amp;/g, '&' ) );
    135                     wrap.find('div.post-locked-avatar').empty().append( avatar );
     210            } else if ( received.new_lock ) {
     211                $('#active_post_lock').val( received.new_lock );
     212            }
     213        }
     214    }).on( 'before-autosave.update-post-slug', function() {
     215        titleHasFocus = document.activeElement && document.activeElement.id === 'title';
     216    }).on( 'after-autosave.update-post-slug', function() {
     217
     218        /*
     219         * Create slug area only if not already there
     220         * and the title field was not focused (user was not typing a title) when autosave ran.
     221         */
     222        if ( ! $('#edit-slug-box > *').length && ! titleHasFocus ) {
     223            $.post( ajaxurl, {
     224                    action: 'sample-permalink',
     225                    post_id: $('#post_ID').val(),
     226                    new_title: $('#title').val(),
     227                    samplepermalinknonce: $('#samplepermalinknonce').val()
     228                },
     229                function( data ) {
     230                    if ( data != '-1' ) {
     231                        $('#edit-slug-box').html(data);
     232                    }
    136233                }
    137 
    138                 wrap.show().find('.currently-editing').text( received.lock_error.text );
    139                 wrap.find('.wp-tab-first').focus();
    140             }
    141         } else if ( received.new_lock ) {
    142             $('#active_post_lock').val( received.new_lock );
    143         }
    144     }
    145 }).on( 'before-autosave.update-post-slug', function() {
    146     titleHasFocus = document.activeElement && document.activeElement.id === 'title';
    147 }).on( 'after-autosave.update-post-slug', function() {
    148     // Create slug area only if not already there
    149     // and the title field was not focused (user was not typing a title) when autosave ran
    150     if ( ! $('#edit-slug-box > *').length && ! titleHasFocus ) {
    151         $.post( ajaxurl, {
    152                 action: 'sample-permalink',
    153                 post_id: $('#post_ID').val(),
    154                 new_title: $('#title').val(),
    155                 samplepermalinknonce: $('#samplepermalinknonce').val()
    156             },
    157             function( data ) {
    158                 if ( data != '-1' ) {
    159                     $('#edit-slug-box').html(data);
    160                 }
    161             }
    162         );
    163     }
    164 });
     234            );
     235        }
     236    });
    165237
    166238}(jQuery));
    167239
     240/**
     241 * Heartbeat refresh nonces.
     242 */
    168243(function($) {
    169244    var check, timeout;
    170245
     246    /**
     247     * Only allow to check for nonce refresh every 30 seconds.
     248     */
    171249    function schedule() {
    172250        check = false;
     
    206284}(jQuery));
    207285
     286/**
     287 * All post and postbox controls and functionality.
     288 */
    208289jQuery(document).ready( function($) {
    209290    var stamp, visibility, $submitButtons, updateVisibility, updateText,
     
    221302    postboxes.add_postbox_toggles(pagenow);
    222303
    223     // Clear the window name. Otherwise if this is a former preview window where the user navigated to edit another post,
    224     // and the first post is still being edited, clicking Preview there will use this window to show the preview.
     304    /*
     305     * Clear the window name. Otherwise if this is a former preview window where the user navigated to edit another post,
     306     * and the first post is still being edited, clicking Preview there will use this window to show the preview.
     307     */
    225308    window.name = '';
    226309
    227310    // Post locks: contain focus inside the dialog. If the dialog is shown, focus the first item.
    228311    $('#post-lock-dialog .notification-dialog').on( 'keydown', function(e) {
     312        // Don't do anything when [tab] is pressed.
    229313        if ( e.which != 9 )
    230314            return;
     
    232316        var target = $(e.target);
    233317
     318        // [shift] + [tab] on first tab cycles back to last tab.
    234319        if ( target.hasClass('wp-tab-first') && e.shiftKey ) {
    235320            $(this).find('.wp-tab-last').focus();
    236321            e.preventDefault();
     322        // [tab] on last tab cycles back to first tab.
    237323        } else if ( target.hasClass('wp-tab-last') && ! e.shiftKey ) {
    238324            $(this).find('.wp-tab-first').focus();
     
    241327    }).filter(':visible').find('.wp-tab-first').focus();
    242328
    243     // Set the heartbeat interval to 15 sec. if post lock dialogs are enabled
     329    // Set the heartbeat interval to 15 sec. if post lock dialogs are enabled.
    244330    if ( wp.heartbeat && $('#post-lock-dialog').length ) {
    245331        wp.heartbeat.interval( 15 );
    246332    }
    247333
    248     // The form is being submitted by the user
     334    // The form is being submitted by the user.
    249335    $submitButtons = $submitpost.find( ':submit, a.submitdelete, #post-preview' ).on( 'click.edit-post', function( event ) {
    250336        var $button = $(this);
     
    266352            }
    267353
    268             // Stop autosave
     354            // Stop auto save.
    269355            if ( wp.autosave ) {
    270356                wp.autosave.server.suspend();
     
    351437    });
    352438
    353     // Autosave new posts after a title is typed
     439    // Auto save new posts after a title is typed.
    354440    if ( $( '#auto_draft' ).val() ) {
    355441        $( '#title' ).blur( function() {
     
    360446            }
    361447
    362             // Cancel the autosave when the blur was triggered by the user submitting the form
     448            // Cancel the auto save when the blur was triggered by the user submitting the form.
    363449            $('form#post').one( 'submit', function() {
    364450                cancel = true;
     
    389475    });
    390476
     477    /*
     478     * When the user is trying to load another page, or reloads current page
     479     * show a confirmation dialog when there are unsaved changes.
     480     */
    391481    $(window).on( 'beforeunload.edit-post', function() {
    392482        var editor = typeof tinymce !== 'undefined' && tinymce.get('content');
     
    402492        }
    403493
    404         // Unload is triggered (by hand) on removing the Thickbox iframe.
    405         // Make sure we process only the main document unload.
     494        /*
     495         * Unload is triggered (by hand) on removing the Thickbox iframe.
     496         * Make sure we process only the main document unload.
     497         */
    406498        if ( event.target && event.target.nodeName != '#document' ) {
    407499            return;
     
    436528    });
    437529
    438     // multi-taxonomies
     530    // Multiple Taxonomies.
    439531    if ( $('#tagsdiv-post_tag').length ) {
    440532        window.tagBox && window.tagBox.init();
     
    448540    }
    449541
    450     // categories
     542    // Handle categories.
    451543    $('.categorydiv').each( function(){
    452544        var this_id = $(this).attr('id'), catAddBefore, catAddAfter, taxonomyParts, taxonomy, settingName;
     
    456548        taxonomy = taxonomyParts.join('-');
    457549        settingName = taxonomy + '_tab';
    458         if ( taxonomy == 'category' )
     550
     551        if ( taxonomy == 'category' ) {
    459552            settingName = 'cats';
     553        }
    460554
    461555        // TODO: move to jQuery 1.3+, support for multiple hierarchical taxonomies, see wp-lists.js
     
    466560            $('#' + taxonomy + '-tabs').siblings('.tabs-panel').hide();
    467561            $(t).show();
    468             if ( '#' + taxonomy + '-all' == t )
     562            if ( '#' + taxonomy + '-all' == t ) {
    469563                deleteUserSetting( settingName );
    470             else
     564            } else {
    471565                setUserSetting( settingName, 'pop' );
     566            }
    472567        });
    473568
     
    475570            $('a[href="#' + taxonomy + '-pop"]', '#' + taxonomy + '-tabs').click();
    476571
    477         // Ajax Cat
    478         $( '#new' + taxonomy ).one( 'focus', function() { $( this ).val( '' ).removeClass( 'form-input-tip' ); } );
    479 
     572        // Add category button controls.
     573        $('#new' + taxonomy).one( 'focus', function() {
     574            $( this ).val( '' ).removeClass( 'form-input-tip' );
     575        });
     576
     577        // On [enter] submit the taxonomy.
    480578        $('#new' + taxonomy).keypress( function(event){
    481579            if( 13 === event.keyCode ) {
     
    484582            }
    485583        });
    486         $('#' + taxonomy + '-add-submit').click( function(){ $('#new' + taxonomy).focus(); });
    487 
     584
     585        // After submitting a new taxonomy, re-focus the input field.
     586        $('#' + taxonomy + '-add-submit').click( function() {
     587            $('#new' + taxonomy).focus();
     588        });
     589
     590        /**
     591         * Before adding a new taxonomy, disable submit button.
     592         *
     593         * @param {Object} s Taxonomy object which will be added.
     594         *
     595         * @returns {Object}
     596         */
    488597        catAddBefore = function( s ) {
    489             if ( !$('#new'+taxonomy).val() )
     598            if ( !$('#new'+taxonomy).val() ) {
    490599                return false;
     600            }
     601
    491602            s.data += '&' + $( ':checked', '#'+taxonomy+'checklist' ).serialize();
    492603            $( '#' + taxonomy + '-add-submit' ).prop( 'disabled', true );
     
    494605        };
    495606
     607        /**
     608         * Re-enable submit button after a taxonomy has been added.
     609         *
     610         * Re-enable submit button.
     611         * If the taxonomy has a parent place the taxonomy underneath the parent.
     612         *
     613         * @param {Object} r Response.
     614         * @param {Object} s Taxonomy data.
     615         *
     616         * @returns void
     617         */
    496618        catAddAfter = function( r, s ) {
    497619            var sup, drop = $('#new'+taxonomy+'_parent');
     
    511633        });
    512634
     635        // Add new taxonomy button toggles input form visibility.
    513636        $('#' + taxonomy + '-add-toggle').click( function( e ) {
    514637            e.preventDefault();
     
    518641        });
    519642
     643        // Sync checked items between "All {taxonomy}" and "Most used" lists.
    520644        $('#' + taxonomy + 'checklist, #' + taxonomy + 'checklist-pop').on( 'click', 'li.popular-category > label input[type="checkbox"]', function() {
    521645            var t = $(this), c = t.is(':checked'), id = t.val();
     
    526650    }); // end cats
    527651
    528     // Custom Fields
     652    // Custom Fields postbox.
    529653    if ( $('#postcustom').length ) {
    530         $( '#the-list' ).wpList( { addAfter: function() {
    531             $('table#list-table').show();
    532         }, addBefore: function( s ) {
    533             s.data += '&post_id=' + $('#post_ID').val();
    534             return s;
    535         }
     654        $( '#the-list' ).wpList( {
     655            /**
     656             * Add current post_ID to request to fetch custom fields
     657             *
     658             * @param {Object} s Request object.
     659             *
     660             * @returns {Object} Data modified with post_ID attached.
     661             */
     662            addBefore: function( s ) {
     663                s.data += '&post_id=' + $('#post_ID').val();
     664                return s;
     665            },
     666            /**
     667             * Show the listing of custom fields after fetching.
     668             */
     669            addAfter: function() {
     670                $('table#list-table').show();
     671            }
    536672        });
    537673    }
    538674
    539     // submitdiv
     675    /*
     676     * Publish Post box (#submitdiv)
     677     */
    540678    if ( $('#submitdiv').length ) {
    541679        stamp = $('#timestamp').html();
    542680        visibility = $('#post-visibility-display').html();
    543681
     682        /**
     683         * When the visibility of a post changes sub-options should be shown or hidden.
     684         *
     685         * @returns void
     686         */
    544687        updateVisibility = function() {
     688            // Show sticky for public posts.
    545689            if ( $postVisibilitySelect.find('input:radio:checked').val() != 'public' ) {
    546690                $('#sticky').prop('checked', false);
     
    549693                $('#sticky-span').show();
    550694            }
     695
     696            // Show password input field for password protected post.
    551697            if ( $postVisibilitySelect.find('input:radio:checked').val() != 'password' ) {
    552698                $('#password-span').hide();
     
    556702        };
    557703
     704        /**
     705         * Make sure all labels represent the current settings.
     706         *
     707         * @returns {boolean} False when an invalid timestamp has been selected, otherwise True.
     708         */
    558709        updateText = function() {
    559710
     
    569720            currentDate = new Date( $('#cur_aa').val(), $('#cur_mm').val() -1, $('#cur_jj').val(), $('#cur_hh').val(), $('#cur_mn').val() );
    570721
     722            // Catch unexpected date problems.
    571723            if ( attemptedDate.getFullYear() != aa || (1 + attemptedDate.getMonth()) != mm || attemptedDate.getDate() != jj || attemptedDate.getMinutes() != mn ) {
    572724                $timestampdiv.find('.timestamp-wrap').addClass('form-invalid');
     
    576728            }
    577729
     730            // Determine what the publish should be depending on the date and post status.
    578731            if ( attemptedDate > currentDate && $('#original_post_status').val() != 'future' ) {
    579732                publishOn = postL10n.publishOnFuture;
     
    586739                $('#publish').val( postL10n.update );
    587740            }
    588             if ( originalDate.toUTCString() == attemptedDate.toUTCString() ) { //hack
     741
     742            // If the date is the same, set it to trigger update events.
     743            if ( originalDate.toUTCString() == attemptedDate.toUTCString() ) {
     744                // Re-set to the current value.
    589745                $('#timestamp').html(stamp);
    590746            } else {
     
    601757            }
    602758
     759            // Add "privately published" to post status when applies.
    603760            if ( $postVisibilitySelect.find('input:radio:checked').val() == 'private' ) {
    604761                $('#publish').val( postL10n.update );
     
    622779                    $('#misc-publishing-actions .edit-post-status').show();
    623780            }
     781
     782            // Update "Status:" to currently selected status.
    624783            $('#post-status-display').html($('option:selected', postStatus).text());
     784
     785            // Show or hide the "Save Draft" button.
    625786            if ( $('option:selected', postStatus).val() == 'private' || $('option:selected', postStatus).val() == 'publish' ) {
    626787                $('#save-post').hide();
     
    636797        };
    637798
     799        // Show the visibility options and hide the toggle button when opened.
    638800        $( '#visibility .edit-visibility').click( function( e ) {
    639801            e.preventDefault();
     
    647809        });
    648810
     811        // Cancel visibility selection area and hide it from view.
    649812        $postVisibilitySelect.find('.cancel-post-visibility').click( function( event ) {
    650813            $postVisibilitySelect.slideUp('fast');
     
    658821        });
    659822
     823        // Set the selected visibility as current.
    660824        $postVisibilitySelect.find('.save-post-visibility').click( function( event ) { // crazyhorse - multiple ok cancels
    661825            $postVisibilitySelect.slideUp('fast');
     
    665829            if ( $postVisibilitySelect.find('input:radio:checked').val() != 'public' ) {
    666830                $('#sticky').prop('checked', false);
    667             } // WEAPON LOCKED
     831            }
    668832
    669833            if ( $('#sticky').prop('checked') ) {
     
    677841        });
    678842
     843        // When the selection changes, update labels.
    679844        $postVisibilitySelect.find('input:radio').change( function() {
    680845            updateVisibility();
    681846        });
    682847
     848        // Edit publish time click.
    683849        $timestampdiv.siblings('a.edit-timestamp').click( function( event ) {
    684850            if ( $timestampdiv.is( ':hidden' ) ) {
     
    691857        });
    692858
     859        // Cancel editing the publish time and hide the settings.
    693860        $timestampdiv.find('.cancel-timestamp').click( function( event ) {
    694861            $timestampdiv.slideUp('fast').siblings('a.edit-timestamp').show().focus();
     
    702869        });
    703870
     871        // Save the changed timestamp.
    704872        $timestampdiv.find('.save-timestamp').click( function( event ) { // crazyhorse - multiple ok cancels
    705873            if ( updateText() ) {
     
    710878        });
    711879
     880        // Cancel submit when an invalid timestamp has been selected.
    712881        $('#post').on( 'submit', function( event ) {
    713882            if ( ! updateText() ) {
     
    723892        });
    724893
     894        // Post Status edit click.
    725895        $postStatusSelect.siblings('a.edit-post-status').click( function( event ) {
    726896            if ( $postStatusSelect.is( ':hidden' ) ) {
     
    733903        });
    734904
     905        // Save the Post Status changes and hide the options.
    735906        $postStatusSelect.find('.save-post-status').click( function( event ) {
    736907            $postStatusSelect.slideUp( 'fast' ).siblings( 'a.edit-post-status' ).show().focus();
     
    739910        });
    740911
     912        // Cancel Post Status editing and hide the options.
    741913        $postStatusSelect.find('.cancel-post-status').click( function( event ) {
    742914            $postStatusSelect.slideUp( 'fast' ).siblings( 'a.edit-post-status' ).show().focus();
     
    745917            event.preventDefault();
    746918        });
    747     } // end submitdiv
    748 
    749     // permalink
     919    }
     920
     921    /**
     922     * Handle the editing of the post_name. Create the required HTML elements and update the changes via AJAX.
     923     *
     924     * @summary Permalink aka slug aka post_name editing
     925     *
     926     * @global
     927     *
     928     * @returns void
     929     */
    750930    function editPermalink() {
    751931        var i, slug_value,
     
    761941            full = $('#editable-post-name-full');
    762942
    763         // Deal with Twemoji in the post-name
     943        // Deal with Twemoji in the post-name.
    764944        full.find( 'img' ).replaceWith( function() { return this.alt; } );
    765945        full = full.html();
    766946
    767947        permalink.html( permalinkInner );
     948
     949        // Save current content to revert to when cancelling.
    768950        $el = $( '#editable-post-name' );
    769951        revert_e = $el.html();
    770952
    771953        buttons.html( '<button type="button" class="save button button-small">' + postL10n.ok + '</button> <button type="button" class="cancel button-link">' + postL10n.cancel + '</button>' );
     954
     955        // Save permalink changes.
    772956        buttons.children( '.save' ).click( function() {
    773957            var new_slug = $el.children( 'input' ).val();
     
    777961                return;
    778962            }
    779             $.post(ajaxurl, {
    780                 action: 'sample-permalink',
    781                 post_id: postId,
    782                 new_slug: new_slug,
    783                 new_title: $('#title').val(),
    784                 samplepermalinknonce: $('#samplepermalinknonce').val()
    785             }, function(data) {
    786                 var box = $('#edit-slug-box');
    787                 box.html(data);
    788                 if (box.hasClass('hidden')) {
    789                     box.fadeIn('fast', function () {
    790                         box.removeClass('hidden');
    791                     });
     963
     964            $.post(
     965                ajaxurl,
     966                {
     967                    action: 'sample-permalink',
     968                    post_id: postId,
     969                    new_slug: new_slug,
     970                    new_title: $('#title').val(),
     971                    samplepermalinknonce: $('#samplepermalinknonce').val()
     972                },
     973                function(data) {
     974                    var box = $('#edit-slug-box');
     975                    box.html(data);
     976                    if (box.hasClass('hidden')) {
     977                        box.fadeIn('fast', function () {
     978                            box.removeClass('hidden');
     979                        });
     980                    }
     981
     982                    buttons.html(buttonsOrig);
     983                    permalink.html(permalinkOrig);
     984                    real_slug.val(new_slug);
     985                    $( '.edit-slug' ).focus();
     986                    wp.a11y.speak( postL10n.permalinkSaved );
    792987                }
    793 
    794                 buttons.html(buttonsOrig);
    795                 permalink.html(permalinkOrig);
    796                 real_slug.val(new_slug);
    797                 $( '.edit-slug' ).focus();
    798                 wp.a11y.speak( postL10n.permalinkSaved );
    799             });
    800         });
    801 
     988            );
     989        });
     990
     991        // Cancel editing of permalink.
    802992        buttons.children( '.cancel' ).click( function() {
    803993            $('#view-post-btn').show();
     
    809999        });
    8101000
     1001        // If more than 1/4th of 'full' is '%', make it empty.
    8111002        for ( i = 0; i < full.length; ++i ) {
    8121003            if ( '%' == full.charAt(i) )
    8131004                c++;
    8141005        }
    815 
    8161006        slug_value = ( c > full.length / 4 ) ? '' : full;
     1007
    8171008        $el.html( '<input type="text" id="new-post-slug" value="' + slug_value + '" autocomplete="off" />' ).children( 'input' ).keydown( function( e ) {
    8181009            var key = e.which;
    819             // On enter, just save the new slug, don't save the post.
     1010            // On [enter], just save the new slug, don't save the post.
    8201011            if ( 13 === key ) {
    8211012                e.preventDefault();
    8221013                buttons.children( '.save' ).click();
    8231014            }
     1015            // On [esc] cancel the editing.
    8241016            if ( 27 === key ) {
    8251017                buttons.children( '.cancel' ).click();
     
    8341026    });
    8351027
     1028    /**
     1029     * Add screen reader text to the title prompt when needed.
     1030     *
     1031     * @summary Title screen reader text handler.
     1032     *
     1033     * @param {string} id Optional. HTML ID to add the screen reader helper text to.
     1034     *
     1035     * @global
     1036     *
     1037     * @returns void
     1038     */
    8361039    wptitlehint = function(id) {
    8371040        id = id || 'title';
     
    8601063    wptitlehint();
    8611064
    862     // Resize the visual and text editors
     1065    // Resize the WYSIWYG and plain text editors.
    8631066    ( function() {
    8641067        var editor, offset, mce,
     
    8661069            $postdivrich = $('#postdivrich');
    8671070
    868         // No point for touch devices
     1071        // If there are no textareas or we are on a touch device, we can't do anything.
    8691072        if ( ! $textarea.length || 'ontouchstart' in window ) {
    870             // Hide the resize handle
     1073            // Hide the resize handle.
    8711074            $('#content-resize-handle').hide();
    8721075            return;
    8731076        }
    8741077
     1078        /**
     1079         * Handle drag event.
     1080         *
     1081         * @param {Object} event Event containing details about the drag.
     1082         */
    8751083        function dragging( event ) {
    8761084            if ( $postdivrich.hasClass( 'wp-editor-expand' ) ) {
     
    8871095        }
    8881096
     1097        /**
     1098         * When the dragging stopped make sure we return focus and do a sanity check on the height.
     1099         */
    8891100        function endDrag() {
    8901101            var height, toolbarHeight;
     
    9101121            $document.off( '.wp-editor-resize' );
    9111122
    912             // sanity check
     1123            // Sanity check: normalize height to stay within acceptable ranges.
    9131124            if ( height && height > 50 && height < 5000 ) {
    9141125                setUserSetting( 'ed_size', height );
     
    9371148    })();
    9381149
     1150    // TinyMCE specific handling of Post Format changes to reflect in the editor.
    9391151    if ( typeof tinymce !== 'undefined' ) {
    940         // When changing post formats, change the editor body class
     1152        // When changing post formats, change the editor body class.
    9411153        $( '#post-formats-select input.post-format' ).on( 'change.set-editor-class', function() {
    9421154            var editor, body, format = this.id;
     
    9511163    }
    9521164
    953     // Save on pressing Ctrl/Command + S in the Text editor
     1165    // Save on pressing [ctrl]/[command] + [s] in the Text editor.
    9541166    $textarea.on( 'keydown.wp-autosave', function( event ) {
     1167        // Key [s] has code 83.
    9551168        if ( event.which === 83 ) {
    9561169            if ( event.shiftKey || event.altKey || ( isMac && ( ! event.metaKey || event.ctrlKey ) ) || ( ! isMac && ! event.ctrlKey ) ) {
     
    9631176    });
    9641177
     1178    // If the last status was auto-draft and the save is triggered, edit the current URL.
    9651179    if ( $( '#original_post_status' ).val() === 'auto-draft' && window.history.replaceState ) {
    9661180        var location;
     
    9761190});
    9771191
     1192/**
     1193 * TinyMCE word count display
     1194 */
    9781195( function( $, counter ) {
    9791196    $( function() {
     
    9831200            contentEditor;
    9841201
     1202        /**
     1203         * Get the word count from TinyMCE and display it
     1204         */
    9851205        function update() {
    9861206            var text, count;
     
    10011221        }
    10021222
     1223        /**
     1224         * Bind the word count update triggers.
     1225         *
     1226         * When a node change in the main TinyMCE editor has been triggered.
     1227         * When a key has been released in the plain text content editor.
     1228         */
    10031229        $( document ).on( 'tinymce-editor-init', function( event, editor ) {
    10041230            if ( editor.id !== 'content' ) {
Note: See TracChangeset for help on using the changeset viewer.