wp/wp-admin/js/common.js
changeset 7 cf61fcea0001
parent 5 5e2f62d02dcd
child 9 177826044cd9
equal deleted inserted replaced
6:490d5cc509ed 7:cf61fcea0001
     1 /* global setUserSetting, ajaxurl, commonL10n, alert, confirm, pagenow */
     1 /* global setUserSetting, ajaxurl, commonL10n, alert, confirm, pagenow */
     2 var showNotice, adminMenu, columns, validateForm, screenMeta;
     2 var showNotice, adminMenu, columns, validateForm, screenMeta;
     3 ( function( $, window, undefined ) {
     3 ( function( $, window, undefined ) {
       
     4 	var $document = $( document ),
       
     5 		$window = $( window ),
       
     6 		$body = $( document.body );
       
     7 
     4 // Removed in 3.3.
     8 // Removed in 3.3.
     5 // (perhaps) needed for back-compat
     9 // (perhaps) needed for back-compat
     6 adminMenu = {
    10 adminMenu = {
     7 	init : function() {},
    11 	init : function() {},
     8 	fold : function() {},
    12 	fold : function() {},
    35 			page: pagenow
    39 			page: pagenow
    36 		});
    40 		});
    37 	},
    41 	},
    38 
    42 
    39 	checked : function(column) {
    43 	checked : function(column) {
    40 		$('.column-' + column).show();
    44 		$('.column-' + column).removeClass( 'hidden' );
    41 		this.colSpanChange(+1);
    45 		this.colSpanChange(+1);
    42 	},
    46 	},
    43 
    47 
    44 	unchecked : function(column) {
    48 	unchecked : function(column) {
    45 		$('.column-' + column).hide();
    49 		$('.column-' + column).addClass( 'hidden' );
    46 		this.colSpanChange(-1);
    50 		this.colSpanChange(-1);
    47 	},
    51 	},
    48 
    52 
    49 	hidden : function() {
    53 	hidden : function() {
    50 		return $('.manage-column').filter(':hidden').map(function() { return this.id; }).get().join(',');
    54 		return $( '.manage-column[id]' ).filter( ':hidden' ).map(function() {
       
    55 			return this.id;
       
    56 		}).get().join( ',' );
    51 	},
    57 	},
    52 
    58 
    53 	useCheckboxesForHidden : function() {
    59 	useCheckboxesForHidden : function() {
    54 		this.hidden = function(){
    60 		this.hidden = function(){
    55 			return $('.hide-column-tog').not(':checked').map(function() {
    61 			return $('.hide-column-tog').not(':checked').map(function() {
    66 		n = parseInt( $t.attr('colspan'), 10 ) + diff;
    72 		n = parseInt( $t.attr('colspan'), 10 ) + diff;
    67 		$t.attr('colspan', n.toString());
    73 		$t.attr('colspan', n.toString());
    68 	}
    74 	}
    69 };
    75 };
    70 
    76 
    71 $(document).ready(function(){columns.init();});
    77 $document.ready(function(){columns.init();});
    72 
    78 
    73 validateForm = function( form ) {
    79 validateForm = function( form ) {
    74 	return !$( form )
    80 	return !$( form )
    75 		.find( '.form-required' )
    81 		.find( '.form-required' )
    76 		.filter( function() { return $( 'input:visible', this ).val() === ''; } )
    82 		.filter( function() { return $( ':input:visible', this ).val() === ''; } )
    77 		.addClass( 'form-invalid' )
    83 		.addClass( 'form-invalid' )
    78 		.find( 'input:visible' )
    84 		.find( ':input:visible' )
    79 		.change( function() { $( this ).closest( '.form-invalid' ).removeClass( 'form-invalid' ); } )
    85 		.change( function() { $( this ).closest( '.form-invalid' ).removeClass( 'form-invalid' ); } )
    80 		.size();
    86 		.length;
    81 };
    87 };
    82 
    88 
    83 // stub for doing better warnings
    89 // stub for doing better warnings
    84 showNotice = {
    90 showNotice = {
    85 	warn : function() {
    91 	warn : function() {
   101 	toggles: null, // .screen-meta-toggle
   107 	toggles: null, // .screen-meta-toggle
   102 	page:    null, // #wpcontent
   108 	page:    null, // #wpcontent
   103 
   109 
   104 	init: function() {
   110 	init: function() {
   105 		this.element = $('#screen-meta');
   111 		this.element = $('#screen-meta');
   106 		this.toggles = $('.screen-meta-toggle a');
   112 		this.toggles = $( '#screen-meta-links' ).find( '.show-settings' );
   107 		this.page    = $('#wpcontent');
   113 		this.page    = $('#wpcontent');
   108 
   114 
   109 		this.toggles.click( this.toggleEvent );
   115 		this.toggles.click( this.toggleEvent );
   110 	},
   116 	},
   111 
   117 
   112 	toggleEvent: function( e ) {
   118 	toggleEvent: function() {
   113 		var panel = $( this.href.replace(/.+#/, '#') );
   119 		var panel = $( '#' + $( this ).attr( 'aria-controls' ) );
   114 		e.preventDefault();
       
   115 
   120 
   116 		if ( !panel.length )
   121 		if ( !panel.length )
   117 			return;
   122 			return;
   118 
   123 
   119 		if ( panel.is(':visible') )
   124 		if ( panel.is(':visible') )
   120 			screenMeta.close( panel, $(this) );
   125 			screenMeta.close( panel, $(this) );
   121 		else
   126 		else
   122 			screenMeta.open( panel, $(this) );
   127 			screenMeta.open( panel, $(this) );
   123 	},
   128 	},
   124 
   129 
   125 	open: function( panel, link ) {
   130 	open: function( panel, button ) {
   126 
   131 
   127 		$('.screen-meta-toggle').not( link.parent() ).css('visibility', 'hidden');
   132 		$( '#screen-meta-links' ).find( '.screen-meta-toggle' ).not( button.parent() ).css( 'visibility', 'hidden' );
   128 
   133 
   129 		panel.parent().show();
   134 		panel.parent().show();
   130 		panel.slideDown( 'fast', function() {
   135 		panel.slideDown( 'fast', function() {
   131 			panel.focus();
   136 			panel.focus();
   132 			link.addClass('screen-meta-active').attr('aria-expanded', true);
   137 			button.addClass( 'screen-meta-active' ).attr( 'aria-expanded', true );
   133 		});
   138 		});
   134 
   139 
   135 		$( document ).trigger( 'screen:options:open' );
   140 		$document.trigger( 'screen:options:open' );
   136 	},
   141 	},
   137 
   142 
   138 	close: function( panel, link ) {
   143 	close: function( panel, button ) {
   139 		panel.slideUp( 'fast', function() {
   144 		panel.slideUp( 'fast', function() {
   140 			link.removeClass('screen-meta-active').attr('aria-expanded', false);
   145 			button.removeClass( 'screen-meta-active' ).attr( 'aria-expanded', false );
   141 			$('.screen-meta-toggle').css('visibility', '');
   146 			$('.screen-meta-toggle').css('visibility', '');
   142 			panel.parent().hide();
   147 			panel.parent().hide();
   143 		});
   148 		});
   144 
   149 
   145 		$( document ).trigger( 'screen:options:close' );
   150 		$document.trigger( 'screen:options:close' );
   146 	}
   151 	}
   147 };
   152 };
   148 
   153 
   149 /**
   154 /**
   150  * Help tabs.
   155  * Help tabs.
   168 	// Panels
   173 	// Panels
   169 	$('.help-tab-content').not( panel ).removeClass('active').hide();
   174 	$('.help-tab-content').not( panel ).removeClass('active').hide();
   170 	panel.addClass('active').show();
   175 	panel.addClass('active').show();
   171 });
   176 });
   172 
   177 
   173 $(document).ready( function() {
   178 /**
   174 	var checks, first, last, checked, sliced, mobileEvent, transitionTimeout, focusedRowActions, $firstHeading,
   179  * Update custom permalink structure via buttons.
       
   180  */
       
   181 
       
   182 var permalinkStructureFocused = false,
       
   183     $permalinkStructure       = $( '#permalink_structure' ),
       
   184     $permalinkStructureInputs = $( '.permalink-structure input:radio' ),
       
   185     $permalinkCustomSelection = $( '#custom_selection' ),
       
   186     $availableStructureTags   = $( '.form-table.permalink-structure .available-structure-tags button' );
       
   187 
       
   188 // Change permalink structure input when selecting one of the common structures.
       
   189 $permalinkStructureInputs.on( 'change', function() {
       
   190 	if ( 'custom' === this.value ) {
       
   191 		return;
       
   192 	}
       
   193 
       
   194 	$permalinkStructure.val( this.value );
       
   195 
       
   196 	// Update button states after selection.
       
   197 	$availableStructureTags.each( function() {
       
   198 		changeStructureTagButtonState( $( this ) );
       
   199 	} );
       
   200 } );
       
   201 
       
   202 $permalinkStructure.on( 'click input', function() {
       
   203 	$permalinkCustomSelection.prop( 'checked', true );
       
   204 } );
       
   205 
       
   206 // Check if the permalink structure input field has had focus at least once.
       
   207 $permalinkStructure.on( 'focus', function( event ) {
       
   208 	permalinkStructureFocused = true;
       
   209 	$( this ).off( event );
       
   210 } );
       
   211 
       
   212 /**
       
   213  * Enables or disables a structure tag button depending on its usage.
       
   214  *
       
   215  * If the structure is already used in the custom permalink structure,
       
   216  * it will be disabled.
       
   217  *
       
   218  * @param {object} button Button jQuery object.
       
   219  */
       
   220 function changeStructureTagButtonState( button ) {
       
   221 	if ( -1 !== $permalinkStructure.val().indexOf( button.text().trim() ) ) {
       
   222 		button.attr( 'data-label', button.attr( 'aria-label' ) );
       
   223 		button.attr( 'aria-label', button.attr( 'data-used' ) );
       
   224 		button.attr( 'aria-pressed', true );
       
   225 		button.addClass( 'active' );
       
   226 	} else if ( button.attr( 'data-label' ) ) {
       
   227 		button.attr( 'aria-label', button.attr( 'data-label' ) );
       
   228 		button.attr( 'aria-pressed', false );
       
   229 		button.removeClass( 'active' );
       
   230 	}
       
   231 }
       
   232 
       
   233 // Check initial button state.
       
   234 $availableStructureTags.each( function() {
       
   235 	changeStructureTagButtonState( $( this ) );
       
   236 } );
       
   237 
       
   238 // Observe permalink structure field and disable buttons of tags that are already present.
       
   239 $permalinkStructure.on( 'change', function() {
       
   240 	$availableStructureTags.each( function() {
       
   241 		changeStructureTagButtonState( $( this ) );
       
   242 	} );
       
   243 } );
       
   244 
       
   245 $availableStructureTags.on( 'click', function() {
       
   246 	var permalinkStructureValue = $permalinkStructure.val(),
       
   247 	    selectionStart          = $permalinkStructure[ 0 ].selectionStart,
       
   248 	    selectionEnd            = $permalinkStructure[ 0 ].selectionEnd,
       
   249 	    textToAppend            = $( this ).text().trim(),
       
   250 	    textToAnnounce          = $( this ).attr( 'data-added' ),
       
   251 	    newSelectionStart;
       
   252 
       
   253 	// Remove structure tag if already part of the structure.
       
   254 	if ( -1 !== permalinkStructureValue.indexOf( textToAppend ) ) {
       
   255 		permalinkStructureValue = permalinkStructureValue.replace( textToAppend + '/', '' );
       
   256 
       
   257 		$permalinkStructure.val( '/' === permalinkStructureValue ? '' : permalinkStructureValue );
       
   258 
       
   259 		// Announce change to screen readers.
       
   260 		$( '#custom_selection_updated' ).text( textToAnnounce );
       
   261 
       
   262 		// Disable button.
       
   263 		changeStructureTagButtonState( $( this ) );
       
   264 
       
   265 		return;
       
   266 	}
       
   267 
       
   268 	// Input field never had focus, move selection to end of input.
       
   269 	if ( ! permalinkStructureFocused && 0 === selectionStart && 0 === selectionEnd ) {
       
   270 		selectionStart = selectionEnd = permalinkStructureValue.length;
       
   271 	}
       
   272 
       
   273 	$permalinkCustomSelection.prop( 'checked', true );
       
   274 
       
   275 	// Prepend and append slashes if necessary.
       
   276 	if ( '/' !== permalinkStructureValue.substr( 0, selectionStart ).substr( -1 ) ) {
       
   277 		textToAppend = '/' + textToAppend;
       
   278 	}
       
   279 
       
   280 	if ( '/' !== permalinkStructureValue.substr( selectionEnd, 1 ) ) {
       
   281 		textToAppend = textToAppend + '/';
       
   282 	}
       
   283 
       
   284 	// Insert structure tag at the specified position.
       
   285 	$permalinkStructure.val( permalinkStructureValue.substr( 0, selectionStart ) + textToAppend + permalinkStructureValue.substr( selectionEnd ) );
       
   286 
       
   287 	// Announce change to screen readers.
       
   288 	$( '#custom_selection_updated' ).text( textToAnnounce );
       
   289 
       
   290 	// Disable button.
       
   291 	changeStructureTagButtonState( $( this ) );
       
   292 
       
   293 	// If input had focus give it back with cursor right after appended text.
       
   294 	if ( permalinkStructureFocused && $permalinkStructure[0].setSelectionRange ) {
       
   295 		newSelectionStart = ( permalinkStructureValue.substr( 0, selectionStart ) + textToAppend ).length;
       
   296 		$permalinkStructure[0].setSelectionRange( newSelectionStart, newSelectionStart );
       
   297 		$permalinkStructure.focus();
       
   298 	}
       
   299 } );
       
   300 
       
   301 $document.ready( function() {
       
   302 	var checks, first, last, checked, sliced, mobileEvent, transitionTimeout, focusedRowActions,
   175 		lastClicked = false,
   303 		lastClicked = false,
   176 		pageInput = $('input.current-page'),
   304 		pageInput = $('input.current-page'),
   177 		currentPage = pageInput.val(),
   305 		currentPage = pageInput.val(),
   178 		isIOS = /iPhone|iPad|iPod/.test( navigator.userAgent ),
   306 		isIOS = /iPhone|iPad|iPod/.test( navigator.userAgent ),
   179 		isAndroid = navigator.userAgent.indexOf( 'Android' ) !== -1,
   307 		isAndroid = navigator.userAgent.indexOf( 'Android' ) !== -1,
   180 		isIE8 = $( document.documentElement ).hasClass( 'ie8' ),
   308 		isIE8 = $( document.documentElement ).hasClass( 'ie8' ),
   181 		$document = $( document ),
       
   182 		$window = $( window ),
       
   183 		$body = $( document.body ),
       
   184 		$adminMenuWrap = $( '#adminmenuwrap' ),
   309 		$adminMenuWrap = $( '#adminmenuwrap' ),
   185 		$wpwrap = $( '#wpwrap' ),
   310 		$wpwrap = $( '#wpwrap' ),
   186 		$adminmenu = $( '#adminmenu' ),
   311 		$adminmenu = $( '#adminmenu' ),
   187 		$overlay = $( '#wp-responsive-overlay' ),
   312 		$overlay = $( '#wp-responsive-overlay' ),
   188 		$toolbar = $( '#wp-toolbar' ),
   313 		$toolbar = $( '#wp-toolbar' ),
   192 		$adminbar = $( '#wpadminbar' ),
   317 		$adminbar = $( '#wpadminbar' ),
   193 		lastScrollPosition = 0,
   318 		lastScrollPosition = 0,
   194 		pinnedMenuTop = false,
   319 		pinnedMenuTop = false,
   195 		pinnedMenuBottom = false,
   320 		pinnedMenuBottom = false,
   196 		menuTop = 0,
   321 		menuTop = 0,
       
   322 		menuState,
   197 		menuIsPinned = false,
   323 		menuIsPinned = false,
   198 		height = {
   324 		height = {
   199 			window: $window.height(),
   325 			window: $window.height(),
   200 			wpwrap: $wpwrap.height(),
   326 			wpwrap: $wpwrap.height(),
   201 			adminbar: $adminbar.height(),
   327 			adminbar: $adminbar.height(),
   202 			menu: $adminMenuWrap.height()
   328 			menu: $adminMenuWrap.height()
   203 		};
   329 		},
       
   330 		$headerEnd = $( '.wp-header-end' );
   204 
   331 
   205 
   332 
   206 	// when the menu is folded, make the fly-out submenu header clickable
   333 	// when the menu is folded, make the fly-out submenu header clickable
   207 	$adminmenu.on('click.wp-submenu-head', '.wp-submenu-head', function(e){
   334 	$adminmenu.on('click.wp-submenu-head', '.wp-submenu-head', function(e){
   208 		$(e.target).parent().siblings('a').get(0).click();
   335 		$(e.target).parent().siblings('a').get(0).click();
   209 	});
   336 	});
   210 
   337 
   211 	$('#collapse-menu').on('click.collapse-menu', function() {
   338 	$( '#collapse-button' ).on( 'click.collapse-menu', function() {
   212 		var body = $( document.body ), respWidth, state;
   339 		var viewportWidth = getViewportWidth() || 961;
   213 
   340 
   214 		// reset any compensation for submenus near the bottom of the screen
   341 		// reset any compensation for submenus near the bottom of the screen
   215 		$('#adminmenu div.wp-submenu').css('margin-top', '');
   342 		$('#adminmenu div.wp-submenu').css('margin-top', '');
   216 
   343 
   217 		if ( window.innerWidth ) {
   344 		if ( viewportWidth < 960 ) {
   218 			// window.innerWidth is affected by zooming on phones
   345 			if ( $body.hasClass('auto-fold') ) {
   219 			respWidth = Math.max( window.innerWidth, document.documentElement.clientWidth );
   346 				$body.removeClass('auto-fold').removeClass('folded');
   220 		} else {
       
   221 			// IE < 9 doesn't support @media CSS rules
       
   222 			respWidth = 961;
       
   223 		}
       
   224 
       
   225 		if ( respWidth && respWidth < 960 ) {
       
   226 			if ( body.hasClass('auto-fold') ) {
       
   227 				body.removeClass('auto-fold').removeClass('folded');
       
   228 				setUserSetting('unfold', 1);
   347 				setUserSetting('unfold', 1);
   229 				setUserSetting('mfold', 'o');
   348 				setUserSetting('mfold', 'o');
   230 				state = 'open';
   349 				menuState = 'open';
   231 			} else {
   350 			} else {
   232 				body.addClass('auto-fold');
   351 				$body.addClass('auto-fold');
   233 				setUserSetting('unfold', 0);
   352 				setUserSetting('unfold', 0);
   234 				state = 'folded';
   353 				menuState = 'folded';
   235 			}
   354 			}
   236 		} else {
   355 		} else {
   237 			if ( body.hasClass('folded') ) {
   356 			if ( $body.hasClass('folded') ) {
   238 				body.removeClass('folded');
   357 				$body.removeClass('folded');
   239 				setUserSetting('mfold', 'o');
   358 				setUserSetting('mfold', 'o');
   240 				state = 'open';
   359 				menuState = 'open';
   241 			} else {
   360 			} else {
   242 				body.addClass('folded');
   361 				$body.addClass('folded');
   243 				setUserSetting('mfold', 'f');
   362 				setUserSetting('mfold', 'f');
   244 				state = 'folded';
   363 				menuState = 'folded';
   245 			}
   364 			}
   246 		}
   365 		}
   247 
   366 
   248 		$( document ).trigger( 'wp-collapse-menu', { state: state } );
   367 		$document.trigger( 'wp-collapse-menu', { state: menuState } );
   249 	});
   368 	});
       
   369 
       
   370 	// Handle the `aria-haspopup` attribute on the current menu item when it has a sub-menu.
       
   371 	function currentMenuItemHasPopup() {
       
   372 		var $current = $( 'a.wp-has-current-submenu' );
       
   373 
       
   374 		if ( 'folded' === menuState ) {
       
   375 			// When folded or auto-folded and not responsive view, the current menu item does have a fly-out sub-menu.
       
   376 			$current.attr( 'aria-haspopup', 'true' );
       
   377 		} else {
       
   378 			// When expanded or in responsive view, reset aria-haspopup.
       
   379 			$current.attr( 'aria-haspopup', 'false' );
       
   380 		}
       
   381 	}
       
   382 
       
   383 	$document.on( 'wp-menu-state-set wp-collapse-menu wp-responsive-activate wp-responsive-deactivate', currentMenuItemHasPopup );
   250 
   384 
   251 	/**
   385 	/**
   252 	 * Ensure an admin submenu is within the visual viewport.
   386 	 * Ensure an admin submenu is within the visual viewport.
   253 	 *
   387 	 *
   254 	 * @since 4.1.0
   388 	 * @since 4.1.0
   286 	if ( 'ontouchstart' in window || /IEMobile\/[1-9]/.test(navigator.userAgent) ) { // touch screen device
   420 	if ( 'ontouchstart' in window || /IEMobile\/[1-9]/.test(navigator.userAgent) ) { // touch screen device
   287 		// iOS Safari works with touchstart, the rest work with click
   421 		// iOS Safari works with touchstart, the rest work with click
   288 		mobileEvent = isIOS ? 'touchstart' : 'click';
   422 		mobileEvent = isIOS ? 'touchstart' : 'click';
   289 
   423 
   290 		// close any open submenus when touch/click is not on the menu
   424 		// close any open submenus when touch/click is not on the menu
   291 		$(document.body).on( mobileEvent+'.wp-mobile-hover', function(e) {
   425 		$body.on( mobileEvent+'.wp-mobile-hover', function(e) {
   292 			if ( $adminmenu.data('wp-responsive') ) {
   426 			if ( $adminmenu.data('wp-responsive') ) {
   293 				return;
   427 				return;
   294 			}
   428 			}
   295 
   429 
   296 			if ( ! $( e.target ).closest( '#adminmenu' ).length ) {
   430 			if ( ! $( e.target ).closest( '#adminmenu' ).length ) {
   366 		}).find( 'li.wp-has-submenu.wp-not-current-submenu' ).on( 'focusin.adminmenu', function() {
   500 		}).find( 'li.wp-has-submenu.wp-not-current-submenu' ).on( 'focusin.adminmenu', function() {
   367 			adjustSubmenu( $( this ) );
   501 			adjustSubmenu( $( this ) );
   368 		});
   502 		});
   369 	}
   503 	}
   370 
   504 
   371 	// Move .notice, .updated and .error alert boxes. Don't move boxes designed to be inline.
   505 	/*
   372 	$firstHeading = $( 'div.wrap h2:first' );
   506 	 * The `.below-h2` class is here just for backward compatibility with plugins
   373 	$firstHeading.nextAll( 'div.updated, div.error, div.notice' ).addClass( 'below-h2' );
   507 	 * that are (incorrectly) using it. Do not use. Use `.inline` instead. See #34570.
   374 	$( 'div.updated, div.error, div.notice' ).not( '.below-h2, .inline' ).insertAfter( $firstHeading );
   508 	 * If '.wp-header-end' is found, append the notices after it otherwise
       
   509 	 * after the first h1 or h2 heading found within the main content.
       
   510 	 */
       
   511 	if ( ! $headerEnd.length ) {
       
   512 		$headerEnd = $( '.wrap h1, .wrap h2' ).first();
       
   513 	}
       
   514 	$( 'div.updated, div.error, div.notice' ).not( '.inline, .below-h2' ).insertAfter( $headerEnd );
   375 
   515 
   376 	// Make notices dismissible
   516 	// Make notices dismissible
   377 	$( '.notice.is-dismissible' ).each( function() {
   517 	function makeNoticesDismissible() {
   378 		var $this = $( this ),
   518 		$( '.notice.is-dismissible' ).each( function() {
   379 			$button = $( '<button type="button" class="notice-dismiss"><span class="screen-reader-text"></span></button>' ),
   519 			var $el = $( this ),
   380 			btnText = commonL10n.dismiss || '';
   520 				$button = $( '<button type="button" class="notice-dismiss"><span class="screen-reader-text"></span></button>' ),
   381 
   521 				btnText = commonL10n.dismiss || '';
   382 		// Ensure plain text
   522 
   383 		$button.find( '.screen-reader-text' ).text( btnText );
   523 			// Ensure plain text
   384 
   524 			$button.find( '.screen-reader-text' ).text( btnText );
   385 		$this.append( $button );
   525 			$button.on( 'click.wp-dismiss-notice', function( event ) {
   386 
   526 				event.preventDefault();
   387 		$button.on( 'click.wp-dismiss-notice', function( event ) {
   527 				$el.fadeTo( 100, 0, function() {
   388 			event.preventDefault();
   528 					$el.slideUp( 100, function() {
   389 			$this.fadeTo( 100 , 0, function() {
   529 						$el.remove();
   390 				$(this).slideUp( 100, function() {
   530 					});
   391 					$(this).remove();
       
   392 				});
   531 				});
   393 			});
   532 			});
   394 		});
   533 
   395 	});
   534 			$el.append( $button );
       
   535 		});
       
   536 	}
       
   537 
       
   538 	$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 );
   396 
   539 
   397 	// Init screen meta
   540 	// Init screen meta
   398 	screenMeta.init();
   541 	screenMeta.init();
   399 
   542 
   400 	// check all checkboxes
   543 	// This event needs to be delegated. Ticket #37973.
   401 	$('tbody').children().children('.check-column').find(':checkbox').click( function(e) {
   544 	$body.on( 'click', 'tbody > tr > .check-column :checkbox', function( event ) {
   402 		if ( 'undefined' == e.shiftKey ) { return true; }
   545 		// Shift click to select a range of checkboxes.
   403 		if ( e.shiftKey ) {
   546 		if ( 'undefined' == event.shiftKey ) { return true; }
       
   547 		if ( event.shiftKey ) {
   404 			if ( !lastClicked ) { return true; }
   548 			if ( !lastClicked ) { return true; }
   405 			checks = $( lastClicked ).closest( 'form' ).find( ':checkbox' );
   549 			checks = $( lastClicked ).closest( 'form' ).find( ':checkbox' ).filter( ':visible:enabled' );
   406 			first = checks.index( lastClicked );
   550 			first = checks.index( lastClicked );
   407 			last = checks.index( this );
   551 			last = checks.index( this );
   408 			checked = $(this).prop('checked');
   552 			checked = $(this).prop('checked');
   409 			if ( 0 < first && 0 < last && first != last ) {
   553 			if ( 0 < first && 0 < last && first != last ) {
   410 				sliced = ( last > first ) ? checks.slice( first, last ) : checks.slice( last, first );
   554 				sliced = ( last > first ) ? checks.slice( first, last ) : checks.slice( last, first );
   416 				});
   560 				});
   417 			}
   561 			}
   418 		}
   562 		}
   419 		lastClicked = this;
   563 		lastClicked = this;
   420 
   564 
   421 		// toggle "check all" checkboxes
   565 		// Toggle the "Select all" checkboxes depending if the other ones are all checked or not.
   422 		var unchecked = $(this).closest('tbody').find(':checkbox').filter(':visible').not(':checked');
   566 		var unchecked = $(this).closest('tbody').find(':checkbox').filter(':visible:enabled').not(':checked');
   423 		$(this).closest('table').children('thead, tfoot').find(':checkbox').prop('checked', function() {
   567 		$(this).closest('table').children('thead, tfoot').find(':checkbox').prop('checked', function() {
   424 			return ( 0 === unchecked.length );
   568 			return ( 0 === unchecked.length );
   425 		});
   569 		});
   426 
   570 
   427 		return true;
   571 		return true;
   428 	});
   572 	});
   429 
   573 
   430 	$('thead, tfoot').find('.check-column :checkbox').on( 'click.wp-toggle-checkboxes', function( event ) {
   574 	// This event needs to be delegated. Ticket #37973.
       
   575 	$body.on( 'click.wp-toggle-checkboxes', 'thead .check-column :checkbox, tfoot .check-column :checkbox', function( event ) {
   431 		var $this = $(this),
   576 		var $this = $(this),
   432 			$table = $this.closest( 'table' ),
   577 			$table = $this.closest( 'table' ),
   433 			controlChecked = $this.prop('checked'),
   578 			controlChecked = $this.prop('checked'),
   434 			toggle = event.shiftKey || $this.data('wp-toggle');
   579 			toggle = event.shiftKey || $this.data('wp-toggle');
   435 
   580 
   436 		$table.children( 'tbody' ).filter(':visible')
   581 		$table.children( 'tbody' ).filter(':visible')
   437 			.children().children('.check-column').find(':checkbox')
   582 			.children().children('.check-column').find(':checkbox')
   438 			.prop('checked', function() {
   583 			.prop('checked', function() {
   439 				if ( $(this).is(':hidden') ) {
   584 				if ( $(this).is(':hidden,:disabled') ) {
   440 					return false;
   585 					return false;
   441 				}
   586 				}
   442 
   587 
   443 				if ( toggle ) {
   588 				if ( toggle ) {
   444 					return ! $(this).prop( 'checked' );
   589 					return ! $(this).prop( 'checked' );
   476 			// the .row-actions div gets hidden in transit in some browsers (ahem, Firefox).
   621 			// the .row-actions div gets hidden in transit in some browsers (ahem, Firefox).
   477 			transitionTimeout = setTimeout( function() {
   622 			transitionTimeout = setTimeout( function() {
   478 				focusedRowActions.removeClass( 'visible' );
   623 				focusedRowActions.removeClass( 'visible' );
   479 			}, 30 );
   624 			}, 30 );
   480 		}
   625 		}
   481 	}, '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' );
   626 	}, '.has-row-actions' );
       
   627 
       
   628 	// Toggle list table rows on small screens
       
   629 	$( 'tbody' ).on( 'click', '.toggle-row', function() {
       
   630 		$( this ).closest( 'tr' ).toggleClass( 'is-expanded' );
       
   631 	});
   482 
   632 
   483 	$('#default-password-nag-no').click( function() {
   633 	$('#default-password-nag-no').click( function() {
   484 		setUserSetting('default_password_nag', 'hide');
   634 		setUserSetting('default_password_nag', 'hide');
   485 		$('div.default-password-nag').hide();
   635 		$('div.default-password-nag').hide();
   486 		return false;
   636 		return false;
   738 			$( '#wp-admin-bar-menu-toggle a' ).attr( 'aria-expanded', 'false' );
   888 			$( '#wp-admin-bar-menu-toggle a' ).attr( 'aria-expanded', 'false' );
   739 
   889 
   740 			// Toggle sidebar when toggle is clicked
   890 			// Toggle sidebar when toggle is clicked
   741 			$( '#wp-admin-bar-menu-toggle' ).on( 'click.wp-responsive', function( event ) {
   891 			$( '#wp-admin-bar-menu-toggle' ).on( 'click.wp-responsive', function( event ) {
   742 				event.preventDefault();
   892 				event.preventDefault();
       
   893 
       
   894 				// close any open toolbar submenus
       
   895 				$adminbar.find( '.hover' ).removeClass( 'hover' );
       
   896 
   743 				$wpwrap.toggleClass( 'wp-responsive-open' );
   897 				$wpwrap.toggleClass( 'wp-responsive-open' );
   744 				if ( $wpwrap.hasClass( 'wp-responsive-open' ) ) {
   898 				if ( $wpwrap.hasClass( 'wp-responsive-open' ) ) {
   745 					$(this).find('a').attr( 'aria-expanded', 'true' );
   899 					$(this).find('a').attr( 'aria-expanded', 'true' );
   746 					$( '#adminmenu a:first' ).focus();
   900 					$( '#adminmenu a:first' ).focus();
   747 				} else {
   901 				} else {
   788 			$adminmenu.removeData('wp-responsive');
   942 			$adminmenu.removeData('wp-responsive');
   789 			this.enableSortables();
   943 			this.enableSortables();
   790 		},
   944 		},
   791 
   945 
   792 		trigger: function() {
   946 		trigger: function() {
   793 			var width;
   947 			var viewportWidth = getViewportWidth();
   794 
   948 
   795 			if ( window.innerWidth ) {
   949 			// Exclude IE < 9, it doesn't support @media CSS rules.
   796 				// window.innerWidth is affected by zooming on phones
   950 			if ( ! viewportWidth ) {
   797 				width = Math.max( window.innerWidth, document.documentElement.clientWidth );
       
   798 			} else {
       
   799 				// Exclude IE < 9, it doesn't support @media CSS rules
       
   800 				return;
   951 				return;
   801 			}
   952 			}
   802 
   953 
   803 			if ( width <= 782 ) {
   954 			if ( viewportWidth <= 782 ) {
   804 				if ( ! wpResponsiveActive ) {
   955 				if ( ! wpResponsiveActive ) {
   805 					$document.trigger( 'wp-responsive-activate' );
   956 					$document.trigger( 'wp-responsive-activate' );
   806 					wpResponsiveActive = true;
   957 					wpResponsiveActive = true;
   807 				}
   958 				}
   808 			} else {
   959 			} else {
   810 					$document.trigger( 'wp-responsive-deactivate' );
   961 					$document.trigger( 'wp-responsive-deactivate' );
   811 					wpResponsiveActive = false;
   962 					wpResponsiveActive = false;
   812 				}
   963 				}
   813 			}
   964 			}
   814 
   965 
   815 			if ( width <= 480 ) {
   966 			if ( viewportWidth <= 480 ) {
   816 				this.enableOverlay();
   967 				this.enableOverlay();
   817 			} else {
   968 			} else {
   818 				this.disableOverlay();
   969 				this.disableOverlay();
   819 			}
   970 			}
   820 		},
   971 		},
   855 				} catch(e) {}
  1006 				} catch(e) {}
   856 			}
  1007 			}
   857 		}
  1008 		}
   858 	};
  1009 	};
   859 
  1010 
       
  1011 	// Add an ARIA role `button` to elements that behave like UI controls when JavaScript is on.
       
  1012 	function aria_button_if_js() {
       
  1013 		$( '.aria-button-if-js' ).attr( 'role', 'button' );
       
  1014 	}
       
  1015 
       
  1016 	$( document ).ajaxComplete( function() {
       
  1017 		aria_button_if_js();
       
  1018 	});
       
  1019 
       
  1020 	/**
       
  1021 	 * @summary Get the viewport width.
       
  1022 	 *
       
  1023 	 * @since 4.7.0
       
  1024 	 *
       
  1025 	 * @returns {number|boolean} The current viewport width or false if the
       
  1026 	 *                           browser doesn't support innerWidth (IE < 9).
       
  1027 	 */
       
  1028 	function getViewportWidth() {
       
  1029 		var viewportWidth = false;
       
  1030 
       
  1031 		if ( window.innerWidth ) {
       
  1032 			// On phones, window.innerWidth is affected by zooming.
       
  1033 			viewportWidth = Math.max( window.innerWidth, document.documentElement.clientWidth );
       
  1034 		}
       
  1035 
       
  1036 		return viewportWidth;
       
  1037 	}
       
  1038 
       
  1039 	/**
       
  1040 	 * @summary Set the admin menu collapsed/expanded state.
       
  1041 	 *
       
  1042 	 * Sets the global variable `menuState` and triggers a custom event passing
       
  1043 	 * the current menu state.
       
  1044 	 *
       
  1045 	 * @since 4.7.0
       
  1046 	 *
       
  1047 	 * @returns {void}
       
  1048 	 */
       
  1049 	function setMenuState() {
       
  1050 		var viewportWidth = getViewportWidth() || 961;
       
  1051 
       
  1052 		if ( viewportWidth <= 782  ) {
       
  1053 			menuState = 'responsive';
       
  1054 		} else if ( $body.hasClass( 'folded' ) || ( $body.hasClass( 'auto-fold' ) && viewportWidth <= 960 && viewportWidth > 782 ) ) {
       
  1055 			menuState = 'folded';
       
  1056 		} else {
       
  1057 			menuState = 'open';
       
  1058 		}
       
  1059 
       
  1060 		$document.trigger( 'wp-menu-state-set', { state: menuState } );
       
  1061 	}
       
  1062 
       
  1063 	// Set the menu state when the window gets resized.
       
  1064 	$document.on( 'wp-window-resized.set-menu-state', setMenuState );
       
  1065 
       
  1066 	/**
       
  1067 	 * @summary Set ARIA attributes on the collapse/expand menu button.
       
  1068 	 *
       
  1069 	 * When the admin menu is open or folded, updates the `aria-expanded` and
       
  1070 	 * `aria-label` attributes of the button to give feedback to assistive
       
  1071 	 * technologies. In the responsive view, the button is always hidden.
       
  1072 	 *
       
  1073 	 * @since 4.7.0
       
  1074 	 *
       
  1075 	 * @returns {void}
       
  1076 	 */
       
  1077 	$document.on( 'wp-menu-state-set wp-collapse-menu', function( event, eventData ) {
       
  1078 		var $collapseButton = $( '#collapse-button' ),
       
  1079 			ariaExpanded = 'true',
       
  1080 			ariaLabelText = commonL10n.collapseMenu;
       
  1081 
       
  1082 		if ( 'folded' === eventData.state ) {
       
  1083 			ariaExpanded = 'false';
       
  1084 			ariaLabelText = commonL10n.expandMenu;
       
  1085 		}
       
  1086 
       
  1087 		$collapseButton.attr({
       
  1088 			'aria-expanded': ariaExpanded,
       
  1089 			'aria-label': ariaLabelText
       
  1090 		});
       
  1091 	});
       
  1092 
   860 	window.wpResponsive.init();
  1093 	window.wpResponsive.init();
   861 	setPinMenu();
  1094 	setPinMenu();
   862 
  1095 	setMenuState();
   863 	$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 );
  1096 	currentMenuItemHasPopup();
       
  1097 	makeNoticesDismissible();
       
  1098 	aria_button_if_js();
       
  1099 
       
  1100 	$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 );
       
  1101 
       
  1102 	// Set initial focus on a specific element.
       
  1103 	$( '.wp-initial-focus' ).focus();
       
  1104 
       
  1105 	// Toggle update details on update-core.php.
       
  1106 	$body.on( 'click', '.js-update-details-toggle', function() {
       
  1107 		var $updateNotice = $( this ).closest( '.js-update-details' ),
       
  1108 			$progressDiv = $( '#' + $updateNotice.data( 'update-details' ) );
       
  1109 
       
  1110 		/*
       
  1111 		 * When clicking on "Show details" move the progress div below the update
       
  1112 		 * notice. Make sure it gets moved just the first time.
       
  1113 		 */
       
  1114 		if ( ! $progressDiv.hasClass( 'update-details-moved' ) ) {
       
  1115 			$progressDiv.insertAfter( $updateNotice ).addClass( 'update-details-moved' );
       
  1116 		}
       
  1117 
       
  1118 		// Toggle the progress div visibility.
       
  1119 		$progressDiv.toggle();
       
  1120 		// Toggle the Show Details button expanded state.
       
  1121 		$( this ).attr( 'aria-expanded', $progressDiv.is( ':visible' ) );
       
  1122 	});
   864 });
  1123 });
   865 
  1124 
   866 // Fire a custom jQuery event at the end of window resize
  1125 // Fire a custom jQuery event at the end of window resize
   867 ( function() {
  1126 ( function() {
   868 	var timeout;
  1127 	var timeout;
   869 
  1128 
   870 	function triggerEvent() {
  1129 	function triggerEvent() {
   871 		$(document).trigger( 'wp-window-resized' );
  1130 		$document.trigger( 'wp-window-resized' );
   872 	}
  1131 	}
   873 
  1132 
   874 	function fireOnce() {
  1133 	function fireOnce() {
   875 		window.clearTimeout( timeout );
  1134 		window.clearTimeout( timeout );
   876 		timeout = window.setTimeout( triggerEvent, 200 );
  1135 		timeout = window.setTimeout( triggerEvent, 200 );
   877 	}
  1136 	}
   878 
  1137 
   879 	$(window).on( 'resize.wp-fire-once', fireOnce );
  1138 	$window.on( 'resize.wp-fire-once', fireOnce );
   880 }());
  1139 }());
   881 
  1140 
   882 // Make Windows 8 devices play along nicely.
  1141 // Make Windows 8 devices play along nicely.
   883 (function(){
  1142 (function(){
   884 	if ( '-ms-user-select' in document.documentElement.style && navigator.userAgent.match(/IEMobile\/10\.0/) ) {
  1143 	if ( '-ms-user-select' in document.documentElement.style && navigator.userAgent.match(/IEMobile\/10\.0/) ) {