--- a/wp/wp-admin/js/common.js Tue Jun 09 11:14:17 2015 +0000
+++ b/wp/wp-admin/js/common.js Mon Oct 14 17:39:30 2019 +0200
@@ -1,6 +1,10 @@
/* global setUserSetting, ajaxurl, commonL10n, alert, confirm, pagenow */
var showNotice, adminMenu, columns, validateForm, screenMeta;
( function( $, window, undefined ) {
+ var $document = $( document ),
+ $window = $( window ),
+ $body = $( document.body );
+
// Removed in 3.3.
// (perhaps) needed for back-compat
adminMenu = {
@@ -37,17 +41,19 @@
},
checked : function(column) {
- $('.column-' + column).show();
+ $('.column-' + column).removeClass( 'hidden' );
this.colSpanChange(+1);
},
unchecked : function(column) {
- $('.column-' + column).hide();
+ $('.column-' + column).addClass( 'hidden' );
this.colSpanChange(-1);
},
hidden : function() {
- return $('.manage-column').filter(':hidden').map(function() { return this.id; }).get().join(',');
+ return $( '.manage-column[id]' ).filter( ':hidden' ).map(function() {
+ return this.id;
+ }).get().join( ',' );
},
useCheckboxesForHidden : function() {
@@ -68,16 +74,16 @@
}
};
-$(document).ready(function(){columns.init();});
+$document.ready(function(){columns.init();});
validateForm = function( form ) {
return !$( form )
.find( '.form-required' )
- .filter( function() { return $( 'input:visible', this ).val() === ''; } )
+ .filter( function() { return $( ':input:visible', this ).val() === ''; } )
.addClass( 'form-invalid' )
- .find( 'input:visible' )
+ .find( ':input:visible' )
.change( function() { $( this ).closest( '.form-invalid' ).removeClass( 'form-invalid' ); } )
- .size();
+ .length;
};
// stub for doing better warnings
@@ -103,15 +109,14 @@
init: function() {
this.element = $('#screen-meta');
- this.toggles = $('.screen-meta-toggle a');
+ this.toggles = $( '#screen-meta-links' ).find( '.show-settings' );
this.page = $('#wpcontent');
this.toggles.click( this.toggleEvent );
},
- toggleEvent: function( e ) {
- var panel = $( this.href.replace(/.+#/, '#') );
- e.preventDefault();
+ toggleEvent: function() {
+ var panel = $( '#' + $( this ).attr( 'aria-controls' ) );
if ( !panel.length )
return;
@@ -122,27 +127,27 @@
screenMeta.open( panel, $(this) );
},
- open: function( panel, link ) {
+ open: function( panel, button ) {
- $('.screen-meta-toggle').not( link.parent() ).css('visibility', 'hidden');
+ $( '#screen-meta-links' ).find( '.screen-meta-toggle' ).not( button.parent() ).css( 'visibility', 'hidden' );
panel.parent().show();
panel.slideDown( 'fast', function() {
panel.focus();
- link.addClass('screen-meta-active').attr('aria-expanded', true);
+ button.addClass( 'screen-meta-active' ).attr( 'aria-expanded', true );
});
- $( document ).trigger( 'screen:options:open' );
+ $document.trigger( 'screen:options:open' );
},
- close: function( panel, link ) {
+ close: function( panel, button ) {
panel.slideUp( 'fast', function() {
- link.removeClass('screen-meta-active').attr('aria-expanded', false);
+ button.removeClass( 'screen-meta-active' ).attr( 'aria-expanded', false );
$('.screen-meta-toggle').css('visibility', '');
panel.parent().hide();
});
- $( document ).trigger( 'screen:options:close' );
+ $document.trigger( 'screen:options:close' );
}
};
@@ -170,17 +175,137 @@
panel.addClass('active').show();
});
-$(document).ready( function() {
- var checks, first, last, checked, sliced, mobileEvent, transitionTimeout, focusedRowActions, $firstHeading,
+/**
+ * Update custom permalink structure via buttons.
+ */
+
+var permalinkStructureFocused = false,
+ $permalinkStructure = $( '#permalink_structure' ),
+ $permalinkStructureInputs = $( '.permalink-structure input:radio' ),
+ $permalinkCustomSelection = $( '#custom_selection' ),
+ $availableStructureTags = $( '.form-table.permalink-structure .available-structure-tags button' );
+
+// Change permalink structure input when selecting one of the common structures.
+$permalinkStructureInputs.on( 'change', function() {
+ if ( 'custom' === this.value ) {
+ return;
+ }
+
+ $permalinkStructure.val( this.value );
+
+ // Update button states after selection.
+ $availableStructureTags.each( function() {
+ changeStructureTagButtonState( $( this ) );
+ } );
+} );
+
+$permalinkStructure.on( 'click input', function() {
+ $permalinkCustomSelection.prop( 'checked', true );
+} );
+
+// Check if the permalink structure input field has had focus at least once.
+$permalinkStructure.on( 'focus', function( event ) {
+ permalinkStructureFocused = true;
+ $( this ).off( event );
+} );
+
+/**
+ * Enables or disables a structure tag button depending on its usage.
+ *
+ * If the structure is already used in the custom permalink structure,
+ * it will be disabled.
+ *
+ * @param {object} button Button jQuery object.
+ */
+function changeStructureTagButtonState( button ) {
+ if ( -1 !== $permalinkStructure.val().indexOf( button.text().trim() ) ) {
+ button.attr( 'data-label', button.attr( 'aria-label' ) );
+ button.attr( 'aria-label', button.attr( 'data-used' ) );
+ button.attr( 'aria-pressed', true );
+ button.addClass( 'active' );
+ } else if ( button.attr( 'data-label' ) ) {
+ button.attr( 'aria-label', button.attr( 'data-label' ) );
+ button.attr( 'aria-pressed', false );
+ button.removeClass( 'active' );
+ }
+}
+
+// Check initial button state.
+$availableStructureTags.each( function() {
+ changeStructureTagButtonState( $( this ) );
+} );
+
+// Observe permalink structure field and disable buttons of tags that are already present.
+$permalinkStructure.on( 'change', function() {
+ $availableStructureTags.each( function() {
+ changeStructureTagButtonState( $( this ) );
+ } );
+} );
+
+$availableStructureTags.on( 'click', function() {
+ var permalinkStructureValue = $permalinkStructure.val(),
+ selectionStart = $permalinkStructure[ 0 ].selectionStart,
+ selectionEnd = $permalinkStructure[ 0 ].selectionEnd,
+ textToAppend = $( this ).text().trim(),
+ textToAnnounce = $( this ).attr( 'data-added' ),
+ newSelectionStart;
+
+ // Remove structure tag if already part of the structure.
+ if ( -1 !== permalinkStructureValue.indexOf( textToAppend ) ) {
+ permalinkStructureValue = permalinkStructureValue.replace( textToAppend + '/', '' );
+
+ $permalinkStructure.val( '/' === permalinkStructureValue ? '' : permalinkStructureValue );
+
+ // Announce change to screen readers.
+ $( '#custom_selection_updated' ).text( textToAnnounce );
+
+ // Disable button.
+ changeStructureTagButtonState( $( this ) );
+
+ return;
+ }
+
+ // Input field never had focus, move selection to end of input.
+ if ( ! permalinkStructureFocused && 0 === selectionStart && 0 === selectionEnd ) {
+ selectionStart = selectionEnd = permalinkStructureValue.length;
+ }
+
+ $permalinkCustomSelection.prop( 'checked', true );
+
+ // Prepend and append slashes if necessary.
+ if ( '/' !== permalinkStructureValue.substr( 0, selectionStart ).substr( -1 ) ) {
+ textToAppend = '/' + textToAppend;
+ }
+
+ if ( '/' !== permalinkStructureValue.substr( selectionEnd, 1 ) ) {
+ textToAppend = textToAppend + '/';
+ }
+
+ // Insert structure tag at the specified position.
+ $permalinkStructure.val( permalinkStructureValue.substr( 0, selectionStart ) + textToAppend + permalinkStructureValue.substr( selectionEnd ) );
+
+ // Announce change to screen readers.
+ $( '#custom_selection_updated' ).text( textToAnnounce );
+
+ // Disable button.
+ changeStructureTagButtonState( $( this ) );
+
+ // If input had focus give it back with cursor right after appended text.
+ if ( permalinkStructureFocused && $permalinkStructure[0].setSelectionRange ) {
+ newSelectionStart = ( permalinkStructureValue.substr( 0, selectionStart ) + textToAppend ).length;
+ $permalinkStructure[0].setSelectionRange( newSelectionStart, newSelectionStart );
+ $permalinkStructure.focus();
+ }
+} );
+
+$document.ready( function() {
+ var checks, first, last, checked, sliced, mobileEvent, transitionTimeout, focusedRowActions,
lastClicked = false,
pageInput = $('input.current-page'),
currentPage = pageInput.val(),
isIOS = /iPhone|iPad|iPod/.test( navigator.userAgent ),
isAndroid = navigator.userAgent.indexOf( 'Android' ) !== -1,
isIE8 = $( document.documentElement ).hasClass( 'ie8' ),
- $document = $( document ),
- $window = $( window ),
- $body = $( document.body ),
$adminMenuWrap = $( '#adminmenuwrap' ),
$wpwrap = $( '#wpwrap' ),
$adminmenu = $( '#adminmenu' ),
@@ -194,13 +319,15 @@
pinnedMenuTop = false,
pinnedMenuBottom = false,
menuTop = 0,
+ menuState,
menuIsPinned = false,
height = {
window: $window.height(),
wpwrap: $wpwrap.height(),
adminbar: $adminbar.height(),
menu: $adminMenuWrap.height()
- };
+ },
+ $headerEnd = $( '.wp-header-end' );
// when the menu is folded, make the fly-out submenu header clickable
@@ -208,46 +335,53 @@
$(e.target).parent().siblings('a').get(0).click();
});
- $('#collapse-menu').on('click.collapse-menu', function() {
- var body = $( document.body ), respWidth, state;
+ $( '#collapse-button' ).on( 'click.collapse-menu', function() {
+ var viewportWidth = getViewportWidth() || 961;
// reset any compensation for submenus near the bottom of the screen
$('#adminmenu div.wp-submenu').css('margin-top', '');
- if ( window.innerWidth ) {
- // window.innerWidth is affected by zooming on phones
- respWidth = Math.max( window.innerWidth, document.documentElement.clientWidth );
- } else {
- // IE < 9 doesn't support @media CSS rules
- respWidth = 961;
- }
-
- if ( respWidth && respWidth < 960 ) {
- if ( body.hasClass('auto-fold') ) {
- body.removeClass('auto-fold').removeClass('folded');
+ if ( viewportWidth < 960 ) {
+ if ( $body.hasClass('auto-fold') ) {
+ $body.removeClass('auto-fold').removeClass('folded');
setUserSetting('unfold', 1);
setUserSetting('mfold', 'o');
- state = 'open';
+ menuState = 'open';
} else {
- body.addClass('auto-fold');
+ $body.addClass('auto-fold');
setUserSetting('unfold', 0);
- state = 'folded';
+ menuState = 'folded';
}
} else {
- if ( body.hasClass('folded') ) {
- body.removeClass('folded');
+ if ( $body.hasClass('folded') ) {
+ $body.removeClass('folded');
setUserSetting('mfold', 'o');
- state = 'open';
+ menuState = 'open';
} else {
- body.addClass('folded');
+ $body.addClass('folded');
setUserSetting('mfold', 'f');
- state = 'folded';
+ menuState = 'folded';
}
}
- $( document ).trigger( 'wp-collapse-menu', { state: state } );
+ $document.trigger( 'wp-collapse-menu', { state: menuState } );
});
+ // Handle the `aria-haspopup` attribute on the current menu item when it has a sub-menu.
+ function currentMenuItemHasPopup() {
+ var $current = $( 'a.wp-has-current-submenu' );
+
+ if ( 'folded' === menuState ) {
+ // When folded or auto-folded and not responsive view, the current menu item does have a fly-out sub-menu.
+ $current.attr( 'aria-haspopup', 'true' );
+ } else {
+ // When expanded or in responsive view, reset aria-haspopup.
+ $current.attr( 'aria-haspopup', 'false' );
+ }
+ }
+
+ $document.on( 'wp-menu-state-set wp-collapse-menu wp-responsive-activate wp-responsive-deactivate', currentMenuItemHasPopup );
+
/**
* Ensure an admin submenu is within the visual viewport.
*
@@ -288,7 +422,7 @@
mobileEvent = isIOS ? 'touchstart' : 'click';
// close any open submenus when touch/click is not on the menu
- $(document.body).on( mobileEvent+'.wp-mobile-hover', function(e) {
+ $body.on( mobileEvent+'.wp-mobile-hover', function(e) {
if ( $adminmenu.data('wp-responsive') ) {
return;
}
@@ -368,41 +502,51 @@
});
}
- // Move .notice, .updated and .error alert boxes. Don't move boxes designed to be inline.
- $firstHeading = $( 'div.wrap h2:first' );
- $firstHeading.nextAll( 'div.updated, div.error, div.notice' ).addClass( 'below-h2' );
- $( 'div.updated, div.error, div.notice' ).not( '.below-h2, .inline' ).insertAfter( $firstHeading );
+ /*
+ * The `.below-h2` class is here just for backward compatibility with plugins
+ * that are (incorrectly) using it. Do not use. Use `.inline` instead. See #34570.
+ * If '.wp-header-end' is found, append the notices after it otherwise
+ * after the first h1 or h2 heading found within the main content.
+ */
+ if ( ! $headerEnd.length ) {
+ $headerEnd = $( '.wrap h1, .wrap h2' ).first();
+ }
+ $( 'div.updated, div.error, div.notice' ).not( '.inline, .below-h2' ).insertAfter( $headerEnd );
// Make notices dismissible
- $( '.notice.is-dismissible' ).each( function() {
- var $this = $( this ),
- $button = $( '<button type="button" class="notice-dismiss"><span class="screen-reader-text"></span></button>' ),
- btnText = commonL10n.dismiss || '';
-
- // Ensure plain text
- $button.find( '.screen-reader-text' ).text( btnText );
+ function makeNoticesDismissible() {
+ $( '.notice.is-dismissible' ).each( function() {
+ var $el = $( this ),
+ $button = $( '<button type="button" class="notice-dismiss"><span class="screen-reader-text"></span></button>' ),
+ btnText = commonL10n.dismiss || '';
- $this.append( $button );
-
- $button.on( 'click.wp-dismiss-notice', function( event ) {
- event.preventDefault();
- $this.fadeTo( 100 , 0, function() {
- $(this).slideUp( 100, function() {
- $(this).remove();
+ // Ensure plain text
+ $button.find( '.screen-reader-text' ).text( btnText );
+ $button.on( 'click.wp-dismiss-notice', function( event ) {
+ event.preventDefault();
+ $el.fadeTo( 100, 0, function() {
+ $el.slideUp( 100, function() {
+ $el.remove();
+ });
});
});
+
+ $el.append( $button );
});
- });
+ }
+
+ $document.on( 'wp-updates-notice-added wp-plugin-install-error wp-plugin-update-error wp-plugin-delete-error wp-theme-install-error wp-theme-delete-error', makeNoticesDismissible );
// Init screen meta
screenMeta.init();
- // check all checkboxes
- $('tbody').children().children('.check-column').find(':checkbox').click( function(e) {
- if ( 'undefined' == e.shiftKey ) { return true; }
- if ( e.shiftKey ) {
+ // This event needs to be delegated. Ticket #37973.
+ $body.on( 'click', 'tbody > tr > .check-column :checkbox', function( event ) {
+ // Shift click to select a range of checkboxes.
+ if ( 'undefined' == event.shiftKey ) { return true; }
+ if ( event.shiftKey ) {
if ( !lastClicked ) { return true; }
- checks = $( lastClicked ).closest( 'form' ).find( ':checkbox' );
+ checks = $( lastClicked ).closest( 'form' ).find( ':checkbox' ).filter( ':visible:enabled' );
first = checks.index( lastClicked );
last = checks.index( this );
checked = $(this).prop('checked');
@@ -418,8 +562,8 @@
}
lastClicked = this;
- // toggle "check all" checkboxes
- var unchecked = $(this).closest('tbody').find(':checkbox').filter(':visible').not(':checked');
+ // Toggle the "Select all" checkboxes depending if the other ones are all checked or not.
+ var unchecked = $(this).closest('tbody').find(':checkbox').filter(':visible:enabled').not(':checked');
$(this).closest('table').children('thead, tfoot').find(':checkbox').prop('checked', function() {
return ( 0 === unchecked.length );
});
@@ -427,7 +571,8 @@
return true;
});
- $('thead, tfoot').find('.check-column :checkbox').on( 'click.wp-toggle-checkboxes', function( event ) {
+ // This event needs to be delegated. Ticket #37973.
+ $body.on( 'click.wp-toggle-checkboxes', 'thead .check-column :checkbox, tfoot .check-column :checkbox', function( event ) {
var $this = $(this),
$table = $this.closest( 'table' ),
controlChecked = $this.prop('checked'),
@@ -436,7 +581,7 @@
$table.children( 'tbody' ).filter(':visible')
.children().children('.check-column').find(':checkbox')
.prop('checked', function() {
- if ( $(this).is(':hidden') ) {
+ if ( $(this).is(':hidden,:disabled') ) {
return false;
}
@@ -478,7 +623,12 @@
focusedRowActions.removeClass( 'visible' );
}, 30 );
}
- }, 'td.post-title, td.title, td.comment, .tags td.column-name, .bookmarks td.column-name, td.blogname, .users-network td.column-blogs, td.username, .dashboard-comment-wrap' );
+ }, '.has-row-actions' );
+
+ // Toggle list table rows on small screens
+ $( 'tbody' ).on( 'click', '.toggle-row', function() {
+ $( this ).closest( 'tr' ).toggleClass( 'is-expanded' );
+ });
$('#default-password-nag-no').click( function() {
setUserSetting('default_password_nag', 'hide');
@@ -740,6 +890,10 @@
// Toggle sidebar when toggle is clicked
$( '#wp-admin-bar-menu-toggle' ).on( 'click.wp-responsive', function( event ) {
event.preventDefault();
+
+ // close any open toolbar submenus
+ $adminbar.find( '.hover' ).removeClass( 'hover' );
+
$wpwrap.toggleClass( 'wp-responsive-open' );
if ( $wpwrap.hasClass( 'wp-responsive-open' ) ) {
$(this).find('a').attr( 'aria-expanded', 'true' );
@@ -790,17 +944,14 @@
},
trigger: function() {
- var width;
+ var viewportWidth = getViewportWidth();
- if ( window.innerWidth ) {
- // window.innerWidth is affected by zooming on phones
- width = Math.max( window.innerWidth, document.documentElement.clientWidth );
- } else {
- // Exclude IE < 9, it doesn't support @media CSS rules
+ // Exclude IE < 9, it doesn't support @media CSS rules.
+ if ( ! viewportWidth ) {
return;
}
- if ( width <= 782 ) {
+ if ( viewportWidth <= 782 ) {
if ( ! wpResponsiveActive ) {
$document.trigger( 'wp-responsive-activate' );
wpResponsiveActive = true;
@@ -812,7 +963,7 @@
}
}
- if ( width <= 480 ) {
+ if ( viewportWidth <= 480 ) {
this.enableOverlay();
} else {
this.disableOverlay();
@@ -857,10 +1008,118 @@
}
};
+ // Add an ARIA role `button` to elements that behave like UI controls when JavaScript is on.
+ function aria_button_if_js() {
+ $( '.aria-button-if-js' ).attr( 'role', 'button' );
+ }
+
+ $( document ).ajaxComplete( function() {
+ aria_button_if_js();
+ });
+
+ /**
+ * @summary Get the viewport width.
+ *
+ * @since 4.7.0
+ *
+ * @returns {number|boolean} The current viewport width or false if the
+ * browser doesn't support innerWidth (IE < 9).
+ */
+ function getViewportWidth() {
+ var viewportWidth = false;
+
+ if ( window.innerWidth ) {
+ // On phones, window.innerWidth is affected by zooming.
+ viewportWidth = Math.max( window.innerWidth, document.documentElement.clientWidth );
+ }
+
+ return viewportWidth;
+ }
+
+ /**
+ * @summary Set the admin menu collapsed/expanded state.
+ *
+ * Sets the global variable `menuState` and triggers a custom event passing
+ * the current menu state.
+ *
+ * @since 4.7.0
+ *
+ * @returns {void}
+ */
+ function setMenuState() {
+ var viewportWidth = getViewportWidth() || 961;
+
+ if ( viewportWidth <= 782 ) {
+ menuState = 'responsive';
+ } else if ( $body.hasClass( 'folded' ) || ( $body.hasClass( 'auto-fold' ) && viewportWidth <= 960 && viewportWidth > 782 ) ) {
+ menuState = 'folded';
+ } else {
+ menuState = 'open';
+ }
+
+ $document.trigger( 'wp-menu-state-set', { state: menuState } );
+ }
+
+ // Set the menu state when the window gets resized.
+ $document.on( 'wp-window-resized.set-menu-state', setMenuState );
+
+ /**
+ * @summary Set ARIA attributes on the collapse/expand menu button.
+ *
+ * When the admin menu is open or folded, updates the `aria-expanded` and
+ * `aria-label` attributes of the button to give feedback to assistive
+ * technologies. In the responsive view, the button is always hidden.
+ *
+ * @since 4.7.0
+ *
+ * @returns {void}
+ */
+ $document.on( 'wp-menu-state-set wp-collapse-menu', function( event, eventData ) {
+ var $collapseButton = $( '#collapse-button' ),
+ ariaExpanded = 'true',
+ ariaLabelText = commonL10n.collapseMenu;
+
+ if ( 'folded' === eventData.state ) {
+ ariaExpanded = 'false';
+ ariaLabelText = commonL10n.expandMenu;
+ }
+
+ $collapseButton.attr({
+ 'aria-expanded': ariaExpanded,
+ 'aria-label': ariaLabelText
+ });
+ });
+
window.wpResponsive.init();
setPinMenu();
+ setMenuState();
+ currentMenuItemHasPopup();
+ makeNoticesDismissible();
+ aria_button_if_js();
- $document.on( 'wp-window-resized.pin-menu postboxes-columnchange.pin-menu postbox-toggled.pin-menu wp-collapse-menu.pin-menu wp-scroll-start.pin-menu', setPinMenu );
+ $document.on( 'wp-pin-menu wp-window-resized.pin-menu postboxes-columnchange.pin-menu postbox-toggled.pin-menu wp-collapse-menu.pin-menu wp-scroll-start.pin-menu', setPinMenu );
+
+ // Set initial focus on a specific element.
+ $( '.wp-initial-focus' ).focus();
+
+ // Toggle update details on update-core.php.
+ $body.on( 'click', '.js-update-details-toggle', function() {
+ var $updateNotice = $( this ).closest( '.js-update-details' ),
+ $progressDiv = $( '#' + $updateNotice.data( 'update-details' ) );
+
+ /*
+ * When clicking on "Show details" move the progress div below the update
+ * notice. Make sure it gets moved just the first time.
+ */
+ if ( ! $progressDiv.hasClass( 'update-details-moved' ) ) {
+ $progressDiv.insertAfter( $updateNotice ).addClass( 'update-details-moved' );
+ }
+
+ // Toggle the progress div visibility.
+ $progressDiv.toggle();
+ // Toggle the Show Details button expanded state.
+ $( this ).attr( 'aria-expanded', $progressDiv.is( ':visible' ) );
+ });
});
// Fire a custom jQuery event at the end of window resize
@@ -868,7 +1127,7 @@
var timeout;
function triggerEvent() {
- $(document).trigger( 'wp-window-resized' );
+ $document.trigger( 'wp-window-resized' );
}
function fireOnce() {
@@ -876,7 +1135,7 @@
timeout = window.setTimeout( triggerEvent, 200 );
}
- $(window).on( 'resize.wp-fire-once', fireOnce );
+ $window.on( 'resize.wp-fire-once', fireOnce );
}());
// Make Windows 8 devices play along nicely.