| 1 |
/* global ajaxurl, wsrwjs */ |
| 2 |
const WSRSearchReplace = window.WSRSearchReplace || ( |
| 3 |
function ( document, window, $ ) { |
| 4 |
// jquery-confirm defaults. |
| 5 |
jconfirm.defaults = { |
| 6 |
closeIcon: true, |
| 7 |
closeIconClass: 'close-icon-svg', |
| 8 |
backgroundDismiss: false, |
| 9 |
escapeKey: true, |
| 10 |
animationBounce: 1, |
| 11 |
useBootstrap: false, |
| 12 |
theme: 'modern', |
| 13 |
boxWidth: '400px', |
| 14 |
type: 'blue', |
| 15 |
animateFromElement: false, |
| 16 |
}; |
| 17 |
const app = { |
| 18 |
pages: 0, |
| 19 |
dry_run: true, |
| 20 |
init() { |
| 21 |
app.find_elements(); |
| 22 |
app.init_form(); |
| 23 |
app.init_upsell(); |
| 24 |
}, |
| 25 |
find_elements() { |
| 26 |
app.form = $( '#wsrw-search-replace-form' ); |
| 27 |
app.results = $( '#wsrw-results' ); |
| 28 |
app.progress = $( '#wsrw-progress-bar-replace .wsrw-progress-bar-inner' ); |
| 29 |
app.$table = $( '#wsrw-results-table' ); |
| 30 |
app.$start_button = $( '#wsrw-start-replace' ); |
| 31 |
app.$do_button = $( '#wsrw-perform-search-replace' ); |
| 32 |
app.$text_display = $( '#wsrw-progress-text-replace' ); |
| 33 |
app.$modal = $( '#wsrw-search-replace-progress' ); |
| 34 |
app.$undo_button = $( document.getElementById( 'wsrw-results-undo-button' ) ); |
| 35 |
}, |
| 36 |
init_form() { |
| 37 |
app.form.on( |
| 38 |
'submit', |
| 39 |
function ( e ) { |
| 40 |
e.preventDefault(); |
| 41 |
WSRSpinner.show_button_spinner( app.$start_button ); |
| 42 |
app.start_search_replace(); |
| 43 |
} |
| 44 |
); |
| 45 |
app.$do_button.on( |
| 46 |
'click', |
| 47 |
function ( e ) { |
| 48 |
e.preventDefault(); |
| 49 |
// Jconfirm the user before proceeding. |
| 50 |
$.confirm( { |
| 51 |
title: wsrwjs.sr_confirm_title, |
| 52 |
content: wsrwjs.sr_confirm_message, |
| 53 |
type: 'blue', |
| 54 |
icon: 'fa fa-exclamation-circle', |
| 55 |
animateFromElement: false, |
| 56 |
buttons: { |
| 57 |
confirm: { |
| 58 |
text: wsrwjs.yes, |
| 59 |
btnClass: 'btn-confirm', |
| 60 |
keys: ['enter'], |
| 61 |
}, |
| 62 |
cancel: { |
| 63 |
text: wsrwjs.no, |
| 64 |
btnClass: 'btn-cancel', |
| 65 |
keys: ['esc'], |
| 66 |
}, |
| 67 |
}, |
| 68 |
onAction: function ( action ) { |
| 69 |
if ( action === 'confirm' ) { |
| 70 |
app.$do_button.prop( 'disabled', true ); |
| 71 |
app.start_search_replace( false ); |
| 72 |
} |
| 73 |
}, |
| 74 |
} ); |
| 75 |
|
| 76 |
} |
| 77 |
); |
| 78 |
}, |
| 79 |
start_search_replace( dry_run = true ) { |
| 80 |
app.dry_run = dry_run; |
| 81 |
const search = $( '#wsrw-search' ).val(); |
| 82 |
const data = { |
| 83 |
action: 'wsrw_start_search_replace', |
| 84 |
nonce: wsrwjs.nonce, |
| 85 |
search: search, |
| 86 |
replace: $( '#wsrw-replace' ).val(), |
| 87 |
}; |
| 88 |
// If search term is empty return and show error. |
| 89 |
if ( search === '' ) { |
| 90 |
WSRSpinner.hide_button_spinner( app.$start_button ); |
| 91 |
$.alert( { |
| 92 |
title: wsrwjs.no_search_term_title, |
| 93 |
content: wsrwjs.no_search_term_message, |
| 94 |
type: 'blue', |
| 95 |
icon: 'fa fa-exclamation-circle', |
| 96 |
animateFromElement: false, |
| 97 |
buttons: { |
| 98 |
confirm: { |
| 99 |
text: wsrwjs.ok, |
| 100 |
btnClass: 'btn-confirm', |
| 101 |
keys: ['enter'], |
| 102 |
}, |
| 103 |
}, |
| 104 |
} ); |
| 105 |
return; |
| 106 |
} |
| 107 |
if ( $( '#wsrw-case-insensitive' ).is( ':checked' ) ) { |
| 108 |
data.case_insensitive = 1; |
| 109 |
} |
| 110 |
if ( !dry_run ) { |
| 111 |
data.dry_run = 0; |
| 112 |
} |
| 113 |
// Let's get the tables value from all the checkboxes with the name of tables[]. |
| 114 |
const tables = $( 'input[name="tables[]"]:checked' ).map( |
| 115 |
function () { |
| 116 |
return $( this ).val(); |
| 117 |
} |
| 118 |
).get(); |
| 119 |
// If no tables selected, return and show error. |
| 120 |
if ( tables.length === 0 ) { |
| 121 |
WSRSpinner.hide_button_spinner( app.$start_button ); |
| 122 |
$.alert( { |
| 123 |
title: wsrwjs.no_table_selected_title, |
| 124 |
content: wsrwjs.no_table_selected_message, |
| 125 |
type: 'blue', |
| 126 |
icon: 'fa fa-exclamation-circle', |
| 127 |
animateFromElement: false, |
| 128 |
buttons: { |
| 129 |
confirm: { |
| 130 |
text: wsrwjs.ok, |
| 131 |
btnClass: 'btn-confirm', |
| 132 |
keys: ['enter'], |
| 133 |
}, |
| 134 |
}, |
| 135 |
} ); |
| 136 |
return; |
| 137 |
} |
| 138 |
|
| 139 |
data['tables[]'] = tables; |
| 140 |
|
| 141 |
$( document ).trigger( 'wsr_before_start_search_replace', [data] ); |
| 142 |
|
| 143 |
app.$do_button.prop( 'disabled', true ); |
| 144 |
$.ajax( |
| 145 |
{ |
| 146 |
url: ajaxurl, |
| 147 |
type: 'POST', |
| 148 |
data: data, |
| 149 |
beforeSend: function () { |
| 150 |
app.form.find( 'input, button' ).prop( 'disabled', true ); |
| 151 |
}, |
| 152 |
success: function ( response ) { |
| 153 |
// Let's show the modal at this stage. |
| 154 |
app.$undo_button.hide(); |
| 155 |
$( 'body' ).addClass( 'wsrw-show-modal wsrw-no-close' ); |
| 156 |
app.fit_results(); |
| 157 |
WSRSpinner.hide_button_spinner( app.$start_button ); |
| 158 |
app.form.find( 'input, button' ).prop( 'disabled', false ); |
| 159 |
app.pages = response.data.pages; |
| 160 |
// Remove all the rows from the table except the first one. |
| 161 |
app.$table.find( 'tr:gt(0)' ).remove(); |
| 162 |
app.do_search_replace( response.data ); |
| 163 |
}, |
| 164 |
error: function ( response ) { |
| 165 |
app.form.find( 'input, button' ).prop( 'disabled', false ); |
| 166 |
app.show_results( response ); |
| 167 |
} |
| 168 |
} |
| 169 |
); |
| 170 |
}, |
| 171 |
do_search_replace() { |
| 172 |
const data = { |
| 173 |
action: 'wsrw_do_search_replace', |
| 174 |
nonce: wsrwjs.nonce, |
| 175 |
}; |
| 176 |
$.ajax( |
| 177 |
{ |
| 178 |
url: ajaxurl, |
| 179 |
type: 'POST', |
| 180 |
data: data, |
| 181 |
success: function ( response ) { |
| 182 |
app.show_results( response ); |
| 183 |
// Let's calculate the progress bar width. |
| 184 |
const progress = ( |
| 185 |
response.data.page / app.pages |
| 186 |
) * 100; |
| 187 |
app.progress.css( 'width', progress + '%' ); |
| 188 |
if ( response.data.page < response.data.pages ) { |
| 189 |
app.do_search_replace(); |
| 190 |
} else { |
| 191 |
app.show_finish_message(); |
| 192 |
} |
| 193 |
}, |
| 194 |
error: function ( response ) { |
| 195 |
app.show_results( response ); |
| 196 |
} |
| 197 |
} |
| 198 |
); |
| 199 |
}, |
| 200 |
show_results( response ) { |
| 201 |
if ( response.data.updated_data && response.data.updated_data.length > 0 ) { |
| 202 |
// Loop through the updated data and show it. |
| 203 |
$.each( |
| 204 |
response.data.updated_data, |
| 205 |
function ( key, value ) { |
| 206 |
// The value here has the format of an object with the keys: table, column, row, old, new. |
| 207 |
app.$table.append( |
| 208 |
$( |
| 209 |
'<tr data-table="' + value.table + '" data-row="' + value.row + '" data-column="' + value.column + '">' + |
| 210 |
'<td><span class="wsrw-check-row-input"><input type="checkbox" data-table="' + value.table + '" data-row="' + value.row + '" data-column="' + value.column + '" class="wsrw-check-row" /></span></td>' + |
| 211 |
'<td>' + value.table + '</td>' + |
| 212 |
'<td>' + value.column + '</td>' + |
| 213 |
'<td><button class="wsrw-row-info wsrw-button wsrw-button-text" type="button">' + value.row + '</button></td>' + |
| 214 |
'<td><pre>' + value.old + '</pre></td>' + |
| 215 |
'<td><pre>' + value.new + '</pre></td>' + |
| 216 |
'</tr>' |
| 217 |
) |
| 218 |
); |
| 219 |
} |
| 220 |
); |
| 221 |
} |
| 222 |
|
| 223 |
if ( response.data.message ) { |
| 224 |
app.display_text( response.data.message ); |
| 225 |
} |
| 226 |
}, |
| 227 |
show_finish_message() { |
| 228 |
// If no rows were added to the table, show a message. |
| 229 |
if ( app.$table.find( 'tr' ).length === 1 ) { |
| 230 |
app.display_text( wsrwjs.no_results_found ); |
| 231 |
} else { |
| 232 |
app.display_text( wsrwjs.finished ); |
| 233 |
} |
| 234 |
// Remove the no-close class so the modal can be closed. |
| 235 |
$( 'body' ).removeClass( 'wsrw-no-close' ); |
| 236 |
if ( !app.dry_run ) { |
| 237 |
app.$undo_button.show(); |
| 238 |
} else { |
| 239 |
app.$do_button.prop( 'disabled', false ); |
| 240 |
} |
| 241 |
|
| 242 |
// Trigger event so we can clear data. |
| 243 |
$( document ).trigger( 'wsr_search_replace_finished' ); |
| 244 |
}, |
| 245 |
display_text( text ) { |
| 246 |
app.$text_display.text( text ); |
| 247 |
}, |
| 248 |
fit_results() { |
| 249 |
// Let's fit the results box to the modal height. |
| 250 |
const modal_height = app.$modal.height(); |
| 251 |
let other_height = 0; |
| 252 |
app.$modal.children().each( |
| 253 |
function () { |
| 254 |
if ( !$( this ).is( app.results ) ) { |
| 255 |
const childHeight = $( this ).outerHeight( true ); |
| 256 |
other_height += childHeight; |
| 257 |
} |
| 258 |
} |
| 259 |
); |
| 260 |
app.results.height( modal_height - other_height ); |
| 261 |
}, |
| 262 |
init_upsell() { |
| 263 |
// If the body class is "wsrw-not-licensed" we show upsell message when .wsrw-check-row is clicked. |
| 264 |
if ( !$( 'body' ).hasClass( 'wsrw-not-licensed' ) ) { |
| 265 |
return; |
| 266 |
} |
| 267 |
app.$table.on( |
| 268 |
'click', |
| 269 |
'.wsrw-check-row-input', |
| 270 |
function ( e ) { |
| 271 |
e.preventDefault(); |
| 272 |
app.show_upsell( wsrwjs.check_row_title, wsrwjs.check_row_content, wsrwjs.check_row_url ); |
| 273 |
} |
| 274 |
); |
| 275 |
app.$table.on( |
| 276 |
'click', |
| 277 |
'.wsrw-row-info', |
| 278 |
function ( e ) { |
| 279 |
e.preventDefault(); |
| 280 |
e.stopPropagation(); |
| 281 |
app.show_upsell( wsrwjs.row_info_title, wsrwjs.row_info_content, wsrwjs.row_info_url ); |
| 282 |
} |
| 283 |
); |
| 284 |
}, |
| 285 |
show_upsell( title, content, button_url, button_text ) { |
| 286 |
// If button_text is not set let's default it to wsrwjs.upgrade_to_pro. |
| 287 |
button_text = button_text || wsrwjs.upgrade_to_pro; |
| 288 |
$.alert( { |
| 289 |
title: title, |
| 290 |
content: content, |
| 291 |
type: 'blue', |
| 292 |
animateFromElement: false, |
| 293 |
backgroundDismiss: true, |
| 294 |
boxWidth: '550px', |
| 295 |
draggable: false, |
| 296 |
buttons: { |
| 297 |
confirm: { |
| 298 |
text: button_text, |
| 299 |
btnClass: 'wsrw-button wsrw-button-large wsrw-button-orange', |
| 300 |
keys: ['enter'], |
| 301 |
action: function () { |
| 302 |
// Open in new window wsrwjs.check_row_url. |
| 303 |
window.open( button_url, '_blank' ); |
| 304 |
}, |
| 305 |
}, |
| 306 |
}, |
| 307 |
onOpenBefore() { |
| 308 |
if ( wsrwjs.upgrade_bonus ) { |
| 309 |
this.$btnc.after( '<div class="wsrw-discount-note">' + wsrwjs.upgrade_bonus + '</div>' ); |
| 310 |
this.$body.find( '.jconfirm-content' ).addClass( 'wsrw-lite-upgrade' ); |
| 311 |
} |
| 312 |
this.$icon.html( wsrwjs.lock_icon ); |
| 313 |
}, |
| 314 |
onContentReady() { |
| 315 |
this.$icon.html( wsrwjs.lock_icon ); |
| 316 |
} |
| 317 |
} ); |
| 318 |
} |
| 319 |
}; |
| 320 |
return app; |
| 321 |
}( document, window, jQuery ) |
| 322 |
); |
| 323 |
|
| 324 |
WSRSearchReplace.init(); |