Advanced table filtre using js - javascript

I am a newcomer and I need some help with a js code.
I want to create a tabel filter like https://www.w3schools.com/howto/howto_js_filter_table.asp .
The script works almost perfect.
On the first 3 columns the filter work perfect, what I want more is that on the last 2 columns when you search for a dimension or code I want to display only the matched value, not all of product values.
To explain the table a bit:
Is an 5 columns table, where some of the first 3 columns have rowspan attribute because is same product but with different dimensions and codes.
If I search on dimension input the value "70" the script output all the products where is found the value 70 with all dimensions, but i want to display only the value requested and hide other values that does not meet the request ( currently it displays 170 as well as 210 values, but I need to display only the 170 values.)
I put the link for the code here: https://jsfiddle.net/mitza_dragan/vg9e0fkr/3/
Part of my js code below:
if(inp.id === "my" + cell.className) {
// Daca se gaseste valoarea din input in valoare din celula,
// seteaza seteaza true (s-a gasit macar o valoare in tot randul)
if(matchedCellText.indexOf(inp.value.toLowerCase()) > -1) {
matched = true;
// Daca s-a gasit macar un match, sari peste restul celulelor
// din randul actual
break;
}
}
For the complet view of the app follow the link above.
Thanks.

Welcome to StackOverflow :)
Thanks for sharing a working JS fiddle. I tried working on the fiddle and came up with a solution, can you check this fiddle and let me know whether it works out for you as per your requirements?
I'll explain the approach followed:
First of all, as the last two columns are a little bit different, you'll have to treat them separately. So, in case the search fields of the last two columns are not empty, we will not break out of all the loops and hide the entire row, instead we will loop through until all the cells are checked and then hide the miniRow or the entire row.
We can check whether mydimensiune or mycod inputs are empty of not by the following line of code :
const isDimensiuneOrCodSearchInput = nonEmptySearchInputs.findIndex( (input) => {
return (input.id == "mydimensiune" || input.id == "mycod")
});
If isDimensiuneOrCodSearchInput is -1 then both the 4th and 5th column search fields are empty and we need not worry about showing/ hiding any miniRow. This is where your code is working perfectly fine for the first three columns.
If isDimensiuneOrCodSearchInput is not -1, then either of the 4th or 5th column search fields are not empty and we need to check whether we should show/ hide the miniRow based on the cell value match.
Inside the miniRows for loop, a new variable has been introduced called as isHideMiniRow which would determine whether the current miniRow should be hidden or not.
Inside the cells for loop, if the cell value doesn't match with the input value, an if block has been added
if( cell.className == "dimensiune" || cell.className == "cod" ) {
isHideMiniRow = true;
}
This block sets the isHideMiniRow to true and in the miniRow for loop we check for this variable and hide the miniRow if none of the search fields match.
Also, we'll have to again show the miniRows when backspace is pressed, so the following lines of code has been added to do that :
const tableRows = document.querySelectorAll("tbody.table-row>tr");
tableRows.forEach(tableRow => tableRow.style.display = "table-row");
I've tried my best to describe the changes done to the code. Let me know if you want further clarity in the above approach.

Related

How can I write the code to append all of the items(XPages)?

I have many documents in Notes, all of the documents have a different form, like this picture :
(possibly like pic 1, pic 2, or pic 3)
How can I write the code in Xpages?
use the "computed field"? Or use the "input text"?
I used the "input text".But only for one item, not for all.
var doc = purchase.getDocument();
var A0 = doc.getItemValueString("DAY_A0");
if(A0 != 0){
return "Division processing";
}
If the form not only has one item, like the pics. How can I write the code to append all of the items?
I'm making the following assumptions here:
You have 10 fields in the document with numbers that might or might not be > 0
The 11th value (Total) shall be computed
You want to show one document at a time, not a list
You know how to add a data source to a page
Version 1:
Create a regular XPages form, use the wizard when adding the document data source. It now would show also the field with 0 values
Click on each ROW and change visibility property to computed (make sure you hit the row, not the cell or field) and add a visibility formula based on the field oof that row. Something like doc.DAY_A0 > 0
Add a computed field where you add the values of all 11 fields
done
Version 2:
in the page open event, get a handle on the document and compute a scoped variable that only contains the values you are interested in. Could be messy since you need a label (that is not your field name) and a value
Use a repeat control to render the values
Hope that helps

Qualtrics display logic interferes with javascript .hide()

I have a side-by-side question in Qualtrics with 30 rows. Each of the first 20 rows has display logic such that they only appear when something is entered in text boxes in prior questions. Each of the last 10 rows has display logic such that at least 10 rows show up in the entire question, i.e. row 21 only shows up if none of the first 20 are displayed, row 22 shows up if only one of the first 20 are displayed... row 30 shows up if 9 of the first rows are displayed, and none of them appear if at least 10 of the first rows are displayed.
The first column of the question is a checkbox, and I'm using the following Javascript to hide the checkboxes for the last 10 rows:
Qualtrics.SurveyEngine.addOnload(function()
{
var qid = this.questionId;
var p = $(qid);
p.down('label[for="QR~'+qid+'#1~21~1"]').hide();
p.down('label[for="QR~'+qid+'#1~22~1"]').hide();
p.down('label[for="QR~'+qid+'#1~23~1"]').hide();
p.down('label[for="QR~'+qid+'#1~24~1"]').hide();
p.down('label[for="QR~'+qid+'#1~25~1"]').hide();
p.down('label[for="QR~'+qid+'#1~26~1"]').hide();
p.down('label[for="QR~'+qid+'#1~27~1"]').hide();
p.down('label[for="QR~'+qid+'#1~28~1"]').hide();
p.down('label[for="QR~'+qid+'#1~29~1"]').hide();
p.down('label[for="QR~'+qid+'#1~30~1"]').hide();
});
It works fine if none of the previous rows are displayed:
But bombs if even one of the previous rows is displayed:
I poked around with Inspect Element on the preview to see if the tags changed somehow, but couldn't find anything unexpected as far as changing IDs. When checking the element for the checkbox on row 23 when none of the first 20 rows appear:
<input id="QR~QID4#1~23~1" name="QR~QID4#1~23~1" value="Selected"
data-runtime-checked="runtime.Children.1.Choices.23.Answers.1.Selected"
aria-labelledby="question1QID4 question1QID4-answer1QID4 choice23QID4"
class="QWatchTimer" type="checkbox">
<label for="QR~QID4#1~23~1" class="q-checkbox" data-runtime-class
-q-checked="runtime.Children.1.Choices.23.Answers.1.Selected"
style="display: none;"></label>
As expected, the label code is grayed out. When one of the first 20 rows appears, it's much the same, but style="display: none;" does not appear at the end:
<input id="QR~QID4#1~23~1" name="QR~QID4#1~23~1" value="Selected"
data-runtime-checked="runtime.Children.1.Choices.23.Answers.1.Selected"
aria-labelledby="question1QID4 question1QID4-answer1QID4 choice23QID4"
class="QWatchTimer" type="checkbox">
<label for="QR~QID4#1~23~1" class="q-checkbox" data-runtime-class
-q-checked="runtime.Children.1.Choices.23.Answers.1.Selected"></label>
I'm at a loss for how activation of display logic would interfere with the Javascript.
After a few hours of percolating, I remembered that if a display logic hides an item with Javascript, that script won't run. I hadn't realized that it's not just on a line-by line basis - looks like if one element controlled by one line of code gets hidden, the whole block of code gets invalidated.
I was able to solve it with a loop that dynamically considered only the rows that would be displayed:
Qualtrics.SurveyEngine.addOnload(function()
{
//Remove checkboxes for last ten options
var qid = this.questionId;
var p = $(qid);
var count = Qualtrics.SurveyEngine.getEmbeddedData('count');
var min = 21+count;
for (var i = min; i < 31; i++) {
p.down('label[for="QR~'+qid+'#1~'+i+'~1"]').hide();
}
});
At least in my case, the count variable was used to determine how many of the last 10 rows to display. Once I built that into the parameters for the loop, nothing would be invalidated by the display logic. (Check here for the process on that if interested.)
Lesson learned: I should've been using a loop to begin with - modifying the parameters is an easy step after that.

DataTables column.visible hides the first column despite returning true

I'm using Data Tables and jQuery right now. I have a simple table that has settings that are toggled via checkbox. When the setting is clicked (checked), I get the elements attr('data-column') and use that to either show or hide that table column based on what the user wants.
This works when the user selects a setting by using the following code:
// User clicks on a checkbox to toggle a setting on/off
$('.setting').click(function(){
let table = $('#my-table');
const current_element = $('input[name="test"][type="checkbox"]');
const data_column_number = current_element.attr('data-column');
if(current_element.is(":checked")){
current_element.prop('checked',false);
table.column(data_column_number).visible(false);
}
else {
current_element.prop('checked',true);
table.column(data_column_number).visible(true);
}
});
Now, I have the user's pre-saved settings in a JSON array. I iterate through the array, and if a setting is checked I make the column number visible (visible(true)). If the setting should not be checked I set it's visible attribute to false (visible(false)). It looks like this:
let table = $('#my-table');
// assume value has an index called ['checked'] that is empty or set to 'checked'
$.each(settings,function(key,value){
let current_element = $('input[name="'+key+'"][type="checkbox"]');
let data_column_number = current_element.attr('data-column');
if(value['checked'] === 'checked'){
current_element.prop('checked',true);
if(table.column(data_column_number).visible() === false){
table.column(data_column_number).visible(true);
}
}
else {
current_element.prop('checked',false);
if(table.column(data_column_number).visible() === true){
table.column(data_column_number).visible(false);
}
}
});
For whatever reason, the code block above works except for the first data-column. I've used console.log to print out each data-column and to see what the values before and after table.column(data_column_number).visible() are and they are correct.
So if I check "test", and then click something to load settings where "test" is enabled within those settings, it will hide "test" despite console.log showing that the data-column is 0 (correct), that visible() is set to true before any change (correct) and that visible() is still set to true by the end of the $.each() loop. Despite this, my first column disappears.
If my settings hide another column that is not at position 0, it works though.
Does anyone see what could be causing this?
I found the answer. This might not apply to everyone, but just in case, make sure that the attribute data-column is not undefined. What was happening in my case was that somewhere down the line I had sub-items in the table, so some headings had no data-column attribute.
The way data tables works (at least in my case) was that setting an undefined column's visible status to either true or false, in essence, calling table.column(undefined).visible(false) or table.column(undefined).visible(true) would set table.column(0).visible(false), no matter what.
Just adding a check to see if data_column_number !== undefined before proceeding with setting a visible state eliminated my issue.

jQuery For Loop Image Check and Display

Good afternoon Stack Overflow,
I'm inexperienced when it comes to coding in general and I've been having a problem that's doing my head in!
If you'll allow me to set the scene...
The section of the project I am currently working on involves a user picking items from a warehouse in order to fulfil a shipment and in some cases they have to pick the same item from various locations, when that needs to be done, the small "!" type icon appears next to the item.
The user then can click on the icon and choose which locations they will be retrieving the stock from, they then press confirm on the modal and when it closes it sets the text back to blue and hides the icon.
The part I am having trouble with is that once all the locations have been established, the order needs to be processed and this requires a button to be clicked on, which I only want to appear once all the "!" icons are hidden.
I know there are alot of questions based on for loops and images checks and believe me when I say I've tried hard to figure this out myself and I've tried different approaches:
ShowProcess = false
for (i = 0; i<Picker; i++) {
if ($('#MultiLocIcon'+i).is(':visible')){
ShowProcess = true
}
if (ShowProcess == true) {
$('#ProcessConfirm').show()
};
};
This obviously wouldn't work because its setting the first variable in the list to "true" and will always read it as true, therefore always showing the image, even if the "!" icon still exists in other rows.
I also tried using .each() to test each rows text color of a specific but also had no luck:
var table = $('#RequestedItemsTable');
table.find('tbody > tr').each(function(){
if $('#Desc').css('color') == '#0000FF'){
//do something
I feel like my experience is letting me down as I still have a lot to learn and have a suspicious feeling that the solution is going to be really easy, but then again, its only easy if you know how.
If anyone could take the time to help me with this problem or offer me any advice, I'd be really grateful.
Here is a section of my code which might be useful:
Modal "Confirm" button:
//CONFIRM Button which will submit final picks.
'Confirm': function() {
//Reset the length loop
length = undefined;
//Remove "Multiple Location" icon from the row.
$('#icon'+id).hide();
//Change text colour back to blue to have visual confirmation that item is ready for picking
$('#Desc'+id).css('color', '#0000FF');
$('#QtyReq'+id).css('color', '#0000FF');
$('#QtyinStock'+id).css('color', '#0000FF');
$(this).dialog('close');
The "!" Icon:
<td id= "MultiLocIcon<?=$i;?>"><?if($row->Count_Location > 1)
{?><img src="<?=base_url();?>public/css/images/error.png" alt="LocPick" title="Multiple Locations" style="cursor: pointer;" id= "icon<?=$i;?>" onClick="$.LocPick(<?=$i;?>);"/><?}?></td>
Basically just need to know how my image can show once the loop checks and knows that the "!" icon is hidden from every possible row.
Thank you for your patience.
You'll need to add a second check in your modal logic, perhaps after your .hide():
//Remove "Multiple Location" icon from the row.
$('#icon'+id).hide();
$('img[id^=icon]:visible').length || $('#ProcessConfirm').show();
What this does is combines the :visible pseudo-selector and a regex selector for all img tags with id starting with "icon". This assumes you won't have any other unrelated image tags with an id like "icon*". If the length is 0, it will go ahead and show the #ProcessConfirm element.
simplest solution I would give is to add a class warning to all the table column which has warning icon & then check for visibility of the same.
if($('.warning:visible').length === 0){
//all warning icons are hidden
}
What I would do is based off your HTML, select all the alert icons, and do a :visible psuedo selector on it. This will return all the visible alert icons, if there are none in the array, you know none of them are visible. You will need to identify them with a class, such as .alert:
if( $(".alert:visible").length === 0 ){
// Do your code in here for no visible alert icons!
}
When user clicks confirm on modal you should run a check on how many icons are still visible, and if the amount is 0 then show the button, like this:
// This searchs for every <td> with an id that contains '#MultiLocIcon'
// Then checks if the amount of those which are visible is 0 and do something
if ( $('td[id*=MultiLocIcon]').not(':visible').length === 0 ) {
$('#ProcessConfirm').show()
}

How to sort by a second column while keeping the sorting on the first column?

I am working on table that is built dynamically depending on filters chosen. I currently am able to sort by any row that I click. The problem is I need the first row that I sort by to stay when I click on another row, so that the second row I click is sorted within the means of the first row. An example I have two columns, first name and last name.
**FirstName** **LastName**
Bob Zimmer
Bob Anderson
Kathy Walege
Kathy Ball
So say I click on the first name row. It will stay the same since the first names are already in order. But when I click on the Last Name row I want the following to happen.
**FirstName** **LastName**
Bob Anderson
Bob Zimmer
Kathy Ball
Kathy Walege
I currently have it working so it only sorts by one column at a time. I am using both javascript and vb.net to get this to work with my code.
Here's the javascript:
function SortColumn(col)
{
__doPostBack('SortBy',col);
}
Here's the vb function that calls the javascript function:
Private Function AddSortLinkToColumn(ByVal sSortColumn As String) As String
Dim sVal As String = ""
sVal = "<a href=""javascript:SortColumn('" & sSortColumn & "');""><font face=""Webdings"">"
If m_sSort <> "" AndAlso Split(m_sSort, "-")(0) = sSortColumn AndAlso m_sSortDrxn = "ASC" Then
sVal &= "5"
Else
sVal &= "6"
End If
sVal &= "</font></a>"
Return sVal
End Function
This is currently taking the column that is being clicked and matching it up with my global sort variable. If they match it displays an up arrow. If it fails it displays a down arrow.
I know that I need to somehow keep track of the first column that was clicked, but I am not sure how to do so. I have tried it on the vb.net side and javascript sides by adding another column to the sort but it doesn't do me any good if I can't get the first column value to stay!
How can I keep the first column's sort and then sort by the second column as well? Any help would be greatly appreciated!
UPDATE
With the help of the answer listed below I finally got this working! Here's the code:
function SortColumn(col)
{
<% if m_sSort = nothing then %>
__doPostBack('SortBy', col);
<% else %>
__doPostBack('SortBy', document.getElementById("SortField").value + "," + col);
<% end if %>
}
The m_sSort was a public variable on the vb.net side. The "SortField" was the name of the hidden field where the m_sSort value was being stored.
Add a hidden field to the page called prevCol or something like that. Since it is a hidden field it will be posted back with the form.
In your postBack event handler, make sure to consume that hidden field and replace its value with the currently clicked column.
In this way you will have the column that is clicked as well as the column that was previously clicked. If you check the value and it is empty you know you are starting off.
Your remove sort button would then clear the prevCol field to ensure that you are starting fresh.
So your flow would look like this:
First column click: prevCol is empty so you sort by the currently clicked column and write its identifier to the prevCol field on the
returned page.
Second column Click: prevCol now has a value. So first sort by that value, then sort by the supplied column. Make sure you write the
supplied column to prevCol in the return.
Xth column Click: Same as second click. Inherintly this is going to make the prevCol the first column that is sorted each time.
When you click your remove sort button, ensure you are not writing a value to prevCol and thus starting the cycle over.
In this way you are kind of caching your previous column on the client with each response so that it is always present during post back.
EDIT:
I thought it would be simple to alternatively do this entirely on the client side with jQuery as long as the server did not need to know the order of the rows.
So I spent some time thinking about how this would be done using jQuery and I found it was a bit more challenging than I originally anticipated.
with some help from James Padolsey I was able to easily sort the table rows, but the logic of sorting based on the previous column was a bit strange.
This is what I ended up with.

Categories

Resources