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> ' + $(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' ); |