Highlight Rows of Grid based on search terms match - javascript

I have a search box that allows user to type in the values they want to search the grid on. Whatever the user types in the search box should be highlighted on the grid if there is any match.
The code i'm using to try and achieve this is below:
const searchTerms = searchTerm.trim().split(' ').filter((item) => item !== '');
let result = rawGridRecord;
searchTerms.forEach((val) => {
const reText = new RegExp(val, 'gi');
result = result.replace(reText, '<span class="text-highlight">$&</span>');
});
The problem i'm having currently is that if there are more than 1 search terms, it starts to match against '<span class="text-highlight">$&</span>' which is now part of the result string. and this causes a behavior that we dont want. The html starts showing as string in the grid.
How is it possible to achieve this functionality so that all the searchTerms can be highlighted properly without creating issues.

const searchTerms = searchTerm.replace('*', '').trim().split(' ').filter((item) => item !== '');
const searchString = '(' + searchTerms.join('|') + ')';
let result = newName;
if (result) {
const reText = new RegExp(new RegExp(searchString), 'gi');
result = result.replace(reText, '<span class="text-highlight">$&</span>');
}
Tried this and it seems to be working better now. Not sure how full proof this is.

Related

How do I search through an array using a string, which is split into an array?

I currently have a half solution to this, but I was wondering if there is a better way to write this. I have the following array with equipment deliveries:
var deliveries = ["14/02/2020, 11:47,cubicles,A32", "13/02/2020,11:48,relays,A59",etc....]
Which I search through using an input:
var pn = document.getElementById("PN").value;
pn = pn.split(" ");
What I'm trying to achieve is to split the search word with spaces, and check if an index in the array contains all of these words. I currently search up to three words, since the code would become too long using my "solution", if I searched for more. This is my code:
var sArray = []//search results
for(var i = 0; i < deliveries.length; i++){
if (pn.length == 2) {
if(new RegExp(pn[0],"i").test(deliveries[i]) && new RegExp(pn[1],"i").test(deliveries[i])) sArray.push(deliveries[i]);
}
else if (pn.length == 3) {
if(new RegExp(pn[0],"i").test(deliveries[i]) && new RegExp(pn[1],"i").test(deliveries[i])&& new RegExp(pn[2],"i").test(deliveries[i])) sArray.push(deliveries[i]);
}
else {if(new RegExp(pn[0],"i").test(deliveries[i])) sArray.push(deliveries[i])};
}
What would be the correct way to search using all the words in the pn array?
I tried saving the if statements as a string, adding code to the string for each index of pn and then using eval. This turned out to slow the search to a crawl though.
Any help would be appreciated.
Example added for a user searching for "cub a32":
pn = "cub a32"
Which turns into:
pn = ["cub, "a32"]
Results in:
sArray = ["14/02/2020, 11:47,cubicles,A32"]
You could filter the array and check with every or some, depending if you want all or just one search string in an item of deliveries.
var deliveries = ["14/02/2020, 11:47,cubicles,A32", "13/02/2020,11:48,relays,A59"],
input = "cub a32",
pn = input.toLowerCase().split(' '),
result = deliveries.filter(s => pn.every(v => s.toLowerCase().includes(v)));
console.log(result);

Using map\reduce with nested elements in javascript

I have a search form that allows the user to add as many search terms as they like. When the user enters all of the search terms and their search values and clicks search, a text box will be updated with the search terms. I've got this working with a for loop, but I'm trying to improve my dev skills and am looking for a way to do this with map\filter instead.
Here's the code I'm trying to replace:
var searchTerms = $("#search-form").find(".mdc-layout-grid__inner");
var searchString = "";
for(var i = 0; i < searchTerms.length - 1; i ++)
{
var select = $(searchTerms[i]).find(".select2-selection")[0];
var selectText = $(select).select2('data')[0].text + ":";
var textBox = $(searchTerms[i]).find(".mdc-text-field__input")[0];
searchString = searchString += selectText.replace(/\./g,"").replace(/ /g,"") + textBox.value;
if(i < searchTerms.length - 1)
{
searchString = searchString += " ";
}
}
$("#er-search-input").val(searchString);
Here's a codepen of the current solution.
i'm trying the below, but I get the feeling I'm miles away:
const ret = searchTerms.map((u,i) => [
$($(u[i]).find(".select2-selection")[0]).select2('data')[0].text + ":",
$(u[i]).find(".mdc-text-field__input")[0].value,
]);
My question is, is it possible to do this with map?
Firstly you're repeatedly creating a jQuery object, accessing it by index to get an Element object only to then create another jQuery object from that. Instead of doing this, you can use eq() to get a specific element in a jQuery object by its index.
However if you use map() to loop through the jQuery object then you can avoid that entirely by using this to reference the current element in the iteration. From there you can access the required elements. The use of map() also builds the array for you, so all you need to do is join() the results together to build the required string output.
Finally, note that you can combine the regex expressions in the replace() call by using the | operator, and also \s is more robust than using a whitespace character. Try this:
var $searchTerms = $("#search-form").find(".mdc-layout-grid__inner");
var searchString = $searchTerms.map(function() {
var $searchTerm = $(this);
var selectText = $searchTerm.find('.select2-selection').select2('data')[0].text + ':';
var $textBox = $searchTerm.find('.mdc-text-field__input:first');
return selectText.replace(/\.|\s/g, "") + $textBox.val();
}).get().join(' ');
$("#er-search-input").val(searchString);

JS Array Find and Replace?

I have a regular expression happening that searching for all the capitals in a document. It gathers them and puts them into an array no problem.
The issue I am having is I want to replace the items in that array to include a span around each item that was captured in the array and then display the updated result. I've tried a variety of things.
I am at a complete loss. Any help is appreciated. Here was my last attempt
var allCaps = new RegExp(/(?:[A-Z]{2,30})/g);
var capsArray = [];
var capsFound;
while (capsFound = allCaps.exec(searchInput)) {
capsArray.push(capsFound[0]);
}
//for(var x = 0; x < capsArray.length; x++){
//var test = ;
capsArray.splice(0, '<span style="color:green">'+ capsArray +'</span>');
//}
}
You can't convert an entire array's elements like that using splice - you can use .map instead:
capsArray = capsArray.map(c => '<span style="color:green">' + c + '</span>');
Do you need the results in an array? If not, you can wrap all caps in a str using a modified regex:
str.replace(/([A-Z])/g, '<span>$1</span>')
example:
'A--B--C' becomes '<span>A</span>---<span>B</span>---<span>C</span>'
if the array is needed for whatever reason:
str.split(/[^A-Z]+/g).map(x => `<span>${x}</span>`)
example:
'A--B--C' becomes ['<span>A</span>', '<span>B</span>', '<span>C</span>']
Thanks to everyone for the help.
Heres my final solution for anyone else that gets lost along the way
var allCaps = new RegExp(/(?:[A-Z]{2,30})/g);
var capsArray = [];
var capsFound;
while (capsFound = allCaps.exec(searchInput)) {
capsArray.push(capsFound[0]);
}
if(capsArray.length > 0){
resultsLog.innerHTML += "<br><span class='warning'>So many capitals</span><br>";
searchInput = document.getElementById('findAllErrors').innerHTML;
searchInput = searchInput.replace(/([A-Z]{3,30})/g, '<span style="background-color:green">$1</span>');
document.getElementById('findAllErrors').innerHTML = searchInput;
}
else {
resultsLog.innerHTML += "";
}

Inserting a string at a variable index

I have not been able to find a working example or a good explanation of how I can achieve the following: (I would appreciate if anyone can point me in the right direction.
I have a query string: **"/api/bla?sources=[1,2]&plans=[1,2]&codes=[1,2,3]"**
I will be updating the query string via either javascript or jquery when certain events occur on my page, doesnt matter which.
For example, there is a multi select dropdown on the page which houses [sources] and [plans] and [codes]... These dropdowns have IDs which i am to update my request url with upons selecting items in teh dropdowns.
When a source with ID "3" is selected from the dropdown (or checkbox, doesnt matter what page controls are being used) the query string parameter sources[1,2] will need a "3" appended. Likewise then if the item with an ID of "2" is unselected, it will likewise be removed from the query string leaving the new string as sources[1,3]
I am somewhat new to javascript/jquery and especially more advanced string manipulation. I have been attempting to recreate something to demonstrate this and have gotten to the following which is not fully working.
Basically my initial if statement works as intended, but the moment the else is hit (when another ID needs to be added to an existing model in the query string - like a second ID for [sources] or [codes]) it returns wonky output - seeng as I couldnt get the right formula to update everything correctly.
//TIMEMTABLE QUERY
function updateCalendar(filter_id, filter_element) {
//Run through the filter checks before making final call to query and update timetable?
//GET THE MODEL/OBJECT NAME
var queryName = filter_element.attr('data-owner');
//GET THE IDs //this is either an array of all selected IDs or a single id which is used in the else statement
var queryId = filter_element.attr('value');
var queryIds = $('#'+filter_id).val();
var modelCheckIndex = requestString.toLowerCase().indexOf(queryName.toLowerCase());
//build a request string
if (modelCheckIndex < 0) {
console.info('ADD MODEL TO QUERY STRING');
requestString = requestString + "&" + (queryName.toLowerCase() + "[" + queryIds + "]");
console.log(requestString);
}
else{
console.info('UPDATE MODEL ON QUERY STRING');
var position = requestString.toLowerCase().indexOf(queryName.toLowerCase());
//requestString = requestString.substr(modelCheckIndex -1, requestString.length -1) + "," + queryId + "]";
requestString = requestString.slice(modelCheckIndex.indexOf("]"), modelCheckIndex) + "," + queryId;
console.log(requestString);
}
//MAKE THE API CALL USING CREATED QUERY STRING
}
If anyone has any examples or fiddles lying around I would also appreciate it.
Fiddle I am trying to get to work
It looks like you are just having trouble parsing and updating a query string. In which case, I have a function I've been using for that (thank you Google)
function getUriParams(string) {
var params = {},
queryString = string.slice(string.lastIndexOf('?')).substring(1),
regex = /([^&=]+)=([^&]*)/g,
m;
while (m = regex.exec(queryString)) {
params[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
}
return params;
}
The input is your requestString and the output is an object of key value pairs of the query string.
To make the object a string, jQuery makes it easy with $.param().
//get key value pairs
var obj = getUriParams(requestString);
//make query string
var str = $.param(obj);
I suggest to change the logic a bit. I would use some data storage for the wanted parameter and rebuild the request string every time when it's necessary, like the below example.
It is much more better, than rebuild the string each time when some value has changed.
var data = {
sources: [1, 2],
plans: [],
codes: [1, 3, 4]
};
function buildStr() {
function get(key) { return key + '=' + JSON.stringify(data[key]); }
return '/api/bla?' + ['sources', 'plans', 'codes'].map(get).join('&');
}
document.write('<pre>' + buildStr() + '</pre>');

Need to place comma after each field with proper validation

I have 3 fields for user input.. say textbox1,textbox2,textbox3. What i need to do is represent them like this if values are not empty:
Albany, New York, USA
The last textbox value shouldnt have a comma after that. I was able to do it with an associative array but the problem is i couldnt find a way to detect if it was the last value and after that the comma need not appear.Here is what i did
var addressObjToFormat= {};
addressObjToFormat.City = $("#companyentry").find("#City").val();
addressObjToFormat.State = $("#companyentry").find("#State").val();
addressObjToFormat.Country = $("#companyentry").find("#Country").val();
var formattedAddress = $Utils.mapInfoMarkerAddressFormatter(addressObjToFormat);
mapInfoMarkerAddressFormatter = function mapInfoMarkerAddressFormatter(arraddressObjToFormat) {
var formattedAddress = '';
for (var key in addressToFormatObj) {
if (addressToFormatObj.hasOwnProperty(key)) {
if (addressToFormatObj[key] != '') {
formattedAddress += addressToFormatObj[key] + ',';
}
}
}
alert(formattedAddress);
}
Above code gives me result as :
Albany, New York, USA,
Mumbai, Maharshtra, India,
What i want is it should be able to check if its the last field incase if a textbox is left empty and place comma accordingly after each value. Or is there a better way to do this?
You can use substring, jsfiddle
formattedAddress = formattedAddress.substring(0, formattedAddress.length-1);
or
you can save all values in an array and use Array.join eg.
var arr = ['item1','item3','item3','item4'];
formattedAddress = arr.join(' ,');
There are multiple ways to do this
After all your processing, you can just trim off the last ',' as using a regex
formattedAddress = formattedAddress.replace (/,$/g, "");
Alternatively, you can just push your strings into an array and then join them all.
var tmp = [];
for (var key in addressToFormatObj) {
if (addressToFormatObj.hasOwnProperty(key)) {
if (addressToFormatObj[key]) { // your condition
tmp.push(addressToFormatObj[key]);
}
}
}
var formattedAddress = tmp.join(',');
var formattedAddress = addressToFormatObj.join(',');
The array function join() uses its first parameter as a glue to put in between array segments.

Categories

Resources