Cannot get selectedIndex from select element positioned in cell in hidden row - javascript

I'm using DataTable and I'm trying to get some filtering function working with select element positioned in cells of the table.
The filtering works by entering text in input field positioned below each column. Then the filter function checks the selected text in all cells of that column and if no match is found in one cell, related row is hidden.
When the table has been loaded, it works to filter the table once. The problem is when clearing the filter, then it doesn't work. The reason seems to be related to that I'm using selectedIndex for the select DOM objects positioned in the rows that are not visible for the moment.
"qu_owner_xxx" is the ID of the select elements.
var el1 = document.getElementById("qu_owner_4"); //Visible, works like a charm
console.log("ID 1 " + el1.id); //ID is printed
console.log("EL 1 " + el1.selectedIndex);
var el2 = document.getElementById("qu_owner_17"); //Hidden, returns null
console.log("ID 2 " + el2.id); //Not reaching here
console.log("EL 2 " + el2.selectedIndex) ; //Not reaching here
str = el.options[el.selectedIndex].text; //Just for showing how to get the string used for filtering later
The thing is that the data of the cell is passed to the filter function as pure html, not as object. I can get the id from that part doing $(aData[i2]).attr('id') where aData is the table row. But using jQuery there seems to be some information you cannot reach compared to using the actual DOM object (e.g. selectedIndex), especially when you have to "recreate" the object from html.
How can I get the text from the selected value of the hidden select box/row? Is it even possible?
UPDATE
I tested my theory in jsfiddle, but it actually works retrieving the information from the hidden row/select. But it's no question about it, in my filter function is the rows that are not displayed that's failing.
My filter function (DataTable is calling this function when it is time for filtering)
$.fn.dataTableExt.afnFiltering.push(
function( oSettings, aData, iDataIndex ) {
var ret = true;
//Loop through all input fields i tfoot that has class 'sl_filter' attached
$('tfoot .sl_filter').each(function(i, obj){
//$(this) can be used. Get the index of this colum.
var i2 = $("tfoot input").index($(this));
//Create regexp to math
var r = new RegExp($(this).val(), "i");
var str = "";
if(i2 == 5){//This is just during development, don't want to care about other columns with select element so just doing things on this column
//Here I just pick two id, one that I know is visible and one that is not
var el1 = document.getElementById("qu_owner_4"); //Visible, works like a charm
console.log("ID 1 " + el1.id); //ID is printed
console.log("EL 1 " + el1.selectedIndex); //selectedIndex is printed
var el2 = document.getElementById("qu_owner_17"); //Hidden, returns null
console.log("ID 2 " + el2.id); //Not reaching here
console.log("EL 2 " + el2.selectedIndex) ; //Not reaching here
//This is how I intended to get it working, but fail
var el = document.getElementById($(aData[i2]).attr('id'));
str = el.options[el.selectedIndex].text; //String to be used for comparing
}
/*Test to see if there is a match or if the input value is the default
(the initial value of input before it has any fokus/text) */
if(r.test(str) || $(this).val()=="Search"){
//Return true only exits this function
return true;
}else{
/*Return false returns both function an .each. Retain 'false' in a variable scoped
to be reached outside the .each */
ret = false;
return false;
}
});
//Return true or false
return ret;
}
);
aData = the row. aData[x] gives me the cell content of cell x on that row. For the select element it's the raw html.
this = the input field in which the search string i entered.

Of course you can have the text from the selected value !
Here is one way (probably not the best, but works) :
$('select').change(function() {
var selectedValue = jQuery(this).val();
var selectedText = '';
jQuery(this).children('option').each(function() {
if (jQuery(this).val() == selectedValue) {
selectedText = jQuery(this).text();
}
});
});
The selectedText variable will contain the text from the selected value.
See here.

Related

How to do custom filtering in Datatables with comma separated values?

I am using Datatables to display table data in my JSP page. I have enabled search functionality in my datatable.
Here is my fiddle
I want to allow the user to use "," (comma separated values) in the search box and want the comma's to be treated or OR. I have tried to implement it but as soon as i enter "," things don't work. What change should i do in order to achieve the required functionality
$.fn.dataTable.ext.search.push(function(settings, data, dataIndex) {
var search = $('.dataTables_filter input').val().toLowerCase();
var inputArray=search.split(",");
var node = table.cell({ column: 0, row: dataIndex }).nodes().to$();
var text = node.find('b').text();
text += node.find('[name$=locationId] option:selected').text()
text += node.find('[name$=empRole] option:selected').text();
for(var i=0;i<inputArray.length;i++){
return text.toLowerCase().indexOf(inputArray[i])>-1;
}
return false;
})
DataTables seems to stop calling search() internally if all rows is filtered out (there is probably other reasons). I could achieve the functionality by turning off() all bindings and trigger the filter programmatically; if you have a custom filter you can invoke it by draw() :
initComplete: function() {
$('.dataTables_filter input').off().on('keyup', function(e) {
table.draw()
})
}
This also give the possibility to filter only when the user hits enter :
if (e.which == 13) table.draw()
Then only return true if there is a match, and a sanity check is also a good idea: obama, will give two indexes in the array, and everything matches an empty string :
$.fn.dataTable.ext.search.push(function(settings, data, dataIndex) {
var search = $('.dataTables_filter input').val().toLowerCase().split(',');
var node = table.cell({ column: 0, row: dataIndex }).nodes().to$();
var text = node.find('b').text();
text += node.find('[name$=locationId] option:selected').text()
text += node.find('[name$=empRole] option:selected').text();
text = text.toLowerCase();
for (var i=0, l=search.length; i<l; i++) {
if (search[i].trim() != '' && text.indexOf(search[i]) >-1) return true
}
return false;
})
Not sure if this is the brightest solution; or if it works as expected in your real life scenario, but at least it return correct rows for obama,, obama, trump, trump, obama, obama, test etc.
updated fiddle -> https://jsfiddle.net/1rde0nbm/16/

Remove empty cells and their label cells from a table

I've got a two-row table (label row and data row) that gets filled in with all relevant information about a running service, however, about half of the cells are empty at any given time depending on which test is run.
I'm looking for a jquery statement that will find all empty cells and hide them along with the label for that cell. I've searched quite a bit and found this code that is meant to hide the empty cells
$('table#yourTable tr').each(function(){
if($(this).children('td:empty').length === $(this).children('td').length){
$(this).hide();
}
});
However, my "empty" cells are populated with "&nbsp" and not truly empty. Is there a way to hide a cell and its associated label cell?
You can use .filter()
$(document).ready(function() {
var elems = $("tr").filter(function() {
return this.querySelector("td").innerHTML === " "
});
elems.hide();
})
following code will hide all of your not truly empty cell and it's label cell.
$(function () {
var $label = $('tr:first');
$('tr:last td').each(function (index, td) {
var $td = $(td);
if ($td.html() != ' ') return;
$td.hide();
$label.find('td:eq(' + index + ')').hide();
});
});

Jquery - check column checkboxes then do something with those rows

I've been trying to find a good match to my question, but nothing really concrete. I'm still learning and don't know exactly what I'm missing.
So my code can be found here: Fiddle
This is a simplified version of what I'm working with. In the final version, I will upload a csv file to the html table you see there (id="dvCSV"). Upon uploading, the table will look like it is shown (with added dropdowns and a column of checkboxes). The checkboxes come "pre-chcecked" when I generate them but what I want is the user to be able to turn "off" the rows that I do not want to calculate on.
I'll run you through the process:
This function reads the columns that the user designates. I don't know which column they will upload the data into.
function CheckLocations() {
//Checks the uploaded data for the locations of the Lat/Lon Data based on user dropdowns
colLocs[0] = ($('#Value_0 :selected').text());
colLocs[1] = ($('#Value_1 :selected').text());
colLocs[2] = ($('#Value_2 :selected').text());
colLocs[3] = ($('#Value_3 :selected').text());
LatColumn = colLocs.indexOf("Lat");
LongColumn = colLocs.indexOf("Long");
}
function AllTheSame(array) { //if they do not designate the checkboxes, I prompt them to
var first = array[0];
return array.every(function (element) {
return element === first;
});
}
This function takes all of the data in the designated columns and places them into an array for calculation.
function data2Array() {
//gets the lat and long data from the assigned columns and transfers them to an array for calculation
$("#dvCSV tr td:nth-child(" + (LatColumn + 1) + ")").each(function () {
var tdNode = $("<td/>");
tdNode.html(this.innerHTML);
LatData.push(tdNode.text());
});
LatData.splice(0, 2);
LatData.unshift(1, 1);
$("#dvCSV tr td:nth-child(" + (LongColumn + 1) + ")").each(function () {
var tdNode = $("<td/>");
tdNode.html(this.innerHTML);
LongData.push(tdNode.text());
});
LongData.splice(0, 2); //these two lines remove the first two items then replace them with 0
LongData.unshift(1, 1);
}
The first of these functions removes the checkbox column after calculations are done then new calculated columns are appended at the end. The second one was my attempt to read the checkboxes into an array. Ideally I'd want an array of values true or false, then do the calculations and return the calculated values back to the dvCSV table. For the td's where no calculation was performed, the cell would be empty.
function removeChecks() {
$("#dvCSV th:last-child, #dvCSV td:last-child").remove();
}
function makeCheckArray() {
var searchIDs = $("#dvCSV tbody td:last() input:checkbox:checked").map(function () {
return $(this).val();
}).get();
alert(searchIDs);
}
Hopefully I made the problem clear. Any help would be appreciated.
Pass a class when your table is generated into the tr element. Then create an on change method for your checkboxes. Read more here: http://api.jquery.com/on/
Also if you cannot get the inserted rows id's from your table then start a counter outside of your js like this
counter = 0;
Then inside of your loop add counter++
SO..
<tr class="row-1">
<td>
</td>
</tr>
Then add this snippet outside all of your other JS
$( "tr" ).on( "change", function() {
//do something
$(this+'.row-'+(counter)).hide();
});
This should get you headed in the right direction.

Removing options from a dependent dropdown based on dropdown selection

Could someone please help me handle this issue in jQuery
I have a requirement where I have two dropdowns:
The no of floors of the flat (numberOfFloors)
The flat where the user stays (whichFloorYouStay)
I need to remove all the invalid options from the second dropdown. How do I achieve this?
For example:
If a user select the numberOfFloors option as 3, then I should remove options 4 and 5 from whichFloorYouStay dropdown and just load 1,2,3 as whichFloorYouStay options.
Similarly, if a user select the numberOfFloors option as 1, then I should remove options 2,3,4,5 from whichFloorYouStay dropdown and just load 1 as whichFloorYouStay option.
Please find my JSBin link:
http://jsbin.com/sibufive/1/edit?html,js,output
Try this:
$(document).ready(function () {
//NEW CODE:
var floorsvals = new Array();
var lastvalue = Number.MAX_VALUE; //Useful for checking whether we need to append or remove elements - Initialize this with an arbitrarily large number
//Fill possible floor vals with value of <option>'s
$("#numberOfFloors option").each(function () {
floorsvals.push($(this).val());
});
//NOTE: If you already know the values of the numberOfFloors array, you can just add those values straight into the "floorsvals" array
//The above loop is just handy if you are dynamically generating a <select> list and don't already know the values
$("#numberOfFloors").change(function () {
alert($("#numberOfFloors").val());
var value = $("#numberOfFloors").val();
//NEW CODE:
//If we need to append...
if (value > lastvalue) { //This value is larger than the last value we just had
for (i = 0; i < floorsvals.length; i++) {
if (floorsvals[i] <= value && $('#whichFloorYouStay option[value=' + floorsvals[i] + ']').length === 0) { //Floor value is less than the selected maxvalue and an option with this floor value doesn't already exist...
$('<option value="' + floorsvals[i] + '">' + floorsvals[i] + '</option>').appendTo("#whichFloorYouStay"); //...So add that floor value
}
}
} else { //Otherwise, we need to remove
//OLD CODE:
$('#whichFloorYouStay option').each(function () { //Go through each option
if ($(this).val() > value) { //If this option's value is greater than the numberOfFloors value, remove it
$(this).remove();
}
});
}
//NEW CODE:
lastvalue = value; //Update last value chosen with this value
});
});
Here's a demo: http://jsbin.com/sibufive/40/edit
var value = $("#numberOfFloors").val();
should become
var value = $("#numberOfFloors").val();
value-=1
I would also suggest adding a value 0 to the first set of options one so you never have a user begin at 1 and try to move to the second menu

changing text for a selected option only when its in selected mode

I am not sure if I confused everyone with the above title. My problem is as follows.
I am using standard javascript (no jQuery) and HTML for my code. The requirement is that for the <select>...</select> menu, I have a dynamic list of varying length.
Now if the length of the option[selectedIndex].text > 43 characters, I want to change the option[selectecIndex] to a new text.
I am able to do this by calling
this.options[this.selectedIndex].text = "changed text";
in the onChange event which works fine. The issue here is once the user decides to change the selection, the dropdownlist is showing the pervious-selected-text with changed text. This needs to show the original list.
I am stumped! is there a simpler way to do this?
Any help would be great.
Thanks
You can store previous text value in some data attribute and use it to reset text back when necessary:
document.getElementById('test').onchange = function() {
var option = this.options[this.selectedIndex];
option.setAttribute('data-text', option.text);
option.text = "changed text";
// Reset texts for all other options but current
for (var i = this.options.length; i--; ) {
if (i == this.selectedIndex) continue;
var text = this.options[i].getAttribute('data-text');
if (text) this.options[i].text = text;
}
};
http://jsfiddle.net/kb7CW/
You can do it pretty simply with jquery. Here is a working fiddle: http://jsfiddle.net/kb7CW/1/
Here is the script for it also:
//check if the changed text option exists, if so, hide it
$("select").on('click', function(){
if($('option#changed').length > 0)
{
$("#changed").hide()
}
});
//bind on change
$("select").on('change', function(){
var val = $(":selected").val(); //get the value of the selected item
var text = $(':selected').html(); //get the text inside the option tag
$(":selected").removeAttr('selected'); //remove the selected item from the selectedIndex
if($("#changed").length <1) //if the changed option doesn't exist, create a new option with the text you want it to have (perhaps substring 43 would be right
$(this).append('<option id="changed" value =' + val + ' selected="selected">Changed Text</option>');
else
$('#changed').val(val) //if it already exists, change its value
$(this).prop('selectedIndex', $("#changed").prop('index')); //set the changed text option to selected;
});

Categories