wp/wp-admin/js/plugin-install.js
changeset 7 cf61fcea0001
parent 5 5e2f62d02dcd
child 9 177826044cd9
equal deleted inserted replaced
6:490d5cc509ed 7:cf61fcea0001
     1 /* global plugininstallL10n, tb_click */
     1 /* global plugininstallL10n, tb_click, tb_remove */
     2 
     2 
     3 /* Plugin Browser Thickbox related JS*/
     3 /**
       
     4  * Functionality for the plugin install screens.
       
     5  */
     4 var tb_position;
     6 var tb_position;
     5 jQuery( document ).ready( function( $ ) {
     7 jQuery( document ).ready( function( $ ) {
       
     8 
       
     9 	var tbWindow,
       
    10 		$iframeBody,
       
    11 		$tabbables,
       
    12 		$firstTabbable,
       
    13 		$lastTabbable,
       
    14 		$focusedBefore = $(),
       
    15 		$uploadViewToggle = $( '.upload-view-toggle' ),
       
    16 		$wrap = $ ( '.wrap' ),
       
    17 		$body = $( document.body );
       
    18 
     6 	tb_position = function() {
    19 	tb_position = function() {
     7 		var tbWindow = $( '#TB_window' ),
    20 		var width = $( window ).width(),
     8 			width = $( window ).width(),
       
     9 			H = $( window ).height() - ( ( 792 < width ) ? 60 : 20 ),
    21 			H = $( window ).height() - ( ( 792 < width ) ? 60 : 20 ),
    10 			W = ( 792 < width ) ? 772 : width - 20;
    22 			W = ( 792 < width ) ? 772 : width - 20;
    11 
    23 
    12 		if ( tbWindow.size() ) {
    24 		tbWindow = $( '#TB_window' );
       
    25 
       
    26 		if ( tbWindow.length ) {
    13 			tbWindow.width( W ).height( H );
    27 			tbWindow.width( W ).height( H );
    14 			$( '#TB_iframeContent' ).width( W ).height( H );
    28 			$( '#TB_iframeContent' ).width( W ).height( H );
    15 			tbWindow.css({
    29 			tbWindow.css({
    16 				'margin-left': '-' + parseInt( ( W / 2 ), 10 ) + 'px'
    30 				'margin-left': '-' + parseInt( ( W / 2 ), 10 ) + 'px'
    17 			});
    31 			});
    36 
    50 
    37 	$( window ).resize( function() {
    51 	$( window ).resize( function() {
    38 		tb_position();
    52 		tb_position();
    39 	});
    53 	});
    40 
    54 
    41 	$( '.plugin-card, .plugins .column-description' ).on( 'click', 'a.thickbox', function() {
    55 	/*
       
    56 	 * Custom events: when a Thickbox iframe has loaded and when the Thickbox
       
    57 	 * modal gets removed from the DOM.
       
    58 	 */
       
    59 	$body
       
    60 		.on( 'thickbox:iframe:loaded', tbWindow, function() {
       
    61 			/*
       
    62 			 * Return if it's not the modal with the plugin details iframe. Other
       
    63 			 * thickbox instances might want to load an iframe with content from
       
    64 			 * an external domain. Avoid to access the iframe contents when we're
       
    65 			 * not sure the iframe loads from the same domain.
       
    66 			 */
       
    67 			if ( ! tbWindow.hasClass( 'plugin-details-modal' ) ) {
       
    68 				return;
       
    69 			}
       
    70 
       
    71 			iframeLoaded();
       
    72 		})
       
    73 		.on( 'thickbox:removed', function() {
       
    74 			// Set focus back to the element that opened the modal dialog.
       
    75 			// Note: IE 8 would need this wrapped in a fake setTimeout `0`.
       
    76 			$focusedBefore.focus();
       
    77 		});
       
    78 
       
    79 	function iframeLoaded() {
       
    80 		var $iframe = tbWindow.find( '#TB_iframeContent' );
       
    81 
       
    82 		// Get the iframe body.
       
    83 		$iframeBody = $iframe.contents().find( 'body' );
       
    84 
       
    85 		// Get the tabbable elements and handle the keydown event on first load.
       
    86 		handleTabbables();
       
    87 
       
    88 		// Set initial focus on the "Close" button.
       
    89 		$firstTabbable.focus();
       
    90 
       
    91 		/*
       
    92 		 * When the "Install" button is disabled (e.g. the Plugin is already installed)
       
    93 		 * then we can't predict where the last focusable element is. We need to get
       
    94 		 * the tabbable elements and handle the keydown event again and again,
       
    95 		 * each time the active tab panel changes.
       
    96 		 */
       
    97 		$( '#plugin-information-tabs a', $iframeBody ).on( 'click', function() {
       
    98 			handleTabbables();
       
    99 		});
       
   100 
       
   101 		// Close the modal when pressing Escape.
       
   102 		$iframeBody.on( 'keydown', function( event ) {
       
   103 			if ( 27 !== event.which ) {
       
   104 				return;
       
   105 			}
       
   106 			tb_remove();
       
   107 		});
       
   108 	}
       
   109 
       
   110 	/*
       
   111 	 * Get the tabbable elements and detach/attach the keydown event.
       
   112 	 * Called after the iframe has fully loaded so we have all the elements we need.
       
   113 	 * Called again each time a Tab gets clicked.
       
   114 	 * @todo Consider to implement a WordPress general utility for this and don't use jQuery UI.
       
   115 	 */
       
   116 	function handleTabbables() {
       
   117 		var $firstAndLast;
       
   118 		// Get all the tabbable elements.
       
   119 		$tabbables = $( ':tabbable', $iframeBody );
       
   120 		// Our first tabbable element is always the "Close" button.
       
   121 		$firstTabbable = tbWindow.find( '#TB_closeWindowButton' );
       
   122 		// Get the last tabbable element.
       
   123 		$lastTabbable = $tabbables.last();
       
   124 		// Make a jQuery collection.
       
   125 		$firstAndLast = $firstTabbable.add( $lastTabbable );
       
   126 		// Detach any previously attached keydown event.
       
   127 		$firstAndLast.off( 'keydown.wp-plugin-details' );
       
   128 		// Attach again the keydown event on the first and last focusable elements.
       
   129 		$firstAndLast.on( 'keydown.wp-plugin-details', function( event ) {
       
   130 			constrainTabbing( event );
       
   131 		});
       
   132 	}
       
   133 
       
   134 	// Constrain tabbing within the plugin modal dialog.
       
   135 	function constrainTabbing( event ) {
       
   136 		if ( 9 !== event.which ) {
       
   137 			return;
       
   138 		}
       
   139 
       
   140 		if ( $lastTabbable[0] === event.target && ! event.shiftKey ) {
       
   141 			event.preventDefault();
       
   142 			$firstTabbable.focus();
       
   143 		} else if ( $firstTabbable[0] === event.target && event.shiftKey ) {
       
   144 			event.preventDefault();
       
   145 			$lastTabbable.focus();
       
   146 		}
       
   147 	}
       
   148 
       
   149 	/*
       
   150 	 * Open the Plugin details modal. The event is delegated to get also the links
       
   151 	 * in the plugins search tab, after the AJAX search rebuilds the HTML. It's
       
   152 	 * delegated on the closest ancestor and not on the body to avoid conflicts
       
   153 	 * with other handlers, see Trac ticket #43082.
       
   154 	 */
       
   155 	$( '.wrap' ).on( 'click', '.thickbox.open-plugin-details-modal', function( e ) {
       
   156 		// The `data-title` attribute is used only in the Plugin screens.
       
   157 		var title = $( this ).data( 'title' ) ? plugininstallL10n.plugin_information + ' ' + $( this ).data( 'title' ) : plugininstallL10n.plugin_modal_label;
       
   158 
       
   159 		e.preventDefault();
       
   160 		e.stopPropagation();
       
   161 
       
   162 		// Store the element that has focus before opening the modal dialog, i.e. the control which opens it.
       
   163 		$focusedBefore = $( this );
       
   164 
    42 		tb_click.call(this);
   165 		tb_click.call(this);
    43 
   166 
    44 		$('#TB_title').css({'background-color':'#23282d','color':'#cfcfcf'});
   167 		// Set ARIA role, ARIA label, and add a CSS class.
    45 		$('#TB_ajaxWindowTitle').html( '<strong>' + plugininstallL10n.plugin_information + '</strong>&nbsp;' + $(this).data( 'title' ) );
   168 		tbWindow
    46 		$('#TB_iframeContent').attr( 'title', plugininstallL10n.plugin_information + ' ' + $(this).data( 'title' ) );
   169 			.attr({
    47 		$('#TB_closeWindowButton').focus();
   170 				'role': 'dialog',
    48 
   171 				'aria-label': plugininstallL10n.plugin_modal_label
    49 		return false;
   172 			})
       
   173 			.addClass( 'plugin-details-modal' );
       
   174 
       
   175 		// Set title attribute on the iframe.
       
   176 		tbWindow.find( '#TB_iframeContent' ).attr( 'title', title );
    50 	});
   177 	});
    51 
   178 
    52 	/* Plugin install related JS */
   179 	/* Plugin install related JS */
    53 	$( '#plugin-information-tabs a' ).click( function( event ) {
   180 	$( '#plugin-information-tabs a' ).click( function( event ) {
    54 		var tab = $( this ).attr( 'name' );
   181 		var tab = $( this ).attr( 'name' );
    67 
   194 
    68 		// Flip the content.
   195 		// Flip the content.
    69 		$( '#section-holder div.section' ).hide(); // Hide 'em all.
   196 		$( '#section-holder div.section' ).hide(); // Hide 'em all.
    70 		$( '#section-' + tab ).show();
   197 		$( '#section-' + tab ).show();
    71 	});
   198 	});
       
   199 
       
   200 	/*
       
   201 	 * When a user presses the "Upload Plugin" button, show the upload form in place
       
   202 	 * rather than sending them to the devoted upload plugin page.
       
   203 	 * The `?tab=upload` page still exists for no-js support and for plugins that
       
   204 	 * might access it directly. When we're in this page, let the link behave
       
   205 	 * like a link. Otherwise we're in the normal plugin installer pages and the
       
   206 	 * link should behave like a toggle button.
       
   207 	 */
       
   208 	if ( ! $wrap.hasClass( 'plugin-install-tab-upload' ) ) {
       
   209 		$uploadViewToggle
       
   210 			.attr({
       
   211 				role: 'button',
       
   212 				'aria-expanded': 'false'
       
   213 			})
       
   214 			.on( 'click', function( event ) {
       
   215 				event.preventDefault();
       
   216 				$body.toggleClass( 'show-upload-view' );
       
   217 				$uploadViewToggle.attr( 'aria-expanded', $body.hasClass( 'show-upload-view' ) );
       
   218 			});
       
   219 	}
    72 });
   220 });