Continued development on the search feature
This commit is contained in:
parent
869a1879cb
commit
f2ea22d0ad
@ -140,14 +140,14 @@ TODO
|
||||
+ *Author*: [Llewellyn van der Merwe](mailto:joomla@vdm.io)
|
||||
+ *Name*: [Component Builder](https://git.vdm.dev/joomla/Component-Builder)
|
||||
+ *First Build*: 30th April, 2015
|
||||
+ *Last Build*: 23rd October, 2022
|
||||
+ *Last Build*: 30th October, 2022
|
||||
+ *Version*: 3.1.9
|
||||
+ *Copyright*: Copyright (C) 2015 Vast Development Method. All rights reserved.
|
||||
+ *License*: GNU General Public License version 2 or later; see LICENSE.txt
|
||||
+ *Line count*: **332840**
|
||||
+ *Line count*: **333093**
|
||||
+ *Field count*: **2004**
|
||||
+ *File count*: **2174**
|
||||
+ *Folder count*: **378**
|
||||
+ *File count*: **2183**
|
||||
+ *Folder count*: **381**
|
||||
|
||||
> This **component** was build with a [Joomla](https://extensions.joomla.org/extension/component-builder/) [Automated Component Builder](http://joomlacomponentbuilder.com).
|
||||
> Developed by [Llewellyn van der Merwe](mailto:llewellyn@joomlacomponentbuilder.com)
|
||||
|
@ -140,14 +140,14 @@ TODO
|
||||
+ *Author*: [Llewellyn van der Merwe](mailto:joomla@vdm.io)
|
||||
+ *Name*: [Component Builder](https://git.vdm.dev/joomla/Component-Builder)
|
||||
+ *First Build*: 30th April, 2015
|
||||
+ *Last Build*: 23rd October, 2022
|
||||
+ *Last Build*: 30th October, 2022
|
||||
+ *Version*: 3.1.9
|
||||
+ *Copyright*: Copyright (C) 2015 Vast Development Method. All rights reserved.
|
||||
+ *License*: GNU General Public License version 2 or later; see LICENSE.txt
|
||||
+ *Line count*: **332840**
|
||||
+ *Line count*: **333093**
|
||||
+ *Field count*: **2004**
|
||||
+ *File count*: **2174**
|
||||
+ *Folder count*: **378**
|
||||
+ *File count*: **2183**
|
||||
+ *Folder count*: **381**
|
||||
|
||||
> This **component** was build with a [Joomla](https://extensions.joomla.org/extension/component-builder/) [Automated Component Builder](http://joomlacomponentbuilder.com).
|
||||
> Developed by [Llewellyn van der Merwe](mailto:llewellyn@joomlacomponentbuilder.com)
|
||||
|
@ -14,38 +14,36 @@
|
||||
*/
|
||||
const doSearch = async (signal, tables) => {
|
||||
try {
|
||||
let searchValue = document.querySelector('input[name="search_value"]').value;
|
||||
let replaceValue = document.querySelector('input[name="replace_value"]').value;
|
||||
// build form
|
||||
const formData = new FormData();
|
||||
|
||||
// load the result table
|
||||
const resultsTable = new DataTable('#search_results_table');
|
||||
|
||||
// set some search values
|
||||
let searchValue = searchObject.value;
|
||||
let replaceValue = replaceObject.value;
|
||||
|
||||
// add the form data
|
||||
formData.append('table_name', '');
|
||||
formData.append('search_value', searchValue);
|
||||
formData.append('replace_value', replaceValue);
|
||||
formData.append('match_case', matchObject.checked ? 1 : 0);
|
||||
formData.append('whole_word', wholeObject.checked ? 1 : 0);
|
||||
formData.append('regex_search', regexObject.checked ? 1 : 0);
|
||||
|
||||
// Display 'loading' message in search results message div
|
||||
document.getElementById('search-mssg-box').innerHTML =
|
||||
'<progress id="search-loading-progressbar" class="uk-progress" value="10" max="100" style="width: 200px; display: inline-block; margin: 0 !important;"></progress>' +
|
||||
' <div id="search-loading-spinner" style="margin: -4px 12px 0;" uk-spinner="ratio: 0.8"></div>' +
|
||||
' <span id="search-loading-percent">0%</span> ' +
|
||||
'Loading for search text: <b style="font-size: 2em;">' + searchValue + '</b>'
|
||||
;
|
||||
// Clear results table
|
||||
let search_loading_percent = document.getElementById('search-loading-percent');
|
||||
let tbl_obj_body = document.getElementById('search-results-tbl-tbody');
|
||||
tbl_obj_body.innerHTML = '';
|
||||
let abort_this_search_value = false;
|
||||
|
||||
let total = 0;
|
||||
let index;
|
||||
|
||||
for (index = 0; index < searchTables.length; index++) {
|
||||
const formData = new FormData();
|
||||
let tableName = searchTables[index];
|
||||
for (index = 0; index < tables.length; index++) {
|
||||
|
||||
formData.append('table_name', '');
|
||||
formData.append('search_value', searchValue);
|
||||
formData.append('replace_value', replaceValue);
|
||||
formData.append('match_case', document.querySelector('input[name="match_case"]').checked ? 1 : 0);
|
||||
formData.append('whole_word', document.querySelector('input[name="whole_word"]').checked ? 1 : 0);
|
||||
formData.append('regex_search', document.querySelector('input[name="regex_search"]').checked ? 1 : 0);
|
||||
formData.append('table_name', tableName);
|
||||
let tableName = tables[index];
|
||||
|
||||
// add the table name
|
||||
formData.set('table_name', tableName);
|
||||
|
||||
let url = document.getElementById('adminForm').getAttribute('action') + '&layout=dosearch';
|
||||
let options = {
|
||||
signal: signal,
|
||||
method: 'POST', // *GET, POST, PUT, DELETE, etc.
|
||||
@ -56,71 +54,19 @@ const doSearch = async (signal, tables) => {
|
||||
console.log('Aborting this searchValue:' + searchValue);
|
||||
break;
|
||||
}
|
||||
console.log(total + ' -- SEARCHING: ' + searchValue + ' @[' + tableName + ']');
|
||||
const response = await fetch(url, options)
|
||||
// Note: response.text() is a promise ...
|
||||
.then(response => {
|
||||
total++;
|
||||
//console.log(total + ' ' + sTables.length);
|
||||
if (sTables.length == total) setTimeout(function () {
|
||||
document.getElementById('search-mssg-box').innerHTML = '<div class="alert alert-success" role="alert"><strong>Enter</strong> your text.</div>';
|
||||
}, 200);
|
||||
|
||||
response.text().then(data => {
|
||||
console.log('++ Fetched for ' + searchValue + ' [' + tableName + ']');
|
||||
let percent = 100.0 * (total / sTables.length);
|
||||
search_loading_percent.innerHTML = '' + percent.toFixed(2) + '%';
|
||||
document.getElementById('search-loading-progressbar').value = percent;
|
||||
|
||||
let use_json = false, json_data = false, items = false;
|
||||
if (use_json) {
|
||||
try {
|
||||
json_data = data ? JSON.parse(data) : false;
|
||||
items = json_data ? json_data.items : false;
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
// Very fast and low memory display HTML table row prepared server-side via PHP instead of JS !!
|
||||
if (!json_data) {
|
||||
tbl_obj_body.innerHTML = tbl_obj_body.innerHTML + data;
|
||||
}
|
||||
|
||||
// Very slow fast and very high memory: Display HTML table rows by creating them now in browser (client-side) via JS instead of using PHP
|
||||
if (json_data && items) {
|
||||
let table_rows = '';
|
||||
for (const [row_num, row_field_vals] of Object.entries(items)) {
|
||||
for (const [fname, fvals] of Object.entries(row_field_vals)) {
|
||||
for (const [line, fval] of Object.entries(fvals)) {
|
||||
let lnk = 'getFSText(this, \'' + tableName + '\', ' + row_num + ', \'' + fname + '\', line)';
|
||||
let val = fval;
|
||||
val = val.replaceAll(marker_start, '<b>');
|
||||
val = val.replaceAll(marker_end, '</b>');
|
||||
table_rows = table_rows + '<tr onclick="' + lnk + '; return false" style="cursor: pointer;">' +
|
||||
'<td>' + val + '</td>' +
|
||||
'<td>' + tableName + '</td>' +
|
||||
'<td>' + fname + '</td>' +
|
||||
'<td>' + row_num + '</td>' +
|
||||
'<td>' + line + '</td>' +
|
||||
'</tr>';
|
||||
}
|
||||
}
|
||||
}
|
||||
tbl_obj_body.innerHTML = tbl_obj_body.innerHTML + table_rows;
|
||||
} // END IF json_data && items
|
||||
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
total++;
|
||||
if (sTables.length == total) document.getElementById('search-mssg-box').innerHTML = '<div class="alert alert-success" role="alert"><strong>Enter</strong> your text.</div>';
|
||||
// Stop further searches for this search value
|
||||
if (error.name === "AbortError") abort_this_search_value = true;
|
||||
error.name === "AbortError"
|
||||
? console.log(" ... ABORTED fetch() for: " + searchValue)
|
||||
: console.log(error.toString());
|
||||
});
|
||||
const response = await fetch(Url + 'doSearch', options).then(response => {
|
||||
total++;
|
||||
if (response.ok) {
|
||||
return response.json();
|
||||
}
|
||||
}).then((data) => {
|
||||
if (typeof data.items !== 'undefined') {
|
||||
console.log('++ Fetched for ' + searchValue + ' [' + tableName + ']');
|
||||
addTableItems(resultsTable, data.items);
|
||||
}
|
||||
}).catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
@ -130,183 +76,133 @@ const doSearch = async (signal, tables) => {
|
||||
};
|
||||
|
||||
/**
|
||||
* JS Function to execute the search
|
||||
* JS Function to fetch selected item
|
||||
*/
|
||||
const getFSText = async (el, table_name, row_id, field_name, line) => {
|
||||
let sibling = el.parentNode.firstElementChild;
|
||||
do {
|
||||
sibling != el
|
||||
? sibling.classList.remove('active')
|
||||
: sibling.classList.add('active');
|
||||
} while (sibling = sibling.nextElementSibling);
|
||||
|
||||
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('table_name', table_name);
|
||||
formData.append('get_full_search_text', 1);
|
||||
formData.append('row_id', row_id);
|
||||
formData.append('field_name', field_name);
|
||||
// get search value
|
||||
if (mode == 1) {
|
||||
formData.append('field_name', field);
|
||||
formData.append('row_id', row);
|
||||
formData.append('table_name', table);
|
||||
|
||||
// calling URL
|
||||
getURL = Url + 'getSearchValue';
|
||||
} else {
|
||||
formData.append('field_name', field);
|
||||
formData.append('row_id', row);
|
||||
formData.append('line_nr', line);
|
||||
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);
|
||||
|
||||
// calling URL
|
||||
getURL = Url + 'getReplaceValue';
|
||||
}
|
||||
|
||||
//let url = `https://jsonplaceholder.typicode.com/posts/${searchValue}`,
|
||||
let url = document.getElementById('adminForm').getAttribute('action') + '&layout=dosearch';
|
||||
let options = {
|
||||
method: 'POST', // *GET, POST, PUT, DELETE, etc.
|
||||
mode: 'cors', // no-cors, *cors, same-origin
|
||||
cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
|
||||
credentials: 'same-origin', // include, *same-origin, omit
|
||||
/*
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json', //'application/x-www-form-urlencoded',
|
||||
},*/
|
||||
redirect: 'follow', // manual, *follow, error
|
||||
referrerPolicy: 'no-referrer', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
|
||||
// body: JSON.stringify(formData) // body data type must match "Content-Type" header
|
||||
body: formData
|
||||
}
|
||||
|
||||
// Clear full text box
|
||||
document.getElementById('match-full-text-box').innerHTML = 'Loading ...';
|
||||
const response = await fetch(url, options)
|
||||
// Note: response.text() is a promise ...
|
||||
.then(response => {
|
||||
response.text().then(data => {
|
||||
console.log("Fetched full text for row: " + row_id + ' field name: ' + field_name + ' for Table: ' + table_name);
|
||||
document.getElementById('match-full-text-box').innerHTML = '<div id="match-full-text-header">'
|
||||
+ table_name + ' @ ' + field_name + ': ' + row_id + '</div><textarea id="match-full-text">' + data + '</textarea>';
|
||||
document.getElementById('match-full-text-box').style.display = '';
|
||||
attachCodeMirror(jQuery('#match-full-text'), null);
|
||||
cm_toggle_fully_searchable('match-full-text', 1);
|
||||
cm_jumpToLine('match-full-text', line);
|
||||
//cm_toggle_plain_textarea('match-full-text-box', 1);
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
// Stop further searches for this search value
|
||||
if (error.name === "AbortError") abort_this_search_value = true;
|
||||
error.name === "AbortError"
|
||||
? console.log(" ... ABORTED fetch() for: " + searchValue)
|
||||
: console.log(error.toString());
|
||||
});
|
||||
const response = await fetch(getURL, options).then(response => {
|
||||
if (response.ok) {
|
||||
return response.json();
|
||||
}
|
||||
}).then((data) => {
|
||||
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
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const cm_jumpToLine = function (tag_id, row)
|
||||
{
|
||||
console.log('#' + tag_id);
|
||||
let codeMirrorEl = jQuery('#' + tag_id).next('.CodeMirror');
|
||||
if (!codeMirrorEl.length) return;
|
||||
let codeMirrorRef = jQuery('#' + tag_id).next('.CodeMirror').get(0).CodeMirror;
|
||||
let t = codeMirrorRef.charCoords({line: row, ch: 0}, "local").top;
|
||||
let middleHeight = codeMirrorRef.getScrollerElement().offsetHeight / 2;
|
||||
codeMirrorRef.scrollTo(null, t - middleHeight - 5);
|
||||
}
|
||||
|
||||
/* Attach CodeMirror with optional settings */
|
||||
const cm_toggle_fully_searchable = function (el, toggle)
|
||||
{
|
||||
if (typeof CodeMirror === 'undefined') {alert('CodeMirror not loaded'); return;}
|
||||
|
||||
jQuery([el]).each(function(i, tag_id) {
|
||||
let codeMirrorEl = jQuery('#' + tag_id).next('.CodeMirror');
|
||||
if (!codeMirrorEl.length) return;
|
||||
let codeMirrorRef = jQuery('#' + tag_id).next('.CodeMirror').get(0).CodeMirror;
|
||||
codeMirrorRef.setOption('viewportMargin', toggle ? '9999' : '');
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
const cm_toggle_plain_textarea = function (el, toggle)
|
||||
{
|
||||
if (typeof CodeMirror === 'undefined') {alert('CodeMirror not loaded'); return;}
|
||||
|
||||
jQuery([el]).each(function(i, tag_id) {
|
||||
let codeMirrorEl = jQuery('#' + tag_id).next('.CodeMirror');
|
||||
if (toggle) {
|
||||
let options = jQuery('#' + tag_id).data('options');
|
||||
options.viewportMargin = jQuery('#cm_toggle_fully_searchable_btn input').prop('checked') ? '9999' : '';
|
||||
jQuery('#' + tag_id).prev('p').show();
|
||||
attachCodeMirror(jQuery('#' + tag_id), options);
|
||||
}
|
||||
else if (codeMirrorEl.length)
|
||||
{
|
||||
let codeMirrorRef = codeMirrorEl.get(0).CodeMirror;
|
||||
jQuery('#' + tag_id).prev('p').hide();
|
||||
jQuery('#' + tag_id).css({width: '100%', height: '400px'});
|
||||
codeMirrorRef.toTextArea();
|
||||
// Remove codemirror container in case that removing it failed
|
||||
if (jQuery('#' + tag_id).next('.CodeMirror').length) {
|
||||
jQuery('#' + tag_id).next('.CodeMirror').remove();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
const attachCodeMirror = function (txtareas, CMoptions, mode)
|
||||
{
|
||||
CMoptions = typeof CMoptions!=='undefined' && CMoptions ? CMoptions : {
|
||||
mode: mode || 'application/x-httpd-php',
|
||||
indentUnit: 2,
|
||||
lineNumbers: true,
|
||||
matchBrackets: true,
|
||||
lineWrapping: true,
|
||||
onCursorActivity: function(CM)
|
||||
{
|
||||
CM.setLineClass(hlLine, null);
|
||||
hlLine = CM.setLineClass(CM.getCursor().line, 'activeline');
|
||||
}
|
||||
};
|
||||
|
||||
var editor, theArea;
|
||||
txtareas.each(function(i, txtarea)
|
||||
/**
|
||||
* JS Function to add item to the editor
|
||||
*/
|
||||
const addSelectedItem = async (value, table, row, field, line) => {
|
||||
// display area
|
||||
if (value.length > 1)
|
||||
{
|
||||
theArea = jQuery(txtarea);
|
||||
theArea.removeClass(); // Remove all classes from the textarea
|
||||
editor = CodeMirror.fromTextArea(theArea.get(0), CMoptions);
|
||||
editor.refresh();
|
||||
});
|
||||
editorObject.setValue(value);
|
||||
editorNoticeObject.innerHTML = 'Table: <b>' + table + '</b>(id:<b>' + row + '</b>) | Field: <b>' + field + '</b>(line:<b>' + line + '</b>)';
|
||||
}
|
||||
}
|
||||
|
||||
return txtareas.length==1 ? editor : true;
|
||||
/**
|
||||
* JS Function to clear item from the editor and hide it
|
||||
*/
|
||||
const clearSelectedItem = async () => {
|
||||
// display area
|
||||
editorObject.setValue('');
|
||||
editorNoticeObject.innerHTML = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* JS Function to clear table items
|
||||
*/
|
||||
const clearTableItems = async () => {
|
||||
let table = new DataTable('#search_results_table');
|
||||
table.clear().draw( true );
|
||||
}
|
||||
|
||||
/**
|
||||
* JS Function to clear all details of the search
|
||||
*/
|
||||
const clearAll = async () => {
|
||||
// clear all details
|
||||
clearTableItems();
|
||||
clearSelectedItem();
|
||||
}
|
||||
|
||||
/**
|
||||
* JS Function to add items to the table
|
||||
*/
|
||||
const addTableItems = async (table, items) => {
|
||||
table.rows.add(items).draw( false );
|
||||
}
|
||||
|
||||
/**
|
||||
* JS Function to execute (A) on search text change , (B) on search options changes
|
||||
*/
|
||||
const onChange = () => {
|
||||
const searchValue = searchValueInp.value;
|
||||
const searchValue = searchObject.value;
|
||||
if (searchValue.length > 2) {
|
||||
// Cancel any ongoing requests
|
||||
if (controller) controller.abort();
|
||||
|
||||
// we clear the table again
|
||||
clearAll();
|
||||
|
||||
// Create new controller and issue new request
|
||||
controller = new AbortController();
|
||||
doSearch(controller.signal, sTables);
|
||||
|
||||
// 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 any message in search results message div
|
||||
//document.getElementById('search-mssg-box').innerHTML = '';
|
||||
// Clear the table
|
||||
clearAll();
|
||||
}
|
||||
};
|
||||
|
||||
const previewReplace = () => {
|
||||
const replaceValue = replaceValueInp.value;
|
||||
console.log(replaceValueInp);
|
||||
if (replaceValue.length) {
|
||||
document.getElementById('search-mssg-box').innerHTML = replaceValue;
|
||||
}
|
||||
}
|
||||
|
||||
// Do the search on key up of search or replace input element
|
||||
searchValueInp.onkeyup = onChange;
|
||||
replaceValueInp.onkeyup = previewReplace;
|
||||
|
||||
// Do the search on key up of search input element
|
||||
caseSensitiveLbl.onchange = onChange;
|
||||
completeWordLbl.onchange = onChange;
|
||||
regexpSearchLbl.onchange = onChange;
|
||||
|
@ -67,8 +67,8 @@ class ComponentbuilderControllerAjax extends BaseController
|
||||
$this->registerTask('fieldTypeProperties', 'ajax');
|
||||
$this->registerTask('getFieldPropertyDesc', 'ajax');
|
||||
$this->registerTask('getCodeGlueOptions', 'ajax');
|
||||
$this->registerTask('searchTable', 'ajax');
|
||||
$this->registerTask('updateTable', 'ajax');
|
||||
$this->registerTask('doSearch', 'ajax');
|
||||
$this->registerTask('replaceAll', 'ajax');
|
||||
$this->registerTask('getSearchValue', 'ajax');
|
||||
$this->registerTask('getReplaceValue', 'ajax');
|
||||
$this->registerTask('setValue', 'ajax');
|
||||
@ -1636,7 +1636,7 @@ class ComponentbuilderControllerAjax extends BaseController
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'searchTable':
|
||||
case 'doSearch':
|
||||
try
|
||||
{
|
||||
$table_nameValue = $jinput->get('table_name', NULL, 'WORD');
|
||||
@ -1647,7 +1647,7 @@ class ComponentbuilderControllerAjax extends BaseController
|
||||
$component_idValue = $jinput->get('component_id', 0, 'INT');
|
||||
if($table_nameValue && $user->id != 0 && $search_valueValue)
|
||||
{
|
||||
$result = $this->getModel('ajax')->searchTable($table_nameValue, $search_valueValue, $match_caseValue, $whole_wordValue, $regex_searchValue, $component_idValue);
|
||||
$result = $this->getModel('ajax')->doSearch($table_nameValue, $search_valueValue, $match_caseValue, $whole_wordValue, $regex_searchValue, $component_idValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1682,7 +1682,7 @@ class ComponentbuilderControllerAjax extends BaseController
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'updateTable':
|
||||
case 'replaceAll':
|
||||
try
|
||||
{
|
||||
$table_nameValue = $jinput->get('table_name', NULL, 'WORD');
|
||||
@ -1694,7 +1694,7 @@ class ComponentbuilderControllerAjax extends BaseController
|
||||
$component_idValue = $jinput->get('component_id', 0, 'INT');
|
||||
if($table_nameValue && $user->id != 0 && $search_valueValue)
|
||||
{
|
||||
$result = $this->getModel('ajax')->updateTable($table_nameValue, $search_valueValue, $replace_valueValue, $match_caseValue, $whole_wordValue, $regex_searchValue, $component_idValue);
|
||||
$result = $this->getModel('ajax')->replaceAll($table_nameValue, $search_valueValue, $replace_valueValue, $match_caseValue, $whole_wordValue, $regex_searchValue, $component_idValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -5448,6 +5448,7 @@ COM_COMPONENTBUILDER_FOLDER_BSB_WAS_MOVED_TO_BSB="Folder <b>%s</b> was moved to
|
||||
COM_COMPONENTBUILDER_FOLDER_BSB_WAS_NOT_MOVED_TO_BSB="Folder <b>%s</b> was not moved to <b>%s</b>"
|
||||
COM_COMPONENTBUILDER_FORCE_LOCAL_UPDATE="Force Local Update"
|
||||
COM_COMPONENTBUILDER_FORCE_THAT_THIS_JCB_PACKAGE_IMPORT_SEARCH_FOR_LOCAL_ITEMS_TO_BE_DONE_WITH_GUID_VALUE_ONLY_IF_BMERGEB_IS_SET_TO_YES_ABOVE="Force that this JCB package import (search for local items) to be done with GUID value only, if <b>Merge</b> is set to yes above."
|
||||
COM_COMPONENTBUILDER_FOUND="Found"
|
||||
COM_COMPONENTBUILDER_FOUND_TEXT="Found Text"
|
||||
COM_COMPONENTBUILDER_FREEOPEN="Free/Open"
|
||||
COM_COMPONENTBUILDER_FULL_TEXT="Full Text"
|
||||
@ -5493,6 +5494,7 @@ COM_COMPONENTBUILDER_GREAT_THIS_PLACEHOLDER_WILL_WORK="Great, this placeholder w
|
||||
COM_COMPONENTBUILDER_GREAT_THIS_VALIDATION_RULE_NAME_S_WILL_WORK="Great, this validation rule name (%s) will work!"
|
||||
COM_COMPONENTBUILDER_GROUP="group"
|
||||
COM_COMPONENTBUILDER_HAS_METADATA="Has Metadata"
|
||||
COM_COMPONENTBUILDER_HEADERS="Headers"
|
||||
COM_COMPONENTBUILDER_HELP_DOCUMENT="Help Document"
|
||||
COM_COMPONENTBUILDER_HELP_DOCUMENTS="Help Documents"
|
||||
COM_COMPONENTBUILDER_HELP_DOCUMENTS_ACCESS="Help Documents Access"
|
||||
|
43
admin/layouts/rows.php
Normal file
43
admin/layouts/rows.php
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
|
||||
// No direct access to this file
|
||||
defined('JPATH_BASE') or die('Restricted access');
|
||||
|
||||
$headers = $displayData['headers'];
|
||||
$items = $displayData['items'];
|
||||
|
||||
?>
|
||||
<?php if (is_array($items)): ?>
|
||||
<?php foreach ($items as $row => $values): ?>
|
||||
<tr>
|
||||
<?php foreach($values as $value): ?>
|
||||
<td class=""><?php echo $value; ?></td>
|
||||
<?php endforeach; ?>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php elseif (is_numeric($items) && is_array($headers)): ?>
|
||||
<?php for( $row = 0; $row < $items; $row++): ?>
|
||||
<tr class="">
|
||||
<?php foreach($headers as $header): ?>
|
||||
<td class=""> </td>
|
||||
<?php endforeach; ?>
|
||||
</tr>
|
||||
<?php endfor; ?>
|
||||
<?php elseif (is_numeric($items) && is_numeric($headers)): ?>
|
||||
<?php for( $row = 0; $row < $items; $row++): ?>
|
||||
<tr class="">
|
||||
<?php for( $column = 0; $column < $headers; $column++): ?>
|
||||
<td class=""> </td>
|
||||
<?php endfor; ?>
|
||||
</tr>
|
||||
<?php endfor; ?>
|
||||
<?php endif; ?>
|
72
admin/layouts/table.php
Normal file
72
admin/layouts/table.php
Normal file
@ -0,0 +1,72 @@
|
||||
<?php
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
|
||||
// No direct access to this file
|
||||
defined('JPATH_BASE') or die('Restricted access');
|
||||
|
||||
$table_id = (isset($displayData['id'])) ? $displayData['id'] : ComponentbuilderHelper::randomkey(7);
|
||||
$name = (isset($displayData['name'])) ? $displayData['name'] : false;
|
||||
$headers = (isset($displayData['headers'])) ? $displayData['headers'] : [JText::_('COM_COMPONENTBUILDER_NO'), JText::_('COM_COMPONENTBUILDER_HEADERS'), JText::_('COM_COMPONENTBUILDER_FOUND')];
|
||||
$items = (isset($displayData['items'])) ? $displayData['items'] : 6;
|
||||
|
||||
?>
|
||||
<div class="uk-overflow-auto">
|
||||
<table id="<?php echo $table_id; ?>" class="uk-table">
|
||||
<thead>
|
||||
<?php if (is_array($headers)): ?>
|
||||
<?php if ($name): ?>
|
||||
<tr>
|
||||
<th colspan="<?php echo count($headers); ?>" style="text-align:center"><b><?php echo $name; ?></b></th>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
<tr>
|
||||
<?php foreach($headers as $code_name => $header): ?>
|
||||
<?php
|
||||
if (is_numeric($code_name))
|
||||
{
|
||||
$code_name = ComponentbuilderHelper::safeString($header);
|
||||
}
|
||||
?>
|
||||
<th data-name="<?php echo $code_name; ?>"><?php echo $header; ?></th>
|
||||
<?php endforeach; ?>
|
||||
</tr>
|
||||
<?php elseif (is_numeric($headers)): ?>
|
||||
<?php if ($name): ?>
|
||||
<tr>
|
||||
<th colspan="<?php echo (int) $headers; ?>" style="text-align:center"><b><?php echo $name; ?></b></th>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
<tr style="position: absolute; top: -9999px; left: -9999px;">
|
||||
<?php for( $row = 0; $row < $headers; $row++): ?>
|
||||
<th><?php echo ComponentbuilderHelper::safeString($row); ?></th>
|
||||
<?php endfor; ?>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php echo JLayoutHelper::render('rows', ['headers' => $headers, 'items' => $items]); ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php
|
||||
// Initialize the table if [init is not set], or [is true]
|
||||
// To stop initialization set $displayData['init'] = false;
|
||||
if (!isset($displayData['init']) || $displayData['init']) :
|
||||
?>
|
||||
<script type="text/javascript">
|
||||
jQuery(document).ready(function() {
|
||||
var <?php echo $table_id; ?> = jQuery('#<?php echo $table_id; ?>').DataTable({
|
||||
paging: false,
|
||||
select: true
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<?php endif; ?>
|
@ -3619,7 +3619,7 @@ class ComponentbuilderModelAjax extends ListModel
|
||||
* @return array|null
|
||||
* @since 3.2.0
|
||||
**/
|
||||
public function searchTable(string $tableName, string $searchValue,
|
||||
public function doSearch(string $tableName, string $searchValue,
|
||||
int $matchCase, int $wholeWord, int $regexSearch, int $componentId): ?array
|
||||
{
|
||||
// check if this is a valid table
|
||||
@ -3633,7 +3633,7 @@ class ComponentbuilderModelAjax extends ListModel
|
||||
SearchFactory::_('Config')->regex_search = $regexSearch;
|
||||
SearchFactory::_('Config')->component_id = $componentId;
|
||||
|
||||
if (($items = SearchFactory::_('Agent')->find()) !== null)
|
||||
if (($items = SearchFactory::_('Agent')->table($tableName)) !== null)
|
||||
{
|
||||
return ['success' => JText::sprintf('COM_COMPONENTBUILDER_WE_FOUND_SOME_INSTANCES_IN_S', $tableName), 'items' => $items];
|
||||
}
|
||||
@ -3658,7 +3658,7 @@ class ComponentbuilderModelAjax extends ListModel
|
||||
* @return array|null
|
||||
* @since 3.2.0
|
||||
**/
|
||||
public function updateTable(string $tableName, string $searchValue, ?string $replaceValue = null,
|
||||
public function replaceAll(string $tableName, string $searchValue, ?string $replaceValue = null,
|
||||
int $matchCase, int $wholeWord, int $regexSearch, int $componentId): ?array
|
||||
{
|
||||
// check if this is a valid table
|
||||
@ -3673,7 +3673,7 @@ class ComponentbuilderModelAjax extends ListModel
|
||||
SearchFactory::_('Config')->regex_search = $regexSearch;
|
||||
SearchFactory::_('Config')->component_id = $componentId;
|
||||
|
||||
SearchFactory::_('Agent')->replace();
|
||||
// SearchFactory::_('Agent')->replace(); // TODO show danger message before allowing this!!!!!
|
||||
|
||||
return ['success' => JText::sprintf('COM_COMPONENTBUILDER_ALL_FOUND_INSTANCES_IN_S_WHERE_REPLACED', $tableName)];
|
||||
}
|
||||
@ -3693,11 +3693,22 @@ class ComponentbuilderModelAjax extends ListModel
|
||||
public function getSearchValue(string $fieldName, int $rowId, string $tableName): array
|
||||
{
|
||||
// check if this is a valid table and field
|
||||
if ($rowId > 0 && SearchFactory('Table')->exist($tableName, $fieldName) &&
|
||||
($value = SearchFactory('Agent')->getValue($fieldName, $rowId, 0, $tableName)) !== null)
|
||||
if ($rowId > 0 && SearchFactory::_('Table')->exist($tableName, $fieldName))
|
||||
{
|
||||
// load the value
|
||||
return ['value' => $value];
|
||||
// load the configurations
|
||||
SearchFactory::_('Config')->table_name = $tableName;
|
||||
// load dummy data... TODO this should not be needed!
|
||||
SearchFactory::_('Config')->search_value = '';
|
||||
SearchFactory::_('Config')->replace_value = '';
|
||||
SearchFactory::_('Config')->match_case = 0;
|
||||
SearchFactory::_('Config')->whole_word = 0;
|
||||
SearchFactory::_('Config')->regex_search = 0;
|
||||
|
||||
if (($value = SearchFactory::_('Agent')->getValue($rowId, $fieldName, 0, $tableName)) !== null)
|
||||
{
|
||||
// load the value
|
||||
return ['value' => $value];
|
||||
}
|
||||
}
|
||||
return ['error' => JText::_('COM_COMPONENTBUILDER_THERE_HAS_BEEN_AN_ERROR_PLEASE_TRY_AGAIN')];
|
||||
}
|
||||
@ -3722,7 +3733,7 @@ class ComponentbuilderModelAjax extends ListModel
|
||||
string $searchValue, ?string $replaceValue = null, int $matchCase, int $wholeWord, int $regexSearch): array
|
||||
{
|
||||
// check if this is a valid table and field
|
||||
if ($rowId > 0 && SearchFactory('Table')->exist($tableName, $fieldName))
|
||||
if ($rowId > 0 && SearchFactory::_('Table')->exist($tableName, $fieldName))
|
||||
{
|
||||
// load the configurations
|
||||
SearchFactory::_('Config')->table_name = $tableName;
|
||||
@ -3733,7 +3744,7 @@ class ComponentbuilderModelAjax extends ListModel
|
||||
SearchFactory::_('Config')->regex_search = $regexSearch;
|
||||
|
||||
// load the value
|
||||
if (($value = SearchFactory('Agent')->getValue($fieldName, $rowId, $line, $tableName, true)) !== null)
|
||||
if (($value = SearchFactory::_('Agent')->getValue($rowId, $fieldName, $line, $tableName, true)) !== null)
|
||||
{
|
||||
return ['value' => $value];
|
||||
}
|
||||
@ -3755,8 +3766,8 @@ class ComponentbuilderModelAjax extends ListModel
|
||||
public function setValue($value, int $rowId, string $fieldName, string $tableName): array
|
||||
{
|
||||
// check if this is a valid table and field
|
||||
if ($rowId > 0 && SearchFactory('Table')->exist($tableName, $fieldName) &&
|
||||
SearchFactory('Agent')->setValue($value, $rowId, $fieldName, $tableName))
|
||||
if ($rowId > 0 && SearchFactory::_('Table')->exist($tableName, $fieldName) &&
|
||||
SearchFactory::_('Agent')->setValue($value, $rowId, $fieldName, $tableName))
|
||||
{
|
||||
return ['success' => JText::sprintf(
|
||||
'<b>%s</b> (%s:%s) was successfully updated!',
|
||||
|
File diff suppressed because one or more lines are too long
@ -16,7 +16,6 @@ JHtml::addIncludePath(JPATH_COMPONENT.'/helpers/html');
|
||||
JHtml::_('behavior.formvalidator');
|
||||
JHtml::_('formbehavior.chosen', 'select');
|
||||
JHtml::_('behavior.keepalive');
|
||||
use VDM\Joomla\Componentbuilder\Search\Factory as SearchFactory;
|
||||
|
||||
$this->app->input->set('hidemainmenu', false);
|
||||
$selectNotice = '<h3>' . JText::_('COM_COMPONENTBUILDER_HI') . ' ' . $this->user->name . '</h3>';
|
||||
@ -54,33 +53,25 @@ $selectNotice .= '<p>' . JText::_('COM_COMPONENTBUILDER_ENTER_YOUR_SEARCH_TEXT')
|
||||
name="adminForm" id="adminForm" class="form-validate" enctype="multipart/form-data">
|
||||
<div class="form-horizontal">
|
||||
<div class="row-fluid">
|
||||
<div class="span8">
|
||||
<div class="span7">
|
||||
<?php echo $this->form->renderField('type_search'); ?>
|
||||
<?php echo $this->form->renderField('search_value'); ?>
|
||||
<?php echo $this->form->renderField('replace_value'); ?>
|
||||
</div>
|
||||
<div class="span3">
|
||||
<div class="span4">
|
||||
<?php echo $this->form->renderFieldset('settings'); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid" id="search_view">
|
||||
<div id="search-results-tbl-box">
|
||||
<table id="search-results-tbl" class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?php echo JText::_('COM_COMPONENTBUILDER_FOUND_TEXT'); ?></th>
|
||||
<th><?php echo JText::_('COM_COMPONENTBUILDER_TABLE'); ?></th>
|
||||
<th><?php echo JText::_('COM_COMPONENTBUILDER_FIELD'); ?></th>
|
||||
<th><?php echo JText::_('ID'); ?></th>
|
||||
<th><?php echo JText::_('COM_COMPONENTBUILDER_LINE'); ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="search-results-tbl-tbody"></tbody>
|
||||
</table>
|
||||
<div class="row-fluid" id="search_results_view">
|
||||
<hr>
|
||||
<div id="search_results_table_box">
|
||||
<?php echo JLayoutHelper::render('table', ['id' => 'search_results_table', 'headers' => $this->table_headers, 'items' => 7, 'init' => false]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid" id="item_view" style="display: none;">
|
||||
<?php echo $this->form->renderFieldset('view'); ?>
|
||||
<div class="row-fluid" id="item_view_box">
|
||||
<hr>
|
||||
<div id="item_notice"></div>
|
||||
<?php echo $this->form->getInput('full_text'); ?>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@ -88,14 +79,115 @@ $selectNotice .= '<p>' . JText::_('COM_COMPONENTBUILDER_ENTER_YOUR_SEARCH_TEXT')
|
||||
</div>
|
||||
<?php if (isset($this->item['tables']) && ComponentbuilderHelper::checkArray($this->item['tables'])) : ?>
|
||||
<script>
|
||||
var searchTables = json_encode($this->item['tables']);
|
||||
const searchTables = <?php echo json_encode($this->item['tables']); ?>;
|
||||
|
||||
const searchValueInp = document.getElementById("search_value");
|
||||
const replaceValueInp = document.getElementById("replace_value");
|
||||
const caseSensitiveLbl = document.getElementById("match_case_lbl");
|
||||
const completeWordLbl = document.getElementById("whole_word_lbl");
|
||||
const regexpSearchLbl = document.getElementById("regex_search_lbl");
|
||||
// the search Ajax URLs
|
||||
const Url = '<?php echo JUri::base(); ?>index.php?option=com_componentbuilder&format=json&raw=true&<?php echo JSession::getFormToken(); ?>=1&task=ajax.';
|
||||
|
||||
// make sure our controller is set
|
||||
let controller = null;
|
||||
|
||||
// set the search mode object
|
||||
const modeObject = document.getElementById("type_search");
|
||||
|
||||
// set the search settings objects
|
||||
const searchObject = document.getElementById("search_value");
|
||||
const replaceObject = document.getElementById("replace_value");
|
||||
const matchObject = document.getElementById("search_behaviour0");
|
||||
const wholeObject = document.getElementById("search_behaviour1");
|
||||
const regexObject = document.getElementById("search_behaviour2");
|
||||
const tableObject = document.getElementById("table_name");
|
||||
|
||||
// Do the search on key up of search or replace input elements
|
||||
searchObject.onkeyup = onChange;
|
||||
replaceObject.onkeyup = onChange;
|
||||
|
||||
// Do the search on key up of search input elements
|
||||
matchObject.onchange = onChange;
|
||||
wholeObject.onchange = onChange;
|
||||
regexObject.onchange = onChange;
|
||||
tableObject.onchange = onChange;
|
||||
|
||||
// get the editor
|
||||
var editorObject;
|
||||
var editorBoxObject;
|
||||
var editorNoticeObject;
|
||||
|
||||
// set some global objects
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
// get the editor
|
||||
editorObject = Joomla.editors.instances['full_text'];
|
||||
editorBoxObject = document.getElementById("item_view_box");
|
||||
editorNoticeObject = document.getElementById("item_notice");
|
||||
});
|
||||
|
||||
// configurations of the table
|
||||
const tableConfigObject = {
|
||||
responsive: true,
|
||||
order: [[ 2, "asc" ]],
|
||||
select: true,
|
||||
paging: true,
|
||||
lengthMenu: [5, 10, 20 ,50, 80, 100, 150, 200, 500, 1000, 1500, 2000],
|
||||
pageLength: 80,
|
||||
scrollY: 170,
|
||||
columnDefs: [
|
||||
{ 'targets': [ 4, 5 ], 'visible': false, 'searchable': false },
|
||||
{ 'targets': [ 0, 1 ], type: 'html' },
|
||||
{ responsivePriority: 1, targets: 1 },
|
||||
{ responsivePriority: 2, targets: 0 },
|
||||
{ responsivePriority: 3, targets: 2 },
|
||||
{ responsivePriority: 4, targets: 3 }
|
||||
],
|
||||
columns: [
|
||||
{
|
||||
data: 'edit'
|
||||
},
|
||||
{
|
||||
data: 'code'
|
||||
},
|
||||
{
|
||||
data: 'table'
|
||||
},
|
||||
{
|
||||
data: 'field'
|
||||
},
|
||||
{
|
||||
data: 'id'
|
||||
},
|
||||
{
|
||||
data: 'line'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
// The Result Table Code
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
|
||||
// init the table
|
||||
let searchResultsTable = new DataTable('#search_results_table', tableConfigObject);
|
||||
|
||||
searchResultsTable.on( 'select', function ( e, dt, type, indexes ) {
|
||||
if ( type === 'row' ) {
|
||||
// get the data from the row
|
||||
let data = searchResultsTable.rows( indexes ).data();
|
||||
|
||||
// get the item data
|
||||
let item_id = data[0].id;
|
||||
let item_table = data[0].table;
|
||||
let item_field = data[0].field;
|
||||
let item_line = data[0].line;
|
||||
|
||||
// get selected item
|
||||
getSelectedItem(item_table, item_id, item_field, item_line);
|
||||
}
|
||||
});
|
||||
|
||||
searchResultsTable.on( 'deselect', function ( e, dt, type, indexes ) {
|
||||
if ( type === 'row' ) {
|
||||
clearSelectedItem(false);
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<?php endif; ?>
|
||||
<?php else: ?>
|
||||
|
@ -13,7 +13,6 @@
|
||||
defined('_JEXEC') or die('Restricted access');
|
||||
|
||||
use Joomla\CMS\MVC\View\HtmlView;
|
||||
use Joomla\CMS\Filesystem\File;
|
||||
use Joomla\CMS\Form\Form;
|
||||
use VDM\Joomla\Componentbuilder\Search\Factory as SearchFactory;
|
||||
|
||||
@ -45,7 +44,16 @@ class ComponentbuilderViewSearch extends HtmlView
|
||||
|
||||
// get the needed form fields
|
||||
$this->form = $this->getDynamicForm();
|
||||
|
||||
|
||||
// build our table headers
|
||||
$this->table_headers = array(
|
||||
'edit' => 'E',
|
||||
'code' => JText::_('COM_COMPONENTBUILDER_FOUND_TEXT'),
|
||||
'table' => JText::_('COM_COMPONENTBUILDER_TABLE'),
|
||||
'field' => JText::_('COM_COMPONENTBUILDER_FIELD'),
|
||||
'id' => JText::_('ID'),
|
||||
'line' => JText::_('COM_COMPONENTBUILDER_LINE')
|
||||
);
|
||||
|
||||
// We don't need toolbar in the modal window.
|
||||
if ($this->getLayout() !== 'modal')
|
||||
@ -223,7 +231,7 @@ class ComponentbuilderViewSearch extends HtmlView
|
||||
'name' => 'full_text',
|
||||
'label' => 'COM_COMPONENTBUILDER_FULL_TEXT',
|
||||
'width' => '100%',
|
||||
'height' => '450px',
|
||||
'height' => '250px',
|
||||
'class' => 'full_text_editor',
|
||||
'syntax' => 'php',
|
||||
'buttons' => 'false',
|
||||
@ -257,6 +265,12 @@ class ComponentbuilderViewSearch extends HtmlView
|
||||
// Initialize the header checker.
|
||||
$HeaderCheck = new componentbuilderHeaderCheck;
|
||||
|
||||
// always load these files.
|
||||
$this->document->addStyleSheet(JURI::root(true) . "/media/com_componentbuilder/datatable/css/datatables.min.css", (ComponentbuilderHelper::jVersion()->isCompatible("3.8.0")) ? array("version" => "auto") : "text/css");
|
||||
$this->document->addScript(JURI::root(true) . "/media/com_componentbuilder/datatable/js/pdfmake.min.js", (ComponentbuilderHelper::jVersion()->isCompatible("3.8.0")) ? array("version" => "auto") : "text/javascript");
|
||||
$this->document->addScript(JURI::root(true) . "/media/com_componentbuilder/datatable/js/vfs_fonts.js", (ComponentbuilderHelper::jVersion()->isCompatible("3.8.0")) ? array("version" => "auto") : "text/javascript");
|
||||
$this->document->addScript(JURI::root(true) . "/media/com_componentbuilder/datatable/js/datatables.min.js", (ComponentbuilderHelper::jVersion()->isCompatible("3.8.0")) ? array("version" => "auto") : "text/javascript");
|
||||
|
||||
// Add View JavaScript File
|
||||
$this->document->addScript(JURI::root(true) . "/administrator/components/com_componentbuilder/assets/js/search.js", (ComponentbuilderHelper::jVersion()->isCompatible("3.8.0")) ? array("version" => "auto") : "text/javascript");
|
||||
|
||||
@ -277,42 +291,16 @@ class ComponentbuilderViewSearch extends HtmlView
|
||||
{
|
||||
JHtml::_('script', 'media/com_componentbuilder/uikit-v2/js/uikit'.$size.'.js', ['version' => 'auto']);
|
||||
}
|
||||
|
||||
// Load the script to find all uikit components needed.
|
||||
if ($uikit != 2)
|
||||
{
|
||||
// Set the default uikit components in this view.
|
||||
$uikitComp = array();
|
||||
$uikitComp[] = 'uk-progress';
|
||||
}
|
||||
|
||||
// Load the needed uikit components in this view.
|
||||
if ($uikit != 2 && isset($uikitComp) && ComponentbuilderHelper::checkArray($uikitComp))
|
||||
{
|
||||
// load just in case.
|
||||
jimport('joomla.filesystem.file');
|
||||
// loading...
|
||||
foreach ($uikitComp as $class)
|
||||
{
|
||||
foreach (ComponentbuilderHelper::$uk_components[$class] as $name)
|
||||
{
|
||||
// check if the CSS file exists.
|
||||
if (File::exists(JPATH_ROOT.'/media/com_componentbuilder/uikit-v2/css/components/'.$name.$style.$size.'.css'))
|
||||
{
|
||||
// load the css.
|
||||
JHtml::_('stylesheet', 'media/com_componentbuilder/uikit-v2/css/components/'.$name.$style.$size.'.css', ['version' => 'auto']);
|
||||
}
|
||||
// check if the JavaScript file exists.
|
||||
if (File::exists(JPATH_ROOT.'/media/com_componentbuilder/uikit-v2/js/components/'.$name.$size.'.js'))
|
||||
{
|
||||
// load the js.
|
||||
JHtml::_('script', 'media/com_componentbuilder/uikit-v2/js/components/'.$name.$size.'.js', ['version' => 'auto'], ['type' => 'text/javascript', 'async' => 'async']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// add the document default css file
|
||||
$this->document->addStyleSheet(JURI::root(true) .'/administrator/components/com_componentbuilder/assets/css/search.css', (ComponentbuilderHelper::jVersion()->isCompatible('3.8.0')) ? array('version' => 'auto') : 'text/css');
|
||||
// Set the Custom CSS script to view
|
||||
$this->document->addStyleDeclaration("
|
||||
.found_code {
|
||||
color: #46a546;
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<extension type="component" version="4" method="upgrade">
|
||||
<name>COM_COMPONENTBUILDER</name>
|
||||
<creationDate>23rd October, 2022</creationDate>
|
||||
<creationDate>30th October, 2022</creationDate>
|
||||
<author>Llewellyn van der Merwe</author>
|
||||
<authorEmail>joomla@vdm.io</authorEmail>
|
||||
<authorUrl>https://dev.vdm.io</authorUrl>
|
||||
@ -39,6 +39,7 @@ Whether you're a seasoned [Joomla](https://extensions.joomla.org/extension/compo
|
||||
<folder>js</folder>
|
||||
<folder>css</folder>
|
||||
<folder>images</folder>
|
||||
<folder>datatable</folder>
|
||||
<folder>uikit-v2</folder>
|
||||
<folder>footable-v3</folder>
|
||||
</media>
|
||||
|
@ -12,6 +12,7 @@
|
||||
namespace VDM\Joomla\Componentbuilder\Search;
|
||||
|
||||
|
||||
use Joomla\CMS\Language\Text;
|
||||
use VDM\Joomla\Componentbuilder\Search\Factory;
|
||||
use VDM\Joomla\Componentbuilder\Search\Config;
|
||||
use VDM\Joomla\Componentbuilder\Search\Database\Get;
|
||||
@ -20,6 +21,7 @@ use VDM\Joomla\Componentbuilder\Search\Agent\Find;
|
||||
use VDM\Joomla\Componentbuilder\Search\Agent\Replace;
|
||||
use VDM\Joomla\Componentbuilder\Search\Agent\Search;
|
||||
use VDM\Joomla\Componentbuilder\Search\Agent\Update;
|
||||
use VDM\Joomla\Componentbuilder\Search\Table;
|
||||
|
||||
|
||||
/**
|
||||
@ -85,21 +87,55 @@ class Agent
|
||||
*/
|
||||
protected Update $update;
|
||||
|
||||
/**
|
||||
* Table
|
||||
*
|
||||
* @var Table
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected Table $table;
|
||||
|
||||
/**
|
||||
* Return value to search view
|
||||
*
|
||||
* @var string
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected string $return;
|
||||
|
||||
/**
|
||||
* Marker start and end values
|
||||
*
|
||||
* @var array
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected array $marker;
|
||||
|
||||
/**
|
||||
* Marker start and end html values
|
||||
*
|
||||
* @var array
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected array $markerHtml;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param Config|null $config The search config object.
|
||||
* @param Get|null $get The search get database object.
|
||||
* @param Set|null $set The search get database object.
|
||||
* @param Find|null $find The search find object.
|
||||
* @param Replace|null $replace The search replace object.
|
||||
* @param Search|null $search The search object.
|
||||
* @param Config|null $config The search config object.
|
||||
* @param Get|null $get The search get database object.
|
||||
* @param Set|null $set The search get database object.
|
||||
* @param Find|null $find The search find object.
|
||||
* @param Replace|null $replace The search replace object.
|
||||
* @param Search|null $search The search object.
|
||||
* @param Update|null $update The update object.
|
||||
* @param Table|null $table The table object.
|
||||
*
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function __construct(?Config $config = null, ?Get $get = null,
|
||||
?Set$set = null, ?Find $find = null, ?Replace $replace = null,
|
||||
?Search $search = null, ?Update $update = null)
|
||||
?Search $search = null, ?Update $update = null, ?Table $table = null)
|
||||
{
|
||||
$this->config = $config ?: Factory::_('Config');
|
||||
$this->get = $get ?: Factory::_('Get.Database');
|
||||
@ -108,23 +144,23 @@ class Agent
|
||||
$this->replace = $replace ?: Factory::_('Agent.Replace');
|
||||
$this->search = $search ?: Factory::_('Agent.Search');
|
||||
$this->update = $update ?: Factory::_('Agent.Update');
|
||||
$this->table = $table ?: Factory::_('Table');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of a field in a row and table
|
||||
*
|
||||
* @param mixed $value The field value
|
||||
* @param int $id The item ID
|
||||
* @param string $field The field key
|
||||
* @param mixed $line The field line
|
||||
* @param string|null $table The table
|
||||
* @param bool $update The switch to triger an update (default is false)
|
||||
*
|
||||
* @return mixed
|
||||
* @return string
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function getValue(int $id, string $field, $line = null,
|
||||
?string $table = null, bool $update = false)
|
||||
?string $table = null, bool $update = false): string
|
||||
{
|
||||
// set the table name
|
||||
if (empty($table))
|
||||
@ -134,13 +170,19 @@ class Agent
|
||||
|
||||
if (($value = $this->get->value($id, $field, $table)) !== null)
|
||||
{
|
||||
// try to update the value if required
|
||||
if ($update && ($updated_value = $this->update->value($value, $line)) !== null)
|
||||
// we only return strings that can load in an editor
|
||||
if (is_string($value))
|
||||
{
|
||||
return $updated_value;
|
||||
// try to update the value if required
|
||||
if ($update && ($updated_value = $this->update->value($value, $line)) !== null)
|
||||
{
|
||||
return $updated_value;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
return $value;
|
||||
return '// VALUE CAN NOT BE LOADED (AT THIS TIME) SINCE ITS NOT A STRING';
|
||||
}
|
||||
|
||||
return null;
|
||||
@ -168,6 +210,48 @@ class Agent
|
||||
return $this->set->value($value, $id, $field, $table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return Table Ready Search Results
|
||||
*
|
||||
* @param string|null $table The table being searched
|
||||
*
|
||||
* @return array|null
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function table(?string $table = null): ?array
|
||||
{
|
||||
// set the table name
|
||||
if (empty($table))
|
||||
{
|
||||
$table = $this->config->table_name;
|
||||
}
|
||||
|
||||
if(($values = $this->find($table)) !== null)
|
||||
{
|
||||
$table_rows = [];
|
||||
|
||||
// set the return value
|
||||
$this->return = urlencode(base64_encode('index.php?option=com_componentbuilder&view=search'));
|
||||
|
||||
// set the markers
|
||||
$this->marker = [$this->config->marker_start, $this->config->marker_end];
|
||||
$this->markerHtml = ['<span class="found_code">','</span>'];
|
||||
|
||||
foreach ($values as $id => $fields)
|
||||
{
|
||||
foreach ($fields as $field => $lines)
|
||||
{
|
||||
foreach ($lines as $line => $code)
|
||||
{
|
||||
$table_rows[] = $this->getRow($code, $table, $field, $id, $line);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $table_rows;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search the posted table for the search value and return all
|
||||
*
|
||||
@ -233,6 +317,68 @@ class Agent
|
||||
$set++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return prepared code string for table
|
||||
*
|
||||
* @param string $code The code value fro the table
|
||||
* @param string|null $table The table
|
||||
* @param string $field The field key
|
||||
* @param int $id The the row id
|
||||
* @param mixed $line The code line where found
|
||||
*
|
||||
* @return array
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected function getRow(string $code, string $table, string $field, int $id, $line): array
|
||||
{
|
||||
return [
|
||||
'edit' => $this->getRowEditButton($table, $field, $id, $line),
|
||||
'code' => $this->getRowCode($code),
|
||||
'table' => $table,
|
||||
'field' => $field,
|
||||
'id' => $id,
|
||||
'line' => $line
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return prepared code string for table
|
||||
*
|
||||
* @param string $code The code value fro the table
|
||||
*
|
||||
* @return string
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected function getRowCode(string $code): string
|
||||
{
|
||||
return str_replace($this->marker, $this->markerHtml, htmlentities($code));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Item button to edit an item
|
||||
*
|
||||
* @param string|null $view The single view
|
||||
* @param string $field The field key
|
||||
* @param int $id The the row id
|
||||
* @param mixed $line The code line where found
|
||||
*
|
||||
* @return string
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected function getRowEditButton(string $view, string $field, int $id, $line): string
|
||||
{
|
||||
// get list view
|
||||
$views = $this->table->get($view, $field, 'list');
|
||||
|
||||
// return edit link
|
||||
return '<a class="hasTooltip btn btn-mini" href="index.php?option=com_componentbuilder&view=' .
|
||||
$views . '&task=' .
|
||||
$view . '.edit&id=' .
|
||||
$id . '&return=' .
|
||||
$this->return . '" title="' .
|
||||
Text::_('COM_COMPONENTBUILDER_EDIT') . '" ><span class="icon-edit"></span></a>';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,7 @@ class Basic extends Engine implements SearchTypeInterface
|
||||
parent::__construct($config);
|
||||
|
||||
// quote all regular expression characters
|
||||
$searchValue = \preg_quote($this->searchValue);
|
||||
$searchValue = preg_quote($this->searchValue, '/');
|
||||
|
||||
$start = ''; $end = '';
|
||||
|
||||
|
@ -20,17 +20,17 @@ namespace VDM\Joomla\Componentbuilder\Search\Interfaces;
|
||||
interface GetInterface
|
||||
{
|
||||
/**
|
||||
* Get values from a given table
|
||||
* Get a value from a given table
|
||||
* Example: $this->value(23, 'value_key', 'table_name');
|
||||
*
|
||||
* @param string $field The field key
|
||||
* @param int $id The item ID
|
||||
* @param string $field The field key
|
||||
* @param string|null $table The table
|
||||
*
|
||||
* @return mixed
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function value(string $field, int $id, string $table = null);
|
||||
public function value(int $id, string $field, string $table = null);
|
||||
|
||||
/**
|
||||
* Get values from a given table
|
||||
|
@ -70,7 +70,9 @@ class Agent implements ServiceProviderInterface
|
||||
$container->get('Set.Database'),
|
||||
$container->get('Agent.Find'),
|
||||
$container->get('Agent.Replace'),
|
||||
$container->get('Agent.Search')
|
||||
$container->get('Agent.Search'),
|
||||
$container->get('Agent.Update'),
|
||||
$container->get('Table')
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -237,7 +237,7 @@ abstract class StringHelper
|
||||
*
|
||||
* @since 3.0.9
|
||||
*/
|
||||
public static function html($var, $charset = 'UTF-8', $shorten = false, $length = 40)
|
||||
public static function html($var, $charset = 'UTF-8', $shorten = false, $length = 40, $addTip = true)
|
||||
{
|
||||
if (self::check($var))
|
||||
{
|
||||
@ -254,7 +254,7 @@ abstract class StringHelper
|
||||
);
|
||||
if ($shorten)
|
||||
{
|
||||
return self::shorten($string, $length);
|
||||
return self::shorten($string, $length, $addTip);
|
||||
}
|
||||
return $string;
|
||||
}
|
||||
|
57
media/datatable/css/datatables.min.css
vendored
Normal file
57
media/datatable/css/datatables.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
media/datatable/css/index.html
Normal file
1
media/datatable/css/index.html
Normal file
@ -0,0 +1 @@
|
||||
<html><body bgcolor="#FFFFFF"></body></html>
|
1
media/datatable/index.html
Normal file
1
media/datatable/index.html
Normal file
@ -0,0 +1 @@
|
||||
<html><body bgcolor="#FFFFFF"></body></html>
|
1238
media/datatable/js/datatables.min.js
vendored
Normal file
1238
media/datatable/js/datatables.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
media/datatable/js/index.html
Normal file
1
media/datatable/js/index.html
Normal file
@ -0,0 +1 @@
|
||||
<html><body bgcolor="#FFFFFF"></body></html>
|
3
media/datatable/js/pdfmake.min.js
vendored
Normal file
3
media/datatable/js/pdfmake.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
6
media/datatable/js/vfs_fonts.js
Normal file
6
media/datatable/js/vfs_fonts.js
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user