wp/wp-admin/js/common.js
changeset 21 48c4eec2b7e6
parent 19 3d72ae0968f4
child 22 8c2e4d02f4ef
equal deleted inserted replaced
20:7b1b88e27a20 21:48c4eec2b7e6
   352 };
   352 };
   353 
   353 
   354 window.setPostThumbnailL10n = deprecateL10nObject( 'setPostThumbnailL10n', window.setPostThumbnailL10n, '5.5.0' );
   354 window.setPostThumbnailL10n = deprecateL10nObject( 'setPostThumbnailL10n', window.setPostThumbnailL10n, '5.5.0' );
   355 
   355 
   356 /**
   356 /**
       
   357  * Removed in 6.5.0, needed for back-compatibility.
       
   358  *
       
   359  * @since 4.5.0
       
   360  * @deprecated 6.5.0
       
   361  */
       
   362 window.uiAutocompleteL10n = window.uiAutocompleteL10n || {
       
   363 	noResults: '',
       
   364 	oneResult: '',
       
   365 	manyResults: '',
       
   366 	itemSelected: ''
       
   367 };
       
   368 
       
   369 window.uiAutocompleteL10n = deprecateL10nObject( 'uiAutocompleteL10n', window.uiAutocompleteL10n, '6.5.0' );
       
   370 
       
   371 /**
   357  * Removed in 3.3.0, needed for back-compatibility.
   372  * Removed in 3.3.0, needed for back-compatibility.
   358  *
   373  *
   359  * @since 2.7.0
   374  * @since 2.7.0
   360  * @deprecated 3.3.0
   375  * @deprecated 3.3.0
   361  */
   376  */
   615 		 * @since 3.2.0
   630 		 * @since 3.2.0
   616 		 *
   631 		 *
   617 		 * @return {void}
   632 		 * @return {void}
   618 		 */
   633 		 */
   619 		panel.slideDown( 'fast', function() {
   634 		panel.slideDown( 'fast', function() {
   620 			panel.trigger( 'focus' );
   635 			panel.removeClass( 'hidden' ).trigger( 'focus' );
   621 			button.addClass( 'screen-meta-active' ).attr( 'aria-expanded', true );
   636 			button.addClass( 'screen-meta-active' ).attr( 'aria-expanded', true );
   622 		});
   637 		});
   623 
   638 
   624 		$document.trigger( 'screen:options:open' );
   639 		$document.trigger( 'screen:options:open' );
   625 	},
   640 	},
   644 		 */
   659 		 */
   645 		panel.slideUp( 'fast', function() {
   660 		panel.slideUp( 'fast', function() {
   646 			button.removeClass( 'screen-meta-active' ).attr( 'aria-expanded', false );
   661 			button.removeClass( 'screen-meta-active' ).attr( 'aria-expanded', false );
   647 			$('.screen-meta-toggle').css('visibility', '');
   662 			$('.screen-meta-toggle').css('visibility', '');
   648 			panel.parent().hide();
   663 			panel.parent().hide();
       
   664 			panel.addClass( 'hidden' );
   649 		});
   665 		});
   650 
   666 
   651 		$document.trigger( 'screen:options:close' );
   667 		$document.trigger( 'screen:options:close' );
   652 	}
   668 	}
   653 };
   669 };
   749 $availableStructureTags.on( 'click', function() {
   765 $availableStructureTags.on( 'click', function() {
   750 	var permalinkStructureValue = $permalinkStructure.val(),
   766 	var permalinkStructureValue = $permalinkStructure.val(),
   751 	    selectionStart          = $permalinkStructure[ 0 ].selectionStart,
   767 	    selectionStart          = $permalinkStructure[ 0 ].selectionStart,
   752 	    selectionEnd            = $permalinkStructure[ 0 ].selectionEnd,
   768 	    selectionEnd            = $permalinkStructure[ 0 ].selectionEnd,
   753 	    textToAppend            = $( this ).text().trim(),
   769 	    textToAppend            = $( this ).text().trim(),
   754 	    textToAnnounce          = $( this ).attr( 'data-added' ),
   770 	    textToAnnounce,
   755 	    newSelectionStart;
   771 	    newSelectionStart;
       
   772 
       
   773 	if ( $( this ).hasClass( 'active' ) ) {
       
   774 		textToAnnounce = $( this ).attr( 'data-removed' );
       
   775 	} else {
       
   776 		textToAnnounce = $( this ).attr( 'data-added' );
       
   777 	}
   756 
   778 
   757 	// Remove structure tag if already part of the structure.
   779 	// Remove structure tag if already part of the structure.
   758 	if ( -1 !== permalinkStructureValue.indexOf( textToAppend ) ) {
   780 	if ( -1 !== permalinkStructureValue.indexOf( textToAppend ) ) {
   759 		permalinkStructureValue = permalinkStructureValue.replace( textToAppend + '/', '' );
   781 		permalinkStructureValue = permalinkStructureValue.replace( textToAppend + '/', '' );
   760 
   782 
   879 
   901 
   880 		$document.trigger( 'wp-collapse-menu', { state: menuState } );
   902 		$document.trigger( 'wp-collapse-menu', { state: menuState } );
   881 	});
   903 	});
   882 
   904 
   883 	/**
   905 	/**
   884 	 * Handles the `aria-haspopup` attribute on the current menu item when it has a submenu.
       
   885 	 *
       
   886 	 * @since 4.4.0
       
   887 	 *
       
   888 	 * @return {void}
       
   889 	 */
       
   890 	function currentMenuItemHasPopup() {
       
   891 		var $current = $( 'a.wp-has-current-submenu' );
       
   892 
       
   893 		if ( 'folded' === menuState ) {
       
   894 			// When folded or auto-folded and not responsive view, the current menu item does have a fly-out sub-menu.
       
   895 			$current.attr( 'aria-haspopup', 'true' );
       
   896 		} else {
       
   897 			// When expanded or in responsive view, reset aria-haspopup.
       
   898 			$current.attr( 'aria-haspopup', 'false' );
       
   899 		}
       
   900 	}
       
   901 
       
   902 	$document.on( 'wp-menu-state-set wp-collapse-menu wp-responsive-activate wp-responsive-deactivate', currentMenuItemHasPopup );
       
   903 
       
   904 	/**
       
   905 	 * Ensures an admin submenu is within the visual viewport.
   906 	 * Ensures an admin submenu is within the visual viewport.
   906 	 *
   907 	 *
   907 	 * @since 4.1.0
   908 	 * @since 4.1.0
   908 	 *
   909 	 *
   909 	 * @param {jQuery} $menuItem The parent menu item containing the submenu.
   910 	 * @param {jQuery} $menuItem The parent menu item containing the submenu.
   929 
   930 
   930 		if ( adjustment > maxtop ) {
   931 		if ( adjustment > maxtop ) {
   931 			adjustment = maxtop;
   932 			adjustment = maxtop;
   932 		}
   933 		}
   933 
   934 
   934 		if ( adjustment > 1 ) {
   935 		if ( adjustment > 1 && $('#wp-admin-bar-menu-toggle').is(':hidden') ) {
   935 			$submenu.css( 'margin-top', '-' + adjustment + 'px' );
   936 			$submenu.css( 'margin-top', '-' + adjustment + 'px' );
   936 		} else {
   937 		} else {
   937 			$submenu.css( 'margin-top', '' );
   938 			$submenu.css( 'margin-top', '' );
   938 		}
   939 		}
   939 	}
   940 	}
  1145 			}
  1146 			}
  1146 		}
  1147 		}
  1147 		lastClicked = this;
  1148 		lastClicked = this;
  1148 
  1149 
  1149 		// Toggle the "Select all" checkboxes depending if the other ones are all checked or not.
  1150 		// Toggle the "Select all" checkboxes depending if the other ones are all checked or not.
  1150 		var unchecked = $(this).closest('tbody').find(':checkbox').filter(':visible:enabled').not(':checked');
  1151 		var unchecked = $(this).closest('tbody').find('tr').find(':checkbox').filter(':visible:enabled').not(':checked');
  1151 
  1152 
  1152 		/**
  1153 		/**
  1153 		 * Determines if all checkboxes are checked.
  1154 		 * Determines if all checkboxes are checked.
  1154 		 *
  1155 		 *
  1155 		 * @return {boolean} Returns true if there are no unchecked checkboxes.
  1156 		 * @return {boolean} Returns true if there are no unchecked checkboxes.
  1398 	 * @param {Event} e The event object.
  1399 	 * @param {Event} e The event object.
  1399 	 *
  1400 	 *
  1400 	 * @return {void}
  1401 	 * @return {void}
  1401  	 */
  1402  	 */
  1402 	$('#contextual-help-link, #show-settings-link').on( 'focus.scroll-into-view', function(e){
  1403 	$('#contextual-help-link, #show-settings-link').on( 'focus.scroll-into-view', function(e){
  1403 		if ( e.target.scrollIntoView )
  1404 		if ( e.target.scrollIntoViewIfNeeded )
  1404 			e.target.scrollIntoView(false);
  1405 			e.target.scrollIntoViewIfNeeded(false);
  1405 	});
  1406 	});
  1406 
  1407 
  1407 	/**
  1408 	/**
  1408 	 * Disables the submit upload buttons when no data is entered.
  1409 	 * Disables the submit upload buttons when no data is entered.
  1409 	 *
  1410 	 *
  1671 			this.maybeDisableSortables = this.maybeDisableSortables.bind( this );
  1672 			this.maybeDisableSortables = this.maybeDisableSortables.bind( this );
  1672 
  1673 
  1673 			// Modify functionality based on custom activate/deactivate event.
  1674 			// Modify functionality based on custom activate/deactivate event.
  1674 			$document.on( 'wp-responsive-activate.wp-responsive', function() {
  1675 			$document.on( 'wp-responsive-activate.wp-responsive', function() {
  1675 				self.activate();
  1676 				self.activate();
       
  1677 				self.toggleAriaHasPopup( 'add' );
  1676 			}).on( 'wp-responsive-deactivate.wp-responsive', function() {
  1678 			}).on( 'wp-responsive-deactivate.wp-responsive', function() {
  1677 				self.deactivate();
  1679 				self.deactivate();
       
  1680 				self.toggleAriaHasPopup( 'remove' );
  1678 			});
  1681 			});
  1679 
  1682 
  1680 			$( '#wp-admin-bar-menu-toggle a' ).attr( 'aria-expanded', 'false' );
  1683 			$( '#wp-admin-bar-menu-toggle a' ).attr( 'aria-expanded', 'false' );
  1681 
  1684 
  1682 			// Toggle sidebar when toggle is clicked.
  1685 			// Toggle sidebar when toggle is clicked.
  1693 				} else {
  1696 				} else {
  1694 					$(this).find('a').attr( 'aria-expanded', 'false' );
  1697 					$(this).find('a').attr( 'aria-expanded', 'false' );
  1695 				}
  1698 				}
  1696 			} );
  1699 			} );
  1697 
  1700 
       
  1701 			// Close sidebar when target moves outside of toggle and sidebar.
       
  1702 			$( document ).on( 'click', function( event ) {
       
  1703 				if ( ! $wpwrap.hasClass( 'wp-responsive-open' ) || ! document.hasFocus() ) {
       
  1704 					return;
       
  1705 				}
       
  1706 
       
  1707 				var focusIsInToggle  = $.contains( $( '#wp-admin-bar-menu-toggle' )[0], event.target );
       
  1708 				var focusIsInSidebar = $.contains( $( '#adminmenuwrap' )[0], event.target );
       
  1709 
       
  1710 				if ( ! focusIsInToggle && ! focusIsInSidebar ) {
       
  1711 					$( '#wp-admin-bar-menu-toggle' ).trigger( 'click.wp-responsive' );
       
  1712 				}
       
  1713 			} );
       
  1714 
       
  1715 			// Close sidebar when a keypress completes outside of toggle and sidebar.
       
  1716 			$( document ).on( 'keyup', function( event ) {
       
  1717 				var toggleButton   = $( '#wp-admin-bar-menu-toggle' )[0];
       
  1718 				if ( ! $wpwrap.hasClass( 'wp-responsive-open' ) ) {
       
  1719 				    return;
       
  1720 				}
       
  1721 				if ( 27 === event.keyCode ) {
       
  1722 					$( toggleButton ).trigger( 'click.wp-responsive' );
       
  1723 					$( toggleButton ).find( 'a' ).trigger( 'focus' );
       
  1724 				} else {
       
  1725 					if ( 9 === event.keyCode ) {
       
  1726 						var sidebar        = $( '#adminmenuwrap' )[0];
       
  1727 						var focusedElement = event.relatedTarget || document.activeElement;
       
  1728 						// A brief delay is required to allow focus to switch to another element.
       
  1729 						setTimeout( function() {
       
  1730 							var focusIsInToggle  = $.contains( toggleButton, focusedElement );
       
  1731 							var focusIsInSidebar = $.contains( sidebar, focusedElement );
       
  1732 
       
  1733 							if ( ! focusIsInToggle && ! focusIsInSidebar ) {
       
  1734 								$( toggleButton ).trigger( 'click.wp-responsive' );
       
  1735 							}
       
  1736 						}, 10 );
       
  1737 					}
       
  1738 				}
       
  1739 			});
       
  1740 
  1698 			// Add menu events.
  1741 			// Add menu events.
  1699 			$adminmenu.on( 'click.wp-responsive', 'li.wp-has-submenu > a', function( event ) {
  1742 			$adminmenu.on( 'click.wp-responsive', 'li.wp-has-submenu > a', function( event ) {
  1700 				if ( ! $adminmenu.data('wp-responsive') ) {
  1743 				if ( ! $adminmenu.data('wp-responsive') ) {
  1701 					return;
  1744 					return;
  1702 				}
  1745 				}
  1703 
  1746 				let state = ( 'false' === $( this ).attr( 'aria-expanded' ) ) ? 'true' : 'false';
  1704 				$( this ).parent( 'li' ).toggleClass( 'selected' );
  1747 				$( this ).parent( 'li' ).toggleClass( 'selected' );
       
  1748 				$( this ).attr( 'aria-expanded', state );
       
  1749 				$( this ).trigger( 'focus' );
  1705 				event.preventDefault();
  1750 				event.preventDefault();
  1706 			});
  1751 			});
  1707 
  1752 
  1708 			self.trigger();
  1753 			self.trigger();
  1709 			$document.on( 'wp-window-resized.wp-responsive', this.trigger.bind( this ) );
  1754 			$document.on( 'wp-window-resized.wp-responsive', this.trigger.bind( this ) );
  1770 		deactivate: function() {
  1815 		deactivate: function() {
  1771 			setPinMenu();
  1816 			setPinMenu();
  1772 			$adminmenu.removeData('wp-responsive');
  1817 			$adminmenu.removeData('wp-responsive');
  1773 
  1818 
  1774 			this.maybeDisableSortables();
  1819 			this.maybeDisableSortables();
       
  1820 		},
       
  1821 
       
  1822 		/**
       
  1823 		 * Toggles the aria-haspopup attribute for the responsive admin menu.
       
  1824 		 *
       
  1825 		 * The aria-haspopup attribute is only necessary for the responsive menu.
       
  1826 		 * See ticket https://core.trac.wordpress.org/ticket/43095
       
  1827 		 *
       
  1828 		 * @since 6.6.0
       
  1829 		 *
       
  1830 		 * @param {string} action Whether to add or remove the aria-haspopup attribute.
       
  1831 		 *
       
  1832 		 * @return {void}
       
  1833 		 */
       
  1834 		toggleAriaHasPopup: function( action ) {
       
  1835 			var elements = $adminmenu.find( '[data-ariahaspopup]' );
       
  1836 
       
  1837 			if ( action === 'add' ) {
       
  1838 				elements.each( function() {
       
  1839 					$( this ).attr( 'aria-haspopup', 'menu' ).attr( 'aria-expanded', 'false' );
       
  1840 				} );
       
  1841 
       
  1842 				return;
       
  1843 			}
       
  1844 
       
  1845 			elements.each( function() {
       
  1846 				$( this ).removeAttr( 'aria-haspopup' ).removeAttr( 'aria-expanded' );
       
  1847 			} );
  1775 		},
  1848 		},
  1776 
  1849 
  1777 		/**
  1850 		/**
  1778 		 * Sets the responsiveness and enables the overlay based on the viewport width.
  1851 		 * Sets the responsiveness and enables the overlay based on the viewport width.
  1779 		 *
  1852 		 *
  1969 	});
  2042 	});
  1970 
  2043 
  1971 	window.wpResponsive.init();
  2044 	window.wpResponsive.init();
  1972 	setPinMenu();
  2045 	setPinMenu();
  1973 	setMenuState();
  2046 	setMenuState();
  1974 	currentMenuItemHasPopup();
       
  1975 	makeNoticesDismissible();
  2047 	makeNoticesDismissible();
  1976 	aria_button_if_js();
  2048 	aria_button_if_js();
  1977 
  2049 
  1978 	$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 );
  2050 	$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 );
  1979 
  2051 
  2075 		document.getElementsByTagName( 'head' )[0].appendChild( msViewportStyle );
  2147 		document.getElementsByTagName( 'head' )[0].appendChild( msViewportStyle );
  2076 	}
  2148 	}
  2077 })();
  2149 })();
  2078 
  2150 
  2079 }( jQuery, window ));
  2151 }( jQuery, window ));
       
  2152 
       
  2153 /**
       
  2154  * Freeze animated plugin icons when reduced motion is enabled.
       
  2155  *
       
  2156  * When the user has enabled the 'prefers-reduced-motion' setting, this module
       
  2157  * stops animations for all GIFs on the page with the class 'plugin-icon' or
       
  2158  * plugin icon images in the update plugins table.
       
  2159  *
       
  2160  * @since 6.4.0
       
  2161  */
       
  2162 (function() {
       
  2163 	// Private variables and methods.
       
  2164 	var priv = {},
       
  2165 		pub = {},
       
  2166 		mediaQuery;
       
  2167 
       
  2168 	// Initialize pauseAll to false; it will be set to true if reduced motion is preferred.
       
  2169 	priv.pauseAll = false;
       
  2170 	if ( window.matchMedia ) {
       
  2171 		mediaQuery = window.matchMedia( '(prefers-reduced-motion: reduce)' );
       
  2172 		if ( ! mediaQuery || mediaQuery.matches ) {
       
  2173 			priv.pauseAll = true;
       
  2174 		}
       
  2175 	}
       
  2176 
       
  2177 	// Method to replace animated GIFs with a static frame.
       
  2178 	priv.freezeAnimatedPluginIcons = function( img ) {
       
  2179 		var coverImage = function() {
       
  2180 			var width = img.width;
       
  2181 			var height = img.height;
       
  2182 			var canvas = document.createElement( 'canvas' );
       
  2183 
       
  2184 			// Set canvas dimensions.
       
  2185 			canvas.width = width;
       
  2186 			canvas.height = height;
       
  2187 
       
  2188 			// Copy classes from the image to the canvas.
       
  2189 			canvas.className = img.className;
       
  2190 
       
  2191 			// Check if the image is inside a specific table.
       
  2192 			var isInsideUpdateTable = img.closest( '#update-plugins-table' );
       
  2193 
       
  2194 			if ( isInsideUpdateTable ) {
       
  2195 				// Transfer computed styles from image to canvas.
       
  2196 				var computedStyles = window.getComputedStyle( img ),
       
  2197 					i, max;
       
  2198 				for ( i = 0, max = computedStyles.length; i < max; i++ ) {
       
  2199 					var propName = computedStyles[ i ];
       
  2200 					var propValue = computedStyles.getPropertyValue( propName );
       
  2201 					canvas.style[ propName ] = propValue;
       
  2202 				}
       
  2203 			}
       
  2204 
       
  2205 			// Draw the image onto the canvas.
       
  2206 			canvas.getContext( '2d' ).drawImage( img, 0, 0, width, height );
       
  2207 
       
  2208 			// Set accessibility attributes on canvas.
       
  2209 			canvas.setAttribute( 'aria-hidden', 'true' );
       
  2210 			canvas.setAttribute( 'role', 'presentation' );
       
  2211 
       
  2212 			// Insert canvas before the image and set the image to be near-invisible.
       
  2213 			var parent = img.parentNode;
       
  2214 			parent.insertBefore( canvas, img );
       
  2215 			img.style.opacity = 0.01;
       
  2216 			img.style.width = '0px';
       
  2217 			img.style.height = '0px';
       
  2218 		};
       
  2219 
       
  2220 		// If the image is already loaded, apply the coverImage function.
       
  2221 		if ( img.complete ) {
       
  2222 			coverImage();
       
  2223 		} else {
       
  2224 			// Otherwise, wait for the image to load.
       
  2225 			img.addEventListener( 'load', coverImage, true );
       
  2226 		}
       
  2227 	};
       
  2228 
       
  2229 	// Public method to freeze all relevant GIFs on the page.
       
  2230 	pub.freezeAll = function() {
       
  2231 		var images = document.querySelectorAll( '.plugin-icon, #update-plugins-table img' );
       
  2232 		for ( var x = 0; x < images.length; x++ ) {
       
  2233 			if ( /\.gif(?:\?|$)/i.test( images[ x ].src ) ) {
       
  2234 				priv.freezeAnimatedPluginIcons( images[ x ] );
       
  2235 			}
       
  2236 		}
       
  2237 	};
       
  2238 
       
  2239 	// Only run the freezeAll method if the user prefers reduced motion.
       
  2240 	if ( true === priv.pauseAll ) {
       
  2241 		pub.freezeAll();
       
  2242 	}
       
  2243 
       
  2244 	// Listen for jQuery AJAX events.
       
  2245 	( function( $ ) {
       
  2246 		if ( window.pagenow === 'plugin-install' ) {
       
  2247 			// Only listen for ajaxComplete if this is the plugin-install.php page.
       
  2248 			$( document ).ajaxComplete( function( event, xhr, settings ) {
       
  2249 
       
  2250 				// Check if this is the 'search-install-plugins' request.
       
  2251 				if ( settings.data && typeof settings.data === 'string' && settings.data.includes( 'action=search-install-plugins' ) ) {
       
  2252 					// Recheck if the user prefers reduced motion.
       
  2253 					if ( window.matchMedia ) {
       
  2254 						var mediaQuery = window.matchMedia( '(prefers-reduced-motion: reduce)' );
       
  2255 						if ( mediaQuery.matches ) {
       
  2256 							pub.freezeAll();
       
  2257 						}
       
  2258 					} else {
       
  2259 						// Fallback for browsers that don't support matchMedia.
       
  2260 						if ( true === priv.pauseAll ) {
       
  2261 							pub.freezeAll();
       
  2262 						}
       
  2263 					}
       
  2264 				}
       
  2265 			} );
       
  2266 		}
       
  2267 	} )( jQuery );
       
  2268 
       
  2269 	// Expose public methods.
       
  2270 	return pub;
       
  2271 })();