PluginProbe
TablePress – Tables in WordPress made easy / 3.4
TablePress – Tables in WordPress made easy v3.4
3.4 3.3.4 3.3.3 3.3.2 3.3.1 trunk 1.12 1.14 1.9.2 2.0.4 2.1.7 2.1.8 2.2 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.3 2.3.1 2.3.2 2.4 2.4.1 2.4.2 2.4.3 All 45 releases
tablepress / admin / js / edit / data / contextmenu.js

contextmenu.js in TablePress – Tables in WordPress made easy 3.4, at admin/js/edit/data/contextmenu.js

348 lines 17.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * Definition of the contextmenu for Jspreadsheet on the "Edit" screen.
3 *
4 * @package TablePress
5 * @subpackage Views JavaScript
6 * @author Tobias Bäthge
7 * @since 2.0.0
8 */
9
10 /* globals tp */
11 /* eslint-disable jsdoc/check-param-names, jsdoc/no-undefined-types */
12
13 /**
14 * WordPress dependencies.
15 */
16 import { applyFilters } from '@wordpress/hooks';
17 import { __, _x, _n, sprintf } from '@wordpress/i18n';
18
19 /**
20 * Returns the entries for the table editor's context menu.
21 *
22 * @param {[type]} obj [description]
23 * @param {[type]} x [description]
24 * @param {[type]} y [description]
25 * @param {[type]} e [description]
26 * @return {Array} Context menu items.
27 */
28 const contextMenu = ( obj /*, x, y, e */ ) => {
29 const numRows = tp.editor.options.data.length;
30 const numColumns = tp.editor.options.columns.length;
31 const numSelectedRows = tp.helpers.selection.rows.length;
32 const numSelectedColumns = tp.helpers.selection.columns.length;
33 const isMac = window?.navigator?.platform?.includes( 'Mac' );
34 const metaKey = isMac ?
35 _x( '⌘', 'keyboard shortcut modifier key on a Mac keyboard', 'tablepress' ) :
36 _x( 'Ctrl+', 'keyboard shortcut modifier key on a non-Mac keyboard', 'tablepress' );
37 const optionKey = isMac ?
38 _x( '⌥', 'keyboard shortcut option key on a Mac keyboard', 'tablepress' ) :
39 _x( 'Alt+', 'keyboard shortcut Alt key on a non-Mac keyboard', 'tablepress' );
40
41 // Call-by-reference object for the cell_merge_allowed() call.
42 const errorMessage = {
43 text: '',
44 };
45
46 tp.helpers.visibility.update();
47
48 const items = [
49 // Undo/Redo.
50 {
51 title: __( 'Undo', 'tablepress' ),
52 shortcut: sprintf( _x( '%1$sZ', 'keyboard shortcut for Undo', 'tablepress' ), metaKey ),
53 onclick: obj.undo,
54 disabled: ( -1 === obj.historyIndex ),
55 },
56 {
57 title: __( 'Redo', 'tablepress' ),
58 shortcut: sprintf( _x( '%1$sY', 'keyboard shortcut for Redo', 'tablepress' ), metaKey ),
59 onclick: obj.redo,
60 disabled: ( obj.historyIndex === obj.history.length - 1 ),
61 },
62
63 // Cut/Copy/Paste.
64 {
65 type: 'divisor',
66 },
67 {
68 title: __( 'Cut', 'tablepress' ),
69 shortcut: sprintf( _x( '%1$sX', 'keyboard shortcut for Cut', 'tablepress' ), metaKey ),
70 onclick() {
71 /* eslint-disable @wordpress/no-global-active-element */
72 if ( 'TEXTAREA' === document.activeElement.tagName && document.activeElement.selectionStart !== document.activeElement.selectionEnd ) {
73 document.execCommand( 'copy' ); // If text is selected in the actively edited cell, only copy that.
74 const cursorPosition = document.activeElement.selectionStart;
75 document.activeElement.value = document.activeElement.value.slice( 0, document.activeElement.selectionStart ) + document.activeElement.value.slice( document.activeElement.selectionEnd ); // Cut the selected content.
76 document.activeElement.selectionEnd = cursorPosition;
77 } else {
78 obj.copy( true ); // Otherwise, copy highlighted cells.
79 obj.setValue( obj.highlighted, '' ); // Make cell content empty.
80 }
81 /* eslint-enable @wordpress/no-global-active-element */
82 },
83 },
84 {
85 title: __( 'Copy', 'tablepress' ),
86 shortcut: sprintf( _x( '%1$sC', 'keyboard shortcut for Copy', 'tablepress' ), metaKey ),
87 onclick() {
88 if ( 'TEXTAREA' === document.activeElement.tagName && document.activeElement.selectionStart !== document.activeElement.selectionEnd ) { // eslint-disable-line @wordpress/no-global-active-element
89 document.execCommand( 'copy' ); // If text is selected in the actively edited cell, only copy that.
90 } else {
91 obj.copy( true ); // Otherwise, copy highlighted cells.
92 }
93 },
94 },
95 {
96 title: __( 'Paste', 'tablepress' ),
97 shortcut: sprintf( _x( '%1$sV', 'keyboard shortcut for Paste', 'tablepress' ), metaKey ),
98 onclick() {
99 /* eslint-disable @wordpress/no-global-active-element */
100 if ( 'TEXTAREA' === document.activeElement.tagName ) {
101 window.navigator.clipboard.readText().then( ( text ) => {
102 if ( text ) {
103 const cursorPosition = document.activeElement.selectionStart + text.length;
104 document.activeElement.value = document.activeElement.value.slice( 0, document.activeElement.selectionStart ) + text + document.activeElement.value.slice( document.activeElement.selectionEnd ); // Paste at the selection.
105 document.activeElement.selectionEnd = cursorPosition;
106 }
107 } );
108 } else if ( obj.selectedCell ) {
109 window.navigator.clipboard.readText().then( ( text ) => {
110 if ( text ) {
111 obj.paste( obj.selectedCell[0], obj.selectedCell[1], text );
112 }
113 } );
114 }
115 /* eslint-enable @wordpress/no-global-active-element */
116 },
117 // Firefox does not offer the readText() method, so "Paste" needs to be disabled.
118 disabled: ! window?.navigator?.clipboard?.readText,
119 tooltip: ! window?.navigator?.clipboard?.readText ? __( 'Your browser does not allow pasting via the context menu. Use the keyboard shortcut instead.', 'tablepress' ) : '',
120 },
121
122 // Insert Link, Insert Image, Open Advanced Editor.
123 {
124 type: 'divisor',
125 },
126 {
127 title: __( 'Insert Link', 'tablepress' ),
128 shortcut: sprintf( _x( '%1$sL', 'keyboard shortcut for Insert Link', 'tablepress' ), metaKey ),
129 onclick: tp.callbacks.insert_link.open_dialog.bind( null, ( 'TEXTAREA' === document.activeElement.tagName ) ? document.activeElement : null ), // eslint-disable-line @wordpress/no-global-active-element
130 },
131 {
132 title: __( 'Insert Image', 'tablepress' ),
133 shortcut: sprintf( _x( '%1$sI', 'keyboard shortcut for Insert Image', 'tablepress' ), metaKey ),
134 onclick: tp.callbacks.insert_image.open_dialog.bind( null, ( 'TEXTAREA' === document.activeElement.tagName ) ? document.activeElement : null ), // eslint-disable-line @wordpress/no-global-active-element
135 },
136 {
137 title: __( 'Advanced Editor', 'tablepress' ),
138 shortcut: sprintf( _x( '%1$sE', 'keyboard shortcut for Advanced Editor', 'tablepress' ), metaKey ),
139 onclick: tp.callbacks.advanced_editor.open_dialog.bind( null, ( 'TEXTAREA' === document.activeElement.tagName ) ? document.activeElement : null ), // eslint-disable-line @wordpress/no-global-active-element
140 },
141
142 // Duplicate/Insert/Append/Delete.
143 {
144 type: 'divisor',
145 },
146 {
147 title: __( 'Duplicate …', 'tablepress' ),
148 submenu: [
149 {
150 title: _n( 'Duplicate row', 'Duplicate rows', numSelectedRows, 'tablepress' ),
151 onclick: tp.callbacks.insert_duplicate.bind( null, 'duplicate', 'rows' ),
152 },
153 {
154 title: _n( 'Duplicate column', 'Duplicate columns', numSelectedColumns, 'tablepress' ),
155 onclick: tp.callbacks.insert_duplicate.bind( null, 'duplicate', 'columns' ),
156 },
157 ],
158 },
159 {
160 title: __( 'Insert …', 'tablepress' ),
161 submenu: [
162 {
163 title: _n( 'Insert row above', 'Insert rows above', numSelectedRows, 'tablepress' ),
164 onclick: tp.callbacks.insert_duplicate.bind( null, 'insert', 'rows', 'before' ),
165 },
166 {
167 title: _n( 'Insert row below', 'Insert rows below', numSelectedRows, 'tablepress' ),
168 onclick: tp.callbacks.insert_duplicate.bind( null, 'insert', 'rows', 'after' ),
169 },
170 {
171 title: _n( 'Insert column on the left', 'Insert columns on the left', numSelectedColumns, 'tablepress' ),
172 onclick: tp.callbacks.insert_duplicate.bind( null, 'insert', 'columns', 'before' ),
173 },
174 {
175 title: _n( 'Insert column on the right', 'Insert columns on the right', numSelectedColumns, 'tablepress' ),
176 onclick: tp.callbacks.insert_duplicate.bind( null, 'insert', 'columns', 'after' ),
177 },
178 ],
179 },
180 {
181 title: __( 'Append …', 'tablepress' ),
182 submenu: [
183 {
184 title: __( 'Append row', 'tablepress' ),
185 onclick: tp.callbacks.append.bind( null, 'rows', 1 ),
186 },
187 {
188 title: __( 'Append column', 'tablepress' ),
189 onclick: tp.callbacks.append.bind( null, 'columns', 1 ),
190 },
191 ],
192 },
193 {
194 title: __( 'Delete …', 'tablepress' ),
195 submenu: [
196 {
197 title: _n( 'Delete row', 'Delete rows', numSelectedRows, 'tablepress' ),
198 onclick: tp.callbacks.remove.bind( null, 'rows' ),
199 disabled: numRows === numSelectedRows,
200 tooltip: numRows === numSelectedRows ? __( 'This option is disabled.', 'tablepress' ) + ' ' + __( 'You can not delete all table rows!', 'tablepress' ) : '',
201 },
202 {
203 title: _n( 'Delete column', 'Delete columns', numSelectedColumns, 'tablepress' ),
204 onclick: tp.callbacks.remove.bind( null, 'columns' ),
205 disabled: numColumns === numSelectedColumns,
206 tooltip: numColumns === numSelectedColumns ? __( 'This option is disabled.', 'tablepress' ) + ' ' + __( 'You can not delete all table columns!', 'tablepress' ) : '',
207 },
208 ],
209 },
210
211 // Move rows/columns, Sort by column.
212 {
213 type: 'divisor',
214 },
215 {
216 title: __( 'Move …', 'tablepress' ),
217 submenu: [
218 {
219 title: _n( 'Move row up', 'Move rows up', numSelectedRows, 'tablepress' ),
220 shortcut: sprintf( _x( '%1$s⇧↑', 'keyboard shortcut for Move up', 'tablepress' ), metaKey ),
221 onclick: tp.callbacks.move.bind( null, 'up', 'rows' ),
222 disabled: ! tp.helpers.move_allowed( 'rows', 'up' ),
223 tooltip: ! tp.helpers.move_allowed( 'rows', 'up' ) ? __( 'This option is disabled.', 'tablepress' ) + ' ' + _n( 'The selected row is already at the top.', 'The selected rows are already at the top.', numSelectedRows, 'tablepress' ) : '',
224 },
225 {
226 title: _n( 'Move row down', 'Move rows down', numSelectedRows, 'tablepress' ),
227 shortcut: sprintf( _x( '%1$s⇧↓', 'keyboard shortcut for Move down', 'tablepress' ), metaKey ),
228 onclick: tp.callbacks.move.bind( null, 'down', 'rows' ),
229 disabled: ! tp.helpers.move_allowed( 'rows', 'down' ),
230 tooltip: ! tp.helpers.move_allowed( 'rows', 'down' ) ? __( 'This option is disabled.', 'tablepress' ) + ' ' + _n( 'The selected row is already at the bottom.', 'The selected rows are already at the bottom.', numSelectedRows, 'tablepress' ) : '',
231 },
232 {
233 title: _n( 'Move column left', 'Move columns left', numSelectedColumns, 'tablepress' ),
234 shortcut: sprintf( _x( '%1$s⇧←', 'keyboard shortcut for Move left', 'tablepress' ), metaKey ),
235 onclick: tp.callbacks.move.bind( null, 'left', 'columns' ),
236 disabled: ! tp.helpers.move_allowed( 'columns', 'left' ),
237 tooltip: ! tp.helpers.move_allowed( 'columns', 'left' ) ? __( 'This option is disabled.', 'tablepress' ) + ' ' + _n( 'The selected column is already at the left edge of the table.', 'The selected columns are already at the left edge of the table.', numSelectedColumns, 'tablepress' ) : '',
238 },
239 {
240 title: _n( 'Move column right', 'Move columns right', numSelectedColumns, 'tablepress' ),
241 shortcut: sprintf( _x( '%1$s⇧→', 'keyboard shortcut for Move right', 'tablepress' ), metaKey ),
242 onclick: tp.callbacks.move.bind( null, 'right', 'columns' ),
243 disabled: ! tp.helpers.move_allowed( 'columns', 'right' ),
244 tooltip: ! tp.helpers.move_allowed( 'columns', 'right' ) ? __( 'This option is disabled.', 'tablepress' ) + ' ' + _n( 'The selected column is already at the right edge of the table.', 'The selected columns are already at the right edge of the table.', numSelectedColumns, 'tablepress' ) : '',
245 },
246 {
247 type: 'divisor',
248 },
249 {
250 title: _n( 'Move row to the top', 'Move rows to the top', numSelectedRows, 'tablepress' ),
251 shortcut: sprintf( _x( '%1$s%2$s⇧↑', 'keyboard shortcut for Move to the top', 'tablepress' ), metaKey, optionKey ),
252 onclick: tp.callbacks.move.bind( null, 'top', 'rows' ),
253 disabled: ! tp.helpers.move_allowed( 'rows', 'top' ),
254 tooltip: ! tp.helpers.move_allowed( 'rows', 'top' ) ? __( 'This option is disabled.', 'tablepress' ) + ' ' + _n( 'The selected row is already at the top.', 'The selected rows are already at the top.', numSelectedRows, 'tablepress' ) : '',
255 },
256 {
257 title: _n( 'Move row to the bottom', 'Move rows to the bottom', numSelectedRows, 'tablepress' ),
258 shortcut: sprintf( _x( '%1$s%2$s⇧↓', 'keyboard shortcut for Move to the bottom', 'tablepress' ), metaKey, optionKey ),
259 onclick: tp.callbacks.move.bind( null, 'bottom', 'rows' ),
260 disabled: ! tp.helpers.move_allowed( 'rows', 'bottom' ),
261 tooltip: ! tp.helpers.move_allowed( 'rows', 'bottom' ) ? __( 'This option is disabled.', 'tablepress' ) + ' ' + _n( 'The selected row is already at the bottom.', 'The selected rows are already at the bottom.', numSelectedRows, 'tablepress' ) : '',
262 },
263 {
264 title: _n( 'Move column to first', 'Move columns to first', numSelectedColumns, 'tablepress' ),
265 shortcut: sprintf( _x( '%1$s%2$s⇧←', 'keyboard shortcut for Move to first', 'tablepress' ), metaKey, optionKey ),
266 onclick: tp.callbacks.move.bind( null, 'first', 'columns' ),
267 disabled: ! tp.helpers.move_allowed( 'columns', 'first' ),
268 tooltip: ! tp.helpers.move_allowed( 'columns', 'first' ) ? __( 'This option is disabled.', 'tablepress' ) + ' ' + _n( 'The selected column is already at the left edge of the table.', 'The selected columns are already at the left edge of the table.', numSelectedColumns, 'tablepress' ) : '',
269 },
270 {
271 title: _n( 'Move column to last', 'Move columns to last', numSelectedColumns, 'tablepress' ),
272 shortcut: sprintf( _x( '%1$s%2$s⇧→', 'keyboard shortcut for Move to last', 'tablepress' ), metaKey, optionKey ),
273 onclick: tp.callbacks.move.bind( null, 'last', 'columns' ),
274 disabled: ! tp.helpers.move_allowed( 'columns', 'last' ),
275 tooltip: ! tp.helpers.move_allowed( 'columns', 'last' ) ? __( 'This option is disabled.', 'tablepress' ) + ' ' + _n( 'The selected column is already at the right edge of the table.', 'The selected columns are already at the right edge of the table.', numSelectedColumns, 'tablepress' ) : '',
276 },
277 ],
278 },
279 {
280 title: __( 'Sort by column …', 'tablepress' ),
281 submenu: [
282 {
283 title: __( 'Sort by column ascending', 'tablepress' ),
284 onclick: tp.callbacks.sort.bind( null, 'asc' ),
285 disabled: 1 !== numSelectedColumns || 1 === numRows,
286 tooltip: 1 !== numSelectedColumns ? __( 'This option is disabled.', 'tablepress' ) + ' ' + __( 'More than one column was selected.', 'tablepress' ) : ( 1 === numRows ? __( 'This option is disabled.', 'tablepress' ) + ' ' + __( 'The table has only one row.', 'tablepress' ) : '' ), // eslint-disable-line no-nested-ternary
287 },
288 {
289 title: __( 'Sort by column descending', 'tablepress' ),
290 onclick: tp.callbacks.sort.bind( null, 'desc' ),
291 disabled: 1 !== numSelectedColumns || 1 === numRows,
292 tooltip: 1 !== numSelectedColumns ? __( 'This option is disabled.', 'tablepress' ) + ' ' + __( 'More than one column was selected.', 'tablepress' ) : ( 1 === numRows ? __( 'This option is disabled.', 'tablepress' ) + ' ' + __( 'The table has only one row.', 'tablepress' ) : '' ), // eslint-disable-line no-nested-ternary
293 },
294 ],
295 },
296
297 // Hide/Show rows/columns.
298 {
299 type: 'divisor',
300 },
301 {
302 title: __( 'Hide/Show …', 'tablepress' ),
303 submenu: [
304 {
305 title: _n( 'Hide row', 'Hide rows', numSelectedRows, 'tablepress' ),
306 onclick: tp.callbacks.hide_unhide.bind( null, 'hide', 'rows' ),
307 disabled: ! tp.helpers.visibility.selection_contains( 'rows', 1 ),
308 tooltip: ! tp.helpers.visibility.selection_contains( 'rows', 1 ) ? __( 'This option is disabled.', 'tablepress' ) + ' ' + _n( 'The selected row is already hidden.', 'The selected rows are already hidden.', numSelectedRows, 'tablepress' ) : '',
309 },
310 {
311 title: _n( 'Hide column', 'Hide columns', numSelectedColumns, 'tablepress' ),
312 onclick: tp.callbacks.hide_unhide.bind( null, 'hide', 'columns' ),
313 disabled: ! tp.helpers.visibility.selection_contains( 'columns', 1 ),
314 tooltip: ! tp.helpers.visibility.selection_contains( 'columns', 1 ) ? __( 'This option is disabled.', 'tablepress' ) + ' ' + _n( 'The selected column is already hidden.', 'The selected columns are already hidden.', numSelectedColumns, 'tablepress' ) : '',
315 },
316 {
317 title: _n( 'Show row', 'Show rows', numSelectedRows, 'tablepress' ),
318 onclick: tp.callbacks.hide_unhide.bind( null, 'unhide', 'rows' ),
319 disabled: ! tp.helpers.visibility.selection_contains( 'rows', 0 ),
320 tooltip: ! tp.helpers.visibility.selection_contains( 'rows', 0 ) ? __( 'This option is disabled.', 'tablepress' ) + ' ' + _n( 'The selected row is already visible.', 'The selected rows are already visible.', numSelectedRows, 'tablepress' ) : '',
321 },
322 {
323 title: _n( 'Show column', 'Show columns', numSelectedColumns, 'tablepress' ),
324 onclick: tp.callbacks.hide_unhide.bind( null, 'unhide', 'columns' ),
325 disabled: ! tp.helpers.visibility.selection_contains( 'columns', 0 ),
326 tooltip: ! tp.helpers.visibility.selection_contains( 'columns', 0 ) ? __( 'This option is disabled.', 'tablepress' ) + ' ' + _n( 'The selected column is already visible.', 'The selected columns are already visible.', numSelectedColumns, 'tablepress' ) : '',
327 },
328 ],
329 },
330
331 // Merging/Unmerging cells.
332 {
333 type: 'divisor',
334 },
335 {
336 title: __( 'Combine/Merge cells', 'tablepress' ),
337 onclick: tp.callbacks.merge_cells,
338 disabled: ( 1 === numSelectedRows && 1 === numSelectedColumns ) || ! tp.helpers.cell_merge_allowed(),
339 tooltip: ( 1 === numSelectedRows && 1 === numSelectedColumns ) || ! tp.helpers.cell_merge_allowed( errorMessage ) ? __( 'This option is disabled.', 'tablepress' ) + ' ' + errorMessage.text : '',
340 },
341 ];
342
343 // Allow other scripts to modify the context menu.
344 return applyFilters( 'tablepress.editScreenContextMenuItems', items, obj );
345 };
346
347 export default contextMenu;
348