angelovcom.net

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

plugin-install.js (7086B)


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