WordPress.org

Make WordPress Core

Ticket #46280: hotfix.46280.2.diff

File hotfix.46280.2.diff, 15.8 KB (added by peterwilsoncc, 12 months ago)
  • trunk/hotfix.php

     
    22/*
    33Plugin Name: Hotfix
    44Description: Provides "hotfixes" for selected WordPress bugs, so you don't have to wait for the next WordPress core release. Keep the plugin updated!
    5 Version: 1.1
     5Version: 1.2
    66Author: Mark Jaquith
    77Author URI: http://coveredwebservices.com/
    88*/
     
    3434        $hotfixes = array();
    3535
    3636        switch ( $wp_version ) {
     37                case '5.1' :
     38                        $hotfixes = array( '510_comment_reply_js' );
     39                        break;
    3740                case '3.5' :
    3841                        $hotfixes = array( '350_twentytwelve', '350_iis_http_failure' );
    3942                        break;
     
    238241                return $temp;
    239242        return false;
    240243}
     244
     245function wp_hotfix_510_comment_reply_js() {
     246        add_action( 'wp_enqueue_scripts', 'wp_hotfix_510_enqueue_comment_reply_js', 99 );
     247}
     248
     249function wp_hotfix_510_enqueue_comment_reply_js() {
     250        global $wp_scripts;
     251
     252        $suffix = SCRIPT_DEBUG ? '' : '.min';
     253
     254        $wp_scripts->registered['comment-reply']->src = plugins_url( "js/comment-reply$suffix.js", __FILE__ );
     255        $wp_scripts->registered['comment-reply']->ver = 'wp46280';
     256}
  • trunk/js/comment-reply.js

     
     1/**
     2 * Handles the addition of the comment form.
     3 *
     4 * @since 2.7.0
     5 * @output wp-includes/js/comment-reply.js
     6 *
     7 * @namespace addComment
     8 *
     9 * @type {Object}
     10 */
     11window.addComment = ( function( window ) {
     12        // Avoid scope lookups on commonly used variables.
     13        var document = window.document;
     14
     15        // Settings.
     16        var config = {
     17                commentReplyClass : 'comment-reply-link',
     18                cancelReplyId     : 'cancel-comment-reply-link',
     19                commentFormId     : 'commentform',
     20                temporaryFormId   : 'wp-temp-form-div',
     21                parentIdFieldId   : 'comment_parent',
     22                postIdFieldId     : 'comment_post_ID'
     23        };
     24
     25        // Cross browser MutationObserver.
     26        var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
     27
     28        // Check browser cuts the mustard.
     29        var cutsTheMustard = 'querySelector' in document && 'addEventListener' in window;
     30
     31        /*
     32         * Check browser supports dataset.
     33         * !! sets the variable to true if the property exists.
     34         */
     35        var supportsDataset = !! document.documentElement.dataset;
     36
     37        // For holding the cancel element.
     38        var cancelElement;
     39
     40        // For holding the comment form element.
     41        var commentFormElement;
     42
     43        // The respond element.
     44        var respondElement;
     45
     46        // The mutation observer.
     47        var observer;
     48
     49        if ( cutsTheMustard && document.readyState !== 'loading' ) {
     50                ready();
     51        } else if ( cutsTheMustard ) {
     52                window.addEventListener( 'DOMContentLoaded', ready, false );
     53        }
     54
     55        /**
     56         * Sets up object variables after the DOM is ready.
     57         *
     58         * @since 5.1.0
     59         */
     60        function ready() {
     61                // Initialise the events.
     62                init();
     63
     64                // Set up a MutationObserver to check for comments loaded late.
     65                observeChanges();
     66        }
     67
     68        /**
     69         * Add events to links classed .comment-reply-link.
     70         *
     71         * Searches the context for reply links and adds the JavaScript events
     72         * required to move the comment form. To allow for lazy loading of
     73         * comments this method is exposed as window.commentReply.init().
     74         *
     75         * @since 5.1.0
     76         *
     77         * @memberOf addComment
     78         *
     79         * @param {HTMLElement} context The parent DOM element to search for links.
     80         */
     81        function init( context ) {
     82                if ( ! cutsTheMustard ) {
     83                        return;
     84                }
     85
     86                // Get required elements.
     87                cancelElement = getElementById( config.cancelReplyId );
     88                commentFormElement = getElementById( config.commentFormId );
     89
     90                // No cancel element, no replies.
     91                if ( ! cancelElement ) {
     92                        return;
     93                }
     94
     95                cancelElement.addEventListener( 'touchstart', cancelEvent );
     96                cancelElement.addEventListener( 'click',      cancelEvent );
     97
     98                var links = replyLinks( context );
     99                var element;
     100
     101                for ( var i = 0, l = links.length; i < l; i++ ) {
     102                        element = links[i];
     103
     104                        element.addEventListener( 'touchstart', clickEvent );
     105                        element.addEventListener( 'click',      clickEvent );
     106                }
     107        }
     108
     109        /**
     110         * Return all links classed .comment-reply-link.
     111         *
     112         * @since 5.1.0
     113         *
     114         * @param {HTMLElement} context The parent DOM element to search for links.
     115         *
     116         * @return {HTMLCollection|NodeList|Array}
     117         */
     118        function replyLinks( context ) {
     119                var selectorClass = config.commentReplyClass;
     120                var allReplyLinks;
     121
     122                // childNodes is a handy check to ensure the context is a HTMLElement.
     123                if ( ! context || ! context.childNodes ) {
     124                        context = document;
     125                }
     126
     127                if ( document.getElementsByClassName ) {
     128                        // Fastest.
     129                        allReplyLinks = context.getElementsByClassName( selectorClass );
     130                }
     131                else {
     132                        // Fast.
     133                        allReplyLinks = context.querySelectorAll( '.' + selectorClass );
     134                }
     135
     136                return allReplyLinks;
     137        }
     138
     139        /**
     140         * Cancel event handler.
     141         *
     142         * @since 5.1.0
     143         *
     144         * @param {Event} event The calling event.
     145         */
     146        function cancelEvent( event ) {
     147                var cancelLink = this;
     148                var temporaryFormId  = config.temporaryFormId;
     149                var temporaryElement = getElementById( temporaryFormId );
     150
     151                if ( ! temporaryElement || ! respondElement ) {
     152                        // Conditions for cancel link fail.
     153                        return;
     154                }
     155
     156                getElementById( config.parentIdFieldId ).value = '0';
     157
     158                // Move the respond form back in place of the temporary element.
     159                temporaryElement.parentNode.replaceChild( respondElement ,temporaryElement );
     160                cancelLink.style.display = 'none';
     161                event.preventDefault();
     162        }
     163
     164        /**
     165         * Click event handler.
     166         *
     167         * @since 5.1.0
     168         *
     169         * @param {Event} event The calling event.
     170         */
     171        function clickEvent( event ) {
     172                var replyLink = this,
     173                        commId    = getDataAttribute( replyLink, 'belowelement'),
     174                        parentId  = getDataAttribute( replyLink, 'commentid' ),
     175                        respondId = getDataAttribute( replyLink, 'respondelement'),
     176                        postId    = getDataAttribute( replyLink, 'postid'),
     177                        follow;
     178
     179                if ( ! commId || ! parentId || ! respondId || ! postId ) {
     180                        /*
     181                         * Theme or plugin defines own link via custom `wp_list_comments()` callback
     182                         * and calls `moveForm()` either directly or via a custom event hook.
     183                         */
     184                        return;
     185                }
     186
     187                /*
     188                 * Third party comments systems can hook into this function via the global scope,
     189                 * therefore the click event needs to reference the global scope.
     190                 */
     191                follow = window.addComment.moveForm(commId, parentId, respondId, postId);
     192                if ( false === follow ) {
     193                        event.preventDefault();
     194                }
     195        }
     196
     197        /**
     198         * Creates a mutation observer to check for newly inserted comments.
     199         *
     200         * @since 5.1.0
     201         */
     202        function observeChanges() {
     203                if ( ! MutationObserver ) {
     204                        return;
     205                }
     206
     207                var observerOptions = {
     208                        childList: true,
     209                        subTree: true
     210                };
     211
     212                observer = new MutationObserver( handleChanges );
     213                observer.observe( document.body, observerOptions );
     214        }
     215
     216        /**
     217         * Handles DOM changes, calling init() if any new nodes are added.
     218         *
     219         * @since 5.1.0
     220         *
     221         * @param {Array} mutationRecords Array of MutationRecord objects.
     222         */
     223        function handleChanges( mutationRecords ) {
     224                var i = mutationRecords.length;
     225
     226                while ( i-- ) {
     227                        // Call init() once if any record in this set adds nodes.
     228                        if ( mutationRecords[ i ].addedNodes.length ) {
     229                                init();
     230                                return;
     231                        }
     232                }
     233        }
     234
     235        /**
     236         * Backward compatible getter of data-* attribute.
     237         *
     238         * Uses element.dataset if it exists, otherwise uses getAttribute.
     239         *
     240         * @since 5.1.0
     241         *
     242         * @param {HTMLElement} Element DOM element with the attribute.
     243         * @param {String}      Attribute the attribute to get.
     244         *
     245         * @return {String}
     246         */
     247        function getDataAttribute( element, attribute ) {
     248                if ( supportsDataset ) {
     249                        return element.dataset[attribute];
     250                }
     251                else {
     252                        return element.getAttribute( 'data-' + attribute );
     253                }
     254        }
     255
     256        /**
     257         * Get element by ID.
     258         *
     259         * Local alias for document.getElementById.
     260         *
     261         * @since 5.1.0
     262         *
     263         * @param {HTMLElement} The requested element.
     264         */
     265        function getElementById( elementId ) {
     266                return document.getElementById( elementId );
     267        }
     268
     269        /**
     270         * Moves the reply form from its current position to the reply location.
     271         *
     272         * @since 2.7.0
     273         *
     274         * @memberOf addComment
     275         *
     276         * @param {String} addBelowId HTML ID of element the form follows.
     277         * @param {String} commentId  Database ID of comment being replied to.
     278         * @param {String} respondId  HTML ID of 'respond' element.
     279         * @param {String} postId     Database ID of the post.
     280         */
     281        function moveForm( addBelowId, commentId, respondId, postId ) {
     282                // Get elements based on their IDs.
     283                var addBelowElement = getElementById( addBelowId );
     284                respondElement  = getElementById( respondId );
     285
     286                // Get the hidden fields.
     287                var parentIdField   = getElementById( config.parentIdFieldId );
     288                var postIdField     = getElementById( config.postIdFieldId );
     289                var element, cssHidden, style;
     290
     291                if ( ! addBelowElement || ! respondElement || ! parentIdField ) {
     292                        // Missing key elements, fail.
     293                        return;
     294                }
     295
     296                addPlaceHolder( respondElement );
     297
     298                // Set the value of the post.
     299                if ( postId && postIdField ) {
     300                        postIdField.value = postId;
     301                }
     302
     303                parentIdField.value = commentId;
     304
     305                cancelElement.style.display = '';
     306                addBelowElement.parentNode.insertBefore( respondElement, addBelowElement.nextSibling );
     307
     308                /*
     309                 * This is for backward compatibility with third party commenting systems
     310                 * hooking into the event using older techniques.
     311                 */
     312                cancelElement.onclick = function(){
     313                        return false;
     314                };
     315
     316                // Focus on the first field in the comment form.
     317                try {
     318                        for ( var i = 0; i < commentFormElement.elements.length; i++ ) {
     319                                element = commentFormElement.elements[i];
     320                                cssHidden = false;
     321
     322                                // Get elements computed style.
     323                                if ( 'getComputedStyle' in window ) {
     324                                        // Modern browsers.
     325                                        style = window.getComputedStyle( element );
     326                                } else if ( document.documentElement.currentStyle ) {
     327                                        // IE 8.
     328                                        style = element.currentStyle;
     329                                }
     330
     331                                /*
     332                                 * For display none, do the same thing jQuery does. For visibility,
     333                                 * check the element computed style since browsers are already doing
     334                                 * the job for us. In fact, the visibility computed style is the actual
     335                                 * computed value and already takes into account the element ancestors.
     336                                 */
     337                                if ( ( element.offsetWidth <= 0 && element.offsetHeight <= 0 ) || style.visibility === 'hidden' ) {
     338                                        cssHidden = true;
     339                                }
     340
     341                                // Skip form elements that are hidden or disabled.
     342                                if ( 'hidden' === element.type || element.disabled || cssHidden ) {
     343                                        continue;
     344                                }
     345
     346                                element.focus();
     347                                // Stop after the first focusable element.
     348                                break;
     349                        }
     350                }
     351                catch(e) {
     352
     353                }
     354
     355                /*
     356                 * false is returned for backward compatibility with third party commenting systems
     357                 * hooking into this function.
     358                 */
     359                return false;
     360        }
     361
     362        /**
     363         * Add placeholder element.
     364         *
     365         * Places a place holder element above the #respond element for
     366         * the form to be returned to if needs be.
     367         *
     368         * @since 2.7.0
     369         *
     370         * @param {HTMLelement} respondElement the #respond element holding comment form.
     371         */
     372        function addPlaceHolder( respondElement ) {
     373                var temporaryFormId  = config.temporaryFormId;
     374                var temporaryElement = getElementById( temporaryFormId );
     375
     376                if ( temporaryElement ) {
     377                        // The element already exists, no need to recreate.
     378                        return;
     379                }
     380
     381                temporaryElement = document.createElement( 'div' );
     382                temporaryElement.id = temporaryFormId;
     383                temporaryElement.style.display = 'none';
     384                respondElement.parentNode.insertBefore( temporaryElement, respondElement );
     385        }
     386
     387        return {
     388                init: init,
     389                moveForm: moveForm
     390        };
     391})( window );
  • trunk/js/comment-reply.min.js

     
     1window.addComment=function(a){function b(){c(),g()}function c(a){if(t&&(m=j(r.cancelReplyId),n=j(r.commentFormId),m)){m.addEventListener("touchstart",e),m.addEventListener("click",e);for(var b,c=d(a),g=0,h=c.length;g<h;g++)b=c[g],b.addEventListener("touchstart",f),b.addEventListener("click",f)}}function d(a){var b,c=r.commentReplyClass;return a&&a.childNodes||(a=q),b=q.getElementsByClassName?a.getElementsByClassName(c):a.querySelectorAll("."+c)}function e(a){var b=this,c=r.temporaryFormId,d=j(c);d&&o&&(j(r.parentIdFieldId).value="0",d.parentNode.replaceChild(o,d),b.style.display="none",a.preventDefault())}function f(b){var c,d=this,e=i(d,"belowelement"),f=i(d,"commentid"),g=i(d,"respondelement"),h=i(d,"postid");e&&f&&g&&h&&(c=a.addComment.moveForm(e,f,g,h),!1===c&&b.preventDefault())}function g(){if(s){var a={childList:!0,subTree:!0};p=new s(h),p.observe(q.body,a)}}function h(a){for(var b=a.length;b--;)if(a[b].addedNodes.length)return void c()}function i(a,b){return u?a.dataset[b]:a.getAttribute("data-"+b)}function j(a){return q.getElementById(a)}function k(b,c,d,e){var f=j(b);o=j(d);var g,h,i,k=j(r.parentIdFieldId),p=j(r.postIdFieldId);if(f&&o&&k){l(o),e&&p&&(p.value=e),k.value=c,m.style.display="",f.parentNode.insertBefore(o,f.nextSibling),m.onclick=function(){return!1};try{for(var s=0;s<n.elements.length;s++)if(g=n.elements[s],h=!1,"getComputedStyle"in a?i=a.getComputedStyle(g):q.documentElement.currentStyle&&(i=g.currentStyle),(g.offsetWidth<=0&&g.offsetHeight<=0||"hidden"===i.visibility)&&(h=!0),"hidden"!==g.type&&!g.disabled&&!h){g.focus();break}}catch(t){}return!1}}function l(a){var b=r.temporaryFormId,c=j(b);c||(c=q.createElement("div"),c.id=b,c.style.display="none",a.parentNode.insertBefore(c,a))}var m,n,o,p,q=a.document,r={commentReplyClass:"comment-reply-link",cancelReplyId:"cancel-comment-reply-link",commentFormId:"commentform",temporaryFormId:"wp-temp-form-div",parentIdFieldId:"comment_parent",postIdFieldId:"comment_post_ID"},s=a.MutationObserver||a.WebKitMutationObserver||a.MozMutationObserver,t="querySelector"in q&&"addEventListener"in a,u=!!q.documentElement.dataset;return t&&"loading"!==q.readyState?b():t&&a.addEventListener("DOMContentLoaded",b,!1),{init:c,moveForm:k}}(window);
  • trunk/readme.txt

     
    33Tags: hotfix, bugs, wordpress, update
    44Requires at least: 3.0
    55Tested up to: 3.5
    6 Stable tag: 1.0
     6Stable tag: 1.2
    77
    88Provides unofficial fixes for selected WordPress bugs, so you don't have to wait for the next WordPress core release.
    99
     
    1313
    1414Recent fixes:
    1515
    16 * **WordPress 3.5**
    17         * Lets you update Twenty Twelve if it is shown as "broken" after installing 3.5
    18         * Lets you update WordPress and install or update plugins and themes. (Only some Windows servers running IIS were affected.) You'll need to [install this plugin manually](http://codex.wordpress.org/Managing_Plugins#Manual_Plugin_Installation).
     16* **WordPress 5.0**
     17        * Lets themes enqueue `comment-reply.js` in the HTML header without JavaScript errors, see [WP#46280](https://core.trac.wordpress.org/ticket/46280).
    1918
    20 * **WordPress 3.4.2**
    21         * Fix adding and updating Custom Fields
    22 
    2319Fixes are specific to your version of WordPress. It may be that your version of WordPress has no fixes. That's fine. Keep the plugin activated and updated, in case you need it for a subsequent version of WordPress!
    2420
    2521== Installation ==
     
    3733Read the "Complete Hotfix List" section in the description. A later version of the plugin may list the hotfixes in a special WordPress admin page.
    3834
    3935== Changelog ==
     36= 1.2 =
     37* Lets themes enqueue `comment-reply.js` in the HTML header without JavaScript errors.
     38
    4039= 1.1 =
    4140* Lets you update WordPress and install or update plugins and themes. (Only some Windows servers running IIS were affected.) You'll need to [install this plugin manually](http://codex.wordpress.org/Managing_Plugins#Manual_Plugin_Installation).
    4241