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 | admin/js/edit.js +26 -1259 1.9.2 → 3.4 View file →
@@ -1,1269 +1,36 @@
1 1 /**
2 - * JavaScript code for the "Edit" screen
2 + * JavaScript code for the "Edit" screen.
3 3 *
4 4 * @package TablePress
5 5 * @subpackage Views JavaScript
6 6 * @author Tobias Bäthge
7 - * @since 1.0.0
7 + * @since 2.0.0
8 8 */
9 9
10 -/* global alert, confirm, tp, tablepress_strings, tablepress_options, ajaxurl, wpLink, tb_show, wp, JSON */
10 +/**
11 + * Load the default "Edit" screen sections.
12 + */
13 +import './edit/header-bar';
14 +import './edit/table-information';
15 +import './edit/toolbar';
16 +import './edit/table-options';
17 +import './edit/datatables-features';
18 +import './edit/table-preview';
11 19
12 -// Ensure the global `tp` object exists.
13 -window.tp = window.tp || {};
20 +/**
21 + * Load the non-React "Edit" screen JavaScript code, mostly for the table data editor.
22 + */
23 +import './edit/editor';
24 +import './edit/keyboard-shortcuts';
25 +import './edit/screen-options';
14 26
15 -jQuery( document ).ready( function( $ ) {
27 +/**
28 + * Internal dependencies.
29 + */
30 +import { initializeReactComponent } from './common/react-loader';
31 +import Screen from './edit/screen';
16 32
17 - 'use strict';
18 -
19 - /* Wrapper to find elements in the page faster with JS-native functions */
20 - var $id = function( element_id ) {
21 - return $( document.getElementById( element_id ) );
22 - };
23 -
24 - /**
25 - * TablePress object, mostly with functionality for the "Edit" screen
26 - *
27 - * @since 1.0.0
28 - */
29 - tp.made_changes = false;
30 -
31 - tp.table = {
32 - id: $id( 'table-id' ).val(),
33 - new_id: $id( 'table-new-id' ).val(),
34 - rows: parseInt( $id( 'number-rows' ).val(), 10 ),
35 - columns: parseInt( $id( 'number-columns' ).val(), 10 ),
36 - head: $id( 'option-table-head' ).prop( 'checked' ),
37 - foot: $id( 'option-table-foot' ).prop( 'checked' ),
38 - no_data_columns_pre: 2,
39 - no_data_columns_post: 1,
40 - body_cells_pre: '<tr><td><span class="move-handle"></span></td><td><input type="checkbox" /><input type="hidden" class="visibility" name="table[visibility][rows][]" value="1" /></td>',
41 - body_cells_post: '<td><span class="move-handle"></span></td></tr>',
42 - body_cell: '<td><textarea rows="1"></textarea></td>',
43 - head_cell: '<th class="head"><span class="sort-control sort-desc" title="' + tablepress_strings.sort_desc + '"><span class="sorting-indicator"></span></span><span class="sort-control sort-asc" title="' + tablepress_strings.sort_asc + '"><span class="sorting-indicator"></span></span><span class="move-handle"></span></th>',
44 - foot_cell: '<th><input type="checkbox" /><input type="hidden" class="visibility" name="table[visibility][columns][]" value="1" /></th>',
45 - set_table_changed: function() {
46 - tp.made_changes = true;
47 - },
48 - unset_table_changed: function() {
49 - tp.made_changes = false;
50 - $id( 'edit-form-body' ).one( 'change', 'textarea', tp.table.set_table_changed );
51 - // @TODO: maybe use .tablepress-postbox-table here and further below
52 - $( '#tablepress_edit-table-information, #tablepress_edit-table-options, #tablepress_edit-datatables-features' ).one( 'change', 'input, textarea, select', tp.table.set_table_changed );
53 - },
54 - change_id: function( /* event */ ) {
55 - // empty table IDs are not allowed
56 - if ( '' === $.trim( $id( 'table-new-id' ).val() ) ) {
57 - alert( tablepress_strings.table_id_not_empty );
58 - $id( 'table-new-id' ).val( tp.table.new_id ).focus().select();
59 - return;
60 - }
61 - // the '0' table ID is not allowed
62 - if ( '0' === $.trim( $id( 'table-new-id' ).val() ) ) {
63 - alert( tablepress_strings.table_id_not_zero );
64 - $id( 'table-new-id' ).val( tp.table.new_id ).focus().select();
65 - return;
66 - }
67 -
68 - if ( this.value === tp.table.new_id ) {
69 - return;
70 - }
71 -
72 - if ( confirm( tablepress_strings.ays_change_table_id ) ) {
73 - tp.table.new_id = this.value;
74 - $( '.table-shortcode' ).val( '[' + tablepress_options.shortcode + ' id=' + tp.table.new_id + ' /]' ).click(); // click() to focus and select
75 - tp.table.set_table_changed();
76 - } else {
77 - $(this).val( tp.table.new_id );
78 - }
79 - },
80 - change_table_head: function( /* event */ ) {
81 - tp.table.head = $(this).prop( 'checked' );
82 - $id( 'option-use-datatables' ).prop( 'disabled', ! tp.table.head ).change();
83 - $id( 'notice-datatables-head-row' ).toggle( ! tp.table.head );
84 - tp.rows.stripe();
85 - },
86 - change_table_foot: function( /* event */ ) {
87 - tp.table.foot = $(this).prop( 'checked' );
88 - tp.rows.stripe();
89 - },
90 - change_print_name_description: function( /* event */ ) {
91 - $id( this.id + '-position' ).prop( 'disabled', ! $(this).prop( 'checked' ) );
92 - },
93 - change_datatables: function() {
94 - var $datatables_checkbox = $id( 'option-use-datatables' ),
95 - checkboxes_disabled = ! ( $datatables_checkbox.prop( 'checked' ) && ! $datatables_checkbox.prop( 'disabled' ) );
96 - $datatables_checkbox.closest( 'tbody' ).find( 'input' ).not( $datatables_checkbox ).prop( 'disabled', checkboxes_disabled );
97 - tp.table.change_datatables_pagination();
98 - },
99 - change_datatables_pagination: function() {
100 - var $pagination_checkbox = $id( 'option-datatables-paginate' ),
101 - pagination_enabled = ( $pagination_checkbox.prop( 'checked' ) && ! $pagination_checkbox.prop( 'disabled' ) );
102 - $id( 'option-datatables-lengthchange' ).prop( 'disabled', ! pagination_enabled );
103 - $id( 'option-datatables-paginate_entries' ).prop( 'disabled', ! pagination_enabled );
104 - },
105 - prepare_ajax_request: function( wp_action, wp_nonce ) {
106 - var $table_body = $id( 'edit-form-body' ),
107 - table_data = [],
108 - table_options,
109 - table_number = { rows: tp.table.rows, columns: tp.table.columns, hidden_rows: 0, hidden_columns: 0 },
110 - table_visibility = { rows: [], columns: [] };
111 -
112 - $table_body.children().each( function( idx, row ) {
113 - table_data[ idx ] = $( row ).find( 'textarea' )
114 - .map( function() {
115 - return $(this).val();
116 - } )
117 - .get();
118 - } );
119 - table_data = JSON.stringify( table_data );
120 -
121 - // @TODO: maybe for options saving: https://stackoverflow.com/questions/1184624/convert-form-data-to-javascript-object-with-jquery
122 - // or each()-loop through all checkboxes/textfields/selects
123 - table_options = {
124 - // Table Options
125 - table_head: tp.table.head,
126 - table_foot: tp.table.foot,
127 - alternating_row_colors: $id( 'option-alternating-row-colors' ).prop( 'checked' ),
128 - row_hover: $id( 'option-row-hover' ).prop( 'checked' ),
129 - print_name: $id( 'option-print-name' ).prop( 'checked' ),
130 - print_description: $id( 'option-print-description' ).prop( 'checked' ),
131 - print_name_position: $id( 'option-print-name-position' ).val(),
132 - print_description_position: $id( 'option-print-description-position' ).val(),
133 - extra_css_classes: $id( 'option-extra-css-classes' ).val(),
134 - // DataTables JS features
135 - use_datatables: $id( 'option-use-datatables' ).prop( 'checked' ),
136 - datatables_sort: $id( 'option-datatables-sort' ).prop( 'checked' ),
137 - datatables_filter: $id( 'option-datatables-filter' ).prop( 'checked' ),
138 - datatables_paginate: $id( 'option-datatables-paginate' ).prop( 'checked' ),
139 - datatables_lengthchange: $id( 'option-datatables-lengthchange' ).prop( 'checked' ),
140 - datatables_paginate_entries: $id( 'option-datatables-paginate_entries' ).val(),
141 - datatables_info: $id( 'option-datatables-info' ).prop( 'checked' ),
142 - datatables_scrollx: $id( 'option-datatables-scrollx' ).prop( 'checked' ),
143 - datatables_custom_commands: $id( 'option-datatables-custom-commands' ).val()
144 - };
145 - table_options = JSON.stringify( table_options );
146 -
147 - table_visibility.rows = $table_body.find( 'input[type="hidden"]' )
148 - .map( function() {
149 - if ( '1' === $(this).val() ) {
150 - return 1;
151 - }
152 - table_number.hidden_rows += 1;
153 - return 0;
154 - } )
155 - .get();
156 - table_visibility.columns = $id( 'edit-form-foot' ).find( 'input[type="hidden"]' )
157 - .map( function() {
158 - if ( '1' === $(this).val() ) {
159 - return 1;
160 - }
161 - table_number.hidden_columns += 1;
162 - return 0;
163 - } )
164 - .get();
165 - table_visibility = JSON.stringify( table_visibility );
166 -
167 - // request_data =
168 - return {
169 - action: wp_action,
170 - _ajax_nonce : $( wp_nonce ).val(),
171 - tablepress: {
172 - id: tp.table.id,
173 - new_id: tp.table.new_id,
174 - name: $id( 'table-name' ).val(),
175 - description: $id( 'table-description' ).val(),
176 - number: table_number,
177 - data: table_data,
178 - options: table_options,
179 - visibility: table_visibility
180 - }
181 - };
182 - },
183 - preview: {
184 - trigger: function( /* event */ ) {
185 - if ( ! tp.made_changes ) {
186 - tp.table.preview.show( $(this).attr( 'href' ) + '&TB_iframe=true' );
187 - return false;
188 - }
189 -
190 - // validation checks
191 - if ( $id( 'option-datatables-paginate' ).prop( 'checked' ) && ! ( /^[1-9][0-9]{0,4}$/ ).test( $id( 'option-datatables-paginate_entries' ).val() ) ) {
192 - alert( tablepress_strings.num_pagination_entries_invalid );
193 - $id( 'option-datatables-paginate_entries' ).focus().select();
194 - return;
195 - }
196 - if ( ( /[^A-Za-z0-9- _]/ ).test( $id( 'option-extra-css-classes' ).val() ) ) {
197 - alert( tablepress_strings.extra_css_classes_invalid );
198 - $id( 'option-extra-css-classes' ).focus().select();
199 - return;
200 - }
201 -
202 - $(this).closest( 'p' ).append( '<span class="animation-preview spinner is-active" title="' + tablepress_strings.preparing_preview + '"/>' );
203 - $( 'body' ).addClass( 'wait' );
204 - $id( 'table-preview' ).empty(); // clear preview
205 -
206 - $.ajax({
207 - 'type': 'POST',
208 - 'url': ajaxurl,
209 - 'data': tp.table.prepare_ajax_request( 'tablepress_preview_table', '#nonce-preview-table' ),
210 - 'success': tp.table.preview.ajax_success,
211 - 'error': tp.table.preview.ajax_error,
212 - 'dataType': 'json'
213 - } );
214 -
215 - return false;
216 - },
217 - ajax_success: function( data, status /*, jqXHR */ ) {
218 - if ( ( 'undefined' === typeof status ) || ( 'success' !== status ) ) {
219 - tp.table.preview.error( 'AJAX call successful, but unclear status.' );
220 - } else if ( ( 'undefined' === typeof data ) || ( null === data ) || ( '-1' === data ) || ( 'undefined' === typeof data.success ) || ( true !== data.success ) ) {
221 - tp.table.preview.error( 'AJAX call successful, but unclear data.' );
222 - } else {
223 - tp.table.preview.success( data );
224 - }
225 - },
226 - ajax_error: function( jqXHR, status, error_thrown ) {
227 - tp.table.preview.error( 'AJAX call failed: ' + status + ' - ' + error_thrown );
228 - },
229 - success: function( data ) {
230 - $id( 'table-preview' ).empty();
231 - $( '<iframe id="table-preview-iframe" />' ).load( function() {
232 - var $iframe = $(this).contents();
233 - $iframe.find( 'head' ).append( data.head_html );
234 - $iframe.find( 'body' ).append( data.body_html );
235 - } ).appendTo( '#table-preview' );
236 - $( '.animation-preview' ).remove();
237 - $( 'body' ).removeClass( 'wait' );
238 - tp.table.preview.show( '#TB_inline?inlineId=preview-container' );
239 - },
240 - error: function( message ) {
241 - $( '.animation-preview' ).closest( 'p' )
242 - .after( '<div class="ajax-alert preview-error error"><p>' + tablepress_strings.preview_error + ': ' + message + '</p></div>' );
243 - $( '.animation-preview' ).remove();
244 - $( '.preview-error' ).delay( 6000 ).fadeOut( 2000, function() { $(this).remove(); } );
245 - $( 'body' ).removeClass( 'wait' );
246 - },
247 - show: function( url ) {
248 - var width = $( window ).width() - 120,
249 - height = $( window ).height() - 120;
250 - if ( $( '#wpadminbar' ).length ) {
251 - height -= parseInt( $( '#wpadminbar' ).css( 'height' ), 10 );
252 - }
253 - tb_show( $( '.show-preview-button' ).first().text(), url + '&height=' + height + '&width=' + width, false );
254 - }
255 - }
256 - };
257 -
258 - tp.rows = {
259 - create: function( num_rows ) {
260 - var i, j,
261 - column_idxs,
262 - new_rows = '';
263 -
264 - for ( i = 0; i < num_rows; i++ ) {
265 - new_rows += tp.table.body_cells_pre;
266 - for ( j = 0; j < tp.table.columns; j++ ) {
267 - new_rows += tp.table.body_cell;
268 - }
269 - new_rows += tp.table.body_cells_post;
270 - }
271 -
272 - column_idxs = $id( 'edit-form-foot' ).find( '.column-hidden' )
273 - .map( function() { return $(this).index(); } ).get();
274 - return $( new_rows ).each( function( row_idx, row ) {
275 - $( row ).children()
276 - .filter( function( idx ) { return ( -1 !== $.inArray( idx, column_idxs ) ); } )
277 - .addClass( 'column-hidden' );
278 - } );
279 - },
280 - append: function( /* event */ ) {
281 - var num_rows = $id( 'rows-append-number' ).val();
282 -
283 - if ( ! ( /^[1-9][0-9]{0,4}$/ ).test( num_rows ) ) {
284 - alert( tablepress_strings.append_num_rows_invalid );
285 - $id( 'rows-append-number' ).focus().select();
286 - return;
287 - }
288 -
289 - $id( 'edit-form-body' ).append( tp.rows.create( num_rows ) );
290 -
291 - tp.rows.stripe();
292 - tp.reindex();
293 - },
294 - insert: function( event ) {
295 - var $selected_rows = $id( 'edit-form-body' ).find( 'input:checked' )
296 - .prop( 'checked', event.shiftKey ).closest( 'tr' );
297 -
298 - if ( 0 === $selected_rows.length ) {
299 - alert( tablepress_strings.no_rows_selected );
300 - return;
301 - }
302 -
303 - $selected_rows.before( tp.rows.create( 1 ) );
304 -
305 - tp.rows.stripe();
306 - tp.reindex();
307 - },
308 - duplicate: function( event ) {
309 - var $selected_rows = $id( 'edit-form-body' ).find( 'input:checked' )
310 - .prop( 'checked', event.shiftKey ).closest( 'tr' );
311 -
312 - if ( 0 === $selected_rows.length ) {
313 - alert( tablepress_strings.no_rows_selected );
314 - return;
315 - }
316 -
317 - $selected_rows.each( function( idx, row ) {
318 - var $row = $( row ),
319 - $textareas = $row.find( 'textarea' ),
320 - $duplicated_row = $row.clone();
321 - $duplicated_row.find( 'textarea' ).removeAttr( 'id' ).each( function( idx, cell ) {
322 - $( cell ).val( $textareas.eq( idx ).val() ); // setting val() is necessary, as clone() doesn't copy the current value, see jQuery bugs 5524, 2285, 3016
323 - } );
324 - $row.after( $duplicated_row );
325 - } );
326 -
327 - tp.rows.stripe();
328 - tp.reindex();
329 - },
330 - hide: function( event ) {
331 - var $selected_rows = $id( 'edit-form-body' ).find( 'input:checked' )
332 - .prop( 'checked', event.shiftKey ).closest( 'tr' );
333 -
334 - if ( 0 === $selected_rows.length ) {
335 - alert( tablepress_strings.no_rows_selected );
336 - return;
337 - }
338 -
339 - $selected_rows.addClass( 'row-hidden' ).find( '.visibility' ).val( '0' );
340 -
341 - tp.rows.stripe();
342 - tp.table.set_table_changed();
343 - },
344 - unhide: function( event ) {
345 - var $selected_rows = $id( 'edit-form-body' ).find( 'input:checked' )
346 - .prop( 'checked', event.shiftKey ).closest( 'tr' );
347 -
348 - if ( 0 === $selected_rows.length ) {
349 - alert( tablepress_strings.no_rows_selected );
350 - return;
351 - }
352 -
353 - $selected_rows.removeClass( 'row-hidden' ).find( '.visibility' ).val( '1' );
354 -
355 - tp.rows.stripe();
356 - tp.table.set_table_changed();
357 - },
358 - remove: function( /* event */ ) {
359 - var confirm_message,
360 - $selected_rows = $id( 'edit-form-body' ).find( 'input:checked' ).closest( 'tr' );
361 -
362 - if ( 0 === $selected_rows.length ) {
363 - alert( tablepress_strings.no_rows_selected );
364 - return;
365 - }
366 -
367 - if ( tp.table.rows === $selected_rows.length ) {
368 - alert( tablepress_strings.no_remove_all_rows );
369 - return;
370 - }
371 -
372 - if ( 1 === $selected_rows.length ) {
373 - confirm_message = tablepress_strings.ays_remove_rows_singular;
374 - } else {
375 - confirm_message = tablepress_strings.ays_remove_rows_plural;
376 - }
377 - if ( ! confirm( confirm_message ) ) {
378 - return;
379 - }
380 -
381 - $selected_rows.remove();
382 -
383 - tp.rows.stripe();
384 - tp.reindex();
385 - },
386 - move: {
387 - start: function( event, ui ) {
388 - $( ui.placeholder ).removeClass( 'row-hidden' ).css( 'visibility', 'visible' )
389 - .html( '<td colspan="' + ( tp.table.columns + tp.table.no_data_columns_pre + tp.table.no_data_columns_post ) + '"><div/></td>' );
390 - $( ui.helper ).removeClass( 'odd head-row foot-row' );
391 - },
392 - change: function( event, ui ) {
393 - tp.rows.stripe( ui.helper );
394 - },
395 - stop: function( /* event, ui */ ) {
396 - tp.rows.stripe();
397 - }
398 - },
399 - sort: function() {
400 - var column_idx = $(this).parent().index(),
401 - direction = ( $(this).hasClass( 'sort-asc' ) ) ? 1 : -1,
402 - $table_body = $('#edit-form-body'),
403 - $head_rows = $table_body.find( '.head-row' ).prevAll().addBack(),
404 - $foot_rows = $table_body.find( '.foot-row' ).nextAll().addBack(),
405 - rows = $table_body.children().not( $head_rows ).not( $foot_rows ).get(),
406 - /*
407 - * Natural Sort algorithm for Javascript - Version 0.8.1 - Released under MIT license
408 - * Author: Jim Palmer (based on chunking idea from Dave Koelle)
409 - * See: https://github.com/overset/javascript-natural-sort and http://www.overset.com/2008/09/01/javascript-natural-sort-algorithm-with-unicode-support/
410 - */
411 - natural_sort = function( a, b ) {
412 - var re = /(^([+\-]?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?(?=\D|\s|$))|^0x[\da-fA-F]+$|\d+)/g,
413 - sre = /^\s+|\s+$/g, // trim pre-post whitespace
414 - snre = /\s+/g, // normalize all whitespace to single ' ' character
415 - dre = /(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/,
416 - hre = /^0x[0-9a-f]+$/i,
417 - ore = /^0/,
418 - // strip whitespace
419 - x = a.replace(sre, '') || '',
420 - y = b.replace(sre, '') || '',
421 - // chunk/tokenize
422 - xN = x.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0'),
423 - yN = y.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0'),
424 - // numeric, hex or date detection
425 - xD = parseInt(x.match(hre), 16) || (xN.length !== 1 && Date.parse(x)),
426 - yD = parseInt(y.match(hre), 16) || xD && y.match(dre) && Date.parse(y) || null,
427 - normChunk = function(s, l) {
428 - // normalize spaces; find floats not starting with '0', string or 0 if not defined (Clint Priest)
429 - return (!s.match(ore) || l === 1) && parseFloat(s) || s.replace(snre, ' ').replace(sre, '') || 0;
430 - },
431 - oFxNcL, oFyNcL;
432 - // first try and sort Hex codes or Dates
433 - if (yD) {
434 - if (xD < yD) { return -1; }
435 - else if (xD > yD) { return 1; }
436 - }
437 - // natural sorting through split numeric strings and default strings
438 - for(var cLoc = 0, xNl = xN.length, yNl = yN.length, numS = Math.max(xNl, yNl); cLoc < numS; cLoc++) {
439 - oFxNcL = normChunk(xN[cLoc] || '', xNl);
440 - oFyNcL = normChunk(yN[cLoc] || '', yNl);
441 - // handle numeric vs string comparison - number < string - (Kyle Adams)
442 - if (isNaN(oFxNcL) !== isNaN(oFyNcL)) {
443 - return isNaN(oFxNcL) ? 1 : -1;
444 - }
445 - // if unicode use locale comparison
446 - if (/[^\x00-\x80]/.test(oFxNcL + oFyNcL) && oFxNcL.localeCompare) {
447 - var comp = oFxNcL.localeCompare(oFyNcL);
448 - return comp / Math.abs(comp);
449 - }
450 - if (oFxNcL < oFyNcL) { return -1; }
451 - else if (oFxNcL > oFyNcL) { return 1; }
452 - }
453 - };
454 -
455 - $.each( rows, function( row_idx, row ) {
456 - row.sort_key = ( '' + $( row ).children().eq( column_idx ).find( 'textarea' ).val() ).toLowerCase(); // convert to string, and lower case for case insensitive sorting
457 - } );
458 -
459 - rows.sort( function( a, b ) {
460 - return direction * natural_sort( a.sort_key, b.sort_key );
461 - } );
462 -
463 - // might not be necessary:
464 - $.each( rows, function( row_idx, row ) {
465 - row.sort_key = null;
466 - } );
467 -
468 - $table_body.append( $head_rows );
469 - $table_body.append( rows );
470 - $table_body.append( $foot_rows );
471 -
472 - tp.rows.stripe();
473 - tp.reindex();
474 - },
475 - stripe: function( helper ) {
476 - if ( 'undefined' === typeof helper ) {
477 - helper = null;
478 - }
479 - helper = $( helper );
480 - var $rows = $id( 'edit-form-body' ).children().removeClass( 'odd head-row foot-row' ).not( helper );
481 - $rows.filter( ':even' ).addClass( 'odd' );
482 - $rows = $rows.not( '.row-hidden' );
483 - if ( helper.hasClass( 'row-hidden' ) ) {
484 - $rows = $rows.not( '.ui-sortable-placeholder' );
485 - }
486 - if ( tp.table.head ) {
487 - $rows.first().addClass( 'head-row' );
488 - }
489 - if ( tp.table.foot ) {
490 - $rows.last().addClass( 'foot-row' );
491 - }
492 - }
493 - };
494 -
495 - tp.columns = {
496 - append: function( /* event */ ) {
497 - var i,
498 - num_columns = $id( 'columns-append-number' ).val(),
499 - new_head_cells = '', new_body_cells = '', new_foot_cells = '';
500 -
501 - if ( ! ( /^[1-9][0-9]{0,4}$/ ).test( num_columns ) ) {
502 - alert( tablepress_strings.append_num_columns_invalid );
503 - $id( 'columns-append-number' ).focus().select();
504 - return;
505 - }
506 -
507 - for ( i = 0; i < num_columns; i++ ) {
508 - new_body_cells += tp.table.body_cell;
509 - new_head_cells += tp.table.head_cell;
510 - new_foot_cells += tp.table.foot_cell;
511 - }
512 -
513 - $id( 'edit-form-body' ).children().each( function( row_idx, row ) {
514 - $( row ).children().slice( - tp.table.no_data_columns_post )
515 - .before( new_body_cells );
516 - } );
517 - $id( 'edit-form-head' ).children().slice( - tp.table.no_data_columns_post )
518 - .before( new_head_cells );
519 - $id( 'edit-form-foot' ).children().slice( - tp.table.no_data_columns_post )
520 - .before( new_foot_cells );
521 -
522 - tp.reindex();
523 - },
524 - insert: function( event ) {
525 - var column_idxs,
526 - $selected_columns = $id( 'edit-form-foot' ).find( 'input:checked' )
527 - .prop( 'checked', event.shiftKey ).closest( 'th' );
528 -
529 - if ( 0 === $selected_columns.length ) {
530 - alert( tablepress_strings.no_columns_selected );
531 - return;
532 - }
533 -
534 - column_idxs = $selected_columns.map( function() { return $(this).index(); } ).get();
535 - $id( 'edit-form-body' ).children().each( function( row_idx, row ) {
536 - $( row ).children()
537 - .filter( function( idx ) { return ( -1 !== $.inArray( idx, column_idxs ) ); } )
538 - .before( tp.table.body_cell );
539 - } );
540 - $id( 'edit-form-head' ).children()
541 - .filter( function( idx ) { return ( -1 !== $.inArray( idx, column_idxs ) ); } )
542 - .before( tp.table.head_cell );
543 - $selected_columns.before( tp.table.foot_cell );
544 -
545 - tp.reindex();
546 - },
547 - duplicate: function( event ) {
548 - var column_idxs,
549 - $selected_columns = $id( 'edit-form-foot' ).find( 'input:checked' )
550 - .prop( 'checked', event.shiftKey ).closest( 'th' );
551 -
552 - if ( 0 === $selected_columns.length ) {
553 - alert( tablepress_strings.no_columns_selected );
554 - return;
555 - }
556 -
557 - column_idxs = $selected_columns.map( function() { return $(this).index(); } ).get();
558 - $id( 'edit-form' ).find( 'tr' ).each( function( row_idx, row ) {
559 - $( row ).children().each( function( idx, cell ) {
560 - if ( -1 !== $.inArray( idx, column_idxs ) ) {
561 - var $cell = $( cell ),
562 - $duplicated_cell = $cell.clone();
563 - $duplicated_cell.find( 'textarea' ).removeAttr( 'id' ).val( $cell.find( 'textarea' ).val() ); // setting val() is necessary, as clone() doesn't copy the current value, see jQuery bugs 5524, 2285, 3016
564 - $cell.after( $duplicated_cell );
565 - }
566 - } );
567 - } );
568 -
569 - tp.reindex();
570 - },
571 - hide: function( event ) {
572 - var column_idxs,
573 - $selected_columns = $id( 'edit-form-foot' ).find( 'input:checked' )
574 - .prop( 'checked', event.shiftKey ).closest( 'th' );
575 -
576 - if ( 0 === $selected_columns.length ) {
577 - alert( tablepress_strings.no_columns_selected );
578 - return;
579 - }
580 -
581 - column_idxs = $selected_columns.map( function() { return $(this).index(); } ).get();
582 - $id( 'edit-form-body' ).children().add( '#edit-form-head' ).each( function( row_idx, row ) {
583 - $( row ).children()
584 - .filter( function( idx ) { return ( -1 !== $.inArray( idx, column_idxs ) ); } )
585 - .addClass( 'column-hidden' );
586 - } );
587 - $selected_columns.addClass( 'column-hidden' ).find( '.visibility' ).val( '0' );
588 -
589 - tp.table.set_table_changed();
590 - },
591 - unhide: function( event ) {
592 - var column_idxs,
593 - $selected_columns = $id( 'edit-form-foot' ).find( 'input:checked' )
594 - .prop( 'checked', event.shiftKey ).closest( 'th' );
595 -
596 - if ( 0 === $selected_columns.length ) {
597 - alert( tablepress_strings.no_columns_selected );
598 - return;
599 - }
600 -
601 - column_idxs = $selected_columns.map( function() { return $(this).index(); } ).get();
602 - $id( 'edit-form-body' ).children().add( '#edit-form-head' ).each( function( row_idx, row ) {
603 - $( row ).children()
604 - .filter( function( idx ) { return ( -1 !== $.inArray( idx, column_idxs ) ); } )
605 - .removeClass( 'column-hidden' );
606 - } );
607 - $selected_columns.removeClass( 'column-hidden' ).find( '.visibility' ).val( '1' );
608 -
609 - tp.table.set_table_changed();
610 - },
611 - remove: function( /* event */ ) {
612 - var column_idxs,
613 - confirm_message,
614 - $selected_columns = $id( 'edit-form-foot' ).find( 'input:checked' ).closest( 'th' );
615 -
616 - if ( 0 === $selected_columns.length ) {
617 - alert( tablepress_strings.no_columns_selected );
618 - return;
619 - }
620 -
621 - if ( tp.table.columns === $selected_columns.length ) {
622 - alert( tablepress_strings.no_remove_all_columns );
623 - return;
624 - }
625 -
626 - if ( 1 === $selected_columns.length ) {
627 - confirm_message = tablepress_strings.ays_remove_columns_singular;
628 - } else {
629 - confirm_message = tablepress_strings.ays_remove_columns_plural;
630 - }
631 - if ( ! confirm( confirm_message ) ) {
632 - return;
633 - }
634 -
635 - column_idxs = $selected_columns.map( function() { return $(this).index(); } ).get();
636 - $id( 'edit-form-body' ).children().add( '#edit-form-head' ).each( function( row_idx, row ) {
637 - $( row ).children()
638 - .filter( function( idx ) { return ( -1 !== $.inArray( idx, column_idxs ) ); } )
639 - .remove();
640 - } );
641 - $selected_columns.remove();
642 -
643 - tp.reindex();
644 - },
645 - move: {
646 - source_idx: -1,
647 - target_idx: -1,
648 - $rows: null,
649 - $row_children: null,
650 - $cell: null,
651 - $cells: null,
652 - $placeholder: null,
653 - $helper: null,
654 - start: function( event, ui ) {
655 - var $item = $( ui.item ),
656 - column_width;
657 -
658 - tp.columns.move.source_idx = $item.index();
659 -
660 - tp.columns.move.$rows = $id( 'edit-form-body' ).children().add( '#edit-form-foot' );
661 -
662 - tp.columns.move.$cells = tp.columns.move.$rows
663 - .find( ':nth-child(' + ( tp.columns.move.source_idx + 1 ) + ')' )
664 - .each( function() {
665 - tp.columns.move.$cell = $(this);
666 - $( '<td class="move-placeholder"><div/></td>' ).insertBefore( tp.columns.move.$cell );
667 - tp.columns.move.$cell.insertAfter( tp.columns.move.$cell.nextAll().last() )
668 - .clone().addClass( 'move-hover' ).insertAfter( tp.columns.move.$cell )
669 - .find( 'textarea' ).val( tp.columns.move.$cell.find( 'textarea' ).val() );
670 - // last line works around problem with clone() of textareas, see jQuery bugs 5524, 2285, 3016
671 - } )
672 - .hide();
673 -
674 - tp.columns.move.$helper = tp.columns.move.$rows.find( '.move-hover' );
675 - /* // seems not to be working for rows, so disable it for columns
676 - .each( function() {
677 - tp.columns.move.$cell = $(this);
678 - tp.columns.move.$cell.css( 'top', ( tp.columns.move.$cell.position().top - 3 ) + 'px' );
679 - } );
680 - */
681 -
682 - column_width = tp.columns.move.$helper.eq(1).width(); // eq(0) is table foot
683 - tp.columns.move.$helper.eq(0).width( column_width );
684 - tp.columns.move.$placeholder = tp.columns.move.$rows.find( '.move-placeholder' );
685 - tp.columns.move.$placeholder.find( 'div' ).width( column_width );
686 - },
687 - change: function( event, ui ) {
688 - tp.columns.move.target_idx = $( ui.placeholder ).index();
689 -
690 - if ( ( tp.columns.move.target_idx - tp.columns.move.source_idx ) === 1 ) {
691 - tp.columns.move.target_idx += 1;
692 - } else {
693 - if ( tp.columns.move.target_idx === tp.columns.move.source_idx ) {
694 - tp.columns.move.target_idx -= 1;
695 - }
696 - }
697 -
698 - tp.columns.move.$placeholder.each( function() {
699 - tp.columns.move.$cell = $(this);
700 - tp.columns.move.$cell.insertBefore( tp.columns.move.$cell.parent().children().eq( tp.columns.move.target_idx ) );
701 - } );
702 -
703 - if ( tp.columns.move.target_idx > tp.columns.move.source_idx ) {
704 - tp.columns.move.target_idx -= 1;
705 - }
706 -
707 - tp.columns.move.source_idx = tp.columns.move.target_idx;
708 - },
709 - sort: function( event, ui ) {
710 - tp.columns.move.$helper.css( 'left', ui.position.left );
711 - },
712 - stop: function( /* event, ui */ ) {
713 - tp.columns.move.$helper.remove();
714 - tp.columns.move.$cells
715 - .each( function() {
716 - tp.columns.move.$cell = $(this);
717 - tp.columns.move.$cell.insertBefore( tp.columns.move.$cell.parent().find( '.move-placeholder' ) );
718 - } )
719 - .show();
720 - tp.columns.move.$placeholder.remove();
721 -
722 - tp.columns.move.source_idx = tp.columns.move.target_idx = -1;
723 - tp.columns.move.$rows = tp.columns.move.$row_children = tp.columns.move.$cell = tp.columns.move.$cells = tp.columns.move.$placeholder = tp.columns.move.$helper = null;
724 -
725 - tp.reindex();
726 - }
727 - },
728 - number_to_letter: function( number ) {
729 - var column = '';
730 - while ( number > 0 ) {
731 - column = String.fromCharCode( 65 + ( ( number-1) % 26 ) ) + column;
732 - number = Math.floor( (number-1) / 26 );
733 - }
734 - return column;
735 - }/*,
736 - letter_to_number: function( column ) {
737 - column = column.toUpperCase();
738 - var count = column.length,
739 - number = 0,
740 - i;
741 - for ( i = 0; i < count; i++ ) {
742 - number += ( column.charCodeAt( count-1-i ) - 64 ) * Math.pow( 26, i );
743 - }
744 - return number;
745 - }*/
746 - };
747 -
748 - tp.cells = {
749 - $focus: $( null ),
750 - $textarea: null,
751 - autogrow: function( /* event */ ) {
752 - tp.cells.$focus.removeClass( 'focus' );
753 - tp.cells.$focus = $(this).closest( 'tr' ).addClass( 'focus' );
754 - },
755 - advanced_editor: {
756 - prompt_shown: false,
757 - keyopen: function( event ) {
758 - if ( ! event.shiftKey ) {
759 - return;
760 - }
761 -
762 - var $advanced_editor = $id( 'advanced-editor-content' );
763 - tp.cells.$textarea = $(this).blur();
764 - $advanced_editor.val( tp.cells.$textarea.val() );
765 - $id( 'advanced-editor' ).wpdialog( 'open' );
766 - $advanced_editor.get(0).selectionStart = $advanced_editor.get(0).selectionEnd = $advanced_editor.val().length;
767 - $advanced_editor.focus();
768 - },
769 - buttonopen: function() {
770 - if ( ! tp.cells.advanced_editor.prompt_shown ) {
771 - if ( ! confirm( tablepress_strings.advanced_editor_open ) ) {
772 - return;
773 - }
774 - }
775 -
776 - tp.cells.advanced_editor.prompt_shown = true;
777 - $id( 'edit-form-body' ).one( 'click', 'textarea', function() {
778 - var $advanced_editor = $id( 'advanced-editor-content' );
779 - tp.cells.$textarea = $(this).blur();
780 - $advanced_editor.val( tp.cells.$textarea.val() );
781 - $id( 'advanced-editor' ).wpdialog( 'open' );
782 - $advanced_editor.get(0).selectionStart = $advanced_editor.get(0).selectionEnd = $advanced_editor.val().length;
783 - $advanced_editor.focus();
784 - } );
785 - },
786 - save: function() {
787 - var $ve_content = $id( 'advanced-editor-content' ).blur().val();
788 - if ( tp.cells.$textarea.val() !== $ve_content ) {
789 - tp.cells.$textarea.val( $ve_content );
790 - // position cursor at the end
791 - tp.cells.$textarea.get(0).selectionStart = tp.cells.$textarea.get(0).selectionEnd = tp.cells.$textarea.val().length;
792 - tp.table.set_table_changed();
793 - }
794 - tp.cells.$textarea.focus();
795 - tp.cells.advanced_editor.close();
796 - },
797 - close: function() {
798 - $id( 'advanced-editor' ).wpdialog( 'close' );
799 - return false;
800 - }
801 - },
802 - checkboxes: {
803 - last_clicked: { '#edit-form-body' : false, '#edit-form-foot' : false },
804 - multi_select: function ( event ) {
805 - if ( 'undefined' === event.shiftKey ) {
806 - return true;
807 - }
808 -
809 - if ( event.shiftKey ) {
810 - if ( ! tp.cells.checkboxes.last_clicked[ event.data.parent ] ) {
811 - return true;
812 - }
813 -
814 - var $checkboxes = $( event.data.parent ).find( ':checkbox' ),
815 - first_cb = $checkboxes.index( tp.cells.checkboxes.last_clicked[ event.data.parent ] ),
816 - last_cb = $checkboxes.index( this );
817 - if ( first_cb !== last_cb ) {
818 - $checkboxes.slice( Math.min( first_cb, last_cb ), Math.max( first_cb, last_cb ) ).prop( 'checked', $(this).prop( 'checked' ) );
819 - }
820 - }
821 - tp.cells.checkboxes.last_clicked[ event.data.parent ] = this;
822 - return true;
823 - }
824 - }
825 - };
826 -
827 - tp.content = {
828 - link: {
829 - prompt_shown: false,
830 - add: function( /* event */ ) {
831 - if ( ! tp.content.link.prompt_shown ) {
832 - if ( ! confirm( tablepress_strings.link_add ) ) {
833 - return;
834 - }
835 - }
836 -
837 - tp.content.link.prompt_shown = true;
838 - // mousedown instead of click to allow selection of text
839 - // mousedown will set the desired target textarea, and mouseup anywhere will show the link box
840 - // other approaches can lead to the wrong textarea being selected
841 - $id( 'edit-form-body' ).one( 'mousedown', 'textarea', function() {
842 - var editor_id = this.id;
843 - $( document ).one( 'mouseup', function() {
844 - if ( typeof wpLink !== 'undefined' ) {
845 - wpLink.open( editor_id );
846 - tp.table.set_table_changed();
847 - }
848 - } );
849 - } );
850 - }
851 - },
852 - image: {
853 - prompt_shown: false,
854 - add: function( /* event */ ) {
855 - if ( ! tp.content.image.prompt_shown ) {
856 - if ( ! confirm( tablepress_strings.image_add ) ) {
857 - return;
858 - }
859 - }
860 -
861 - tp.content.image.prompt_shown = true;
862 - $id( 'edit-form-body' ).one( 'click', 'textarea', function() {
863 - var editor = this.id,
864 - options = {
865 - frame: 'post',
866 - state: 'insert',
867 - title: wp.media.view.l10n.addMedia,
868 - multiple: true
869 - };
870 -
871 - // Move caret to the end, to prevent inserting right between existing text, as that's ugly in small cells (though possible in the Advanced Editor and Insert Link dialog).
872 - this.selectionStart = this.selectionEnd = this.value.length;
873 -
874 - // Remove focus from the textarea to prevent Opera from showing the outline of the textarea above the modal.
875 - // See: WP Core #22445
876 - $(this).blur();
877 -
878 - wp.media.editor.open( editor, options );
879 - tp.table.set_table_changed();
880 - } );
881 - }
882 - },
883 - span: {
884 - prompt_shown: false,
885 - add: function( span ) {
886 - var span_add_msg = ( '#rowspan#' === span ) ? tablepress_strings.rowspan_add : tablepress_strings.colspan_add;
887 -
888 - // init object, due to string keys
889 - if ( false === tp.content.span.prompt_shown ) {
890 - tp.content.span.prompt_shown = {};
891 - tp.content.span.prompt_shown['#rowspan#'] = tp.content.span.prompt_shown['#colspan#'] = false;
892 - }
893 -
894 - // Automatically deactivate DataTables, if cells are combined
895 - if ( $id( 'option-use-datatables' ).prop( 'checked' ) ) {
896 - if ( confirm( tablepress_strings.span_add_datatables_warning ) ) {
897 - $id( 'option-use-datatables' ).prop( 'checked', false ).change();
898 - } else {
899 - return;
900 - }
901 - }
902 -
903 - if ( ! tp.content.span.prompt_shown[ span ] ) {
904 - if ( ! confirm( span_add_msg ) ) {
905 - return;
906 - }
907 - }
908 -
909 - tp.content.span.prompt_shown[ span ] = true;
910 - $id( 'edit-form-body' ).one( 'click', 'textarea', function() {
911 - var $textarea = $(this),
912 - col_idx = $textarea.parent().index(),
913 - row_idx = $textarea.closest( 'tr' ).index();
914 - if ( '#rowspan#' === span ) {
915 - if ( 0 === row_idx ) {
916 - alert( tablepress_strings.no_rowspan_first_row );
917 - return;
918 - }
919 - if ( tp.table.head && 1 === row_idx ) {
920 - alert( tablepress_strings.no_rowspan_table_head );
921 - return;
922 - }
923 - if ( tp.table.foot && ( tp.table.rows - 1 ) === row_idx ) {
924 - alert( tablepress_strings.no_rowspan_table_foot );
925 - return;
926 - }
927 - } else if ( ( '#colspan#' === span ) && ( tp.table.no_data_columns_pre === col_idx ) ) {
928 - alert( tablepress_strings.no_colspan_first_col );
929 - return;
930 - }
931 - $textarea.val( span );
932 - tp.table.set_table_changed();
933 - } );
934 - }
935 - }
936 - };
937 -
938 - tp.check = {
939 - table_id: function( event ) {
940 - if ( ( 37 === event.which ) || ( 39 === event.which ) ) {
941 - return;
942 - }
943 - var $input = $(this);
944 - $input.val( $input.val().replace( /[^0-9a-zA-Z-_]/g, '' ) );
945 - },
946 - changes_saved: function() {
947 - if ( tp.made_changes ) {
948 - return tablepress_strings.unsaved_changes_unload;
949 - }
950 - }
951 - };
952 -
953 - tp.reindex = function() {
954 - var $row,
955 - $rows = $id( 'edit-form-body' ).children(),
956 - $cell, known_references = {};
957 -
958 - tp.table.rows = $rows.length;
959 - if ( tp.table.rows > 0 ) {
960 - tp.table.columns = $rows.first().children().length - tp.table.no_data_columns_pre - tp.table.no_data_columns_post;
961 - } else {
962 - tp.table.columns = 0;
963 - }
964 -
965 - $rows
966 - .each( function( row_idx, row ) {
967 - $row = $( row );
968 - $row.find( 'textarea' )
969 - .val( function( column_idx, value ) {
970 - // If the cell is not a formula, there's nothing to do here
971 - if ( ( '' === value ) || ( '=' !== value.charAt(0) ) ) {
972 - return value;
973 - }
974 -
975 - return value.replace( /([A-Z]+[0-9]+)(?::([A-Z]+[0-9]+))?/g, function( full_match, first_cell, second_cell ) {
976 - // first_cell must always exist, while second_cell only exists in ranges like A4:B7
977 - // we will use full_match as our result variable, so that we don't need an extra one
978 -
979 - if ( ! known_references.hasOwnProperty( first_cell ) ) {
980 - $cell = $id( 'cell-' + first_cell );
981 - if ( $cell.length ) {
982 - known_references[ first_cell ] = tp.columns.number_to_letter( $cell.parent().index() - tp.table.no_data_columns_pre + 1 ) + ( $cell.closest( 'tr' ).index() + 1 );
983 - } else {
984 - known_references[ first_cell ] = first_cell;
985 - }
986 - }
987 - full_match = known_references[ first_cell ];
988 -
989 - if ( ( 'undefined' !== typeof second_cell ) && ( '' !== second_cell ) ) { // Chrome and IE pass an undefined variable, while Firefox passes an empty string
990 - if ( ! known_references.hasOwnProperty( second_cell ) ) {
991 - $cell = $id( 'cell-' + second_cell );
992 - if ( $cell.length ) {
993 - known_references[ second_cell ] = tp.columns.number_to_letter( $cell.parent().index() - tp.table.no_data_columns_pre + 1 ) + ( $cell.closest( 'tr' ).index() + 1 );
994 - } else {
995 - known_references[ second_cell ] = second_cell;
996 - }
997 - }
998 - full_match += ':' + known_references[ second_cell ];
999 - }
1000 -
1001 - return full_match;
1002 - } );
1003 - } )
1004 - .attr( 'name', function( column_idx /*, old_name */ ) {
1005 - return 'table[data][' + row_idx + '][' + column_idx + ']';
1006 - } );
1007 -
1008 - $row.find( '.move-handle' ).html( row_idx + 1 );
1009 - } )
1010 - .each( function( row_idx, row ) { // need a second loop here to not break logic in previous loop, that queries textareas by their old ID
1011 - $( row ).find( 'textarea' ).attr( 'id', function( column_idx /*, old_id */ ) {
1012 - return 'cell-' + tp.columns.number_to_letter( column_idx + 1 ) + ( row_idx + 1 );
1013 - } );
1014 - });
1015 - $id( 'edit-form-head' ).find( '.move-handle' )
1016 - .html( function( idx ) { return tp.columns.number_to_letter( idx + 1 ); } );
1017 -
1018 - $id( 'number-rows' ).val( tp.table.rows );
1019 - $id( 'number-columns' ).val( tp.table.columns );
1020 -
1021 - tp.table.set_table_changed();
1022 - };
1023 -
1024 - tp.save_changes = {
1025 - trigger: function( event ) {
1026 - // validation checks
1027 - if ( $id( 'option-datatables-paginate' ).prop( 'checked' ) && ! ( /^[1-9][0-9]{0,4}$/ ).test( $id( 'option-datatables-paginate_entries' ).val() ) ) {
1028 - alert( tablepress_strings.num_pagination_entries_invalid );
1029 - $id( 'option-datatables-paginate_entries' ).focus().select();
1030 - return;
1031 - }
1032 - if ( ( /[^A-Za-z0-9- _]/ ).test( $id( 'option-extra-css-classes' ).val() ) ) {
1033 - alert( tablepress_strings.extra_css_classes_invalid );
1034 - $id( 'option-extra-css-classes' ).focus().select();
1035 - return;
1036 - }
1037 -
1038 - if ( event.shiftKey ) {
1039 - tp.made_changes = false; // to prevent onunload warning
1040 - $id( 'tablepress-page' ).find( 'form' ).submit();
1041 - return;
1042 - }
1043 -
1044 - $(this).closest( 'p' ).append( '<span class="animation-saving spinner is-active" title="' + tablepress_strings.saving_changes + '"/>' );
1045 - $( '.save-changes-button' ).prop( 'disabled', true );
1046 - $( 'body' ).addClass( 'wait' );
1047 -
1048 - $.ajax({
1049 - 'type': 'POST',
1050 - 'url': ajaxurl,
1051 - 'data': tp.table.prepare_ajax_request( 'tablepress_save_table', '#nonce-edit-table' ),
1052 - 'success': tp.save_changes.ajax_success,
1053 - 'error': tp.save_changes.ajax_error,
1054 - 'dataType': 'json'
1055 - } );
1056 - },
1057 - ajax_success: function( data, status /*, jqXHR */ ) {
1058 - if ( ( 'undefined' === typeof status ) || ( 'success' !== status ) ) {
1059 - tp.save_changes.error( 'AJAX call successful, but unclear status. Try again while holding down the &#8220;Shift&#8221; key.' );
1060 - } else if ( ( 'undefined' === typeof data ) || ( null === data ) || ( '-1' === data ) || ( 'undefined' === typeof data.success ) ) {
1061 - tp.save_changes.error( 'AJAX call successful, but unclear data. Try again while holding down the &#8220;Shift&#8221; key.' );
1062 - } else if ( true !== data.success ) {
1063 - var debug_html = '';
1064 - // Print debug information, if we are in debug mode
1065 - if ( ( 'undefined' !== typeof data.error_details ) && ( tablepress_options.print_debug_output ) ) {
1066 - debug_html = '</p><p>These errors were encountered:</p><pre>' + data.error_details + '</pre><p>'; // Some HTML magic because this is wrapped in <p> when printed
1067 - }
1068 - tp.save_changes.error( 'AJAX call successful, internal saving process failed. Try again while holding down the &#8220;Shift&#8221; key.' + debug_html );
1069 - } else {
1070 - tp.save_changes.success( data );
1071 - }
1072 - },
1073 - ajax_error: function( jqXHR, status, error_thrown ) {
1074 - tp.save_changes.error( 'AJAX call failed: ' + status + ' - ' + error_thrown + '. Try again while holding down the &#8220;Shift&#8221; key.' );
1075 - },
1076 - success: function( data ) {
1077 - // saving was successful, so the original ID has changed to the (maybe) new ID -> we need to adjust all occurrences
1078 - if ( tp.table.id !== data.table_id ) {
1079 - // update URL (for HTML5 browsers only), but only if ID really changed, to not get dummy entries in the browser history
1080 - if ( ( 'pushState' in window.history ) && null !== window.history.pushState ) {
1081 - window.history.pushState( '', '', window.location.href.replace( /table_id=[0-9a-zA-Z-_]+/gi, 'table_id=' + data.table_id ) );
1082 - }
1083 - }
1084 - // update CSS class for data field form
1085 - $id( 'edit-form' ).removeClass( 'tablepress-edit-screen-id-' + tp.table.id ).addClass( 'tablepress-edit-screen-id-' + data.table_id );
1086 - // update table ID in input fields (type text and hidden)
1087 - tp.table.id = tp.table.new_id = data.table_id;
1088 - $id( 'table-id' ).val( tp.table.id );
1089 - $id( 'table-new-id' ).val( tp.table.new_id );
1090 - // update the Shortcode text field
1091 - $( '.table-shortcode' ).val( '[' + tablepress_options.shortcode + ' id=' + tp.table.new_id + ' /]' );
1092 - // update the nonces
1093 - $id( 'nonce-edit-table' ).val( data.new_edit_nonce );
1094 - $id( 'nonce-preview-table' ).val( data.new_preview_nonce );
1095 - // update URLs in Preview links
1096 - var $show_preview_buttons = $( '.show-preview-button' );
1097 - if ( $show_preview_buttons.length ) { // check necessary, because Preview button might not be visible
1098 - $show_preview_buttons.attr( 'href',
1099 - $show_preview_buttons.first().attr( 'href' )
1100 - .replace( /item=[a-zA-Z0-9_-]+/g, 'item=' + data.table_id )
1101 - .replace( /&_wpnonce=[a-z0-9]+/ig, '&_wpnonce=' + data.new_preview_nonce )
1102 - );
1103 - }
1104 - // update last modified date and user nickname
1105 - $id( 'last-modified' ).text( data.last_modified );
1106 - $id( 'last-editor' ).text( data.last_editor );
1107 - tp.table.unset_table_changed();
1108 - tp.save_changes.after_saving_dialog( 'success', tablepress_strings[ data.message ] );
1109 - },
1110 - error: function( message ) {
1111 - tp.save_changes.after_saving_dialog( 'error', message );
1112 - },
1113 - after_saving_dialog: function( type, message ) {
1114 - if ( 'undefined' === typeof message ) {
1115 - message = '';
1116 - } else {
1117 - message = ': ' + message;
1118 - }
1119 - var delay,
1120 - div_class = 'save-changes-' + type;
1121 - if ( 'success' === type ) {
1122 - div_class += ' notice notice-success';
1123 - delay = 3000;
1124 - } else {
1125 - div_class += ' notice notice-error';
1126 - delay = 6000;
1127 - }
1128 - $( '.animation-saving' ).closest( 'p' )
1129 - .after( '<div class="ajax-alert ' + div_class + '"><p>' + tablepress_strings['save_changes_' + type] + message + '</p></div>' );
1130 - $( '.animation-saving' ).remove();
1131 - $( '.save-changes-' + type ).delay( delay ).fadeOut( 2000, function() { $(this).remove(); } );
1132 - $( '.save-changes-button' ).prop( 'disabled', false );
1133 - $( 'body' ).removeClass( 'wait' );
1134 - }
1135 - };
1136 -
1137 - tp.init = function() {
1138 - var callbacks = {
1139 - 'click': {
1140 - '#rows-insert': tp.rows.insert,
1141 - '#columns-insert': tp.columns.insert,
1142 - '#rows-duplicate': tp.rows.duplicate,
1143 - '#columns-duplicate': tp.columns.duplicate,
1144 - '#rows-remove': tp.rows.remove,
1145 - '#columns-remove': tp.columns.remove,
1146 - '#rows-hide': tp.rows.hide,
1147 - '#columns-hide': tp.columns.hide,
1148 - '#rows-unhide': tp.rows.unhide,
1149 - '#columns-unhide': tp.columns.unhide,
1150 - '#rows-append': tp.rows.append,
1151 - '#columns-append': tp.columns.append,
1152 - '#link-add': tp.content.link.add,
1153 - '#image-add': tp.content.image.add,
1154 - '#span-add-rowspan': function() { tp.content.span.add( '#rowspan#' ); },
1155 - '#span-add-colspan': function() { tp.content.span.add( '#colspan#' ); },
1156 - '.show-preview-button': tp.table.preview.trigger,
1157 - '.save-changes-button': tp.save_changes.trigger,
1158 - '.show-help-box': function() {
1159 - $(this).next().wpdialog( {
1160 - title: $(this).attr( 'title' ),
1161 - height: 470,
1162 - width: 320,
1163 - modal: true,
1164 - dialogClass: 'wp-dialog',
1165 - resizable: false
1166 - } );
1167 - }
1168 - },
1169 - 'keyup': {
1170 - '#table-new-id': tp.check.table_id
1171 - },
1172 - 'change': {
1173 - '#option-table-head': tp.table.change_table_head,
1174 - '#option-table-foot': tp.table.change_table_foot,
1175 - '#option-use-datatables': tp.table.change_datatables,
1176 - '#option-datatables-paginate': tp.table.change_datatables_pagination
1177 - },
1178 - 'blur': {
1179 - '#table-new-id': tp.table.change_id // onchange would not recognize changed values from tp.check.table_id
1180 - }
1181 - },
1182 - $table = $id( 'edit-form-body' );
1183 -
1184 - $.each( callbacks, function( event, event_callbacks ) {
1185 - $.each( event_callbacks, function( selector, callback ) {
1186 - $( selector ).on( event, callback );
1187 - } );
1188 - } );
1189 -
1190 - $( window ).on( 'beforeunload', tp.check.changes_saved );
1191 -
1192 - // do this before the next lines, to not trigger set_table_changed()
1193 - $id( 'option-table-head' ).change(); // init changed/disabled states of DataTables JS features checkboxes
1194 - $id( 'option-print-name' ).change( tp.table.change_print_name_description ).change(); // init dropdowns for name and description position
1195 - $id( 'option-print-description' ).change( tp.table.change_print_name_description ).change();
1196 -
1197 - // just once is enough, will be reset after saving
1198 - $table.one( 'change', 'textarea', tp.table.set_table_changed );
1199 - $( '#tablepress_edit-table-information, #tablepress_edit-table-options, #tablepress_edit-datatables-features' ).one( 'change', 'input, textarea, select', tp.table.set_table_changed );
1200 -
1201 - if ( tablepress_options.cells_advanced_editor ) {
1202 - $table.on( 'click', 'textarea', tp.cells.advanced_editor.keyopen );
1203 - $id( 'advanced-editor-open' ).on( 'click', tp.cells.advanced_editor.buttonopen );
1204 - $id( 'advanced-editor-confirm' ).on( 'click', tp.cells.advanced_editor.save );
1205 - $id( 'advanced-editor-cancel' ).on( 'click', tp.cells.advanced_editor.close );
1206 - $id( 'advanced-editor' ).wpdialog( {
1207 - autoOpen: false,
1208 - title: $id( 'advanced-editor-open' ).val(),
1209 - width: 600,
1210 - modal: true,
1211 - dialogClass: 'wp-dialog',
1212 - resizable: false
1213 - } );
1214 - // Fix issue with input fields not being usable (they are immediately losing focus without this) in the wpLink dialog when called through the "Advanced Editor"
1215 - $id( 'wp-link' ).on( 'focus', 'input', function( event ) {
1216 - event.stopPropagation();
1217 - } );
1218 - } else {
1219 - $id( 'advanced-editor-open' ).hide();
1220 - }
1221 -
1222 - // Fix issue with input fields not being usable (they are immediately losing focus without this) in the sidebar of the new Media Manager
1223 - $( 'body' ).on( 'focus', '.media-modal .media-frame-content input, .media-modal .media-frame-content textarea', function( event ) {
1224 - event.stopPropagation();
1225 - } );
1226 -
1227 - if ( tablepress_options.cells_auto_grow ) {
1228 - $table.on( 'focus', 'textarea', tp.cells.autogrow );
1229 - }
1230 -
1231 - $id( 'edit-form-body' ).on( 'click', 'input:checkbox', { parent: '#edit-form-body' }, tp.cells.checkboxes.multi_select );
1232 - $id( 'edit-form-foot' ).on( 'click', 'input:checkbox', { parent: '#edit-form-foot' }, tp.cells.checkboxes.multi_select );
1233 -
1234 - $id( 'edit-form-head' ).on( 'click', '.sort-control', tp.rows.sort );
1235 -
1236 - // on form submit: Enable disabled fields, so that they are transmitted in the POST request
1237 - $id( 'tablepress-page' ).find( 'form' ).on( 'submit', function() {
1238 - $(this).find( '.tablepress-postbox-table' ).find( 'input, select' ).prop( 'disabled', false );
1239 - } );
1240 -
1241 - $table.sortable( {
1242 - axis: 'y',
1243 - containment: $id( 'edit-form' ), // to get better behavior when dragging before/after the first/last row
1244 - forceHelperSize: true, // necessary?
1245 - handle: '.move-handle',
1246 - start: tp.rows.move.start,
1247 - change: tp.rows.move.change,
1248 - stop: tp.rows.move.stop,
1249 - update: tp.reindex
1250 - } ); // disableSelection() prohibits selection of text in textareas via keyboard
1251 -
1252 - $id( 'edit-form-head' ).sortable( {
1253 - axis: 'x',
1254 - items: '.head',
1255 - containment: 'parent',
1256 - forceHelperSize: true, // necessary?
1257 - helper: 'clone',
1258 - handle: '.move-handle',
1259 - start: tp.columns.move.start,
1260 - stop: tp.columns.move.stop,
1261 - change: tp.columns.move.change,
1262 - sort: tp.columns.move.sort
1263 - } ).disableSelection();
1264 - };
1265 -
1266 - // Run TablePress initialization.
1267 - tp.init();
1268 -
1269 -} );
33 +initializeReactComponent(
34 + 'tablepress-edit-screen',
35 + <Screen />,
36 +);