I have a condition column == 1 and if this is the case, the function MakeCellsEditable and the function myCallbackFunction are initialized:
<script src="https://raw.githubusercontent.com/ejbeaty/CellEdit/master/js/dataTables.cellEdit.js"></script>
$(document).ready(function () {
var table = $('#myTable').DataTable();
$('#myTable tbody').on('mousedown', 'td', function () {
$('#myTable').data('column', table.cell(this).index().columnVisible);
});
if (column == 1) {
table.MakeCellsEditable({
"onUpdate": myCallbackFunction
});
}
});
function myCallbackFunction(updatedCell, updatedRow, oldValue) {
var array = updatedRow.data();
var id = array[0];
var column = $('#myTable').data('column');
console.log("The column is: " + column);
jQuery.ajax({
type: "POST",
url: "update.php",
data: {
updatedCell: updatedCell.data(),
id: id,
column: column,
},
cache: false
});
}
What I want to do is, after the functions are executed, I want to kill them. Because otherwise if I one time clicked column 1, then all my tables are editable (not only column 1).
I tried table.unbind(); or table.die(), but this didn't work out.
I tested at the end of the code:
function destroyTable() {
if ($.fn.DataTable.isDataTable('#myTable')) {
table.destroy();
table.MakeCellsEditable("destroy");
}
}
But it didn't work out
To answer the question in the headline: Yep:
function thiswilljustworkonce(){
alert("once");
this.thiswilljustworkonce=function(){};
}
thiswilljustworkonce();
thiswilljustworkonce();
Use columns option for CellEdit plugin to specify which column needs to be editable. There would be no need to remove event handler.
var table = $('#example').DataTable();
function myCallbackFunction (updatedCell, updatedRow, oldValue) {
console.log("The new value for the cell is: " + updatedCell.data());
console.log("The values for each cell in that row are: " + updatedRow.data());
}
table.MakeCellsEditable({
"columns": [0],
"onUpdate": myCallbackFunction,
"confirmationButton": true
});
See this example for code and demonstration.
Related
The code below is working fine it's filtering duplicate values from Array but it's not filtering undefined Values console.log([67, undefined]). i want to filter undefined values and duplicate values from array and output in options values as selected. I would be grateful for any help.
i have two datatable with drag and drop functionality. each row of datatable contain the IDs. when i drag the row of table 1 into table 2. the data stored into the Array. i have the addArray function for push the IDs into an Array there also filtering the duplicate IDs and make it uniqueArray. now i want to create the Select option Element which containing the iDs as a value. I want if i drag out a value from Array then the select options update automatically and delete the option from it...?
js
$(document).ready(function () {
new Sortable(drag, {
group: 'sortables',
multiDrag: true, // Enable multi-drag
selectedClass: 'selected', // The class applied to the selected items
fallbackTolerance: 3, // So that we can select items on mobile
animation: 150,
onUpdate: function (e, tr) {
addArray();
checkFields();
},
});
new Sortable(drop, {
group: "sortables",
multiDrag: true, // Enable multi-drag
selectedClass: 'selected', // The class applied to the selected items
fallbackTolerance: 3, // So that we can select items on mobile
animation: 150,
onChange: function (event, tr) {
Sorting();
addArray();
checkFields();
},
});
function addArray() {
let uniqueArray = [],
html = [];
$('#drop').children().each(function () {
const pk = $(this).data('pk');
if (pk && !uniqueArray.includes(pk)) {
uniqueArray.push(pk);
html.push(`<option value="${pk}">${pk}</option>`);
}
});
$('#id_articles').html(html.join(""))
}
function Sorting() {
sort = [];
$('#drop').children().each(function () {
sort.push({ 'pk': $(this).data('pk'), 'order': $(this).index() })
});
let crf_token = $('[name="csrfmiddlewaretoken"]').attr('value') // csrf token
$.ajax({
url: "/rundown/sorts/",
type: "post",
headers: { "X-CSRFToken": crf_token },
datatype: 'json',
data: {
'sort': JSON.stringify(sort),
},
success: function () {
console.log('success')
}
});
};
function checkFields() {
if ($('#drop tr').length >= 1) {
$('#drop').find('#blank_row').remove();
} else {
$('#drop').append($("<tr>").attr("id", "blank_row")
.append($('<td>').attr("colspan", '4')
.text('Drop here...')));
}
};
});
You do not have a filter. Why not just test
function stop_duplicate_in_array(array, value) {
if (!value && value !== 0) return array; // value is falsy but not 0
if (!array.includes(value)) array.push(value);
return array;
}
if 0 is not a possible value, remove && value !== 0
function stop_duplicate_in_array(array, value) {
if (value && !array.includes(value)) array.push(value);
return array;
}
You can simplify
function addArray() {
let uniqueArray = [],
html = [];
$('#drop').children().each(function() {
const pk = $(this).data('pk');
if (pk && !uniqueArray.includes(pk)) {
uniqueArray.push(pk);
html.push(`<option value="${pk}">${pk}</option>`);
}
});
$('#id_articles').html(html.join(""))
}
addArray()
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="drop">
<article data-pk="A">A</article>
<article>Undefined</article>
<article data-pk="B">B</article>
<article data-pk="">Empty</article>
<article data-pk="C">C</article>
</div>
<select id="id_articles"></select>
Some remarks:
Currently you are adding a value, then removing it again in the stop-function, and adding it yet again. True, the values will be unique, but this is not very efficient. Use a Set for efficiently making a collection unique.
Use jQuery more to the full when creating option elements
To answer your question: just check for undefined before including it. But if you use the Set-way of working (see point 1), you can just delete undefined from that Set
Here is how it could look:
function addArray() {
let articles = new Set(
$('#drop').children().map((i, elem) => $(elem).data('pk')).get()
);
articles.delete(undefined);
$('#id_articles').empty().append(
Array.from(articles, value => $("<option>", { value }).text(value))
);
}
addArray();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="drop">
<div data-pk="red"></div>
<div data-pk="blue"></div>
<div data-pk="red"></div>
<div></div>
</div>
<select id="id_articles"></select>
Simply compare element with undefined
const array = [1,2,undefined,3,4,undefined,5];
const result = array.filter((el) => el !== undefined);
console.log(result)
I have a datatable that shows mock json data retrieved from a text file. I have removed the first column as it contains the id and it isn't ideal to display the id on the table. I appended a buy button on each row on the first column only. However, when I sort the table the button disappears and the original first column data also appears.
JavScript:
$(document).ready(function() {
$.getJSON('/apps/mchp/clientlibs/clientlib-site/components/parametrictable/data.txt', function(json) {
var data = json.data;
var $thead = $('#parametrictable').find('thead');
var tr = $("<tr>");
$thead.append(tr);
var columns = [];
var obj = Object.keys(data[0]);
console.log(data[0])
var button = '<div class="left-btn"><i class="download fas fa-file-download"></i></div><div class="right-btn"><div class="input-group"><div class="input-group-area"><input type="text" value="100"></div><div class="input-group-icon">BUY</div></div></div>';
$.each(data[0], function(name, value) {
var column = {
"data": name,
"title":name
};
$('tr').find('th:first-child',).remove();
columns.push(column);
});
for (i=1; i<obj.length; i++) {
$(".dropdown-content").append('<li><input type="checkbox" class="dropcheck" data-column="'+i+'"/>'+obj[i]+'</li>');
}
var table= $('#tableId').DataTable({
data: data,
columns: columns,
columnDefs: [ {
orderable: true,
className: 'select-checkbox',
targets: 1
} ],
select: {
style: 'multi',
selector: 'td:first-child'
},
order: [[ 1, 'asc' ]]
});
$('tr').find('th:first-child').remove();
$('tr').find('td:first-child').remove();
$('tr').find('td:first-child').append(button);
$('tr').on('change', function(e){
e.preventDefault();
console.log('change!');
});
$('input[type=checkbox]').on( 'change', function (e) {
e.preventDefault();
var column = table.column( $(this).attr('data-column') );
column.visible( ! column.visible() );
} );
$('.show-all').on( 'click', function (e) {
e.preventDefault();
var obj = Object.keys(data[0])
for (i=1; i<obj.length; i++) {
var col = table.columns([i]);
if (col.visible().join(', ') == 'false') {
col.visible(true);
$(".dropcheck").prop("checked", false);
}
}
} );
});
})
First, it is not a good practice to hide datatable columns by .remove(), datatables have a built-in code for that by columnDefs refer:
https://datatables.net/examples/basic_init/hidden_columns.html
Second, that is not the right way to append data/html in datatable columns, use rowCallback function for datatable, see:
columnDefs: [
{
"targets": [ 0 ],
"visible": false,
"searchable": false
},
],
rowCallback: function(row, data, index) {
if($('td:eq(1)', row).find('.download').length == 0)
{
$('td:eq(1)', row).append(button);
}
},
When using datatable sort or search or any datatable actions it always refreshes the table therefore, any initialization before the action will be disregarded unless executed again.
I am trying to create an inline edit function to trigger differently on different elements.
I have tried to use other plugins but haven't been able to get them to do exactly what I want so have decided to try to create a plugin of my own, while learning jquery along the way.
The issue I am currently having is that I have a .blur event that is triggering on a span element correctly and this is what I want but when the element is a select element I don't want the blur event to trigger. As the code is below the blur event triggers and it is not the desired result. Can anybody advise how I can only trigger the blur() event on span elements and nothing else
$('.inlineEdit-jmc').inlineEditJmc({
fieldsArray: {
table-column1: 'field-table-column1',
table-column2: 'field-table-column2'
}
});
(function ( $ ) {
$.fn.inlineEditJmc = function(options) {
//Set Default Settings
console.log(options);
var settings = $.extend({
'pk': null,
'table': null,
'field': null,
'url': null,
'type': null,
'fieldsArray': null
},options)
if(settings.fieldsArray == null){}else{
var fields = new Array();
}
function load_settings(this_selected){
settings['pk'] = this_selected.attr("data-pk"); // pk of table to be updated
settings['table'] = this_selected.attr("data-table"); // table name of table to be updated
settings['field'] = this_selected.attr("data-field"); // name of the field in the table being updated
settings['url'] = this_selected.attr("data-url"); // url for the ajax call to be sent to.
settings['type'] = this_selected.attr("data-type"); // type of input being used. Input or Select
settings['value'] = this_selected.text(); //
settings['class'] = this_selected.attr("class"); // The Class
console.log(settings['table'] +' '+ settings['value']+ ' '+ settings['class']);
// if there are optionional inserts passed lets grab them
console.log('passed options:');
if(settings.fieldsArray == null){}else{
//var fields = [];
$.each(settings.fieldsArray,function(k,v){
//console.log('settings['+k+'] '+this_selected.attr(v));
$obj={};
$obj[k] = this_selected.attr(v);
fields.push($obj);
});
}
}
$(this).on('mouseover', function(event) {
$(this).addClass("ui-state-hover");
}).on('mouseout', function(event) {
$(this).removeClass("ui-state-hover");;
});
if($(this).is('select')){
$(this).on('change', function(){
alert('changed');
alert($(this).val());
//console.log($(this));
//load_settings($(this));
var nt = $(this).text();
var jsonstring = JSON.stringify(fields);
// AJAX
});
}
if($(this).is('span')){
$(this).on("blur", function () {
alert('span');
load_settings($(this));
var nt = settings['value']
console.log('comment: '+settings['value']);
// we are going to update the db here.
console.log('Insert');
console.log(fields);
var jsonstring = JSON.stringify(fields);
console.log(jsonstring);
$.ajax({
type: 'POST',
url: settings['url'],
data: {
fieldsArray: fields,
pk: settings['pk'],
table: settings['table'],
field: settings['field'],
value: settings['value']
},
cache: false,
success: function(data,status){
console.log(data);
}
});
});
}
}
})(jQuery);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<td class=''>
<select class='inlineEdit-jmc' ><option value='0' data-pk='3' data-url='/path/to/js/ajax/ajax.php' data-table='mysqltablename' data-field='ignore'>NO</option>
<option value='1' data-pk='3' data-url='/path/to/js/ajax/ajax.php' data-table='mysqltablename' data-field='ignore' selected>YES</option>
</select></td>
<td class=''><span class='inlineEdit-jmc' id='input' data-pk='3' data-url='/path/to/js/ajax/ajax.php' data-table='mysqltablename' data-field='comment' contenteditable='true'>Text that can be edited</td>
Try this code section in place of yours that begins if($(this).is('span')){
$(this).on("blur", function ()
$("span").on("blur", function () {
// your function content here
});
$("span select").on("blur", function () {
e.stopPropagation();
});
The two alternative selectors act like a case statement in jQuery
I have following code for jQuery DataTables:
Contact.DataTable = $('#otable').DataTable( {
"ajax": {
"url" : '/Contact/' + Contact.id,
"dataSrc": function(check) {
return check.data;
},
},
"responsive": true,
"columns": [
{ "data": "id"},
{ "data": "category", "sClass": "category" },
{ "data": "name", "sClass": "name" },
{ "data": "lname" },
{
"render": function ( data, type, method, meta ) {
return Contact.saveContact(method);
}
},
]
} );
Datatable - dropdown - inline edit:
$('#otable tbody').on('click', '.category', function () { //second column
var row = this.parentElement;
if(!$('#otable').hasClass("editing")){
$('#otable').addClass("editing");
var data = Contact.DataTable.row(row).data();
var $row = $(row);
var thiscategory = $row.find("td:nth-child(2)");
var thiscategoryText = thiscategory.text();
thiscategory.empty().append($("<select></select>",{
"id":"category" + data[0],
"class":"in_edit"
}).append(function(){
var options = [];
$.each(Categories, function(key, value){
options.push($("<option></option>",{
"text":value,
"value":value
}))
})
return options;
}));
$("#category" + data[0]).val(thiscategoryText)
}
})
;
For changing values in dropdown
$('#otable tbody').on("change", ".in_edit", function(){ //Inline editing
var val = $(this).val();
$(this).parent("td").empty().text(val);
$('#otable').removeClass("editing");
});
Below code for saving new values(after inline edit) while clicking save:
$('#divsave').on("click", ".saveContact", function() {
var data = Contact.DataTable.row($(this).closest('tr')).data();
// Here I have to get new values after inline editing - but getting old values
});
My problem is : while clicking edit, in 'data', I am getting old values in the row of datatable, not the modified value after inline edit
datatable view - 1:
datatable - dropdown in column:
datatable after inline editing:
What I need: Save modified row while clicking 'save' image - currently it saves older value before inline editing(datatable view - 1)
When using dataTables it is generally a very bad idea to manipulate the DOM <table> or any content by "hand" - you should always go through the dataTables API.
Thats why you are getting "old values" - you have manipulated the content of the <table>, or so it seems - dataTables are not aware of those changes.
In a perfect world you should refactor the setup completely (i.e to use the API) but I guess you can solve the issue by using invalidate() on the row being changed in order to refresh the dataTables internals :
$('#otable tbody').on("change", ".in_edit", function(){ //Inline editing
var val = $(this).val();
$(this).parent("td").empty().text(val);
//add this line to refresh the dataTables internals
Contact.DataTable.row($(this).parent("tr")).invalidate();
//
$('#otable').removeClass("editing");
});
I'm working on a file-upload feature in my MVC 3 application.
I have it working correctly (kinda), the problem is within the onComplete function when I try to remove the qq-uploader class, it gets removed from all the checked table cells.
The workflow would be as follows, user checks multiple check boxes the "upload file" btn appears in each row checked, but once one upload is complete in one row the 'qq-uploader class is removed from all cells not just the cell where the file was uploaded.
The table row cell in question :
#if (Model.ElementAt(index).CertName != null)
{
<td>#Html.DisplayFor(m => Model.ElementAt(index).CertName)</td>
}
else
{
<td id ="attBtn" class="file-uploader-attachment-Class"></td>
}
Script used in view :
<script type="text/javascript">
$(document).ready(function () {
function handleCheckbox() {
if ($(this).find(':checkbox').is(':checked')) {
$(this).find('.file-uploader-attachment-Class').removeClass("upload-placeholder-unchecked");
createUploader($(this));
}
else {
$(this).find('.file-uploader-attachment-Class').addClass("upload-placeholder-unchecked");
$(this).find('.file-uploader-attachment-Class').html($('#myHTML2').html());
}
}
$('tr').each(handleCheckbox);
$('tr').on('click', handleCheckbox);
function createUploader(container) {
var elements = container.find('.file-uploader-attachment-Class');
var CAL_ID = container.find(':checkbox').val()
var row = $(this).parent();
Array.prototype.filter.call(elements, function (element) {
var uploader = new qq.FileUploader({
element: element,
sizeLimit: 2147483647, // max size
action: '/CalibrationViewer/AttachmentUpload',
allowedExtensions: ['xls', 'xlsx', 'pdf', 'doc', 'docx', 'csv', 'txt', 'rtf', 'zip', 'zipx', '7z'],
params: {
customer: CUST_NAME,
calibrationId: CAL_ID
},
multiple: false,
debug: false,
onComplete: function (id, fileName, responseJson) {
alert(responseJson.msg);
$('.qq-uploader').remove();
elements.closest('.file-uploader-attachment-Class').prepend('<div class="uploadedTag"><p>Uploaded</p></div>')
}
});
});
}
});
This worked for me
elements.closest('.file-uploader-attachment-Class').find('.qq-uploader').remove();