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
← All changes | views/view-edit.php +335 -538 1.9.2 → 3.4 View file →
@@ -7,13 +7,16 @@
7 7 * @author Tobias Bäthge
8 8 * @since 1.0.0
9 9 */
10 10
11 +declare(strict_types=1);
12 +
11 13 // Prohibit direct script loading.
12 14 defined( 'ABSPATH' ) || die( 'No direct script access allowed!' );
13 15
14 16 /**
15 17 * Edit Table View class
18 + *
16 19 * @package TablePress
17 20 * @subpackage Views
18 21 * @author Tobias Bäthge
19 22 * @since 1.0.0
@@ -22,477 +25,334 @@
22 25
23 26 /**
24 27 * List of WP feature pointers for this view.
25 28 *
26 - * @since 1.0.0
27 - * @var array
29 + * @since 2.0.0
30 + * @var string[]
28 31 */
29 - protected $wp_pointers = array( 'tp09_edit_drag_drop_sort' );
32 + protected array $wp_pointers = array( 'tp34_edit_toolbar', 'tp33_edit_quick_navigation' );
30 33
31 34 /**
32 - * Set up the view with data and do things that are specific for this view.
35 + * Sets up the view with data and do things that are specific for this view.
33 36 *
34 37 * @since 1.0.0
35 38 *
36 - * @param string $action Action for this view.
37 - * @param array $data Data for this view.
39 + * @param string $action Action for this view.
40 + * @param array<string, mixed> $data Data for this view.
38 41 */
39 - public function setup( $action, array $data ) {
42 + #[\Override]
43 + public function setup( /* string */ $action, array $data ) /* : void */ {
44 + // Don't use type hints in the method declaration to prevent PHP errors, as the method is inherited.
45 +
40 46 parent::setup( $action, $data );
41 47
48 + TablePress::enqueue_script( 'common', array( 'jquery-core', 'postbox' ) );
49 +
50 + $this->add_text_box( 'no-javascript', array( $this, 'textbox_no_javascript' ), 'header' );
51 +
42 52 if ( isset( $data['table']['is_corrupted'] ) && $data['table']['is_corrupted'] ) {
43 - $this->add_text_box( 'table-corrupted', array( $this, 'textbox_corrupted_table' ), 'normal' );
53 + $this->add_text_box( 'table-corrupted', array( $this, 'textbox_corrupted_table' ), 'header' );
44 54 return;
45 - };
55 + }
46 56
47 - $action_messages = array(
48 - 'success_save' => __( 'The table was saved successfully.', 'tablepress' ),
49 - 'success_add' => __( 'The table was added successfully.', 'tablepress' ),
50 - 'success_copy' => _n( 'The table was copied successfully.', 'The tables were copied successfully.', 1, 'tablepress' ) . ' ' . sprintf( __( 'You are now seeing the copied table, which has the table ID &#8220;%s&#8221;.', 'tablepress' ), esc_html( $data['table']['id'] ) ),
51 - 'success_import' => __( 'The table was imported successfully.', 'tablepress' ),
52 - 'success_import_wp_table_reloaded' => __( 'The table was imported successfully from WP-Table Reloaded.', 'tablepress' ),
53 - 'error_save' => __( 'Error: The table could not be saved.', 'tablepress' ),
54 - 'error_delete' => __( 'Error: The table could not be deleted.', 'tablepress' ),
55 - 'success_save_success_id_change' => __( 'The table was saved successfully, and the table ID was changed.', 'tablepress' ),
56 - 'success_save_error_id_change' => __( 'The table was saved successfully, but the table ID could not be changed!', 'tablepress' ),
57 - );
58 - // Custom handling instead of $this->process_action_messages(). Also, $action_messages is used below.
59 - if ( $data['message'] && isset( $action_messages[ $data['message'] ] ) ) {
60 - $class = ( 'error' === substr( $data['message'], 0, 5 ) || in_array( $data['message'], array( 'success_save_error_id_change' ), true ) ) ? 'notice-error' : 'notice-success';
61 - $this->add_header_message( "<strong>{$action_messages[ $data['message'] ]}</strong>", $class );
62 - }
57 + $this->process_action_messages( array(
58 + 'success_add' => __( 'The table was added successfully.', 'tablepress' ),
59 + 'success_copy' => _n( 'The table was copied successfully.', 'The tables were copied successfully.', 1, 'tablepress' ) . ' ' . sprintf( __( 'You are now seeing the copied table, which has the table ID &#8220;%s&#8221;.', 'tablepress' ), esc_html( $data['table']['id'] ) ),
60 + 'success_import' => __( 'The table was imported successfully.', 'tablepress' ),
61 + 'error_delete' => __( 'Error: The table could not be deleted.', 'tablepress' ),
62 + ) );
63 63
64 - // Load jQuery UI dialog here to get the CSS into the HTML <head> part.
64 + // For the Advanced Editor.
65 65 wp_enqueue_style( 'wp-jquery-ui-dialog' );
66 - wp_enqueue_script( 'wpdialogs' ); // for the Advanced Editor
67 - // Remove default media-upload.js, in favor of own code.
68 - add_action( 'admin_print_footer_scripts', array( $this, 'dequeue_media_upload_js' ), 2 );
69 - add_thickbox();
66 + wp_enqueue_style( 'editor-buttons' );
67 + wp_enqueue_script( 'wpdialogs' );
68 + // For the "Insert Image" dialog.
70 69 add_filter( 'media_view_strings', array( $this, 'change_media_view_strings' ) );
71 70 wp_enqueue_media();
72 -
73 - // Enqueue JS for the "Insert Link" button.
71 + // For the "Insert Link" dialog.
74 72 wp_enqueue_script( 'wplink' );
75 73
76 - $this->admin_page->enqueue_style( 'edit' );
77 - $this->admin_page->enqueue_script( 'edit', array( 'jquery-core', 'jquery-ui-sortable', 'json2' ), array(
78 - 'options' => array(
79 - /**
80 - * Filter whether debug output shall be printed to the page.
81 - *
82 - * The value before filtering is determined from the GET parameter "debug" or the WP_DEBUG constant.
83 - *
84 - * @since 1.4.0
85 - *
86 - * @param bool $print Whether debug output shall be printed.
87 - */
88 - 'print_debug_output' => apply_filters( 'tablepress_print_debug_output', isset( $_GET['debug'] ) ? ( 'true' === $_GET['debug'] ) : WP_DEBUG ),
89 - /**
90 - * Filter whether the "Advanced Editor" button shall be enabled.
91 - *
92 - * @since 1.0.0
93 - *
94 - * @param bool $enable Whether the "Advanced Editor" shall be enabled. Default true.
95 - */
96 - 'cells_advanced_editor' => apply_filters( 'tablepress_edit_cells_advanced_editor', true ),
97 - /**
98 - * Filter whether the size of the table input textareas shall increase when they are focused.
99 - *
100 - * @since 1.0.0
101 - *
102 - * @param bool $auto_grow Whether the size of the cell textareas shall increase. Default true.
103 - */
104 - 'cells_auto_grow' => apply_filters( 'tablepress_edit_cells_auto_grow', true ),
105 - 'shortcode' => esc_js( TablePress::$shortcode ),
106 - ),
107 - 'strings' => array_merge( array(
108 - 'no_remove_all_rows' => __( 'You can not delete all table rows!', 'tablepress' ),
109 - 'no_remove_all_columns' => __( 'You can not delete all table columns!', 'tablepress' ),
110 - 'no_rows_selected' => __( 'You did not select any rows!', 'tablepress' ),
111 - 'no_columns_selected' => __( 'You did not select any columns!', 'tablepress' ),
112 - 'append_num_rows_invalid' => __( 'The value for the number of rows is invalid!', 'tablepress' ),
113 - 'append_num_columns_invalid' => __( 'The value for the number of columns is invalid!', 'tablepress' ),
114 - 'ays_remove_rows_singular' => _n( 'Do you really want to delete the selected row?', 'Do you really want to delete the selected rows?', 1, 'tablepress' ),
115 - 'ays_remove_rows_plural' => _n( 'Do you really want to delete the selected row?', 'Do you really want to delete the selected rows?', 2, 'tablepress' ),
116 - 'ays_remove_columns_singular' => _n( 'Do you really want to delete the selected column?', 'Do you really want to delete the selected columns?', 1, 'tablepress' ),
117 - 'ays_remove_columns_plural' => _n( 'Do you really want to delete the selected column?', 'Do you really want to delete the selected columns?', 2, 'tablepress' ),
118 - 'advanced_editor_open' => __( 'Please click into the cell that you want to edit using the &#8220;Advanced Editor&#8221;.', 'tablepress' ),
119 - 'rowspan_add' => __( 'To combine cells within a column, click into the cell below the cell that has the content the combined cells shall have.', 'tablepress' ),
120 - 'colspan_add' => __( 'To combine cells within a row, click into the cell to the right of the cell that has the content the combined cells shall have.', 'tablepress' ),
121 - 'span_add_datatables_warning' => __( 'Attention: You have enabled the usage of the DataTables JavaScript library for features like sorting, search, or pagination.', 'tablepress' ) . "\n" .
122 - __( 'Unfortunately, these can not be used in tables with combined cells.', 'tablepress' ) . "\n" .
123 - __( 'Do you want to proceed and automatically turn off the usage of DataTables for this table?', 'tablepress' ),
124 - 'link_add' => __( 'Please click into the cell that you want to add a link to.', 'tablepress' ) . "\n" .
125 - __( 'You can then enter the Link URL and Text or choose an existing page or post.', 'tablepress' ),
126 - 'image_add' => __( 'Please click into the cell that you want to add an image to.', 'tablepress' ) . "\n" .
127 - __( 'The Media Library will open, where you can select or upload the desired image or enter the image URL.', 'tablepress' ) . "\n" .
128 - sprintf( __( 'Click the &#8220;%s&#8221; button to insert the image.', 'tablepress' ), __( 'Insert into Table', 'tablepress' ) ),
129 - 'unsaved_changes_unload' => __( 'The changes to this table were not saved yet and will be lost if you navigate away from this page.', 'tablepress' ),
130 - 'preparing_preview' => __( 'The Table Preview is being loaded...', 'tablepress' ),
131 - 'preview_error' => __( 'The Table Preview could not be loaded.', 'tablepress' ),
132 - 'save_changes_success' => __( 'Saving successful', 'tablepress' ),
133 - 'save_changes_error' => __( 'Saving failed', 'tablepress' ),
134 - 'saving_changes' => __( 'Changes are being saved...', 'tablepress' ),
135 - 'table_id_not_empty' => __( 'The Table ID field can not be empty. Please enter a Table ID!', 'tablepress' ),
136 - 'table_id_not_zero' => __( 'The Table ID &#8220;0&#8221; is not supported. Please enter a different Table ID!', 'tablepress' ),
137 - 'ays_change_table_id' => __( 'Do you really want to change the Table ID? All Shortcodes for this table in your pages and posts will have to be adjusted!', 'tablepress' ),
138 - 'extra_css_classes_invalid' => __( 'The entered value in the field &#8220;Extra CSS classes&#8221; is invalid.', 'tablepress' ),
139 - 'num_pagination_entries_invalid' => __( 'The entered value in the field &#8220;Pagination Entries&#8221; is not a number.', 'tablepress' ),
140 - 'sort_asc' => __( 'Sort ascending', 'tablepress' ),
141 - 'sort_desc' => __( 'Sort descending', 'tablepress' ),
142 - 'no_rowspan_first_row' => __( 'You can not add rowspan to the first row!', 'tablepress' ),
143 - 'no_colspan_first_col' => __( 'You can not add colspan to the first column!', 'tablepress' ),
144 - 'no_rowspan_table_head' => __( 'You can not connect cells into the table head row!', 'tablepress' ),
145 - 'no_rowspan_table_foot' => __( 'You can not connect cells out of the table foot row!', 'tablepress' ),
146 - ),
147 - // Merge this to have messages available for AJAX after save dialog.
148 - $action_messages )
149 - ) );
74 + TablePress::enqueue_style( 'jspreadsheet' );
75 + TablePress::enqueue_style( 'jsuites', array( 'tablepress-jspreadsheet' ) );
76 + TablePress::enqueue_style( 'edit', array( 'tablepress-jspreadsheet', 'tablepress-jsuites' ) );
77 + if ( ! TABLEPRESS_IS_PLAYGROUND_PREVIEW && tb_tp_fs()->is_free_plan() ) {
78 + TablePress::enqueue_style( 'edit-features', array( 'tablepress-edit' ) );
79 + }
80 + TablePress::enqueue_script( 'jspreadsheet' );
81 + TablePress::enqueue_script( 'jsuites', array( 'tablepress-jspreadsheet' ) );
82 + TablePress::enqueue_script( 'edit', array( 'tablepress-jspreadsheet', 'tablepress-jsuites', 'jquery-core' ) );
150 83
151 84 $this->add_text_box( 'head', array( $this, 'textbox_head' ), 'normal' );
152 - $this->add_text_box( 'buttons-1', array( $this, 'textbox_buttons' ), 'normal' );
85 + $this->add_text_box( 'header-bar', array( $this, 'textbox_header_bar' ), 'normal' );
153 86 $this->add_meta_box( 'table-information', __( 'Table Information', 'tablepress' ), array( $this, 'postbox_table_information' ), 'normal' );
154 87 $this->add_meta_box( 'table-data', __( 'Table Content', 'tablepress' ), array( $this, 'postbox_table_data' ), 'normal' );
155 - $this->add_meta_box( 'table-manipulation', __( 'Table Manipulation', 'tablepress' ), array( $this, 'postbox_table_manipulation' ), 'normal' );
156 88 $this->add_meta_box( 'table-options', __( 'Table Options', 'tablepress' ), array( $this, 'postbox_table_options' ), 'normal' );
157 - $this->add_meta_box( 'datatables-features', __( 'Features of the DataTables JavaScript library', 'tablepress' ), array( $this, 'postbox_datatables_features' ), 'normal' );
89 + $this->add_meta_box( 'datatables-features', __( 'Table Features for Site Visitors', 'tablepress' ), array( $this, 'postbox_datatables_features' ), 'normal' );
158 90 $this->add_text_box( 'hidden-containers', array( $this, 'textbox_hidden_containers' ), 'additional' );
159 - $this->add_text_box( 'buttons-2', array( $this, 'textbox_buttons' ), 'additional' );
160 - $this->add_text_box( 'other-actions', array( $this, 'textbox_other_actions' ), 'submit' );
91 +
92 + add_filter( 'screen_settings', array( $this, 'add_screen_options_output' ), 10, 2 );
161 93 }
162 94
163 95 /**
164 - * Dequeue 'media-upload' JavaScript, which gets added by the Media Library,
165 - * but is undesired here, as we don't want the tb_position() function for resizing.
96 + * Changes the Media View string "Insert into post" to "Insert into Table".
166 97 *
167 98 * @since 1.0.0
99 + *
100 + * @param array<string, string> $strings Current set of Media View strings.
101 + * @return array<string, string> Changed Media View strings.
168 102 */
169 - public function dequeue_media_upload_js() {
170 - wp_dequeue_script( 'media-upload' );
103 + public function change_media_view_strings( array $strings ): array {
104 + $strings['insertIntoPost'] = __( 'Insert into Table', 'tablepress' );
105 + return $strings;
171 106 }
172 107
173 108 /**
174 - * Change Media View string "Insert into post" to "Insert into Table".
109 + * Adds custom screen options to the screen.
175 110 *
176 - * @since 1.0.0
111 + * @since 2.1.0
177 112 *
178 - * @param array $strings Current set of Media View strings.
179 - * @return array Changed Media View strings.
113 + * @param string $screen_settings Screen settings.
114 + * @param WP_Screen $screen WP_Screen object.
115 + * @return string Extended Screen settings.
180 116 */
181 - public function change_media_view_strings( array $strings ) {
182 - $strings['insertIntoPost'] = __( 'Insert into Table', 'tablepress' );
183 - return $strings;
117 + public function add_screen_options_output( /* string */ $screen_settings, WP_Screen $screen ): string {
118 + // Don't use a type hint for the `$screen_settings` argument as many WordPress plugins seem to be returning `null` in their filter hook handlers.
119 +
120 + // Protect against other plugins not returning a string for the `$screen_settings` argument.
121 + if ( ! is_string( $screen_settings ) ) { // @phpstan-ignore function.alreadyNarrowedType (The `is_string()` check is needed as the input is coming from a filter hook.)
122 + $screen_settings = '';
123 + }
124 +
125 + $screen_settings = '<fieldset id="tablepress-screen-options" class="screen-options">';
126 + $screen_settings .= '<legend>' . __( 'Table editor settings', 'tablepress' ) . '</legend>';
127 + $screen_settings .= '<p>' . __( 'Adjust the default size of the table cells in the table editor below.', 'tablepress' ) . ' ' . __( 'Cells with many lines of text will expand to their full height when they are edited.', 'tablepress' ) . '</p>';
128 + $screen_settings .= '<p><em>' . __( 'Please note: These settings only influence the table editor view on this screen, but not the table that the site visitor sees!', 'tablepress' ) . '</em></p>';
129 + $screen_settings .= '<div>';
130 + $screen_settings .= '<label for="table_editor_column_width">' . __( 'Default column width:', 'tablepress' ) . '</label> ';
131 + $input = '<input type="number" id="table_editor_column_width" class="small-text" value="' . esc_attr( TablePress::$model_options->get( 'table_editor_column_width' ) ) . '" min="30" max="9999">';
132 + /* translators: %s: Input field for the number of pixels */
133 + $screen_settings .= sprintf( __( '%s pixels', 'tablepress' ), $input );
134 + $screen_settings .= '</div>';
135 + $screen_settings .= '<div style="margin-top: 6px;">';
136 + $screen_settings .= '<label for="table_editor_line_clamp">' . __( 'Maximum visible lines of text:', 'tablepress' ) . '</label> ';
137 + $input = '<input type="number" id="table_editor_line_clamp" class="tiny-text" value="' . esc_attr( TablePress::$model_options->get( 'table_editor_line_clamp' ) ) . '" min="0" max="999">';
138 + /* translators: %s: Input field for the number of lines */
139 + $screen_settings .= sprintf( __( '%s lines', 'tablepress' ), $input );
140 + $screen_settings .= '</div>';
141 + $screen_settings .= '</fieldset>';
142 + return $screen_settings;
184 143 }
185 144
186 145 /**
187 - * Print hidden field with a nonce for the screen's action, to be transmitted in HTTP requests.
146 + * Renders the current view.
188 147 *
189 - * @since 1.0.0
148 + * In comparison to the parent class method, this contains handling for the no-js case and adjusts the HTML code structure.
190 149 *
191 - * @param array $data Data for this screen
192 - * @param array $box Information about the text box.
150 + * @since 2.0.0
193 151 */
194 - protected function action_nonce_field( array $data, array $box ) {
195 - // use custom nonce field here, that includes the table ID
196 - wp_nonce_field( TablePress::nonce( $this->action, $data['table']['id'] ), 'nonce-edit-table' );
197 - echo "\n";
198 - wp_nonce_field( TablePress::nonce( 'preview_table', $data['table']['id'] ), 'nonce-preview-table', false, true );
152 + #[\Override]
153 + public function render(): void {
154 + $this->print_javascript_data();
155 +
156 + ?>
157 + <div id="tablepress-page" class="wrap">
158 + <form>
159 + <?php
160 + $this->print_nav_tab_menu();
161 + ?>
162 + <div id="tablepress-body">
163 + <hr class="wp-header-end">
164 + <script>document.querySelectorAll('.notice:has(~#tablepress-page)').forEach(e=>document.querySelector('.wp-header-end').after(e));</script>
165 + <?php
166 + // Print all header messages.
167 + foreach ( $this->header_messages as $message ) {
168 + echo $message;
169 + }
170 +
171 + $this->do_text_boxes( 'header' );
172 + ?>
173 + <div id="poststuff" class="hide-if-no-js">
174 + <div id="post-body" class="metabox-holder columns-1">
175 + <div id="postbox-container-2" class="postbox-container">
176 + <?php
177 + $this->do_text_boxes( 'normal' );
178 + $this->do_meta_boxes( 'normal' );
179 +
180 + $this->do_text_boxes( 'additional' );
181 + $this->do_meta_boxes( 'additional' );
182 +
183 + $this->do_text_boxes( 'submit' );
184 +
185 + $this->do_text_boxes( 'side' );
186 + $this->do_meta_boxes( 'side' );
187 + ?>
188 + </div>
189 + </div>
190 + <br class="clear">
191 + </div>
192 + </form>
193 + </div>
194 + </div>
195 + <?php
199 196 }
200 197
201 198 /**
202 - * Print the content of the "Table Information" post meta box.
199 + * Overrides parent class method, as the nonces for this view are generated in the JS code.
203 200 *
204 201 * @since 1.0.0
205 202 *
206 - * @param array $data Data for this screen.
207 - * @param array $box Information about the meta box.
203 + * @param array<string, mixed> $data Data for this screen.
204 + * @param array<string, mixed> $box Information about the text box.
208 205 */
209 - public function postbox_table_information( array $data, array $box ) {
210 -?>
211 -<table class="tablepress-postbox-table fixed">
212 -<tbody>
213 - <tr class="bottom-border">
214 - <th class="column-1" scope="row"><label for="table-new-id"><?php _e( 'Table ID', 'tablepress' ); ?>:</label></th>
215 - <td class="column-2">
216 - <input type="hidden" name="table[id]" id="table-id" value="<?php echo esc_attr( $data['table']['id'] ); ?>" />
217 - <input type="text" name="table[new_id]" id="table-new-id" value="<?php echo esc_attr( $data['table']['id'] ); ?>" title="<?php esc_attr_e( 'The Table ID can only consist of letters, numbers, hyphens (-), and underscores (_).', 'tablepress' ); ?>" pattern="[A-Za-z0-9-_]+" required <?php echo ( ! current_user_can( 'tablepress_edit_table_id', $data['table']['id'] ) ) ? 'readonly ' : ''; ?>/>
218 - <div style="float: right; margin-right: 1%;"><label for="table-information-shortcode"><?php _e( 'Shortcode', 'tablepress' ); ?>:</label>
219 - <input type="text" id="table-information-shortcode" class="table-shortcode" value="<?php echo esc_attr( '[' . TablePress::$shortcode . " id={$data['table']['id']} /]" ); ?>" readonly="readonly" /></div>
220 - </td>
221 - </tr>
222 - <tr class="top-border">
223 - <th class="column-1" scope="row"><label for="table-name"><?php _e( 'Table Name', 'tablepress' ); ?>:</label></th>
224 - <td class="column-2"><input type="text" name="table[name]" id="table-name" class="large-text" value="<?php echo esc_attr( $data['table']['name'] ); ?>" /></td>
225 - </tr>
226 - <tr class="bottom-border">
227 - <th class="column-1 top-align" scope="row"><label for="table-description"><?php _e( 'Description', 'tablepress' ); ?>:</label></th>
228 - <td class="column-2"><textarea name="table[description]" id="table-description" class="large-text" rows="4"><?php echo esc_textarea( $data['table']['description'] ); ?></textarea></td>
229 - </tr>
230 - <tr class="top-border">
231 - <th class="column-1" scope="row"><?php _e( 'Last Modified', 'tablepress' ); ?>:</th>
232 - <td class="column-2"><?php printf( __( '%1$s by %2$s', 'tablepress' ), '<span id="last-modified">' . TablePress::format_datetime( $data['table']['last_modified'] ) . '</span>', '<span id="last-editor">' . TablePress::get_user_display_name( $data['table']['options']['last_editor'] ) . '</span>' ); ?></td>
233 - </tr>
234 -</tbody>
235 -</table>
236 -<?php
206 + #[\Override]
207 + protected function action_nonce_field( array $data, array $box ): void {
208 + // Intentionally left empty. Nonces for this view are generated in `print_javascript_data()`.
237 209 }
238 210
239 211 /**
240 - * Print the content of the "Table Content" post meta box.
212 + * Prints the table data for use in JS code and the main React container.
241 213 *
242 - * @since 1.0.0
243 - *
244 - * @param array $data Data for this screen.
245 - * @param array $box Information about the meta box.
214 + * @since 3.0.0
246 215 */
247 - public function postbox_table_data( array $data, array $box ) {
248 - $table = $data['table']['data'];
249 - $options = $data['table']['options'];
250 - $visibility = $data['table']['visibility'];
251 - $rows = count( $table );
252 - $columns = count( $table[0] );
216 + public function print_javascript_data(): void {
217 + echo "<script>\n";
218 + echo "window.tp = window.tp || {};\n";
253 219
254 - $head_row_idx = $foot_row_idx = -1;
255 - // Determine row index of the table head row, by excluding all hidden rows from the beginning.
256 - if ( $options['table_head'] ) {
257 - for ( $row_idx = 0; $row_idx < $rows; $row_idx++ ) {
258 - if ( 1 === $visibility['rows'][ $row_idx ] ) {
259 - $head_row_idx = $row_idx;
260 - break;
261 - }
262 - }
220 + echo "tp.nonces = {\n";
221 + echo "\tedit_table: '" . wp_create_nonce( TablePress::nonce( $this->action, $this->data['table']['id'] ) ) . "',\n";
222 + echo "\tpreview_table: '" . wp_create_nonce( TablePress::nonce( 'preview_table', $this->data['table']['id'] ) ) . "',\n";
223 + echo "\tcopy_table: '" . wp_create_nonce( TablePress::nonce( 'copy_table', $this->data['table']['id'] ) ) . "',\n";
224 + echo "\tdelete_table: '" . wp_create_nonce( TablePress::nonce( 'delete_table', $this->data['table']['id'] ) ) . "',\n";
225 + echo "\tscreen_options: '" . wp_create_nonce( TablePress::nonce( 'screen_options' ) ) . "',\n";
226 + echo "};\n";
227 +
228 + echo "tp.table = {\n";
229 + echo "\tid: '{$this->data['table']['id']}',\n";
230 + echo "\tshortcode: '" . esc_js( TablePress::$shortcode ) . "',\n";
231 +
232 + // Add the table meta data.
233 + $this->data['table']['meta'] = array(
234 + 'id' => $this->data['table']['id'],
235 + 'name' => $this->data['table']['name'],
236 + 'description' => $this->data['table']['description'],
237 + 'lastModified' => TablePress::format_datetime( $this->data['table']['last_modified'] ),
238 + 'lastEditor' => TablePress::get_user_display_name( $this->data['table']['options']['last_editor'] ),
239 + );
240 +
241 + // JSON-encode array items separately to save some PHP memory.
242 + foreach ( array( 'meta', 'data', 'options', 'visibility' ) as $item ) {
243 + $json = $this->convert_to_json_parse_output( $this->data['table'][ $item ] );
244 + echo "\t{$item}: {$json},\n";
263 245 }
264 - // Fetermine row index of the table foot row, by excluding all hidden rows from the end.
265 - if ( $options['table_foot'] ) {
266 - for ( $row_idx = $rows - 1; $row_idx > -1; $row_idx-- ) {
267 - if ( 1 === $visibility['rows'][ $row_idx ] ) {
268 - $foot_row_idx = $row_idx;
269 - break;
270 - }
271 - }
272 - }
273 -?>
274 -<table id="edit-form" class="tablepress-edit-screen-id-<?php echo esc_attr( $data['table']['id'] ); ?>">
275 - <thead>
276 - <tr id="edit-form-head">
277 - <th scope="col"><span class="screen-reader-text"><?php esc_html_e( 'Row Number', 'tablepress' ); ?></span></th>
278 - <th scope="col"><span class="screen-reader-text"><?php esc_html_e( 'Bulk action selectors for rows', 'tablepress' ); ?></span></th>
279 -<?php
280 - for ( $col_idx = 0; $col_idx < $columns; $col_idx++ ) {
281 - $column_class = '';
282 - if ( 0 === $visibility['columns'][ $col_idx ] ) {
283 - $column_class = ' column-hidden';
284 - }
285 - $column = TablePress::number_to_letter( $col_idx + 1 );
286 - echo "\t\t\t<th scope=\"col\" class=\"head{$column_class}\"><span class=\"sort-control sort-desc hide-if-no-js\" title=\"" . esc_attr__( 'Sort descending', 'tablepress' ) . '"><span class="sorting-indicator"></span></span><span class="sort-control sort-asc hide-if-no-js" title="' . esc_attr__( 'Sort ascending', 'tablepress' ) . "\"><span class=\"sorting-indicator\"></span></span><span class=\"move-handle\">{$column}</span></th>\n";
246 + echo "};\n";
247 +
248 + echo "tp.screenOptions = {\n";
249 + echo "\ttable_editor_column_width: " . absint( TablePress::$model_options->get( 'table_editor_column_width' ) ) . ",\n";
250 + echo "\tshowCustomCommands: " . ( current_user_can( 'unfiltered_html' ) ? 'true' : 'false' ) . ",\n";
251 + echo "\toptionsUrl: '" . TablePress::url( array( 'action' => 'options' ) ) . "',\n";
252 + echo "\tcurrentUserCanEditTableId: " . ( current_user_can( 'tablepress_edit_table_id', $this->data['table']['id'] ) ? 'true' : 'false' ) . ",\n";
253 + echo "\tcurrentUserCanCopyTable: " . ( current_user_can( 'tablepress_copy_table', $this->data['table']['id'] ) ? 'true' : 'false' ) . ",\n";
254 + echo "\tcurrentUserCanDeleteTable: " . ( current_user_can( 'tablepress_delete_table', $this->data['table']['id'] ) ? 'true' : 'false' ) . ",\n";
255 + echo "\tcurrentUserCanExportTable: " . ( current_user_can( 'tablepress_export_table', $this->data['table']['id'] ) ? 'true' : 'false' ) . ",\n";
256 + echo "\tcurrentUserCanPreviewTable: " . ( current_user_can( 'tablepress_preview_table', $this->data['table']['id'] ) ? 'true' : 'false' ) . ",\n";
257 + echo "\tcopyUrl: '" . str_replace( '&amp;', '&', TablePress::url( array( 'action' => 'copy_table', 'item' => $this->data['table']['id'], 'return' => 'edit' ), true, 'admin-post.php' ) ) . "',\n";
258 + echo "\tdeleteUrl: '" . str_replace( '&amp;', '&', TablePress::url( array( 'action' => 'delete_table', 'item' => $this->data['table']['id'], 'return' => 'edit', 'return_item' => $this->data['table']['id'] ), true, 'admin-post.php' ) ) . "',\n";
259 + echo "\texportUrl: '" . str_replace( '&amp;', '&', TablePress::url( array( 'action' => 'export', 'table_id' => $this->data['table']['id'] ) ) ) . "',\n";
260 + echo "\tpreviewUrl: '" . str_replace( '&amp;', '&', TablePress::url( array( 'action' => 'preview_table', 'item' => $this->data['table']['id'], 'return' => 'edit', 'return_item' => $this->data['table']['id'] ), true, 'admin-post.php' ) ) . "',\n";
261 + echo "};\n";
262 +
263 + echo "</script>\n";
264 +
265 + echo '<div id="tablepress-edit-screen"></div>'; // React container.
287 266 }
288 -?>
289 - <th scope="col"><span class="screen-reader-text"><?php esc_html_e( 'Row Number', 'tablepress' ); ?></span></th>
290 - </tr>
291 - </thead>
292 - <tbody id="edit-form-body">
293 -<?php
294 - foreach ( $table as $row_idx => $row_data ) {
295 - $row = $row_idx + 1;
296 - $classes = array();
297 - if ( 0 === ( $row_idx % 2 ) ) {
298 - $classes[] = 'odd';
299 - }
300 - if ( $head_row_idx === $row_idx ) {
301 - $classes[] = 'head-row';
302 - } elseif ( $foot_row_idx === $row_idx ) {
303 - $classes[] = 'foot-row';
304 - }
305 - if ( 0 === $visibility['rows'][ $row_idx ] ) {
306 - $classes[] = 'row-hidden';
307 - }
308 - $row_class = ( ! empty( $classes ) ) ? ' class="' . implode( ' ', $classes ) . '"' : '';
309 - $row_selector_text = esc_html( sprintf( __( 'Bulk action selector for row %s', 'tablepress' ), number_format_i18n( $row ) ) );
310 - echo "\t\t<tr{$row_class}>\n";
311 - echo "\t\t\t<td><span class=\"move-handle\">{$row}</span></td>";
312 - echo "<td><label class=\"hide-if-no-js\"><span class=\"screen-reader-text\">{$row_selector_text}</span><input type=\"checkbox\" /><input type=\"hidden\" class=\"visibility\" name=\"table[visibility][rows][]\" value=\"{$visibility['rows'][ $row_idx ]}\" /></label></td>";
313 - foreach ( $row_data as $col_idx => $cell ) {
314 - $column = TablePress::number_to_letter( $col_idx + 1 );
315 - $column_class = '';
316 - if ( 0 === $visibility['columns'][ $col_idx ] ) {
317 - $column_class = ' class="column-hidden"';
318 - }
319 - // Sanitize, so that HTML is possible in table cells.
320 - $cell = esc_textarea( $cell );
321 - $cell_label = esc_html( sprintf( __( 'Column %1$s, Row %2$s', 'tablepress' ), number_format_i18n( $col_idx + 1 ), number_format_i18n( $row ) ) );
322 - echo "<td{$column_class}><label for=\"cell-{$column}{$row}\"><span class=\"screen-reader-text\">{$cell_label}</span></label><textarea name=\"table[data][{$row_idx}][{$col_idx}]\" id=\"cell-{$column}{$row}\" rows=\"1\">{$cell}</textarea></td>";
323 - }
324 - echo "<td><span class=\"move-handle\">{$row}</span></td>\n";
325 - echo "\t\t</tr>\n";
326 - }
327 -?>
328 - </tbody>
329 - <tfoot>
330 - <tr id="edit-form-foot">
331 - <th scope="col"><span class="screen-reader-text"><?php esc_html_e( 'Row Number', 'tablepress' ); ?></span></th>
332 - <th scope="col"><span class="screen-reader-text"><?php esc_html_e( 'Bulk action selectors for rows', 'tablepress' ); ?></span></th>
333 -<?php
334 - for ( $col_idx = 0; $col_idx < $columns; $col_idx++ ) {
335 - $column_class = '';
336 - if ( 0 === $visibility['columns'][ $col_idx ] ) {
337 - $column_class = ' class="column-hidden"';
338 - }
339 - $column_selector_text = esc_html( sprintf( __( 'Bulk action selector for column %s', 'tablepress' ), TablePress::number_to_letter( $col_idx + 1 ) ) );
340 - echo "\t\t\t<th scope=\"col\" {$column_class}><label class=\"hide-if-no-js\"><span class=\"screen-reader-text\">{$column_selector_text}</span><input type=\"checkbox\" /></label>";
341 - echo "<input type=\"hidden\" class=\"visibility\" name=\"table[visibility][columns][]\" value=\"{$visibility['columns'][ $col_idx ]}\" /></th>\n";
342 - }
343 -?>
344 - <th scope="col"><span class="screen-reader-text"><?php esc_html_e( 'Row Number', 'tablepress' ); ?></span></th>
345 - </tr>
346 - </tfoot>
347 -</table>
348 -<input type="hidden" id="number-rows" name="table[number][rows]" value="<?php echo $rows; ?>" />
349 -<input type="hidden" id="number-columns" name="table[number][columns]" value="<?php echo $columns; ?>" />
350 -<?php
351 - }
352 267
353 268 /**
354 - * Print the content of the "Table Manipulation" post meta box.
269 + * Prints the content of the "Table Information" post meta box.
355 270 *
356 271 * @since 1.0.0
357 272 *
358 - * @param array $data Data for this screen.
359 - * @param array $box Information about the meta box.
273 + * @param array<string, mixed> $data Data for this screen.
274 + * @param array<string, mixed> $box Information about the meta box.
360 275 */
361 - public function postbox_table_manipulation( array $data, array $box ) {
362 -?>
363 -<table class="tablepress-postbox-table fixed hide-if-no-js">
364 -<tbody>
365 - <tr class="bottom-border">
366 - <td class="column-1">
367 - <input type="button" class="button" id="link-add" value="<?php esc_attr_e( 'Insert Link', 'tablepress' ); ?>" />
368 - <input type="button" class="button" id="image-add" value="<?php esc_attr_e( 'Insert Image', 'tablepress' ); ?>" />
369 - <input type="button" class="button" id="advanced-editor-open" value="<?php esc_attr_e( 'Advanced Editor', 'tablepress' ); ?>" />
370 - </td>
371 - <td class="column-2">
372 - <?php _e( 'Combine cells', 'tablepress' ); ?>:&nbsp;
373 - <input type="button" class="button" id="span-add-rowspan" value="<?php esc_attr_e( 'in a column (rowspan)', 'tablepress' ); ?>" />
374 - <input type="button" class="button" id="span-add-colspan" value="<?php esc_attr_e( 'in a row (colspan)', 'tablepress' ); ?>" />
375 - <input type="button" class="button show-help-box" value="<?php esc_attr_e( '?', 'tablepress' ); ?>" title="<?php esc_attr_e( 'Help on combining cells', 'tablepress' ); ?>" />
376 - <div class="hidden-container hidden-help-box-container">
377 - <?php
378 - echo '<p>' . __( 'Table cells can span across more than one column or row.', 'tablepress' ) . '</p>';
379 - echo '<p>' . __( 'Combining consecutive cells within the same row is called &#8220;colspanning&#8221;.', 'tablepress' )
380 - . ' ' . __( 'Combining consecutive cells within the same column is called &#8220;rowspanning&#8221;.', 'tablepress' ) . '</p>';
381 - echo '<p>' . __( 'To combine adjacent cells in a row, add the keyword <code>#colspan#</code> to the cell to the right of the one with the content for the combined cell by using the corresponding button.', 'tablepress' )
382 - . ' ' . __( 'To combine adjacent cells in a column, add the keyword <code>#rowspan#</code> to the cell below the one with the content for the combined cell by using the corresponding button.', 'tablepress' ) . '</p>';
383 - echo '<p>' . __( 'Repeat this to add the keyword to all cells that shall be connected.', 'tablepress' ) . '</p>';
384 - echo '<p><strong>' . __( 'Be aware that the functions of the DataTables JavaScript library will not work on tables which have combined cells.', 'tablepress' ) . '</strong></p>';
276 + public function postbox_table_information( array $data, array $box ): void {
277 + echo '<div id="tablepress-table-information-section"></div>';
278 +
279 + if ( ! TABLEPRESS_IS_PLAYGROUND_PREVIEW && tb_tp_fs()->is_free_plan() ) :
385 280 ?>
281 + <div class="postbox premium-features">
282 + <div>
283 + <div>
284 + <div class="postbox-header">
285 + <h2><span class="dashicons dashicons-lightbulb"></span> <?php _e( 'TablePress has more to offer!', 'tablepress' ); ?></h2>
286 + </div>
287 + <div class="inside">
288 + <?php
289 + TablePress::load_modules_data();
290 + $random_module_slug = array_rand( TablePress::$modules );
291 + $feature_module = TablePress::$modules[ $random_module_slug ];
292 + $module_url = esc_url( "https://tablepress.org/modules/{$random_module_slug}/?utm_source=plugin&utm_medium=textlink&utm_content=edit-screen" );
293 +
294 + echo '<strong>' . __( 'Supercharge your tables with exceptional features:', 'tablepress' ) . '</strong>';
295 + echo '<h3><a href="' . $module_url . '">' . $feature_module['name'] . '</a></h3>';
296 + echo '<span>' . $feature_module['description'] . ' <a href="' . $module_url . '">' . __( 'Read more!', 'tablepress' ) . '</a></span>';
297 + ?>
298 + </div>
299 + </div>
300 + <div class="buttons">
301 + <a href="https://tablepress.org/premium/?utm_source=plugin&utm_medium=textlink&utm_content=edit-screen" class="tablepress-button">
302 + <span><?php _e( 'Compare the TablePress premium versions', 'tablepress' ); ?></span>
303 + <span class="dashicons dashicons-arrow-right-alt"></span>
304 + </a>
305 + </div>
306 + </div>
386 307 </div>
387 - </td>
388 - </tr>
389 - <tr class="top-border">
390 - <td class="column-1">
391 - <?php _e( 'Selected rows', 'tablepress' ); ?>:&nbsp;
392 - <input type="button" class="button" id="rows-hide" value="<?php esc_attr_e( 'Hide', 'tablepress' ); ?>" />
393 - <input type="button" class="button" id="rows-unhide" value="<?php esc_attr_e( 'Show', 'tablepress' ); ?>" />
394 - </td>
395 - <td class="column-2">
396 - <?php _e( 'Selected columns', 'tablepress' ); ?>:&nbsp;
397 - <input type="button" class="button" id="columns-hide" value="<?php esc_attr_e( 'Hide', 'tablepress' ); ?>" />
398 - <input type="button" class="button" id="columns-unhide" value="<?php esc_attr_e( 'Show', 'tablepress' ); ?>" />
399 - </td>
400 - </tr>
401 - <tr class="bottom-border">
402 - <td class="column-1">
403 - <?php _e( 'Selected rows', 'tablepress' ); ?>:&nbsp;
404 - <input type="button" class="button" id="rows-duplicate" value="<?php esc_attr_e( 'Duplicate', 'tablepress' ); ?>" />
405 - <input type="button" class="button" id="rows-insert" value="<?php esc_attr_e( 'Insert', 'tablepress' ); ?>" />
406 - <input type="button" class="button" id="rows-remove" value="<?php esc_attr_e( 'Delete', 'tablepress' ); ?>" />
407 - </td>
408 - <td class="column-2">
409 - <?php _e( 'Selected columns', 'tablepress' ); ?>:&nbsp;
410 - <input type="button" class="button" id="columns-duplicate" value="<?php esc_attr_e( 'Duplicate', 'tablepress' ); ?>" />
411 - <input type="button" class="button" id="columns-insert" value="<?php esc_attr_e( 'Insert', 'tablepress' ); ?>" />
412 - <input type="button" class="button" id="columns-remove" value="<?php esc_attr_e( 'Delete', 'tablepress' ); ?>" />
413 - </td>
414 - </tr>
415 - <tr class="top-border">
416 - <td class="column-1">
417 - <label><?php printf( __( 'Add %s row(s)', 'tablepress' ), '<input type="number" id="rows-append-number" class="small-text numbers-only" title="' . esc_attr__( 'This field must contain a positive number.', 'tablepress' ) . '" value="1" min="1" max="99999" maxlength="5" required />' ); ?></label>&nbsp;<input type="button" class="button" id="rows-append" value="<?php esc_attr_e( 'Add', 'tablepress' ); ?>" />
418 - </td>
419 - <td class="column-2">
420 - <label><?php printf( __( 'Add %s column(s)', 'tablepress' ), '<input type="number" id="columns-append-number" class="small-text numbers-only" title="' . esc_attr__( 'This field must contain a positive number.', 'tablepress' ) . '" value="1" min="1" max="99999" maxlength="5" required />' ); ?></label>&nbsp;<input type="button" class="button" id="columns-append" value="<?php esc_attr_e( 'Add', 'tablepress' ); ?>" />
421 - </td>
422 - </tr>
423 -</table>
424 -<p class="hide-if-js"><?php _e( 'To use the Table Manipulation features, JavaScript needs to be enabled in your browser.', 'tablepress' ); ?></p>
425 -<?php
308 + <?php
309 + endif;
426 310 }
427 311
428 312 /**
429 - * Print the "Preview" and "Save Changes" button.
313 + * Prints the content of the "Table Content" post meta box.
430 314 *
431 315 * @since 1.0.0
432 316 *
433 - * @param array $data Data for this screen.
434 - * @param array $box Information about the text box.
317 + * @param array<string, mixed> $data Data for this screen.
318 + * @param array<string, mixed> $box Information about the meta box.
435 319 */
436 - public function textbox_buttons( array $data, array $box ) {
437 - $preview_url = TablePress::url( array( 'action' => 'preview_table', 'item' => $data['table']['id'], 'return' => 'edit', 'return_item' => $data['table']['id'] ), true, 'admin-post.php' );
438 -
439 - echo '<p class="submit">';
440 - if ( current_user_can( 'tablepress_preview_table', $data['table']['id'] ) ) {
441 - echo '<a href="' . $preview_url . '" class="button button-large show-preview-button" target="_blank">' . __( 'Preview', 'tablepress' ) . '</a>';
442 - }
443 - ?>
444 - <input type="button" class="button button-primary button-large save-changes-button hide-if-no-js" value="<?php esc_attr_e( 'Save Changes', 'tablepress' ); ?>" />
445 - <input type="submit" class="button button-primary button-large hide-if-js" value="<?php esc_attr_e( 'Save Changes', 'tablepress' ); ?>" />
446 - <?php
447 - echo '</p>';
320 + public function postbox_table_data( array $data, array $box ): void {
321 + echo '<div id="tablepress-table-editor-toolbar-section"></div>';
322 + $css_variables = '--table-editor-line-clamp:' . absint( TablePress::$model_options->get( 'table_editor_line_clamp' ) ) . ';';
323 + $css_variables = esc_attr( $css_variables );
324 + echo "<div id=\"table-editor\" style=\"{$css_variables}\"></div>";
448 325 }
449 326
450 327 /**
451 - * Print the "Delete Table" and "Export Table" buttons.
328 + * Prints the container for the sticky "Header Bar".
452 329 *
453 - * @since 1.0.0
330 + * @since 3.3.0
454 331 *
455 - * @param array $data Data for this screen.
456 - * @param array $box Information about the text box.
332 + * @param array<string, mixed> $data Data for this screen.
333 + * @param array<string, mixed> $box Information about the text box.
457 334 */
458 - public function textbox_other_actions( array $data, array $box ) {
459 - $user_can_copy_table = current_user_can( 'tablepress_copy_table', $data['table']['id'] );
460 - $user_can_export_table = current_user_can( 'tablepress_export_table', $data['table']['id'] );
461 - $user_can_delete_table = current_user_can( 'tablepress_delete_table', $data['table']['id'] );
462 -
463 - if ( ! $user_can_copy_table && ! $user_can_export_table && ! $user_can_delete_table ) {
464 - return;
465 - }
466 -
467 - echo '<p class="submit">';
468 - echo __( 'Other Actions', 'tablepress' ) . ':&nbsp; ';
469 - if ( $user_can_copy_table ) {
470 - echo '<a href="' . TablePress::url( array( 'action' => 'copy_table', 'item' => $data['table']['id'], 'return' => 'edit' ), true, 'admin-post.php' ) . '" class="button">' . __( 'Copy Table', 'tablepress' ) . '</a> ';
471 - }
472 - if ( $user_can_export_table ) {
473 - echo '<a href="' . TablePress::url( array( 'action' => 'export', 'table_id' => $data['table']['id'] ) ) . '" class="button">' . __( 'Export Table', 'tablepress' ) . '</a> ';
474 - }
475 - if ( $user_can_delete_table ) {
476 - echo '<a href="' . TablePress::url( array( 'action' => 'delete_table', 'item' => $data['table']['id'], 'return' => 'edit', 'return_item' => $data['table']['id'] ), true, 'admin-post.php' ) . '" class="button delete-link">' . __( 'Delete Table', 'tablepress' ) . '</a>';
477 - }
478 - echo '</p>';
335 + public function textbox_header_bar( array $data, array $box ): void {
336 + echo '<div id="tablepress-header-bar-section" class="section-has-react-loading-text">';
337 + echo '</div>';
479 338 }
480 339
481 340 /**
482 - * Print the hidden containers for the Advanced Editor and the Preview.
341 + * Prints the hidden containers for the Preview.
483 342 *
484 343 * @since 1.0.0
485 344 *
486 - * @param array $data Data for this screen.
487 - * @param array $box Information about the text box.
345 + * @param array<string, mixed> $data Data for this screen.
346 + * @param array<string, mixed> $box Information about the text box.
488 347 */
489 - public function textbox_hidden_containers( array $data, array $box ) {
490 -?>
348 + public function textbox_hidden_containers( array $data, array $box ): void {
349 + ?>
350 +<div id="tablepress-table-preview-section"></div>
491 351 <div class="hidden-container">
492 352 <div id="advanced-editor">
493 - <label for="advanced-editor-content" class="screen-reader-text"><?php esc_html_e( 'Advanced Editor', 'tablepress' ); ?></label>
494 - <?php
353 + <label id="advanced-editor-label" for="advanced-editor-content" class="screen-reader-text"><?php esc_html_e( 'Advanced Editor', 'tablepress' ); ?></label>
354 + <?php
495 355 $wp_editor_options = array(
496 356 'textarea_rows' => 10,
497 357 'tinymce' => false,
498 358 'quicktags' => array(
@@ -499,202 +359,139 @@
499 359 'buttons' => 'strong,em,link,del,ins,img,code,spell,close',
500 360 ),
501 361 );
502 362 wp_editor( '', 'advanced-editor-content', $wp_editor_options );
503 - ?>
504 - <div class="submitbox">
505 - <a href="#" class="submitdelete" id="advanced-editor-cancel"><?php _e( 'Cancel', 'tablepress' ); ?></a>
506 - <input type="button" class="button button-primary button-large" id="advanced-editor-confirm" value="<?php esc_attr_e( 'OK', 'tablepress' ); ?>" />
363 + ?>
507 364 </div>
508 - </div>
365 + <textarea id="textarea-insert-helper" class="hidden"></textarea>
509 366 </div>
510 -<div id="preview-container" class="hidden-container">
511 - <div id="table-preview"></div>
512 -</div>
513 -<?php
367 + <?php
514 368 }
515 369
516 370 /**
517 - * Print the content of the "Table Options" post meta box.
371 + * Prints the content of the "Table Options" post meta box.
518 372 *
519 373 * @since 1.0.0
520 374 *
521 - * @param array $data Data for this screen.
522 - * @param array $box Information about the meta box.
375 + * @param array<string, mixed> $data Data for this screen.
376 + * @param array<string, mixed> $box Information about the meta box.
523 377 */
524 - public function postbox_table_options( array $data, array $box ) {
525 - $options = $data['table']['options'];
526 -?>
527 -<table class="tablepress-postbox-table fixed">
528 -<tbody>
529 - <tr>
530 - <th class="column-1" scope="row"><?php _e( 'Table Head Row', 'tablepress' ); ?>:</th>
531 - <td class="column-2"><label for="option-table-head"><input type="checkbox" id="option-table-head" name="table[options][table_head]" value="true"<?php checked( $options['table_head'] ); ?> /> <?php _e( 'The first row of the table is the table header.', 'tablepress' ); ?></label></td>
532 - </tr>
533 - <tr class="bottom-border">
534 - <th class="column-1" scope="row"><?php _e( 'Table Foot Row', 'tablepress' ); ?>:</th>
535 - <td class="column-2"><label for="option-table-foot"><input type="checkbox" id="option-table-foot" name="table[options][table_foot]" value="true"<?php checked( $options['table_foot'] ); ?> /> <?php _e( 'The last row of the table is the table footer.', 'tablepress' ); ?></label></td>
536 - </tr>
537 - <tr class="top-border">
538 - <th class="column-1" scope="row"><?php _e( 'Alternating Row Colors', 'tablepress' ); ?>:</th>
539 - <td class="column-2"><label for="option-alternating-row-colors"><input type="checkbox" id="option-alternating-row-colors" name="table[options][alternating_row_colors]" value="true"<?php checked( $options['alternating_row_colors'] ); ?> /> <?php _e( 'The background colors of consecutive rows shall alternate.', 'tablepress' ); ?></label></td>
540 - </tr>
541 - <tr class="bottom-border">
542 - <th class="column-1" scope="row"><?php _e( 'Row Hover Highlighting', 'tablepress' ); ?>:</th>
543 - <td class="column-2"><label for="option-row-hover"><input type="checkbox" id="option-row-hover" name="table[options][row_hover]" value="true"<?php checked( $options['row_hover'] ); ?> /> <?php _e( 'Highlight a row while the mouse cursor hovers above it by changing its background color.', 'tablepress' ); ?></label></td>
544 - </tr>
545 - <tr class="top-border">
546 - <th class="column-1" scope="row"><label for="option-print-name"><?php _e( 'Print Table Name', 'tablepress' ); ?></label>:</th>
547 - <?php
548 - $position_select = '<select id="option-print-name-position" name="table[options][print_name_position]">';
549 - $position_select .= '<option' . selected( 'above', $options['print_name_position'], false ) . ' value="above">' . __( 'above', 'tablepress' ) . '</option>';
550 - $position_select .= '<option' . selected( 'below', $options['print_name_position'], false ) . ' value="below">' . __( 'below', 'tablepress' ) . '</option>';
551 - $position_select .= '</select>';
552 - ?>
553 - <td class="column-2"><input type="checkbox" id="option-print-name" name="table[options][print_name]" value="true"<?php checked( $options['print_name'] ); ?> /> <label><?php printf( __( 'Show the table name %s the table.', 'tablepress' ), $position_select ); ?></label></td>
554 - </tr>
555 - <tr class="bottom-border">
556 - <th class="column-1" scope="row"><label for="option-print-description"><?php _e( 'Print Table Description', 'tablepress' ); ?></label>:</th>
557 - <?php
558 - $position_select = '<select id="option-print-description-position" name="table[options][print_description_position]">';
559 - $position_select .= '<option' . selected( 'above', $options['print_description_position'], false ) . ' value="above">' . __( 'above', 'tablepress' ) . '</option>';
560 - $position_select .= '<option' . selected( 'below', $options['print_description_position'], false ) . ' value="below">' . __( 'below', 'tablepress' ) . '</option>';
561 - $position_select .= '</select>';
562 - ?>
563 - <td class="column-2"><input type="checkbox" id="option-print-description" name="table[options][print_description]" value="true"<?php checked( $options['print_description'] ); ?> /> <label><?php printf( __( 'Show the table description %s the table.', 'tablepress' ), $position_select ); ?></label></td>
564 - </tr>
565 - <tr class="top-border">
566 - <th class="column-1" scope="row"><?php _e( 'Extra CSS Classes', 'tablepress' ); ?>:</th>
567 - <td class="column-2"><label for="option-extra-css-classes"><input type="text" id="option-extra-css-classes" class="large-text" name="table[options][extra_css_classes]" value="<?php echo esc_attr( $options['extra_css_classes'] ); ?>" title="<?php esc_attr_e( 'This field can only contain letters, numbers, spaces, hyphens (-), and underscores (_).', 'tablepress' ); ?>" pattern="[A-Za-z0-9- _]*" /><p class="description"><?php echo __( 'Additional CSS classes for styling purposes can be entered here.', 'tablepress' ) . ' ' . sprintf( __( 'This is NOT the place to enter <a href="%s">Custom CSS</a> code!', 'tablepress' ), TablePress::url( array( 'action' => 'options' ) ) ); ?></p></label></td>
568 - </tr>
569 -</tbody>
570 -</table>
571 -<?php
378 + public function postbox_table_options( array $data, array $box ): void {
379 + echo '<div id="tablepress-table-options-section"></div>';
572 380 }
573 381
574 382 /**
575 - * Print the content of the "Features of the DataTables JavaScript library" post meta box.
383 + * Prints the content of the "Table Features for Site Visitors" post meta box.
576 384 *
577 385 * @since 1.0.0
578 386 *
579 - * @param array $data Data for this screen.
580 - * @param array $box Information about the meta box.
387 + * @param array<string, mixed> $data Data for this screen.
388 + * @param array<string, mixed> $box Information about the meta box.
581 389 */
582 - public function postbox_datatables_features( array $data, array $box ) {
583 - $options = $data['table']['options'];
584 -?>
585 -<p id="notice-datatables-head-row" class="hide-if-js"><?php printf( __( 'These features and options are only available, when the &#8220;%1$s&#8221; checkbox in the &#8220;%2$s&#8221; section is checked.', 'tablepress' ), __( 'Table Head Row', 'tablepress' ), __( 'Table Options', 'tablepress' ) ); ?></p>
586 -<table class="tablepress-postbox-table fixed">
587 -<tbody>
588 - <tr class="bottom-border">
589 - <th class="column-1" scope="row"><?php _e( 'Use DataTables', 'tablepress' ); ?>:</th>
590 - <td class="column-2"><label for="option-use-datatables"><input type="checkbox" id="option-use-datatables" name="table[options][use_datatables]" value="true"<?php checked( $options['use_datatables'] ); ?> /> <?php _e( 'Use the following features of the DataTables JavaScript library with this table:', 'tablepress' ); ?></label></td>
591 - </tr>
592 - <tr class="top-border">
593 - <th class="column-1" scope="row"><?php _e( 'Sorting', 'tablepress' ); ?>:</th>
594 - <td class="column-2"><label for="option-datatables-sort"><input type="checkbox" id="option-datatables-sort" name="table[options][datatables_sort]" value="true"<?php checked( $options['datatables_sort'] ); ?> /> <?php _e( 'Enable sorting of the table by the visitor.', 'tablepress' ); ?></label></td>
595 - </tr>
596 - <tr>
597 - <th class="column-1" scope="row"><?php _e( 'Search/Filtering', 'tablepress' ); ?>:</th>
598 - <td class="column-2"><label for="option-datatables-filter"><input type="checkbox" id="option-datatables-filter" name="table[options][datatables_filter]" value="true"<?php checked( $options['datatables_filter'] ); ?> /> <?php _e( 'Enable the visitor to filter or search the table. Only rows with the search word in them are shown.', 'tablepress' ); ?></label></td>
599 - </tr>
600 - <tr>
601 - <th class="column-1" scope="row" style="vertical-align: top;"><?php _e( 'Pagination', 'tablepress' ); ?>:</th>
602 - <td class="column-2"><label for="option-datatables-paginate"><input type="checkbox" id="option-datatables-paginate" name="table[options][datatables_paginate]" value="true"<?php checked( $options['datatables_paginate'] ); ?> /> <?php _e( 'Enable pagination of the table (viewing only a certain number of rows at a time) by the visitor.', 'tablepress' ); ?></label><br />
603 - <label for="option-datatables-paginate_entries" class="checkbox-left"><?php printf( __( 'Show %s rows per page.', 'tablepress' ), '<input type="number" id="option-datatables-paginate_entries" name="table[options][datatables_paginate_entries]" value="' . intval( $options['datatables_paginate_entries'] ) . '" min="1" max="99999" maxlength="5" required />' ); ?></label></td>
604 - </tr>
605 - <tr>
606 - <th class="column-1" scope="row"><?php _e( 'Pagination Length Change', 'tablepress' ); ?>:</th>
607 - <td class="column-2"><label for="option-datatables-lengthchange"><input type="checkbox" id="option-datatables-lengthchange" name="table[options][datatables_lengthchange]" value="true"<?php checked( $options['datatables_lengthchange'] ); ?> /> <?php _e( 'Allow the visitor to change the number of rows shown when using pagination.', 'tablepress' ); ?></label></td>
608 - </tr>
609 - <tr>
610 - <th class="column-1" scope="row"><?php _e( 'Info', 'tablepress' ); ?>:</th>
611 - <td class="column-2"><label for="option-datatables-info"><input type="checkbox" id="option-datatables-info" name="table[options][datatables_info]" value="true"<?php checked( $options['datatables_info'] ); ?> /> <?php _e( 'Enable the table information display, with information about the currently visible data, like the number of rows.', 'tablepress' ); ?></label></td>
612 - </tr>
613 - <tr<?php echo current_user_can( 'unfiltered_html' ) ? ' class="bottom-border"' : ''; ?>>
614 - <th class="column-1" scope="row"><?php _e( 'Horizontal Scrolling', 'tablepress' ); ?>:</th>
615 - <td class="column-2"><label for="option-datatables-scrollx"><input type="checkbox" id="option-datatables-scrollx" name="table[options][datatables_scrollx]" value="true"<?php checked( $options['datatables_scrollx'] ); ?> /> <?php _e( 'Enable horizontal scrolling, to make viewing tables with many columns easier.', 'tablepress' ); ?></label></td>
616 - </tr>
617 - <?php
618 - // "Custom Commands" must only be available to trusted users. The text field must be in the page however, so that it's part of the HTTP POST request.
619 - ?>
620 - <tr class="<?php echo current_user_can( 'unfiltered_html' ) ? 'top-border' : 'hidden'; ?>">
621 - <th class="column-1" scope="row"><?php _e( 'Custom Commands', 'tablepress' ); ?>:</th>
622 - <td class="column-2"><label for="option-datatables-custom-commands"><textarea id="option-datatables-custom-commands" class="large-text" name="table[options][datatables_custom_commands]" rows="1"><?php echo esc_textarea( $options['datatables_custom_commands'] ); ?></textarea><p class="description"><?php echo sprintf( __( 'Additional parameters from the <a href="%s">DataTables documentation</a> to be added to the JS call.', 'tablepress' ), 'https://www.datatables.net/' ) . ' ' . __( 'For advanced use only.', 'tablepress' ); ?></p></label></td>
623 - </tr>
624 -</tbody>
625 -</table>
626 -<?php
390 + public function postbox_datatables_features( array $data, array $box ): void {
391 + echo '<div id="tablepress-datatables-features-section"></div>';
627 392 }
628 393
629 394 /**
630 - * Print a notification about a corrupted table.
395 + * Prints a notification about a corrupted table.
631 396 *
632 397 * @since 1.4.0
633 398 *
634 - * @param array $data Data for this screen.
635 - * @param array $box Information about the text box.
399 + * @param array<string, mixed> $data Data for this screen.
400 + * @param array<string, mixed> $box Information about the text box.
636 401 */
637 - public function textbox_corrupted_table( array $data, array $box ) {
402 + public function textbox_corrupted_table( array $data, array $box ): void {
638 403 ?>
639 - <div class="error">
640 - <p><strong><?php _e( 'Attention: Unfortunately, an error occurred.', 'tablepress' ); ?></strong></p>
641 - <p>
642 - <?php
643 - printf( __( 'The internal data of table &#8220;%1$s&#8221; (ID %2$s) is corrupted.', 'tablepress' ), esc_html( $data['table']['name'] ), esc_html( $data['table']['id'] ) );
644 - echo ' ';
645 - printf( __( 'The following error was registered: %s.', 'tablepress' ), '<code>' . esc_html( $data['table']['json_error'] ) . '</code>' );
646 - ?>
647 - </p>
648 - <p>
649 - <?php
650 - _e( 'Because of this error, the table can not be edited at this time, to prevent possible further data loss.', 'tablepress' );
651 - echo ' ';
652 - printf( __( 'Please see the <a href="%s">TablePress FAQ page</a> for further instructions.', 'tablepress' ), 'https://tablepress.org/faq/corrupted-tables/' );
653 - ?>
654 - </p>
655 - <p>
656 - <?php
657 - echo '<a href="' . TablePress::url( array( 'action' => 'list' ) ) . '" class="button">' . __( 'Back to the List of Tables', 'tablepress' ) . '</a>';
658 - ?>
659 - </p>
404 + <div class="notice components-notice is-error notice-error">
405 + <div class="components-notice__content">
406 + <h3><em>
407 + <?php _e( 'Attention: Unfortunately, an error occurred.', 'tablepress' ); ?>
408 + </em></h3>
409 + <p>
410 + <?php
411 + /* translators: %1$s: Table name, %2$s: Table ID */
412 + printf( __( 'The internal data of table &#8220;%1$s&#8221; (ID %2$s) is corrupted.', 'tablepress' ), esc_html( $data['table']['name'] ), esc_html( $data['table']['id'] ) );
413 + echo ' ';
414 + /* translators: %s: Error message */
415 + printf( __( 'The following error was registered: %s.', 'tablepress' ), '<code>' . esc_html( $data['table']['json_error'] ) . '</code>' );
416 + ?>
417 + </p>
418 + <p>
419 + <?php
420 + _e( 'Because of this error, the table can not be edited at this time, to prevent possible further data loss.', 'tablepress' );
421 + echo ' ';
422 + /* translators: %s: URL to TablePress FAQ page */
423 + printf( __( 'Please see the <a href="%s">TablePress FAQ page</a> for further instructions.', 'tablepress' ), 'https://tablepress.org/faq/corrupted-tables/' );
424 + ?>
425 + </p>
426 + <p>
427 + <?php echo '<a href="' . esc_url( TablePress::url( array( 'action' => 'list' ) ) ) . '" class="components-button is-secondary is-compact">' . __( 'Back to the List of Tables', 'tablepress' ) . '</a>'; ?>
428 + </p>
429 + </div>
660 430 </div>
661 431 <?php
662 432 }
663 433
664 434 /**
665 - * Print the screen head text.
435 + * Prints the screen head text.
666 436 *
667 437 * @since 1.0.0
668 438 *
669 - * @param array $data Data for this screen.
670 - * @param array $box Information about the text box.
439 + * @param array<string, mixed> $data Data for this screen.
440 + * @param array<string, mixed> $box Information about the text box.
671 441 */
672 - public function textbox_head( array $data, array $box ) {
673 - ?>
674 - <p>
675 - <?php printf( __( 'On this screen, you can edit the content and structure of the table with the ID %s.', 'tablepress' ), esc_html( $data['table']['id'] ) ); ?>
676 - <?php _e( 'For example, you can insert things like text, images, or links into the table, or change the used table features. You can also insert, delete, move, hide, and swap columns and rows.', 'tablepress' ); ?>
677 - </p>
678 - <p>
679 - <label class="screen-reader-only" for="table-shortcode-inline"><?php esc_html_e( 'Shortcode text for editor', 'tablepress' ); ?></label>
680 - <?php printf( __( 'To insert the table into a page, post, or text widget, copy the Shortcode %s and paste it at the desired place in the editor.', 'tablepress' ), '<input type="text" id="table-shortcode-inline" class="table-shortcode table-shortcode-inline" value="' . esc_attr( '[' . TablePress::$shortcode . " id={$data['table']['id']} /]" ) . '" readonly="readonly" />' ); ?>
681 - </p>
682 - <?php
442 + public function textbox_head( array $data, array $box ): void {
443 + echo '<p>';
444 + _e( 'To edit the content or modify the structure of this table, use the input fields and buttons below.', 'tablepress' );
445 + echo ' ';
446 + // Show the instructions string depending on whether the Block Editor is used on the site or not.
447 + if ( 'block' === $data['site_used_editor'] ) {
448 + printf( __( 'To insert a table into a post or page, add a “%1$s” block in the block editor and select the desired table.', 'tablepress' ), __( 'TablePress table', 'tablepress' ) );
449 + } elseif ( 'elementor' === $data['site_used_editor'] ) {
450 + printf( __( 'To insert a table into a post or page, add a “%1$s” widget in the Elementor editor and select the desired table.', 'tablepress' ), __( 'TablePress table', 'tablepress' ) );
451 + } else {
452 + _e( 'To insert a table into a post or page, paste its Shortcode at the desired place in the editor.', 'tablepress' );
453 + }
454 + echo '</p>';
683 455 }
684 456
685 457 /**
686 - * Set the content for the WP feature pointer about the drag and drop and sort on the "Edit" screen.
458 + * Sets the content for the WP feature pointer about the Table Editor Toolbar on the "Edit" screen.
687 459 *
688 - * @since 1.0.0
460 + * @since 3.4.0
689 461 */
690 - public function wp_pointer_tp09_edit_drag_drop_sort() {
691 - $content = '<h3>' . __( 'TablePress Feature: Moving rows and columns', 'tablepress' ) . '</h3>';
692 - $content .= '<p>' . __( 'Did you know? You can drag and drop rows and columns via the row number and the column title. And the arrows next to the column title can be used for sorting.', 'tablepress' ) . '</p>';
462 + public function wp_pointer_tp34_edit_toolbar(): void {
463 + $content = '<h3>' . __( 'TablePress feature: Toolbar', 'tablepress' ) . '</h3>';
464 + $content .= '<p style="text-wrap:balance">' . __( 'Adding links or images or modifying the structure of your tables is very easy with the sticky Table Editor Toolbar!', 'tablepress' ) . '</p>';
693 465
694 - $this->admin_page->print_wp_pointer_js( 'tp09_edit_drag_drop_sort', '#edit-form-head', array(
695 - 'content' => $content,
696 - 'position' => array( 'edge' => 'top', 'align' => 'left', 'offset' => '56 2' ),
697 - ) );
466 + $this->print_wp_pointer_js(
467 + 'tp34_edit_toolbar',
468 + '#tablepress-table-editor-toolbar-section > div > div > div:first-child',
469 + array(
470 + 'content' => $content,
471 + 'position' => array( 'edge' => is_rtl() ? 'right' : 'left', 'align' => 'center' ),
472 + 'pointerWidth' => 290,
473 + ),
474 + );
475 + }
476 +
477 + /**
478 + * Sets the content for the WP feature pointer about the Quick Navigation on the "Edit" screen.
479 + *
480 + * @since 3.3.0
481 + */
482 + public function wp_pointer_tp33_edit_quick_navigation(): void {
483 + $content = '<h3>' . __( 'TablePress feature: Quick Navigation', 'tablepress' ) . '</h3>';
484 + $content .= '<p style="text-wrap:balance">' . __( 'You can quickly navigate between different sections of the table editor using the Quick Navigation menu.', 'tablepress' ) . ' ' . __( 'Just click the logo or use the <kbd>%metaKey%J</kbd> keyboard shortcut!', 'tablepress' ) . '</p>';
485 +
486 + $this->print_wp_pointer_js(
487 + 'tp33_edit_quick_navigation',
488 + '#tablepress-header-bar-section',
489 + array(
490 + 'content' => $content,
491 + 'position' => array( 'edge' => 'top', 'align' => is_rtl() ? 'right+16' : 'left-16' ),
492 + 'pointerWidth' => 330,
493 + ),
494 + );
698 495 }
699 496
700 497 } // class TablePress_Edit_View