From 461edf5c3f4d369f4ada94c57a79803df3f71e6c Mon Sep 17 00:00:00 2001 From: Llewellyn van der Merwe Date: Tue, 8 Nov 2022 23:55:02 +0200 Subject: [PATCH] Adds option to stop and start a search. Adds better user experience to the search area. --- README.md | 4 +- admin/README.txt | 4 +- admin/assets/css/search.css | 9 +- admin/assets/js/search.js | 103 ++++++++++++++++-- .../en-GB/en-GB.com_componentbuilder.ini | 6 +- admin/views/search/tmpl/default.php | 99 +++++++++++------ admin/views/search/view.html.php | 11 +- componentbuilder.xml | 2 +- 8 files changed, 179 insertions(+), 59 deletions(-) diff --git a/README.md b/README.md index e74691b70..0be143219 100644 --- a/README.md +++ b/README.md @@ -140,11 +140,11 @@ 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*: 4th November, 2022 ++ *Last Build*: 8th November, 2022 + *Version*: 3.1.11 + *Copyright*: Copyright (C) 2015 Vast Development Method. All rights reserved. + *License*: GNU General Public License version 2 or later; see LICENSE.txt -+ *Line count*: **334175** ++ *Line count*: **334294** + *Field count*: **2004** + *File count*: **2183** + *Folder count*: **381** diff --git a/admin/README.txt b/admin/README.txt index e74691b70..0be143219 100644 --- a/admin/README.txt +++ b/admin/README.txt @@ -140,11 +140,11 @@ 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*: 4th November, 2022 ++ *Last Build*: 8th November, 2022 + *Version*: 3.1.11 + *Copyright*: Copyright (C) 2015 Vast Development Method. All rights reserved. + *License*: GNU General Public License version 2 or later; see LICENSE.txt -+ *Line count*: **334175** ++ *Line count*: **334294** + *Field count*: **2004** + *File count*: **2183** + *Folder count*: **381** diff --git a/admin/assets/css/search.css b/admin/assets/css/search.css index 4e3931cb1..56b77adcf 100644 --- a/admin/assets/css/search.css +++ b/admin/assets/css/search.css @@ -11,13 +11,16 @@ /* CSS Document */ .selected { - background-color:#d7d8db !important + background-color:#d7d8db !important } tr.selected td { - background-color:#d7d8db !important + background-color:#d7d8db !important +} +#search_settings_block .controls { + margin-left: 1px !important; } tr { - cursor:pointer + cursor:pointer } .found_code { color: #46a546; diff --git a/admin/assets/js/search.js b/admin/assets/js/search.js index c19d10da7..b228251b3 100644 --- a/admin/assets/js/search.js +++ b/admin/assets/js/search.js @@ -45,6 +45,12 @@ const doSearch = async (signal, tables) => { // 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(); @@ -99,6 +105,7 @@ const doSearch = async (signal, tables) => { // 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 @@ -109,6 +116,10 @@ const doSearch = async (signal, tables) => { } 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'; @@ -214,8 +225,13 @@ const getSelectedItem = async (table, row, field, line) => { * 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_REPLACE_BALLB_SEARCH_RESULTS') + '
' + + let question = Joomla.JText._('COM_COMPONENTBUILDER_YOUR_ARE_ABOUT_TO_UPDATE_BALLB_VALUES_THAT_CAN_BE_FOUND_IN_THE_DATABASE') + '
' + + Joomla.JText._('COM_COMPONENTBUILDER_YOU_WILL_REPLACE') + ': [' + htmlentities(searchValue) + '] ' + + Joomla.JText._('COM_COMPONENTBUILDER_WITH') + ': [' + htmlentities(replaceValue) + ']
' + Joomla.JText._('COM_COMPONENTBUILDER_THIS_CAN_NOT_BE_UNDONE_BYOU_HAVE_BEEN_WARNEDB') + '

' + Joomla.JText._('COM_COMPONENTBUILDER_ARE_YOU_THEREFORE_ABSOLUTELY_SURE_YOU_WANT_TO_CONTINUE'); // do check @@ -325,7 +341,7 @@ const replaceAll = async (signal, tables) => { setSearch(replaceValue, searchValue, matchValue, wholeValue, regexValue, 2); }, function () { UIkit.modal.confirm(Joomla.JText._('COM_COMPONENTBUILDER_WOULD_YOU_LIKE_TO_REPEAT_THE_SAME_SEARCH'), function(){ - onChange(); + startSearch(); }, function () { clearSearch(); }, {labels: { Ok: Joomla.JText._('COM_COMPONENTBUILDER_YES'), Cancel: Joomla.JText._('COM_COMPONENTBUILDER_NO') }}); @@ -333,7 +349,7 @@ const replaceAll = async (signal, tables) => { } 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(){ - onChange(); + startSearch(); }, function () { clearSearch(); }, {labels: { Ok: Joomla.JText._('COM_COMPONENTBUILDER_YES'), Cancel: Joomla.JText._('COM_COMPONENTBUILDER_NO') }}); @@ -471,7 +487,7 @@ const clearTableItems = async () => { table.clear().draw( true ); // hide the update all items - buttonUpdateAllObject.style.display = 'none'; + buttonUpdateAllStyleDisplay('none'); }; /** @@ -500,14 +516,14 @@ const setSearch = async (search, replace = '', match = 0, whole = 0, regex = 0, // update the type of search if (mode == 1) { window.location.href = UrlSearch + - '&search_value=' + search + + '&search_value=' + urlencode(search) + '&type_search=1&match_case=' + match + '&whole_word=' + whole + '®ex_search=' + regex; } else if (mode == 2) { window.location.href = UrlSearch + - '&search_value=' + search + - '&replace_value=' + replace + + '&search_value=' + urlencode(search) + + '&replace_value=' + urlencode(replace) + '&type_search=2&match_case=' + match + '&whole_word=' + whole + '®ex_search=' + regex; @@ -546,16 +562,25 @@ const removeClass = (elementObject, classNaam) => { const addTableItems = async (table, items, typeSearch) => { table.rows.add(items).draw( false ); if (typeSearch == 2) { - buttonUpdateAllObject.style.display = ''; // TODO should only show once all items are loaded + buttonUpdateAllStyleDisplay(''); // TODO should only show once all items are loaded } else { - buttonUpdateAllObject.style.display = 'none'; // TODO should only show once all items are loaded + 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 onChange = () => { +const startSearch = (field, forced = false) => { // get replace value if set const replaceValue = replaceObject.value; if (replaceValue.length > 0) { @@ -566,7 +591,7 @@ const onChange = () => { } // get search value const searchValue = searchObject.value; - if (searchValue.length > 2) { + if (searchValue.length > 3 || (searchValue.length > 0 && forced)) { // Cancel any ongoing requests if (controller) controller.abort(); @@ -594,6 +619,23 @@ const onChange = () => { } }; +/** + * 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 */ @@ -831,3 +873,42 @@ function getHtmlTranslationTable(table, quoteStyle) { // eslint-disable-line cam 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, '+') +} \ No newline at end of file diff --git a/admin/language/en-GB/en-GB.com_componentbuilder.ini b/admin/language/en-GB/en-GB.com_componentbuilder.ini index 63205ffae..535f2324a 100644 --- a/admin/language/en-GB/en-GB.com_componentbuilder.ini +++ b/admin/language/en-GB/en-GB.com_componentbuilder.ini @@ -8996,6 +8996,8 @@ COM_COMPONENTBUILDER_SORRY_THIS_PLACEHOLDER_IS_ALREADY_IN_USE_IN_THE_COMPILER="S COM_COMPONENTBUILDER_SORRY_THIS_VALIDATION_RULE_NAME_S_ALREADY_EXIST_AS_PART_OF_THE_JOOMLA_CORE_NO_NEED_TO_CREATE_IT_IF_YOU_ARE_ADAPTING_IT_GIVE_IT_YOUR_OWN_UNIQUE_NAME="Sorry this validation rule name (%s) already exist as part of the Joomla core! No need to create it, if you are adapting it give it your own unique name." COM_COMPONENTBUILDER_SORRY_THIS_VALIDATION_RULE_NAME_S_ALREADY_EXIST_IN_YOUR_SYSTEM="Sorry this validation rule name (%s) already exist in your system!" COM_COMPONENTBUILDER_SORTABLE="Sortable" +COM_COMPONENTBUILDER_START_A_SEARCH="Start a Search" +COM_COMPONENTBUILDER_STOP_A_SEARCH="Stop a Search" COM_COMPONENTBUILDER_SUBMENU="Submenu" COM_COMPONENTBUILDER_SUBMENU_ADMIN_VIEWS="Admin Views" COM_COMPONENTBUILDER_SUBMENU_COMPILER="Compiler" @@ -9434,11 +9436,12 @@ COM_COMPONENTBUILDER_WE_SUCCESSFULLY_MOVED_BSB="We successfully moved %s! COM_COMPONENTBUILDER_WHILE_WE_DOWNLOAD_ALL_TWENTY_SIX_COMPILER_GIF_ANIMATIONS_RANDOMLY_USED_IN_THE_COMPILER_GUI_DURING_COMPILATION="While we download all 26 compiler GIF animations randomly used in the compiler GUI during compilation" COM_COMPONENTBUILDER_WHOLE_WORD="Whole Word" COM_COMPONENTBUILDER_WIKI="Wiki" +COM_COMPONENTBUILDER_WITH="with" COM_COMPONENTBUILDER_WOULD_YOU_LIKE_TO_DO_A_REVERSE_SEARCH="Would you like to do a reverse search?" COM_COMPONENTBUILDER_WOULD_YOU_LIKE_TO_REPEAT_THE_SAME_SEARCH="Would you like to repeat the same search?" COM_COMPONENTBUILDER_YES="Yes" COM_COMPONENTBUILDER_YES_UPDATE_ALL="Yes! Update ALL" -COM_COMPONENTBUILDER_YOUR_ARE_ABOUT_TO_REPLACE_BALLB_SEARCH_RESULTS="Your are about to replace ALL search results." +COM_COMPONENTBUILDER_YOUR_ARE_ABOUT_TO_UPDATE_BALLB_VALUES_THAT_CAN_BE_FOUND_IN_THE_DATABASE="Your are about to update ALL values that can be found in the database." COM_COMPONENTBUILDER_YOUR_ARE_ABOUT_TO_UPDATE_ROW="Your are about to update row" COM_COMPONENTBUILDER_YOUR_DATA_IS_ENCRYPTED_WITH_A_AES_ONE_HUNDRED_AND_TWENTY_EIGHT_BIT_ENCRYPTION_USING_THE_ABOVE_THIRTY_TWO_CHARACTER_KEY="Your data is encrypted with a AES 128 bit encryption using the above 32 character key." COM_COMPONENTBUILDER_YOUR_DATA_IS_ENCRYPTED_WITH_A_AES_ONE_HUNDRED_AND_TWENTY_EIGHT_BIT_ENCRYPTION_USING_THE_ABOVE_THIRTY_TWO_CHARACTER_KEY_WITHOUT_THIS_KEY_IT_WILL_TAKE_THE_CURRENT_TECHNOLOGY_WITH_A_BRUTE_FORCE_ATTACK_METHOD_MORE_THEN_A_HREFHTTPRANDOMIZECOMHOWLONGTOHACKPASS_TARGET_BLANK_TITLEHOW_LONG_TO_HACK_PASSSEVEN_HUNDRED_ZERO_ZERO_ZERO_ZERO_ZERO_ZERO_ZERO_ZERO_ZERO_ZEROA_YEARS_TO_CRACK_THEORETICALLY_UNLESS_THEY_HAVE_THIS_KEY_ABOVE_SO_DO_KEEP_IT_SAFE="Your data is encrypted with a AES 128 bit encryption using the above 32 character key. Without this key it will take the current technology with a brute force attack method more then 700 000 000 000 000 000 000 000 000 000 000 years to crack theoretically. Unless they have this key above, so do keep it safe." @@ -9468,6 +9471,7 @@ COM_COMPONENTBUILDER_YOU_MUST_SELECT_A_COMPONENT="You must select a component!" COM_COMPONENTBUILDER_YOU_SHOULD_ADD_THE_CORRECT_OWNER_DETAILS="You should add the correct owner details." COM_COMPONENTBUILDER_YOU_SHOULD_ONLY_CONTINUE_THIS_IMPORT_IF_YOU_HAVE_BACKUP_YOUR_COMPONENTS_AND_INSURED_THAT_THE_PACKAGE_OWNER_IS_REPUTABLE="You should only continue this import if you have backup your components, and insured that the package owner is reputable." COM_COMPONENTBUILDER_YOU_WILL_NEED_TO_KNOW_HOW_S_WORKS_BASIC_YOU_WILL_ALSO_NEED_A_S_ACCOUNT_AND_KNOW_HOW_TO_MAKE_A_PULL_REQUEST_ON_GITHUB="you will need to know how %s works (basic). You will also need a %s account and know how to make a pull request on github." +COM_COMPONENTBUILDER_YOU_WILL_REPLACE="You will replace" COM_COMPONENTBUILDER_ZIPPED_FILE_LOCATION="Zipped File Location" COM_COMPONENTBUILDER__ADD_YOUR_PHP_SCRIPT_HERE="// Add your php script here" COM_COMPONENTBUILDER__HAS_BEEN_CHECKED_OUT_BY_S="% has been checked out by %s" diff --git a/admin/views/search/tmpl/default.php b/admin/views/search/tmpl/default.php index fa0bfe9c4..3861bc6d4 100644 --- a/admin/views/search/tmpl/default.php +++ b/admin/views/search/tmpl/default.php @@ -22,7 +22,10 @@ $this->app->input->set('hidemainmenu', false); // set the basu URL $url_base = JUri::base() . 'index.php?option=com_componentbuilder'; -$url_search = $url_base . '&view=search'; +$url_search = $url_base . '&view=search'; + +// get main search input field +$search_value = $this->form->getField('search_value'); ?> canDo->get('search.access')): ?> diff --git a/admin/views/search/view.html.php b/admin/views/search/view.html.php index 407404325..f6a4578c1 100644 --- a/admin/views/search/view.html.php +++ b/admin/views/search/view.html.php @@ -62,7 +62,9 @@ class ComponentbuilderViewSearch extends HtmlView JText::script('COM_COMPONENTBUILDER_FIELD_IN_THE'); JText::script('COM_COMPONENTBUILDER_TABLE'); JText::script('COM_COMPONENTBUILDER_THIS_CAN_NOT_BE_UNDONE_ARE_YOU_SURE_YOU_WANT_TO_CONTINUE'); - JText::script('COM_COMPONENTBUILDER_YOUR_ARE_ABOUT_TO_REPLACE_BALLB_SEARCH_RESULTS'); + JText::script('COM_COMPONENTBUILDER_YOUR_ARE_ABOUT_TO_UPDATE_BALLB_VALUES_THAT_CAN_BE_FOUND_IN_THE_DATABASE'); + JText::script('COM_COMPONENTBUILDER_YOU_WILL_REPLACE'); + JText::script('COM_COMPONENTBUILDER_WITH'); JText::script('COM_COMPONENTBUILDER_THIS_CAN_NOT_BE_UNDONE_BYOU_HAVE_BEEN_WARNEDB'); JText::script('COM_COMPONENTBUILDER_ARE_YOU_THEREFORE_ABSOLUTELY_SURE_YOU_WANT_TO_CONTINUE'); JText::script('COM_COMPONENTBUILDER_THE_SEARCH_PROCESS_HAD_AN_ERROR_WITH_TABLE'); @@ -127,6 +129,7 @@ class ComponentbuilderViewSearch extends HtmlView $attributes = [ 'type' => 'radio', 'name' => 'type_search', + 'hiddenLabel' => true, 'label' => 'COM_COMPONENTBUILDER_MODE', 'class' => 'btn-group', 'description' => 'COM_COMPONENTBUILDER_SEARCH_OR_SEARCH_AND_REPLACE', @@ -146,12 +149,13 @@ class ComponentbuilderViewSearch extends HtmlView $attributes = [ 'type' => 'text', 'name' => 'search_value', + 'hiddenLabel' => true, 'label' => 'COM_COMPONENTBUILDER_SEARCH', 'size' => 150, 'maxlength' => 200, 'description' => 'COM_COMPONENTBUILDER_HERE_YOU_CAN_ENTER_YOUR_SEARCH_TEXT', 'filter' => 'RAW', - 'class' => 'search-value span12', + 'class' => 'search-value span11', 'hint' => 'COM_COMPONENTBUILDER_ENTER_YOUR_SEARCH_TEXT', 'autocomplete' => true, 'default' => $this->urlvalues['search_value']]; @@ -166,12 +170,13 @@ class ComponentbuilderViewSearch extends HtmlView $attributes = [ 'type' => 'text', 'name' => 'replace_value', + 'hiddenLabel' => true, 'label' => 'COM_COMPONENTBUILDER_REPLACE', 'size' => 150, 'maxlength' => 200, 'description' => 'COM_COMPONENTBUILDER_HERE_YOU_CAN_ENTER_THE_REPLACE_TEXT_THAT_YOU_WOULD_LIKE_TO_USE_AS_REPLACEMENT_FOR_THE_SEARCH_TEXT_FOUND', 'filter' => 'RAW', - 'class' => 'replace-value span12', + 'class' => 'replace-value span11', 'hint' => 'COM_COMPONENTBUILDER_ENTER_YOUR_REPLACE_TEXT', 'autocomplete' => true, 'showon' => 'type_search:2', diff --git a/componentbuilder.xml b/componentbuilder.xml index 75344dfd3..3c5b4b889 100644 --- a/componentbuilder.xml +++ b/componentbuilder.xml @@ -1,7 +1,7 @@ COM_COMPONENTBUILDER - 4th November, 2022 + 8th November, 2022 Llewellyn van der Merwe joomla@vdm.io https://dev.vdm.io