Hy,
The following multi filter select dataTable fits my project.
https://datatables.net/examples/api/multi_filter_select.html
However, I would like to remove all but one of the select inputs (at the bottom of the table) say "Office" select input in the above page and instead of blank should show a default caption like "Choose Office".
Since I am quite new to dataTables and also JS so doesn't know much about how to use dataTAbles API to customize it, so can anybuddy help me out.
Thanks
dk
you just need to modify the given code slightly.
Instead of foreaching every column do it with one column so:
/*this.api().columns().every( function () {
var column = this;
} )*/
var column = this.api().column(2);
to remove the blank and display something like "Chose Office". You need to place the text between the closing and opening tags of option
var select = $('<select><option value="">YOUR TEXT HERE</option></select>')
here is the complete code and a jsfiddle
$(document).ready(function() {
$('#example').DataTable({
initComplete: function() {
var column = this.api().column(2);
var select = $('<select><option value="">Choose Office</option></select>')
.appendTo($(column.footer()).empty())
.on('change', function() {
var val = $.fn.dataTable.util.escapeRegex(
$(this).val()
);
column
.search(val ? '^' + val + '$' : '', true, false)
.draw();
});
column.data().unique().sort().each(function(d, j) {
select.append($('<option>', {value: d, text: d}));
});
}
});
});
edit:
I also was so free and replaced '<option value="'+d+'">'+d+'</option>' with $('<option>', {value: d, text: d}) to fix a xss
vulnerability and allow values with ".
Related
I have a table in which I can edit and modify each cell.
I would like to highlight the cell that I modified.
At the moment I can only highlight the entire row but I don't have what I want to do.
I use createdRow to make the cells editable and get the modified row.
How can I do to highlight that modified cell?
var table = $("#deploymentMap_table").DataTable({
data: constructRaws(dataSet),//tbody
paging: false,
searching: false,
info: false,
fixedHeader: true,
scrollY: false,
scrollX: false,
responsive: false,
dom: 't', //display only the table
order: [[ 0, 'asc' ]],//order by 'service' col
columnDefs:[
{
targets:'_all',
render:function(data){
if(data == null) {return ""
} else {return data;}
}
},
{ targets: [0,1], "width" : "200px"},
],
columns: constructColumns(dataSet),//thead
dom: 'Bfrtip',
// attribute classname (background color) for services
rowCallback: function(row, data, index){
if ( data.code == 1 ) {
$('td', row).each( function ( value, index ) {
if($(this).contents().first().text()){
$(this).addClass('td_colorCD');
}
} );
}
$(row).find('td:eq(0)').css('background-color', '#7f7f7f').css('color', '#fff').css('text-align', 'left');
$(row).find('td:eq(1)').css('background-color', '#7f7f7f').css('color', '#fff').css('text-align', 'left');
$.each(row.childNodes, function(i,value){
if(value.innerText == "NoUP"){
$(value).addClass('td_colorBSF');
}
else if(value.innerText){
$(value).addClass('td_color');
}
})
},
// Make all cell editable
createdRow: function(row, data, dataIndex, cells) {
console.log(cells);
let original
row.setAttribute('contenteditable', true)
row.setAttribute('spellcheck', false)
row.addEventListener('focus', function(e) {
original = e.target.textContent
})
row.addEventListener('blur', function(e) {
if (original !== e.target.textContent) {
$('td', row).removeClass();
$('td', row).addClass('td_color_change');
const r = table.row(e.target.parentElement)
r.invalidate();
var lign = e.target.innerText;
lign = lign.split('\t');
var nRow = $('#deploymentMap_table thead tr')[0].innerText;
head = nRow.split('\n\t\n');
var newAR = mergeArrayObjects(head, lign);
console.log("newAR", newAR);
$(dataSet).each(function( index, values ) {
if(newAR.service[0].Services == values.service_name){
delete values.regions;
values.regions = newAR.region;
console.log(values);
}
})
console.log("dataset", dataSet);
}
})
}
});
I think the easiest way to handle this is to replace your rowCallback with a DataTables delegated event.
Below is a simple example which would change the color of a specific cell when you leave that cell:
Step 1) The onblur event requires the cell to have a tabindex attribute. You can add this however you wish - but here is one way, in your existing code:
$.each(row.childNodes, function(i,value){
$(value).attr('tabindex', i); // this line is new
// your existing code goes here
})
Note - this could be improved as it repeats tab indexes across rows. But it illustrates the approach.
Step 2: Add a new onblur event listener, after the end of your DataTable definition:
$('#deploymentMap_table td').on('blur', function () {
this.classList.remove("td_color");
this.classList.add("td_color_change");
} );
Step 3: The above code would need to be enhanced to include your edit-checking logic, which checks for an actual cell value change.
You can get the "before" cell values using this:
table.cell( this ).data();
And the "after" cell values using this - which gets the value from the HTML table (the DOM node), not from DataTables:
table.cell( this ).node().textContent;
The updated listener would be something like this:
$('#deploymentMap_table td').on('blur', function () {
var cellValueStart = table.cell( this ).data();
var cellValueEnd = table.cell( this ).node().textContent;
//console.log( cellValueStart );
//console.log( cellValueEnd );
if (cellValueEnd !== cellValueStart) {
table.cell( this ).data(cellValueEnd);
this.classList.remove("td_color");
this.classList.add("td_color_change");
}
} );
The table.cell( this ).data(cellValueEnd) command updates the cell in DataTables so that it matches the value you typed into the HTML cell. If you do not do this, then the data in the DataTables object (behind the scenes) will be out-of-sync with the data in the HTML table (what you see on your screen).
Warning: This approach is basic. It does not cover the case where a user may do the following:
Edit a cell from "A" to "B".
Leave the cell, so it is highlighted.
Return to the cell and edit it back from "B" to "A".
Leave the cell again.
In this case, the cell will remain highlighted.
One way around this is to capture the original state of every cell when you first load the table - and then check each edit against the value in the original data. This can be done, if needed - but is outside the scope of this question. But it also depends on what you need to do with the data, after you have finished editing it. If this is important to you, then it may be worth asking a new question for that specific problem.
I'm new in using selectize.js, and this is the simplified version of my problem. Please see fiddle below.
Fiddle
What I want is not to select the item when it is already selected.
Ex.
click the Add button and then select the full name.
click the Add again.
Full name should not be selected in the second <select> or should not be visible.
How will I be able to do this?
HTML
<button>Add</button><br/><br/>
<div id="container"></div>
JS
var saveAsOptions = [
{ value: 'full-name', text: 'Full Name' },
{ value: 'first-name', text: 'First Name' },
{ value: 'last-name', text: 'Last Name' }
];
var i = 1;
var $selectSaveAs;
$('button').on('click', function(){
$('#container').append(generateSaveAs(i));
$selectSaveAs = $('#saveAs' + i).selectize({
options: saveAsOptions,
placeholder: '- Fields -'
});
i++;
});
function generateSaveAs(id){
return '<select id="saveAs' + id + '"></select>';
}
So every time you are creating a new drop down you are inserting static values. By analyzing the code I see the selected value always have a class item. So what we can do is create a new array to show in dropdown and filter out the ones already selected. And then we can bind it in drop down.
To filter out you can use filter
saveAsOptionsFiltered = saveAsOptions; //Initialize with your all drop down options
$(".item").each(function(index,element) {
/*Filter out the already selected ones*/
saveAsOptionsFiltered = saveAsOptionsFiltered.filter(function (savevalue) {return savevalue.text !== $(element).text() });
});
JSFiddle
I have not handled the condition when all are selected and you stop adding more I have just shared the code in which you can filter out the selected ones.
I am creating a jqgrid with editable fields. I have 2 checkbox columns in jqgrid, one is coming from multiselect: true (to get unique rowId), other column is created inside column model.
I want to handle the onchange(checked/unchecked) event of the checkbox in my column model, independent of other checkbox column(multiselect:true). Any help appreciated. Below is the code snippet.
[{name : "userRole", label: 'OV', width: 40, editable:true, edittype:'checkbox',formatter: 'checkbox', editoptions: {value:"True:False"},
formatoptions: { disabled: false},frozen:true}]
multiselect: true,
onSelectRow: function(rowid){
jQuery(this).editRow(rowid, true);
}
You can use beforeSelectRow callback. The demo demonstrate the approach. It uses the following code
beforeSelectRow: function (rowid, e) {
var $target = $(e.target), $td = $target.closest("td"),
iCol = $.jgrid.getCellIndex($td[0]),
colModel = $(this).jqGrid("getGridParam", "colModel");
if (iCol >= 0 && $target.is(":checkbox")) {
alert("checkbox is " +
($target.is(":checked")? "checked" : "unchecked") +
" in the column \"" + colModel[iCol].name +
"\" in the row with rowid=\"" + rowid + "\"");
}
return true;
}
Define your own formatter function like this in your colmodel,
[{name : "userRole", label: 'OV', width: 40,
editable:true, edittype:'checkbox',formatter: checkboxFormatter,
editoptions: {value:"True:False"},
And your formatted checkbox like,
function checkboxFormatter(cellvalue, options, rowObject) {
return "<input type='checkbox' name='checkboxIsCC'
onchange='your_own_function();'>";
}
Hope this helps you.
I had an issue were not only I had more than 1 check box but also I had to update same column check box values based on the selection of the check box as well as modifying the same row columns.
In regards to the modification of the other checkboxes, when jqgrid modifies the data either by 'setCell' or 'setRowData' operations, it removes the click event. Also there is the problem that for checkboxes none of the edit functions are useful.
I manage to get bits from other people's solution and came to use the delegate jquery functions, that allows the binding of the click to be done each time an object that matches the selector is created. Also in this case only 1 checkbox of only 1 column could be checked at a time.
$(document).delegate("#alarmDownloadListView td[aria-describedby*='stopArm'] input", 'click', function () {
// Function that modifies all the other checkboxes of the same column
deselectOthersStopArmAlarms(this, j);
// Set the Pre and Pos Alarm values to default
var fileIndex = $(this).closest('tr').index();
// Modification of the same row cells
if($(this).is(':checked')){
alarmsGrid.jqGrid('setCell',fileIndex,'preAlarm', defaultPrePosStopArmAlarmValue);
}else{
alarmsGrid.jqGrid('setCell',fileIndex,'preAlarm', null);
}
});
Do not mind the exact operations of the code, what is important is the operations that the binded function does. The CSS selector binds this function to all checkboxes whose name in my colmodel is stopArm.
I hope this answer is useful for some people. I found the delegate to be very useful! :)
Previously I asked how to do this and was directed to this:
<script>
jQuery.fn.filterByText = function(textbox) {
return this.each(function() {
var select = this;
var options = [];
$(select).find('option').each(function() {
options.push({value: $(this).val(), text: $(this).text()});
});
$(select).data('options', options);
$(textbox).bind('change keyup', function() {
var options = $(select).empty().scrollTop(0).data('options');
var search = $.trim($(this).val());
var regex = new RegExp(search,"gi");
$.each(options, function(i) {
var option = options[i];
if(option.text.match(regex) !== null) {
$(select).append(
$('<option>').text(option.text).val(option.value)
);
}
});
});
});
};
</script>
(http://www.lessanvaezi.com/filter-select-list-options/)
When I use this filter on the select box it filters both the unselected AND the selected. I'd like it to ONLY filter the unselected because if a user wants to ammend the selections and filters again, the previously selected items go away - unless they meet the filter criteria.
I'm not that good at JavaScript or JQuery and can't understand how I might tell the above script to ignore options that are ":selected" but filter all else.
Here's a jfiddle if it helps: http://jsfiddle.net/UmKXy/ I'd like option one and two to remain selected and in the list when user begins to type.
Thanks for help!
The solution you had would not work with selected elements because he created an array of options at the start and then matched those options against the regex(Without regards to what is actually selected). I've used spans to hide options in the past and created an example for you to see how it works. Here is the link : http://jsfiddle.net/rD6wv/
Here is the code
$(function() {
$("#filterByText").bind('keyup',function(){
var search = $.trim($(this).val());
var regex = new RegExp(search,"gi");
$("#filez").find('option').each(function(){
if(!$(this).is(':selected')){
if($(this).val().match(regex) === null) {
$(this).wrap('<span>');
}else if($(this).parent().is('span')){
$(this).parent().replaceWith($(this));
}
}
});
});
});
You simply need to loop through all the options of the select when you type in the textbox.
You then check if it is selected, if it is you do nothing, else you check if it matches the search filter, if it does you wrap it in a span, making it invisible, else it means you need to see it, so you check if it is already wrapped in a span, and in that case you replace it with the option so you can see it again.
to selected the non selected options, use this:
$('option:not[selected]') or $('#myselect > option:not[selected]')
to remove them, use this:
$('option:not[selected]').remove();
in css, :not filters for opposite of what comes in the curved brackets.
and [] is attribute selector.
so :not[selected] means: does not have an attribute whose key is "selected"
I found more than a couple examples of this with a plain jquery autocomplete but not in a way that will work with the autocomplete included in the combobox code from the demo because the structure of the code is structured so differently.
I want to match every item that has all of the search tokens anywhere in any word. I don't need to match the start of any word, any part of it is fine. I don't care if the search strings are highlighted in the autocomplete list if that makes things too complicated.
Desired search/result combos: (please excuse the spacing)
"fi th" "fi rst second th ird"
"rs on" "fi rs t sec on d third"
"ec rd" "first s ec ond thi rd"
but not limited to any max/min length or number of tokens.
EDIT
I figured part of it out using the code structure from the other autocorrect I had working.
source: function( requestObj, responseFunc ) {
var matchArry = $("select > option").map(function(){return this.innerHTML;}).get();
var srchTerms = $.trim(requestObj.term).split(/\s+/);
// For each search term, remove non-matches
$.each (srchTerms, function (J, term) {
var regX = new RegExp (term, "i");
matchArry = $.map (matchArry, function (item) {
if( regX.test(item) ){
return{
label: item,
value: item,
option: HTMLOptionElement
} ? item :null;
}
} );
});
// Return the match results
responseFunc (matchArry);
},
and
select: function( event, ui ) {
ui.item.option.selected = true;
self._trigger( "selected", event, {
item: ui.item.option
});
$("destination").val(ui.item.value); // I added this line
},
but I can't get both multiple words AND being able to click to select working at the same time.
If I remove the } ? item :null; on the return in the map function I can click to select an item. If I leave it I can type multiple words, but I can't click any of the items...
Is that the problem or the option: this? I've tried replacing it with HTMLOptionElement and null and I'm stuck.
I am able to set the value of another field with ui.item.value within the select label but that doesn't put the value in the search box or close the dropdown menu.
On a whim I added ui.item.option = ui.item.value; to the select label and everything works as expected. the option: value in source doesn't seem to matter now.
*I make no claims that any of this is good coding practice
updated fiddle: http://jsfiddle.net/eY3hM/