2019-11-02 10:38:58 +01:00
/ * *
* Interactions used by the Site Health modules in WordPress .
*
* @ output wp - admin / js / site - health . js
* /
/* global ajaxurl, ClipboardJS, SiteHealth, wp */
jQuery ( document ) . ready ( function ( $ ) {
var _ _ = wp . i18n . _ _ ,
_n = wp . i18n . _n ,
2020-09-15 14:29:22 +02:00
sprintf = wp . i18n . sprintf ,
data ,
clipboard = new ClipboardJS ( '.site-health-copy-buttons .copy-button' ) ,
isDebugTab = $ ( '.health-check-body.health-check-debug-tab' ) . length ,
pathsSizesSection = $ ( '#health-check-accordion-block-wp-paths-sizes' ) ,
successTimeout ;
2019-11-02 10:38:58 +01:00
// Debug information copy section.
clipboard . on ( 'success' , function ( e ) {
2020-09-15 14:29:22 +02:00
var triggerElement = $ ( e . trigger ) ,
successElement = $ ( '.success' , triggerElement . closest ( 'div' ) ) ;
// Clear the selection and move focus back to the trigger.
e . clearSelection ( ) ;
// Handle ClipboardJS focus bug, see https://github.com/zenorocha/clipboard.js/issues/680
triggerElement . focus ( ) ;
// Show success visual feedback.
clearTimeout ( successTimeout ) ;
successElement . removeClass ( 'hidden' ) ;
// Hide success visual feedback after 3 seconds since last success.
successTimeout = setTimeout ( function ( ) {
successElement . addClass ( 'hidden' ) ;
// Remove the visually hidden textarea so that it isn't perceived by assistive technologies.
if ( clipboard . clipboardAction . fakeElem && clipboard . clipboardAction . removeFake ) {
clipboard . clipboardAction . removeFake ( ) ;
}
} , 3000 ) ;
2019-11-02 10:38:58 +01:00
2020-09-15 14:29:22 +02:00
// Handle success audible feedback.
wp . a11y . speak ( _ _ ( 'Site information has been copied to your clipboard.' ) ) ;
2019-11-02 10:38:58 +01:00
} ) ;
// Accordion handling in various areas.
$ ( '.health-check-accordion' ) . on ( 'click' , '.health-check-accordion-trigger' , function ( ) {
var isExpanded = ( 'true' === $ ( this ) . attr ( 'aria-expanded' ) ) ;
if ( isExpanded ) {
$ ( this ) . attr ( 'aria-expanded' , 'false' ) ;
$ ( '#' + $ ( this ) . attr ( 'aria-controls' ) ) . attr ( 'hidden' , true ) ;
} else {
$ ( this ) . attr ( 'aria-expanded' , 'true' ) ;
$ ( '#' + $ ( this ) . attr ( 'aria-controls' ) ) . attr ( 'hidden' , false ) ;
}
} ) ;
// Site Health test handling.
$ ( '.site-health-view-passed' ) . on ( 'click' , function ( ) {
var goodIssuesWrapper = $ ( '#health-check-issues-good' ) ;
goodIssuesWrapper . toggleClass ( 'hidden' ) ;
$ ( this ) . attr ( 'aria-expanded' , ! goodIssuesWrapper . hasClass ( 'hidden' ) ) ;
} ) ;
/ * *
2020-09-15 14:29:22 +02:00
* Appends a new issue to the issue list .
2019-11-02 10:38:58 +01:00
*
* @ since 5.2 . 0
*
* @ param { Object } issue The issue data .
* /
2020-09-15 14:29:22 +02:00
function appendIssue ( issue ) {
2019-11-02 10:38:58 +01:00
var template = wp . template ( 'health-check-issue' ) ,
issueWrapper = $ ( '#health-check-issues-' + issue . status ) ,
heading ,
count ;
2020-09-15 14:29:22 +02:00
2019-11-02 10:38:58 +01:00
SiteHealth . site _status . issues [ issue . status ] ++ ;
count = SiteHealth . site _status . issues [ issue . status ] ;
if ( 'critical' === issue . status ) {
2020-09-15 14:29:22 +02:00
heading = sprintf (
_n ( '%s critical issue' , '%s critical issues' , count ) ,
'<span class="issue-count">' + count + '</span>'
) ;
2019-11-02 10:38:58 +01:00
} else if ( 'recommended' === issue . status ) {
2020-09-15 14:29:22 +02:00
heading = sprintf (
_n ( '%s recommended improvement' , '%s recommended improvements' , count ) ,
'<span class="issue-count">' + count + '</span>'
) ;
2019-11-02 10:38:58 +01:00
} else if ( 'good' === issue . status ) {
2020-09-15 14:29:22 +02:00
heading = sprintf (
_n ( '%s item with no issues detected' , '%s items with no issues detected' , count ) ,
'<span class="issue-count">' + count + '</span>'
) ;
2019-11-02 10:38:58 +01:00
}
if ( heading ) {
$ ( '.site-health-issue-count-title' , issueWrapper ) . html ( heading ) ;
}
$ ( '.issues' , '#health-check-issues-' + issue . status ) . append ( template ( issue ) ) ;
}
/ * *
2020-09-15 14:29:22 +02:00
* Updates site health status indicator as asynchronous tests are run and returned .
2019-11-02 10:38:58 +01:00
*
* @ since 5.2 . 0
* /
2020-09-15 14:29:22 +02:00
function recalculateProgression ( ) {
2019-11-02 10:38:58 +01:00
var r , c , pct ;
var $progress = $ ( '.site-health-progress' ) ;
2019-11-15 22:59:44 +01:00
var $wrapper = $progress . closest ( '.site-health-progress-wrapper' ) ;
var $progressLabel = $ ( '.site-health-progress-label' , $wrapper ) ;
2019-11-02 10:38:58 +01:00
var $circle = $ ( '.site-health-progress svg #bar' ) ;
2020-09-15 14:29:22 +02:00
var totalTests = parseInt ( SiteHealth . site _status . issues . good , 0 ) +
parseInt ( SiteHealth . site _status . issues . recommended , 0 ) +
( parseInt ( SiteHealth . site _status . issues . critical , 0 ) * 1.5 ) ;
var failedTests = ( parseInt ( SiteHealth . site _status . issues . recommended , 0 ) * 0.5 ) +
( parseInt ( SiteHealth . site _status . issues . critical , 0 ) * 1.5 ) ;
2019-11-02 10:38:58 +01:00
var val = 100 - Math . ceil ( ( failedTests / totalTests ) * 100 ) ;
if ( 0 === totalTests ) {
$progress . addClass ( 'hidden' ) ;
return ;
}
2019-11-15 22:59:44 +01:00
$wrapper . removeClass ( 'loading' ) ;
2019-11-02 10:38:58 +01:00
r = $circle . attr ( 'r' ) ;
c = Math . PI * ( r * 2 ) ;
if ( 0 > val ) {
val = 0 ;
}
if ( 100 < val ) {
val = 100 ;
}
pct = ( ( 100 - val ) / 100 ) * c ;
$circle . css ( { strokeDashoffset : pct } ) ;
if ( 1 > parseInt ( SiteHealth . site _status . issues . critical , 0 ) ) {
$ ( '#health-check-issues-critical' ) . addClass ( 'hidden' ) ;
}
if ( 1 > parseInt ( SiteHealth . site _status . issues . recommended , 0 ) ) {
$ ( '#health-check-issues-recommended' ) . addClass ( 'hidden' ) ;
}
2019-11-15 22:59:44 +01:00
if ( 80 <= val && 0 === parseInt ( SiteHealth . site _status . issues . critical , 0 ) ) {
$wrapper . addClass ( 'green' ) . removeClass ( 'orange' ) ;
2019-11-02 10:38:58 +01:00
2019-11-15 22:59:44 +01:00
$progressLabel . text ( _ _ ( 'Good' ) ) ;
wp . a11y . speak ( _ _ ( 'All site health tests have finished running. Your site is looking good, and the results are now available on the page.' ) ) ;
} else {
$wrapper . addClass ( 'orange' ) . removeClass ( 'green' ) ;
2019-11-02 10:38:58 +01:00
2019-11-15 22:59:44 +01:00
$progressLabel . text ( _ _ ( 'Should be improved' ) ) ;
wp . a11y . speak ( _ _ ( 'All site health tests have finished running. There are items that should be addressed, and the results are now available on the page.' ) ) ;
2019-11-02 10:38:58 +01:00
}
if ( ! isDebugTab ) {
$ . post (
ajaxurl ,
{
'action' : 'health-check-site-status-result' ,
'_wpnonce' : SiteHealth . nonce . site _status _result ,
'counts' : SiteHealth . site _status . issues
}
) ;
2019-11-15 22:59:44 +01:00
if ( 100 === val ) {
$ ( '.site-status-all-clear' ) . removeClass ( 'hide' ) ;
$ ( '.site-status-has-issues' ) . addClass ( 'hide' ) ;
}
2019-11-02 10:38:58 +01:00
}
}
/ * *
2020-09-15 14:29:22 +02:00
* Queues the next asynchronous test when we ' re ready to run it .
2019-11-02 10:38:58 +01:00
*
* @ since 5.2 . 0
* /
function maybeRunNextAsyncTest ( ) {
var doCalculation = true ;
if ( 1 <= SiteHealth . site _status . async . length ) {
$ . each ( SiteHealth . site _status . async , function ( ) {
var data = {
'action' : 'health-check-' + this . test . replace ( '_' , '-' ) ,
'_wpnonce' : SiteHealth . nonce . site _status
} ;
if ( this . completed ) {
return true ;
}
doCalculation = false ;
this . completed = true ;
$ . post (
ajaxurl ,
data ,
function ( response ) {
2019-11-15 22:59:44 +01:00
/** This filter is documented in wp-admin/includes/class-wp-site-health.php */
2020-09-15 14:29:22 +02:00
appendIssue ( wp . hooks . applyFilters ( 'site_status_test_result' , response . data ) ) ;
2019-11-02 10:38:58 +01:00
maybeRunNextAsyncTest ( ) ;
}
) ;
return false ;
} ) ;
}
if ( doCalculation ) {
2020-09-15 14:29:22 +02:00
recalculateProgression ( ) ;
2019-11-02 10:38:58 +01:00
}
}
if ( 'undefined' !== typeof SiteHealth && ! isDebugTab ) {
if ( 0 === SiteHealth . site _status . direct . length && 0 === SiteHealth . site _status . async . length ) {
2020-09-15 14:29:22 +02:00
recalculateProgression ( ) ;
2019-11-02 10:38:58 +01:00
} else {
SiteHealth . site _status . issues = {
'good' : 0 ,
'recommended' : 0 ,
'critical' : 0
} ;
}
if ( 0 < SiteHealth . site _status . direct . length ) {
$ . each ( SiteHealth . site _status . direct , function ( ) {
2020-09-15 14:29:22 +02:00
appendIssue ( this ) ;
2019-11-02 10:38:58 +01:00
} ) ;
}
if ( 0 < SiteHealth . site _status . async . length ) {
data = {
'action' : 'health-check-' + SiteHealth . site _status . async [ 0 ] . test . replace ( '_' , '-' ) ,
'_wpnonce' : SiteHealth . nonce . site _status
} ;
SiteHealth . site _status . async [ 0 ] . completed = true ;
$ . post (
ajaxurl ,
data ,
function ( response ) {
2020-09-15 14:29:22 +02:00
appendIssue ( response . data ) ;
2019-11-02 10:38:58 +01:00
maybeRunNextAsyncTest ( ) ;
}
) ;
} else {
2020-09-15 14:29:22 +02:00
recalculateProgression ( ) ;
2019-11-02 10:38:58 +01:00
}
}
function getDirectorySizes ( ) {
var data = {
action : 'health-check-get-sizes' ,
_wpnonce : SiteHealth . nonce . site _status _result
} ;
var timestamp = ( new Date ( ) . getTime ( ) ) ;
// After 3 seconds announce that we're still waiting for directory sizes.
var timeout = window . setTimeout ( function ( ) {
wp . a11y . speak ( _ _ ( 'Please wait...' ) ) ;
} , 3000 ) ;
$ . post ( {
type : 'POST' ,
url : ajaxurl ,
data : data ,
dataType : 'json'
} ) . done ( function ( response ) {
updateDirSizes ( response . data || { } ) ;
} ) . always ( function ( ) {
var delay = ( new Date ( ) . getTime ( ) ) - timestamp ;
$ ( '.health-check-wp-paths-sizes.spinner' ) . css ( 'visibility' , 'hidden' ) ;
2020-09-15 14:29:22 +02:00
recalculateProgression ( ) ;
2019-11-02 10:38:58 +01:00
if ( delay > 3000 ) {
2020-05-06 17:23:38 +02:00
/ *
* We have announced that we ' re waiting .
* Announce that we ' re ready after giving at least 3 seconds
* for the first announcement to be read out , or the two may collide .
* /
2019-11-02 10:38:58 +01:00
if ( delay > 6000 ) {
delay = 0 ;
} else {
delay = 6500 - delay ;
}
window . setTimeout ( function ( ) {
wp . a11y . speak ( _ _ ( 'All site health tests have finished running.' ) ) ;
} , delay ) ;
} else {
// Cancel the announcement.
window . clearTimeout ( timeout ) ;
}
$ ( document ) . trigger ( 'site-health-info-dirsizes-done' ) ;
} ) ;
}
function updateDirSizes ( data ) {
var copyButton = $ ( 'button.button.copy-button' ) ;
2020-05-06 17:23:38 +02:00
var clipboardText = copyButton . attr ( 'data-clipboard-text' ) ;
2019-11-02 10:38:58 +01:00
$ . each ( data , function ( name , value ) {
var text = value . debug || value . size ;
if ( typeof text !== 'undefined' ) {
2020-05-06 17:23:38 +02:00
clipboardText = clipboardText . replace ( name + ': loading...' , name + ': ' + text ) ;
2019-11-02 10:38:58 +01:00
}
} ) ;
2020-05-06 17:23:38 +02:00
copyButton . attr ( 'data-clipboard-text' , clipboardText ) ;
2019-11-02 10:38:58 +01:00
pathsSizesSection . find ( 'td[class]' ) . each ( function ( i , element ) {
var td = $ ( element ) ;
var name = td . attr ( 'class' ) ;
if ( data . hasOwnProperty ( name ) && data [ name ] . size ) {
td . text ( data [ name ] . size ) ;
}
} ) ;
}
if ( isDebugTab ) {
if ( pathsSizesSection . length ) {
getDirectorySizes ( ) ;
} else {
2020-09-15 14:29:22 +02:00
recalculateProgression ( ) ;
2019-11-02 10:38:58 +01:00
}
}
} ) ;