forked from joomla/Component-Builder
Robot
23af2f0b29
Fix the search area layout. Fix the search area code line selection. Fix the input edit button for custom fields. Add the new layout to list fields (GUI UPDATE). Start fixing the field view in Joomla 4. #1096.
957 lines
31 KiB
JavaScript
957 lines
31 KiB
JavaScript
/**
|
|
* @package Joomla.Component.Builder
|
|
*
|
|
* @created 30th April, 2015
|
|
* @author Llewellyn van der Merwe <https://dev.vdm.io>
|
|
* @git Joomla Component Builder <https://git.vdm.dev/joomla/Component-Builder>
|
|
* @copyright Copyright (C) 2015 Vast Development Method. All rights reserved.
|
|
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
|
*/
|
|
|
|
/* JS Document */
|
|
/**
|
|
* JS Function to execute the search
|
|
*/
|
|
const doSearch = async (signal, tables) => {
|
|
try {
|
|
// build form
|
|
const formData = new FormData();
|
|
|
|
// load the result table
|
|
const resultsTable = new DataTable('#search_results_table');
|
|
|
|
// get the search mode
|
|
let typeSearch = modeObject.querySelector('input[type=\'radio\']:checked').value;
|
|
|
|
// set some search values
|
|
let searchValue = searchObject.value;
|
|
let replaceValue = replaceObject.value;
|
|
let matchValue = matchObject.checked ? 1 : 0;
|
|
let wholeValue = wholeObject.checked ? 1 : 0;
|
|
let regexValue = regexObject.checked ? 1 : 0;
|
|
|
|
// add the form data
|
|
formData.append('table_name', '');
|
|
formData.append('type_search', typeSearch);
|
|
formData.append('search_value', searchValue);
|
|
formData.append('replace_value', replaceValue);
|
|
formData.append('match_case', matchValue);
|
|
formData.append('whole_word', wholeValue);
|
|
formData.append('regex_search', regexValue);
|
|
|
|
// update the URL
|
|
updateUrlQuery(searchValue, replaceValue, matchValue, wholeValue, regexValue, typeSearch);
|
|
|
|
let abort_this_search_values = false;
|
|
|
|
// reset the progress bar
|
|
searchProgressBarObject.style.width = '0%';
|
|
searchProgressBarObject.innerHTML = '0%';
|
|
|
|
// show the progress bar
|
|
searchProgressObject.style.display = '';
|
|
|
|
// hidde the search button
|
|
startSearchButton.style.display = 'none';
|
|
|
|
// show the stop search button
|
|
stopSearchButton.style.display = '';
|
|
|
|
// start search timer
|
|
startSearchTimer();
|
|
|
|
// reset our global counters
|
|
fieldCount = 0;
|
|
lineCount = 0;
|
|
|
|
// set our local counters
|
|
let total = 0;
|
|
let progress = tables.length;
|
|
let index;
|
|
|
|
for (index = 0; index < progress; index++) {
|
|
|
|
let tableName = tables[index];
|
|
|
|
// add the table name
|
|
formData.set('table_name', tableName);
|
|
|
|
let options = {
|
|
signal: signal,
|
|
method: 'POST', // *GET, POST, PUT, DELETE, etc.
|
|
body: formData
|
|
}
|
|
|
|
if (abort_this_search_values) {
|
|
break;
|
|
}
|
|
const response = await fetch(UrlAjax + 'doSearch', options).then(response => {
|
|
total++;
|
|
// return the json response
|
|
if (response.ok) {
|
|
return response.json();
|
|
} else {
|
|
UIkit.notify(Joomla.JText._('COM_COMPONENTBUILDER_THE_SEARCH_PROCESS_HAD_AN_ERROR_WITH_TABLE') + ' ' + tableName, {pos:'top-right', status:'danger'});
|
|
}
|
|
}).then((data) => {
|
|
if (typeof data.success !== 'undefined') {
|
|
UIkit.notify(data.success, {pos:'top-right', timeout : 200, status:'success'});
|
|
//} else if (typeof data.not_found !== 'undefined') {
|
|
// UIkit.notify(data.not_found, {pos:'bottom-right', timeout : 200});
|
|
}
|
|
if (typeof data.items !== 'undefined') {
|
|
addTableItems(resultsTable, data.items, typeSearch);
|
|
}
|
|
if (typeof data.fields_count !== 'undefined') {
|
|
fieldCount += data.fields_count;
|
|
}
|
|
if (typeof data.line_count !== 'undefined') {
|
|
lineCount += data.line_count;
|
|
}
|
|
// calculate the percent
|
|
let percent = 100.0 * (total / progress);
|
|
// update the progress bar
|
|
searchProgressObject.style.display = ''; // always make sure it still shows...
|
|
searchProgressBarObject.style.width = percent.toFixed(2) + '%';
|
|
searchProgressBarObject.innerHTML = percent.toFixed(2) + '%';
|
|
// when complete hide the progress bar
|
|
if (progress == total) {
|
|
let total_field_line = ' ' + fieldCount + ' ' + Joomla.JText._('COM_COMPONENTBUILDER_FIELDS_THAT_HAD') + ' ' + lineCount + ' ' + Joomla.JText._('COM_COMPONENTBUILDER_LINES') + ' ';
|
|
if (progress == 1) {
|
|
searchProgressBarObject.innerHTML = Joomla.JText._('COM_COMPONENTBUILDER_SEARCHING') + ' ' + tableName + total_field_line + Joomla.JText._('COM_COMPONENTBUILDER_AND_FINISHED_THE_SEARCH_IN') + ' ' + getSearchLenght() + ' ' + Joomla.JText._('COM_COMPONENTBUILDER_SECONDS');
|
|
} else {
|
|
searchProgressBarObject.innerHTML = Joomla.JText._('COM_COMPONENTBUILDER_SEARCHING') + ' ' + progress + ' ' + Joomla.JText._('COM_COMPONENTBUILDER_TABLES_WITH') + total_field_line + Joomla.JText._('COM_COMPONENTBUILDER_AND_FINISHED_THE_SEARCH_IN') + ' ' + getSearchLenght() + ' ' + Joomla.JText._('COM_COMPONENTBUILDER_SECONDS');
|
|
}
|
|
// show the search button
|
|
startSearchButton.style.display = '';
|
|
// hidde the stop search button
|
|
stopSearchButton.style.display = 'none';
|
|
setTimeout(function () {
|
|
// hide the progress bar again
|
|
searchProgressObject.style.display = 'none';
|
|
}, 13000);
|
|
}
|
|
}).catch(error => {
|
|
console.log(error);
|
|
if (error.name === "AbortError") {
|
|
abort_this_search_values = true;
|
|
}
|
|
});
|
|
}
|
|
} catch (error) {
|
|
console.log(error);
|
|
} finally {
|
|
// Executed regardless if we caught the error
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* JS Function to start search timer
|
|
*/
|
|
const startSearchTimer = () => {
|
|
startSearchTime = new Date();
|
|
};
|
|
|
|
/**
|
|
* JS Function to get search lenght
|
|
*/
|
|
const getSearchLenght = () => {
|
|
// set ending time
|
|
endSearchTime = new Date();
|
|
|
|
// get diff in ms
|
|
var timeDiff = endSearchTime - startSearchTime;
|
|
|
|
// strip the ms
|
|
timeDiff /= 1000;
|
|
|
|
// get seconds
|
|
return Math.round(timeDiff);
|
|
};
|
|
|
|
/**
|
|
* JS Function to fetch selected item
|
|
*/
|
|
const getSelectedItem = async (table, row, field, line) => {
|
|
try {
|
|
// get the search mode
|
|
let mode = modeObject.querySelector('input[type=\'radio\']:checked').value;
|
|
|
|
// build form
|
|
const formData = new FormData();
|
|
|
|
formData.append('field_name', field);
|
|
formData.append('row_id', row);
|
|
formData.append('table_name', table);
|
|
formData.append('search_value', searchObject.value);
|
|
formData.append('replace_value', replaceObject.value);
|
|
formData.append('match_case', matchObject.checked ? 1 : 0);
|
|
formData.append('whole_word', wholeObject.checked ? 1 : 0);
|
|
formData.append('regex_search', regexObject.checked ? 1 : 0);
|
|
|
|
// get search value
|
|
if (mode == 2) {
|
|
// add the line value
|
|
formData.append('line_nr', line);
|
|
// calling URL
|
|
postURL = UrlAjax + 'getReplaceValue';
|
|
} else {
|
|
// calling URL
|
|
postURL = UrlAjax + 'getSearchValue';
|
|
}
|
|
|
|
let options = {
|
|
method: 'POST', // *GET, POST, PUT, DELETE, etc.
|
|
body: formData
|
|
}
|
|
|
|
const response = await fetch(postURL, options).then(response => {
|
|
if (response.ok) {
|
|
return response.json();
|
|
}
|
|
}).then((data) => {
|
|
if (typeof data.success !== 'undefined') {
|
|
UIkit.notify(data.success, {pos:'top-right', status:'success'});
|
|
}
|
|
if (typeof data.value !== 'undefined') {
|
|
addSelectedItem(data.value, table, row, field, line);
|
|
}
|
|
}).catch(error => {
|
|
console.log(error);
|
|
});
|
|
} catch (error) {
|
|
console.log(error);
|
|
} finally {
|
|
// Executed regardless if we caught the error
|
|
}
|
|
};
|
|
|
|
/**
|
|
* JS Function to check if we should save/update the all current found items
|
|
*/
|
|
const replaceAllCheck = () => {
|
|
// get the current searc and replace values
|
|
let searchValue = searchObject.value;
|
|
let replaceValue = replaceObject.value;
|
|
// load question
|
|
let question = Joomla.JText._('COM_COMPONENTBUILDER_YOUR_ARE_ABOUT_TO_UPDATE_BALLB_VALUES_THAT_CAN_BE_FOUND_IN_THE_DATABASE') + '<br />' +
|
|
Joomla.JText._('COM_COMPONENTBUILDER_YOU_WILL_REPLACE') + ': [<span class="found_code">' + htmlentities(searchValue) + '</span>] ' +
|
|
Joomla.JText._('COM_COMPONENTBUILDER_WITH') + ': [<span class="found_code">' + htmlentities(replaceValue) + '</span>]<br />' +
|
|
Joomla.JText._('COM_COMPONENTBUILDER_THIS_CAN_NOT_BE_UNDONE_BYOU_HAVE_BEEN_WARNEDB') + '<br /><br />' +
|
|
Joomla.JText._('COM_COMPONENTBUILDER_ARE_YOU_THEREFORE_ABSOLUTELY_SURE_YOU_WANT_TO_CONTINUE');
|
|
// do check
|
|
UIkit.modal.confirm(question, function () {
|
|
|
|
// show the search settings again
|
|
showSearch();
|
|
|
|
// Create new controller and issue new request
|
|
controller_replace = new AbortController();
|
|
|
|
// check if any specific table was set
|
|
let tables = [];
|
|
let table = tableObject.value;
|
|
if (table != -1) {
|
|
tables.push(table);
|
|
replaceAll(controller_replace.signal, tables);
|
|
} else {
|
|
replaceAll(controller_replace.signal, searchTables);
|
|
}
|
|
}, {labels: { Ok: Joomla.JText._('COM_COMPONENTBUILDER_YES_UPDATE_ALL'), Cancel: Joomla.JText._('COM_COMPONENTBUILDER_NO') }});
|
|
};
|
|
|
|
/**
|
|
* JS Function to execute the search
|
|
*/
|
|
const replaceAll = async (signal, tables) => {
|
|
try {
|
|
// build form
|
|
const formData = new FormData();
|
|
|
|
// get the search mode
|
|
let typeSearch = modeObject.querySelector('input[type=\'radio\']:checked').value;
|
|
|
|
// set some search values
|
|
let searchValue = searchObject.value;
|
|
let replaceValue = replaceObject.value;
|
|
let matchValue = matchObject.checked ? 1 : 0;
|
|
let wholeValue = wholeObject.checked ? 1 : 0;
|
|
let regexValue = regexObject.checked ? 1 : 0;
|
|
|
|
// add the form data
|
|
formData.append('table_name', '');
|
|
formData.append('type_search', typeSearch);
|
|
formData.append('search_value', searchValue);
|
|
formData.append('replace_value', replaceValue);
|
|
formData.append('match_case', matchValue);
|
|
formData.append('whole_word', wholeValue);
|
|
formData.append('regex_search', regexValue);
|
|
|
|
// reset the progress bar
|
|
replaceProgressBarObject.style.width = '0%';
|
|
|
|
// show the progress bar
|
|
replaceProgressObject.style.display = '';
|
|
|
|
let abort_this_replace_values = false;
|
|
|
|
let total = 0;
|
|
let progress = tables.length;
|
|
let index;
|
|
|
|
for (index = 0; index < progress; index++) {
|
|
|
|
let tableName = tables[index];
|
|
|
|
// add the table name
|
|
formData.set('table_name', tableName);
|
|
|
|
let options = {
|
|
signal: signal,
|
|
method: 'POST', // *GET, POST, PUT, DELETE, etc.
|
|
body: formData
|
|
}
|
|
|
|
if (abort_this_replace_values) {
|
|
break;
|
|
}
|
|
const response = await fetch(UrlAjax + 'replaceAll', options).then(response => {
|
|
total++;
|
|
if (response.ok) {
|
|
return response.json();
|
|
} else {
|
|
UIkit.notify(Joomla.JText._('COM_COMPONENTBUILDER_THE_REPLACE_PROCESS_HAD_AN_ERROR_WITH_TABLE') + ' ' + tableName, {pos:'top-right', status:'danger'});
|
|
}
|
|
}).then((data) => {
|
|
if (typeof data.success !== 'undefined') {
|
|
UIkit.notify(data.success, {pos:'top-right', timeout : 200, status:'success'});
|
|
} else if (typeof data.error !== 'undefined') {
|
|
UIkit.notify(data.error, {pos:'bottom-right', timeout : 200});
|
|
}
|
|
// calculate the percent
|
|
let percent = 100.0 * (total / progress);
|
|
// update the progress bar
|
|
replaceProgressBarObject.style.width = percent.toFixed(2) + '%';
|
|
// when complete hide the progress bar
|
|
if (progress == total) {
|
|
setTimeout(function () {
|
|
// hide the progress bar again
|
|
replaceProgressObject.style.display = 'none';
|
|
// we clear the table again
|
|
clearAll();
|
|
// if not reqex we reverse the search for you so you can see the update was a success
|
|
if (regexValue == 0) {
|
|
// set the replace value as the search value
|
|
UIkit.modal.confirm(Joomla.JText._('COM_COMPONENTBUILDER_WOULD_YOU_LIKE_TO_DO_A_REVERSE_SEARCH'), function(){
|
|
startNewSearch(replaceValue, searchValue, matchValue, wholeValue, regexValue, 2);
|
|
}, function () {
|
|
UIkit.modal.confirm(Joomla.JText._('COM_COMPONENTBUILDER_WOULD_YOU_LIKE_TO_REPEAT_THE_SAME_SEARCH'), function(){
|
|
startSearch();
|
|
}, function () {
|
|
clearSearch();
|
|
}, {labels: { Ok: Joomla.JText._('COM_COMPONENTBUILDER_YES'), Cancel: Joomla.JText._('COM_COMPONENTBUILDER_NO') }});
|
|
}, {labels: { Ok: Joomla.JText._('COM_COMPONENTBUILDER_YES'), Cancel: Joomla.JText._('COM_COMPONENTBUILDER_NO') }});
|
|
} else {
|
|
// else we search it again just to prove its changed
|
|
UIkit.modal.confirm(Joomla.JText._('COM_COMPONENTBUILDER_WOULD_YOU_LIKE_TO_REPEAT_THE_SAME_SEARCH'), function(){
|
|
startSearch();
|
|
}, function () {
|
|
clearSearch();
|
|
}, {labels: { Ok: Joomla.JText._('COM_COMPONENTBUILDER_YES'), Cancel: Joomla.JText._('COM_COMPONENTBUILDER_NO') }});
|
|
}
|
|
}, 3000);
|
|
}
|
|
}).catch(error => {
|
|
console.log(error);
|
|
if (error.name === "AbortError") {
|
|
abort_this_replace_values = true;
|
|
}
|
|
});
|
|
}
|
|
} catch (error) {
|
|
console.log(error);
|
|
} finally {
|
|
// Executed regardless if we caught the error
|
|
}
|
|
};
|
|
|
|
/**
|
|
* JS Function to check if we should save/update the current selected item
|
|
*/
|
|
const setValueCheck = (row, field, table) => {
|
|
// load question
|
|
let question = Joomla.JText._('COM_COMPONENTBUILDER_YOUR_ARE_ABOUT_TO_UPDATE_ROW') + ' (' + row + ') -> (' + field + ') ' +
|
|
Joomla.JText._('COM_COMPONENTBUILDER_FIELD_IN_THE') + ' (' + table + ') ' + Joomla.JText._('COM_COMPONENTBUILDER_TABLE') + '.<br /><br />' +
|
|
Joomla.JText._('COM_COMPONENTBUILDER_THIS_CAN_NOT_BE_UNDONE_ARE_YOU_SURE_YOU_WANT_TO_CONTINUE');
|
|
// do check
|
|
UIkit.modal.confirm(question, function () {
|
|
setValue(row, field, table);
|
|
}, {labels: { Ok: Joomla.JText._('COM_COMPONENTBUILDER_YES'), Cancel: Joomla.JText._('COM_COMPONENTBUILDER_NO') }});
|
|
};
|
|
|
|
/**
|
|
* JS Function to set the current selected item
|
|
*/
|
|
const setValue = async (row, field, table) => {
|
|
try {
|
|
// get the value from the editor
|
|
let value = editorObject.getValue();
|
|
|
|
// build form
|
|
const formData = new FormData();
|
|
|
|
formData.append('value', value);
|
|
formData.append('row_id', row);
|
|
formData.append('field_name', field);
|
|
formData.append('table_name', table);
|
|
|
|
let options = {
|
|
method: 'POST', // *GET, POST, PUT, DELETE, etc.
|
|
body: formData
|
|
}
|
|
|
|
const response = await fetch(UrlAjax + 'setValue', options).then(response => {
|
|
if (response.ok) {
|
|
return response.json();
|
|
}
|
|
}).then((data) => {
|
|
if (typeof data.success !== 'undefined') {
|
|
UIkit.notify(data.success, {pos:'top-right', status:'success'});
|
|
clearSelectedItem();
|
|
tableActiveObject.remove().draw();
|
|
}
|
|
}).catch(error => {
|
|
console.log(error);
|
|
});
|
|
} catch (error) {
|
|
console.log(error);
|
|
} finally {
|
|
// Executed regardless if we caught the error
|
|
}
|
|
};
|
|
|
|
/**
|
|
* JS Function to add item to the editor
|
|
*/
|
|
const addSelectedItem = async (value, table, row, field, line) => {
|
|
// display area
|
|
if (value.length > 1)
|
|
{
|
|
// add value to editor
|
|
editorObject.setValue(value);
|
|
|
|
// set item details notice area
|
|
itemNoticeObject.style.display = '';
|
|
itemEditButtonObject.innerHTML = editButtonSelected;
|
|
itemTableNameObject.innerHTML = table;
|
|
itemRowIdObject.innerHTML = row;
|
|
itemFieldNameObject.innerHTML = field;
|
|
itemLineNumberObject.innerHTML = line;
|
|
// set button and editor line if we have a line number
|
|
if (typeof line == 'number') {
|
|
// show and set the save button
|
|
buttonUpdateItemObject.style.display = '';
|
|
buttonUpdateItemObject.setAttribute('onclick',"setValueCheck(" + row + ", '" + field + "', '" + table + "');");
|
|
// Get line info from current state.
|
|
const line_info = editorObject.instance.state.doc.line(line);
|
|
editorObject.instance.dispatch({
|
|
// Set selection to that entire line.
|
|
selection: { head: line_info.from, anchor: line_info.to },
|
|
// Ensure the selection is shown in viewport
|
|
scrollIntoView: true
|
|
});
|
|
} else {
|
|
// no line so no data we can't save this data
|
|
buttonUpdateItemObject.setAttribute('onclick', "");
|
|
buttonUpdateItemObject.style.display = 'none';
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* JS Function to clear item from the editor and hide it
|
|
*/
|
|
const clearSelectedItem = async () => {
|
|
// display area
|
|
editorObject.setValue('');
|
|
// clear notice area
|
|
itemNoticeObject.style.display = 'none';
|
|
itemEditButtonObject.innerHTML = '...';
|
|
itemTableNameObject.innerHTML = '...';
|
|
itemRowIdObject.innerHTML = '...';
|
|
itemFieldNameObject.innerHTML = '...';
|
|
itemLineNumberObject.innerHTML = '...';
|
|
// clear update button
|
|
buttonUpdateItemObject.setAttribute('onclick', '');
|
|
};
|
|
|
|
/**
|
|
* JS Function to clear table items
|
|
*/
|
|
const clearTableItems = async () => {
|
|
let table = new DataTable('#search_results_table');
|
|
// clear search
|
|
table.search('').columns().search( '' );
|
|
// clear items
|
|
table.clear().draw( true );
|
|
|
|
// hide the update all items
|
|
buttonUpdateAllStyleDisplay('none');
|
|
};
|
|
|
|
/**
|
|
* JS Function to clear all details of the search
|
|
*/
|
|
const clearAll = async () => {
|
|
// clear all details
|
|
clearTableItems();
|
|
clearSelectedItem();
|
|
searchedObject.innerHTML = '....';
|
|
};
|
|
|
|
/**
|
|
* JS Function to clear the search and replace values
|
|
*/
|
|
const clearSearch = async () => {
|
|
// clear the search and replace values
|
|
searchObject.value = '';
|
|
replaceObject.value = '';
|
|
};
|
|
|
|
/**
|
|
* JS Function to set the search and replace values
|
|
*/
|
|
const startNewSearch = async (search, replace = '', match = 0, whole = 0, regex = 0, mode = 1) => {
|
|
// redirect to a new search
|
|
window.location.href = getSearchURL(search, replace, match, whole, regex, mode);
|
|
};
|
|
|
|
/**
|
|
* JS Function to update the URL of the browser with the search query
|
|
*/
|
|
const updateUrlQuery = async (search, replace = '', match = 0, whole = 0, regex = 0, mode = 1) => {
|
|
// update the url query
|
|
window.history.pushState({}, '', getSearchURL(search, replace, match, whole, regex, mode));
|
|
};
|
|
|
|
/**
|
|
* JS Function to get the current search URL
|
|
*/
|
|
const getSearchURL = (search, replace = '', match = 0, whole = 0, regex = 0, mode = 1) => {
|
|
// check if its a single table search
|
|
let table = tableObject.value;
|
|
let table_name = '';
|
|
if (table != -1) {
|
|
table_name = '&table_name=' + urlencode(table);
|
|
}
|
|
// update the type of search
|
|
if (mode == 1) {
|
|
return UrlSearch + table_name +
|
|
'&search_value=' + urlencode(search) +
|
|
'&type_search=1&match_case=' + match +
|
|
'&whole_word=' + whole +
|
|
'®ex_search=' + regex;
|
|
} else if (mode == 2) {
|
|
return UrlSearch + table_name +
|
|
'&search_value=' + urlencode(search) +
|
|
'&replace_value=' + urlencode(replace) +
|
|
'&type_search=2&match_case=' + match +
|
|
'&whole_word=' + whole +
|
|
'®ex_search=' + regex;
|
|
}
|
|
return UrlSearch + table_name;
|
|
};
|
|
|
|
/**
|
|
* JS Function to check if a element has a class
|
|
*/
|
|
const hasClass = (elementObject, classNaam) => {
|
|
return !!elementObject.className.match(new RegExp('(\\s|^)' + classNaam + '(\\s|$)'));
|
|
};
|
|
|
|
/**
|
|
* JS Function add a class from an element
|
|
*/
|
|
const addClass = (elementObject, classNaam) => {
|
|
if (!hasClass(elementObject, classNaam)) {
|
|
elementObject.className += " " + classNaam;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* JS Function remove a class from an element
|
|
*/
|
|
const removeClass = (elementObject, classNaam) => {
|
|
if (hasClass(elementObject, classNaam)) {
|
|
var reg = new RegExp('(\\s|^)' + classNaam + '(\\s|$)');
|
|
elementObject.className = elementObject.className.replace(reg, ' ');
|
|
}
|
|
};
|
|
|
|
/**
|
|
* JS Function to add items to the table
|
|
*/
|
|
const addTableItems = async (table, items, typeSearch) => {
|
|
table.rows.add(items).draw( false );
|
|
if (typeSearch == 2) {
|
|
buttonUpdateAllStyleDisplay(''); // TODO should only show once all items are loaded
|
|
} else {
|
|
buttonUpdateAllStyleDisplay('none'); // TODO should only show once all items are loaded
|
|
}
|
|
};
|
|
|
|
/**
|
|
* JS Function to update the update all button
|
|
*/
|
|
const buttonUpdateAllStyleDisplay = async (value) => {
|
|
buttonUpdateAllObject.forEach((buttonObject) => {
|
|
buttonObject.style.display = value;
|
|
});
|
|
};
|
|
|
|
/**
|
|
* JS Function to execute (A) on search/replace text change , (B) on search options changes
|
|
*/
|
|
const startSearch = (field, forced = false) => {
|
|
// check mode
|
|
let mode = modeObject.querySelector('input[type=\'radio\']:checked').value;
|
|
if (mode == 0) {
|
|
// reset the search area
|
|
window.location.href = UrlSearch;
|
|
}
|
|
// check if we have an Enter click
|
|
if (field && typeof field.code !== 'undefined' && field.code === "Enter") {
|
|
forced = true;
|
|
}
|
|
// get replace value if set
|
|
const replaceValue = replaceObject.value;
|
|
if (replaceValue.length > 0) {
|
|
// set the searched value
|
|
replacedObject.innerHTML = htmlentities(replaceValue);
|
|
} else {
|
|
replacedObject.innerHTML = '';
|
|
}
|
|
// get search value
|
|
const searchValue = searchObject.value;
|
|
if (searchValue.length > 2 || (searchValue.length > 0 && forced)) {
|
|
// Cancel any ongoing requests
|
|
if (controller) controller.abort();
|
|
|
|
// we clear the table again
|
|
clearAll();
|
|
|
|
// set the searched value
|
|
searchedObject.innerHTML = htmlentities(searchValue);
|
|
|
|
// Create new controller and issue new request
|
|
controller = new AbortController();
|
|
|
|
// check if any specific table was set
|
|
let tables = [];
|
|
let table = tableObject.value;
|
|
if (table != -1) {
|
|
tables.push(table);
|
|
doSearch(controller.signal, tables);
|
|
} else {
|
|
doSearch(controller.signal, searchTables);
|
|
}
|
|
} else {
|
|
// Clear the table
|
|
clearAll();
|
|
}
|
|
};
|
|
|
|
/**
|
|
* JS Function to stop a search
|
|
*/
|
|
const stopSearch = () => {
|
|
// Cancel any ongoing requests
|
|
if (controller) controller.abort();
|
|
// show the search button
|
|
startSearchButton.style.display = '';
|
|
// hidde the stop search button
|
|
stopSearchButton.style.display = 'none';
|
|
// remove the progress bar at some point
|
|
setTimeout(function () {
|
|
// hide the progress bar again
|
|
searchProgressObject.style.display = 'none';
|
|
}, 13000);
|
|
}
|
|
|
|
/**
|
|
* JS Function to hide search settings and show table search
|
|
*/
|
|
const showSearch = () => {
|
|
searchSettingsObject.style.display = '';
|
|
searchDetailsObject.style.display = 'none';
|
|
replaceDetailsObject.style.display = 'none';
|
|
tableSearchObject.style.display = 'none';
|
|
tableLengthObject.style.display = 'none';
|
|
};
|
|
|
|
/**
|
|
* JS Function to show search settings and hide table search
|
|
*/
|
|
const hideSearch = () => {
|
|
searchSettingsObject.style.display = 'none';
|
|
searchDetailsObject.style.display = '';
|
|
tableSearchObject.style.display = '';
|
|
tableLengthObject.style.display = '';
|
|
// check if we are in replace mode
|
|
let mode = modeObject.querySelector('input[type=\'radio\']:checked').value;
|
|
if (mode == 2) {
|
|
replaceDetailsObject.style.display = '';
|
|
}
|
|
};
|
|
|
|
|
|
function htmlentities(string, quoteStyle, charset, doubleEncode) {
|
|
// discuss at: https://locutus.io/php/htmlentities/
|
|
// original by: Kevin van Zonneveld (https://kvz.io)
|
|
// revised by: Kevin van Zonneveld (https://kvz.io)
|
|
// revised by: Kevin van Zonneveld (https://kvz.io)
|
|
// improved by: nobbler
|
|
// improved by: Jack
|
|
// improved by: Rafał Kukawski (https://blog.kukawski.pl)
|
|
// improved by: Dj (https://locutus.io/php/htmlentities:425#comment_134018)
|
|
// bugfixed by: Onno Marsman (https://twitter.com/onnomarsman)
|
|
// bugfixed by: Brett Zamir (https://brett-zamir.me)
|
|
// input by: Ratheous
|
|
// note 1: function is compatible with PHP 5.2 and older
|
|
// example 1: htmlentities('Kevin & van Zonneveld')
|
|
// returns 1: 'Kevin & van Zonneveld'
|
|
// example 2: htmlentities("foo'bar","ENT_QUOTES")
|
|
// returns 2: 'foo'bar'
|
|
const hashMap = getHtmlTranslationTable('HTML_ENTITIES', quoteStyle)
|
|
string = string === null ? '' : string + ''
|
|
if (!hashMap) {
|
|
return false
|
|
}
|
|
if (quoteStyle && quoteStyle === 'ENT_QUOTES') {
|
|
hashMap["'"] = '''
|
|
}
|
|
doubleEncode = doubleEncode === null || !!doubleEncode
|
|
const regex = new RegExp('&(?:#\\d+|#x[\\da-f]+|[a-zA-Z][\\da-z]*);|[' +
|
|
Object.keys(hashMap)
|
|
.join('')
|
|
// replace regexp special chars
|
|
.replace(/([()[\]{}\-.*+?^$|/\\])/g, '\\$1') + ']',
|
|
'g')
|
|
return string.replace(regex, function (ent) {
|
|
if (ent.length > 1) {
|
|
return doubleEncode ? hashMap['&'] + ent.substr(1) : ent
|
|
}
|
|
return hashMap[ent]
|
|
})
|
|
}
|
|
|
|
function getHtmlTranslationTable(table, quoteStyle) { // eslint-disable-line camelcase
|
|
// discuss at: https://locutus.io/php/get_html_translation_table/
|
|
// original by: Philip Peterson
|
|
// revised by: Kevin van Zonneveld (https://kvz.io)
|
|
// bugfixed by: noname
|
|
// bugfixed by: Alex
|
|
// bugfixed by: Marco
|
|
// bugfixed by: madipta
|
|
// bugfixed by: Brett Zamir (https://brett-zamir.me)
|
|
// bugfixed by: T.Wild
|
|
// improved by: KELAN
|
|
// improved by: Brett Zamir (https://brett-zamir.me)
|
|
// input by: Frank Forte
|
|
// input by: Ratheous
|
|
// note 1: It has been decided that we're not going to add global
|
|
// note 1: dependencies to Locutus, meaning the constants are not
|
|
// note 1: real constants, but strings instead. Integers are also supported if someone
|
|
// note 1: chooses to create the constants themselves.
|
|
// example 1: get_html_translation_table('HTML_SPECIALCHARS')
|
|
// returns 1: {'"': '"', '&': '&', '<': '<', '>': '>'}
|
|
|
|
const entities = {}
|
|
const hashMap = {}
|
|
let decimal
|
|
const constMappingTable = {}
|
|
const constMappingQuoteStyle = {}
|
|
let useTable = {}
|
|
let useQuoteStyle = {}
|
|
|
|
// Translate arguments
|
|
constMappingTable[0] = 'HTML_SPECIALCHARS'
|
|
constMappingTable[1] = 'HTML_ENTITIES'
|
|
constMappingQuoteStyle[0] = 'ENT_NOQUOTES'
|
|
constMappingQuoteStyle[2] = 'ENT_COMPAT'
|
|
constMappingQuoteStyle[3] = 'ENT_QUOTES'
|
|
|
|
useTable = !isNaN(table)
|
|
? constMappingTable[table]
|
|
: table
|
|
? table.toUpperCase()
|
|
: 'HTML_SPECIALCHARS'
|
|
|
|
useQuoteStyle = !isNaN(quoteStyle)
|
|
? constMappingQuoteStyle[quoteStyle]
|
|
: quoteStyle
|
|
? quoteStyle.toUpperCase()
|
|
: 'ENT_COMPAT'
|
|
|
|
if (useTable !== 'HTML_SPECIALCHARS' && useTable !== 'HTML_ENTITIES') {
|
|
throw new Error('Table: ' + useTable + ' not supported')
|
|
}
|
|
|
|
entities['38'] = '&'
|
|
if (useTable === 'HTML_ENTITIES') {
|
|
entities['160'] = ' '
|
|
entities['161'] = '¡'
|
|
entities['162'] = '¢'
|
|
entities['163'] = '£'
|
|
entities['164'] = '¤'
|
|
entities['165'] = '¥'
|
|
entities['166'] = '¦'
|
|
entities['167'] = '§'
|
|
entities['168'] = '¨'
|
|
entities['169'] = '©'
|
|
entities['170'] = 'ª'
|
|
entities['171'] = '«'
|
|
entities['172'] = '¬'
|
|
entities['173'] = '­'
|
|
entities['174'] = '®'
|
|
entities['175'] = '¯'
|
|
entities['176'] = '°'
|
|
entities['177'] = '±'
|
|
entities['178'] = '²'
|
|
entities['179'] = '³'
|
|
entities['180'] = '´'
|
|
entities['181'] = 'µ'
|
|
entities['182'] = '¶'
|
|
entities['183'] = '·'
|
|
entities['184'] = '¸'
|
|
entities['185'] = '¹'
|
|
entities['186'] = 'º'
|
|
entities['187'] = '»'
|
|
entities['188'] = '¼'
|
|
entities['189'] = '½'
|
|
entities['190'] = '¾'
|
|
entities['191'] = '¿'
|
|
entities['192'] = 'À'
|
|
entities['193'] = 'Á'
|
|
entities['194'] = 'Â'
|
|
entities['195'] = 'Ã'
|
|
entities['196'] = 'Ä'
|
|
entities['197'] = 'Å'
|
|
entities['198'] = 'Æ'
|
|
entities['199'] = 'Ç'
|
|
entities['200'] = 'È'
|
|
entities['201'] = 'É'
|
|
entities['202'] = 'Ê'
|
|
entities['203'] = 'Ë'
|
|
entities['204'] = 'Ì'
|
|
entities['205'] = 'Í'
|
|
entities['206'] = 'Î'
|
|
entities['207'] = 'Ï'
|
|
entities['208'] = 'Ð'
|
|
entities['209'] = 'Ñ'
|
|
entities['210'] = 'Ò'
|
|
entities['211'] = 'Ó'
|
|
entities['212'] = 'Ô'
|
|
entities['213'] = 'Õ'
|
|
entities['214'] = 'Ö'
|
|
entities['215'] = '×'
|
|
entities['216'] = 'Ø'
|
|
entities['217'] = 'Ù'
|
|
entities['218'] = 'Ú'
|
|
entities['219'] = 'Û'
|
|
entities['220'] = 'Ü'
|
|
entities['221'] = 'Ý'
|
|
entities['222'] = 'Þ'
|
|
entities['223'] = 'ß'
|
|
entities['224'] = 'à'
|
|
entities['225'] = 'á'
|
|
entities['226'] = 'â'
|
|
entities['227'] = 'ã'
|
|
entities['228'] = 'ä'
|
|
entities['229'] = 'å'
|
|
entities['230'] = 'æ'
|
|
entities['231'] = 'ç'
|
|
entities['232'] = 'è'
|
|
entities['233'] = 'é'
|
|
entities['234'] = 'ê'
|
|
entities['235'] = 'ë'
|
|
entities['236'] = 'ì'
|
|
entities['237'] = 'í'
|
|
entities['238'] = 'î'
|
|
entities['239'] = 'ï'
|
|
entities['240'] = 'ð'
|
|
entities['241'] = 'ñ'
|
|
entities['242'] = 'ò'
|
|
entities['243'] = 'ó'
|
|
entities['244'] = 'ô'
|
|
entities['245'] = 'õ'
|
|
entities['246'] = 'ö'
|
|
entities['247'] = '÷'
|
|
entities['248'] = 'ø'
|
|
entities['249'] = 'ù'
|
|
entities['250'] = 'ú'
|
|
entities['251'] = 'û'
|
|
entities['252'] = 'ü'
|
|
entities['253'] = 'ý'
|
|
entities['254'] = 'þ'
|
|
entities['255'] = 'ÿ'
|
|
}
|
|
|
|
if (useQuoteStyle !== 'ENT_NOQUOTES') {
|
|
entities['34'] = '"'
|
|
}
|
|
if (useQuoteStyle === 'ENT_QUOTES') {
|
|
entities['39'] = '''
|
|
}
|
|
entities['60'] = '<'
|
|
entities['62'] = '>'
|
|
|
|
// ascii decimals to real symbols
|
|
for (decimal in entities) {
|
|
if (entities.hasOwnProperty(decimal)) {
|
|
hashMap[String.fromCharCode(decimal)] = entities[decimal]
|
|
}
|
|
}
|
|
|
|
return hashMap
|
|
}
|
|
|
|
|
|
function urlencode (str) {
|
|
// discuss at: https://locutus.io/php/urlencode/
|
|
// original by: Philip Peterson
|
|
// improved by: Kevin van Zonneveld (https://kvz.io)
|
|
// improved by: Kevin van Zonneveld (https://kvz.io)
|
|
// improved by: Brett Zamir (https://brett-zamir.me)
|
|
// improved by: Lars Fischer
|
|
// improved by: Waldo Malqui Silva (https://fayr.us/waldo/)
|
|
// input by: AJ
|
|
// input by: travc
|
|
// input by: Brett Zamir (https://brett-zamir.me)
|
|
// input by: Ratheous
|
|
// bugfixed by: Kevin van Zonneveld (https://kvz.io)
|
|
// bugfixed by: Kevin van Zonneveld (https://kvz.io)
|
|
// bugfixed by: Joris
|
|
// reimplemented by: Brett Zamir (https://brett-zamir.me)
|
|
// reimplemented by: Brett Zamir (https://brett-zamir.me)
|
|
// note 1: This reflects PHP 5.3/6.0+ behavior
|
|
// note 1: Please be aware that this function
|
|
// note 1: expects to encode into UTF-8 encoded strings, as found on
|
|
// note 1: pages served as UTF-8
|
|
// example 1: urlencode('Kevin van Zonneveld!')
|
|
// returns 1: 'Kevin+van+Zonneveld%21'
|
|
// example 2: urlencode('https://kvz.io/')
|
|
// returns 2: 'https%3A%2F%2Fkvz.io%2F'
|
|
// example 3: urlencode('https://www.google.nl/search?q=Locutus&ie=utf-8')
|
|
// returns 3: 'https%3A%2F%2Fwww.google.nl%2Fsearch%3Fq%3DLocutus%26ie%3Dutf-8'
|
|
str = (str + '')
|
|
return encodeURIComponent(str)
|
|
.replace(/!/g, '%21')
|
|
.replace(/'/g, '%27')
|
|
.replace(/\(/g, '%28')
|
|
.replace(/\)/g, '%29')
|
|
.replace(/\*/g, '%2A')
|
|
.replace(/~/g, '%7E')
|
|
.replace(/%20/g, '+')
|
|
} |