File browse inside datatables row - javascript

I'm using datatables to show some fields and two file upload button like below.
I would like to click on browse and then, after file secetion, call a web service to store file on the server and show the name beside the button, in the input field.
The problem is that the datatable is created from javascript:
function createDatatableTable(){
if ( ! $.fn.DataTable.isDataTable( '#datatableTable' ) ) {
datatableTable = $('#datatableTable').DataTable({
responsive: true,
columnDefs: [
{
targets: [3,4,5],
//set priority to column, so when resize the browser window this botton stay on the screen because have max priority
responsivePriority: 1,
orderable: false,
searchable: false,
}
],
//fix problem with responsive table
"autoWidth": false,
"ajax":{
"url": "datatable/" + $("#selectedCar").val(),
"dataSrc": function ( json ) {
if (typeof json.success == 'undefined')
window.location.href = "/DART/500";
else if (json.success){
return json.result.data;
}else{
notifyMessage(json.result, 'error');
return "";
}
},
"error": function (xhr, error, thrown) {
window.location.href = "/DART/500";
}
},
"columns": [
{ "data": "date",
"render": function (data) {
return (moment(data).format("DD/MM/YYYY"));
}
},
{ "data": "idShift" },
{ data:null, render: function ( data, type, row ) {
return data.beginKm - initialKm;
}
},
{ data:null, render: function ( data, type, row ) {
return '<div class="input-group"><span class="input-group-btn"><span class="btn btn-primary file-upload"> Browse… <input id="dat" type="file" name="file"/></span></span> <input id="datFileName" target="'+row.idAcquisition+'" type="text" class="form-control" readonly="readonly"></div>'
}
},
{ data:null, render: function ( data, type, row ) {
return '<button type="button" class="btn btn-primary" id="otherFiles">Other</button>'
}
},
{ data: "isShown", render: function ( data, type, row ) {
if (data) {
return '<input data="'+row.idAcquisition+'" type="checkbox" name="my-checkbox" checked>';
}
else {
return '<input data="'+row.idAcquisition+'" type="checkbox" name="my-checkbox">';
}
}
},
],
"fnDrawCallback": function() {
//Initialize checkbox for enable/disable user
$("[name='my-checkbox']").bootstrapSwitch({size: "small", onColor:"success", offColor:"danger"});
},
});
}
else {
datatableTable.ajax.url("datatable/" + $("#selectedCar").val()).load();
}
In this way I have given one unique id to the text area where I have to write but now how can I know the row clicked?
I have used:
//File dat upload
$('#datatableTable').on('change', 'input[name="file"]', function(event) {
var input = $(this),
label = input.val().replace(/\\/g, '/').replace(/.*\//, '');
var fieldFileName="datFileName"+ document.getElementById("datFileName").getAttribute("target");
document.getElementById(fieldFileName).value = label;
//uploadFunction('dat');
});
but it returns always the same id so use only the first file browse. I check and the id are all right.
I shouuld use an approach like var test= $(this).parent().parent().parent(); and the get the id of child?
I have used this approach for my switch button and it works:
$('#datatableTable').on('switchChange.bootstrapSwitch', 'input[name="my-checkbox"]', function(event, state) {
//CSRF attribute for spring security
var token = $("meta[name='_csrf']").attr("content");
var header = $("meta[name='_csrf_header']").attr("content");
$.ajax({
type : "POST",
url : "status/" + $(this).attr('data') + "/" + state,
RESOLVED:
I fix the problem using in datatables
return '<div class="input-group"><span class="input-group-btn"><span class="btn btn-primary file-upload"> Browse… <input id="dat" type="file" name="file" target="'+row.idAcquisition+'"/></span></span> <input id="'+row.idAcquisition+'" type="text" class="form-control" readonly="readonly"></div>'
and using
$('#datatableTable').on('change', 'input[name="file"]', function(event) {
var input = $(this),
label = input.val().replace(/\\/g, '/').replace(/.*\//, '');
var test= $(this).attr('target');
document.getElementById(test).value = label;
// uploadFunction('dat');
});

Per definition an element ID must be unique throughout the whole document. Therefore
document.getElementById("datFileName")
and
$("#datFileName") // jQuery equivalent
will only return the first element with the given id. It seems though that in your table every row has the same element IDs inside.
Here's how you can make the IDs unique:
The columns.render function is given 4 arguments (although you're using only 3 of them). The fourth is metaand it has a field called row which is an index for the currently processed row. Use this to generate your ID:
...
{ data:null, render: function ( data, type, row, meta ) {
var idDat = "dat" + meta.row;
var idDatFN = "datFileName" + meta.row;
return '<div class="input-group"><span class="input-group-btn"><span class="btn btn-primary file-upload"> Browse… <input id="'+id+'" type="file" name="file"/></span></span> <input id="'+idDatFN+'" target="'+row.idAcquisition+'" type="text" class="form-control" readonly="readonly"></div>'
}
...
An alternative to this approach that is possibly cleaner is not giving the fields IDs at all but referencing them as siblings and their :nth-of-type(n) selectors. Consider reading the jQuery docs for that.
Example:
$('#datatableTable').on('change', 'input[name="file"]', function(event) {
var input = $(this),
label = input.val().replace(/\\/g, '/').replace(/.*\//, '');
// find the input's first ancestor with class input-group and inside it
// look for an input of type=text. then set its value
input.parent(".input-group").find("input[type=text]").val(label);
});
Not related the the actual problem, but you're also using the data attribute wrong. Instead of
<element data="bar" />
you should use
<element data-foo="bar" />
This way you can have multiple data attributes on each element and you can access them easily through jQuery like this:
$("element").data("foo") // getter
$("element").data("foo", "no bar") // setter

Related

jQuery UI AutoComplete - How to handle multiple values ,when user removes a value in between the selected values

This is What I have :
I have a text box input element as below for loading cities autoloaded and a hidden field to list its ids:
<label class="col-sm-2 control-label" for="city_disp"> City</label>
<div class="col-sm-5">
<div class="input-group">
<input type="hidden" class="hidden_value" name="city" id="city" value="" />
<input type="text" name="city_disp" placeholder="City"
id="city_disp" data-request_type="cities" value=""
class="form-control autocomplete-input-field" autocomplete="off" />
</div>
</div>
jQuery UI AutoComplete which I use, the data array comes from Ajax response :
function split( val ) {
return val.split( /,\s*/ );
}
function extractLast( term ) {
return split( term ).pop();
}
$(".autocomplete-input-field").autocomplete({
source: function (request, response) {
$this = this.element;
var term = extractLast(request.term);
$.ajax({
url: myHome+'/my_ajax',
dataType: "json",
type: "POST",
data: {
term: term,
action_type: "getdata"
},
success: function (data) {
response(data);
}
});
},
minLength: 2,
select: function (event, ui) {
var tempval = $(this).val() ;
var terms = split( this.value );
var split_string = split(
$(this).closest('div').find('.hidden_value').val() );
split_string.pop();
terms.pop();
terms.push( ui.item.label );
split_string.push( ui.item.value );
terms.push( "" );
split_string.push( "" );
var labels = terms.join( ", " );
var new_vals = split_string.join( "," );
$(this).val(labels);
$(this).closest('div').find('.hidden_value').val(new_vals);
return false;
},
focus: function (event, ui) {
event.preventDefault();
}
});
Output I am getting currently:
Currently,autocomplete is working fine when I type atleast 2 characters in the text box name="city_disp" . If user selects 3 values from the autocomplete cities list: 'New York,Washington,London' and the ids corresponding to these cities '45,56,78' gets appended to the hidden html input field name="city".
Modification which I am trying to implement :
Suppose if user selects 'New York,Washington,London' and its id gets '45,56,78' gets appended to the hidden html input field name="city". and the user removes a Washington from the selected values . Then the hidden value must also change accordingly to '45,78'. Also when a user omits Washington to some absurd characters like 'dasdsad' ,then how to handle such situations with this jQuery UI AutoComplete?
There is not a good way to do this with two unique lists of text. there becomes no relationship between the two except for the positioning. When the User removes and item from List A, how do you identify in List B the change, and align the lists.
Consider moving the selected items to a new User interface with the ID attached.
Example: https://jsfiddle.net/Twisty/m3vfk0hg/
HTML
<label class="col-sm-2 control-label" for="city_disp"> City</label>
<div class="col-sm-5">
<div class="input-group">
<input type="hidden" class="hidden_value" name="city" id="city" />
<input type="text" name="city_disp" placeholder="City" id="city_disp" data-request_type="cities" class="form-control autocomplete-input-field" autocomplete="off" />
</div>
<div class="selected"></div>
</div>
Mostly the same HTML, yet now we have a section to display the Selected items, after they have been selected.
CSS
.selected {
margin: 3px;
}
.selected-item {
border: 1px solid #00f;
border-radius: 6px;
padding: 3px;
background: #ccf;
margin: 3px;
}
.selected-item .btn-close {
margin-left: 6px;
}
Giving us some Style.
JavaScript
$(function() {
var myAutoData = [{
label: "New York",
value: "45"
}, {
label: "Washington",
value: "56"
},
{
label: "London",
value: "78"
}
];
function newItem(it) {
var item = $("<span>", {
class: "selected-item",
"data-id": it.value
}).html(it.label);
$("<span>", {
class: "btn-close"
}).appendTo(item);
if ($("#city").val().length > 0) {
$("#city").val($("#city").val() + "," + it.value);
} else {
$("#city").val(it.value);
}
return item;
}
$(".autocomplete-input-field").autocomplete({
source: function(request, response) {
var term = request.term;
$.ajax({
url: "/echo/json/",
dataType: "json",
type: "POST",
data: {
json: JSON.stringify(myAutoData),
term: term
},
success: function(data) {
response(data);
}
});
},
minLength: 2,
select: function(event, ui) {
$(this).parent().parent().find(".selected").append(newItem(ui.item));
$(this).val("");
return false;
},
focus: function(event, ui) {
event.preventDefault();
}
});
$(".selected").on("click", ".btn-close", function() {
var id = $(this).parent().data("id");
$(this).parent().remove();
var sel = $("#city").val().split(",");
sel = sel.splice(sel.indexOf(id), 1);
$("#city").val(sel.join(","));
});
});
The example uses the JSFiddle options to Echo back JSON data Posted to it. You will want to use your own url and data. I also setup some basinc exmaple items based on your post.
When the User types in a option, wash, they get options they can select. When they click on a selection a new item is created.
<span class="selected-item" data-id="56">Washington<span class="btn-close"></span></span>
This element is appended to the .selected element. This help prevent the user from entering dasdsad, this would return no results, and they cannot select anything.
If the User decides to remove a previously selected item, they click the x and it is removed. Behind the scene, as they make selections, the value of #city is updated to a list of IDs, 56,45. When the User removes an item, the list is updated, and that entry is removed. This is done by converting the list into an Array and using Splice to remove the matching element.

Check if value in text filed was changed and post it. JS. Rails

So i'm having page, where we have text_field. The problem that when i press submit button, then he post full page(i mean each record that is on page). To exclude this, i need to check if the value has been changed in text_field or it has been removed. Do you have any ideas how to check it?
P.S I'm having autocomplete on this field, so when he changes the number in text_field, then the hidden field hidden_val0 is filled by number(but this is only when you change value, not remove it).
Its HTML:
<input autocomplete="off" hidden_val0="hidden_val0" id="add_109_01000340001001002_id" name="add_109_01000340001001002[id]" type="hidden" value="111286507">
This is js code that i'm using:
var NewArr = new Array();
$('.something_here').bind('click', function () {
var id= $(this).attr('id');
collectID = $("[hidden_val0='hidden_val0'], [hidden_val1='hidden_val1'], [hidden_val2='hidden_val2']")
.map(function(_, it){
return [it.value] // Collecting 3 values witch we should pass
})
.get();
for (var i=0; i<collectID.length; i=i+3) {
NewArr.push(collectID.slice(i,i+3)); // Here we split values by 3
}
$.post('/do/it',
{
send_array: JSON.stringify(NewArr), // Pass them
id: id
},
function (response) {
location.reload();
}
);
});
Its output:
["01000340001001001", "", ""]
["01000340001001002", "", "2"]
["01000340001001003", "", "3A"]
["01000340001001004", "", "3"]
["01000340001001005", "", "5"]
["01000340001001006", "", "6"]
["01000340001001007", "", "7"]
How HTML looks like:
<input autocomplete="off" autocomplete_key="add_109" hidden_val1="hidden_val1" id="add_109_01000340001001002" name="add_109_01000340001001002" onkeyup="GetNumbers(this)" size="3" style="height: 10px" type="text" value="2" class="ac_input">
You can use something like this: (this code was not tested)
var dataArray = [];
$(function(){
$(document).on('change', 'input', function(){
var hid1 = $(this).data("hidden_val0");
var hid2 = $(this).data("hidden_val1");
var hid3 = $(this).data("hidden_val3");
dataArray.push([hid1, hid2, hid3])
});
});
$('.something_here').bind('click', function (event) {
event.preventDefault();
$.post('/do/it',
{
send_array: dataArray,
id: id
},
function (response) {
location.reload();
}
);

Validate at least one auto generate jquery datatable checkbox is checked using MVC

Trying to make sure the user select at least one check box before submitting the form. At the moment my JavaScript is not working. The checkbox is auto generate in the jquery datatable. The code is still getting to the controller even when none of the checkbox in the table is not selected
HTML
<table id="scheduleAppointment-data-table" class="table table-striped table- bordered" style="width:100%;"></table>
<input type="submit" value="Send" class="btn btn-default" id=btnSubmit onclick="Validate()"/>
Datatable
// Auto generate checkbox
"columns": [
{
targets": [0],
"data": "EDMXID", "autoWidth": true,
"render": function (data, type, full) {
return '<input type="checkbox" id="EDMXID" name="EDMXID" value="'+full.EDMXID+'"/>';
},
}]
Javascript
function Validate() {
var allOk = true;
$(scheduleAppointment-data-table).find("tbody tr").each(function (){
var row = $(this);
var checked = row.find($(':checkbox:checked')).length > 0
if (!checked) {
allOk = false;
alert('At least One Appointment Should Be Selected');
return allOk;
}
});
return allOk;
}
With help from Davidkonrad comment I finally used the JavaScript code below
$(function () {
$('input[id$=btnSubmit]').click(function (e) {
$('#scheduleAppointment-data-table').find("tbody tr").each(function () {
var row = $(this);
var checked = row.find($(':checkbox:checked')).length > 0
if (!checked) {
alert('At least One Appointment Should Be Selected');
e.preventDefault();
}
});
});
});

Unable to select values from the select list

my select list is getting populated via a service call but I cannot select any of the values from the select list.
AJS.$("#select2-actor").auiSelect2(
{
placeholderOption: 'first',
formatResult: function(actor) {
return '<b>' + actor.text ;
},
data: function ()
{
var data = [];
AJS.$.ajax({
dataType: 'json',
type: 'GET',
url: AJS.params.baseURL+"/rest/leangearsrestresource/1.0/message/list/{actor}",
async: false
/*multiple: true*/
}).done(function(result) {
result = JSON.parse(result.value);
for (var actor in result.actors) {
data.push({
text : result.actors[actor]
});
//AJS.log(data)
}
});
return {
results: data
};
}
}
);
<div class="field-group">
<label class="label">Actor Select</label>
<input id="select2-actor" type="hidden" name="actor" style="width: 415px;" placeholder="Add an actor"/>
</div>
I am unable to figure out where I am going wrong.
Here is the JSFiddleLink
Here is the working fiddle: https://jsfiddle.net/64djszjf/14/
If you take a look at the source js file: https://aui-cdn.atlassian.com/aui-adg/5.8.13/js/aui-experimental.js, there are few lines that sets unselectable class:
populateResults: function(container, results, query) {
var populate, id=this.opts.id;
populate=function(results, container, depth) {
var i, l, result, selectable, disabled, compound, node, label, innerContainer, formatted;
results = opts.sortResults(results, container, query);
for (i = 0, l = results.length; i < l; i = i + 1) {
result=results[i];
disabled = (result.disabled === true);
selectable = (!disabled) && (id(result) !== undefined);
compound=result.children && result.children.length > 0;
node=$("<li></li>");
node.addClass("select2-results-dept-"+depth);
node.addClass("select2-result");
node.addClass(selectable ? "select2-result-selectable" : "select2-result-unselectable");
which indicates that this js file requires id attribute of the object passed in.
My fix was to simply add id field to your javascript:
for (var actor in result.actors) {
data.push({
text : result.actors[actor],
id: "1"
});
AJS.log(data)
}
This also indicates that you might want to change your REST service to return ids, along with the names of Actors.

Dynamic Query Builder

I am creating a custom MySQL database query UI. Inside this UI I have a Query Builder interface that I would like to dynamically append query properties based on the user selections in order to create a dynamic query. Please see the below picture for a visual description
From the picture above I would like to append CHARACTER_SET after the FROM and append as asterisk when ALL is selected from the table and so forth with the key being the positions where I place the generated variables.
How can I achieve this with JQuery?
My JavaScript
Selecting a Table
$(document).on("change", ".tbl_list", function () {
var tbls = new Array();
$("input:checkbox[name='tbl[]']:checked").each(function () {
tbls.push($(this).val());
});
var tbl = tbls.join('|');
var db = window.sessionStorage.getItem("db");
$.ajax({
type: "POST",
url: "ajax2.php",
data: {
tbl: tbl,
db: db
},
success: function (html) {
console.log(html);
$("#tblField").html(html).show();
}
});
});
Selecting All option
$(document).on("click", ".tblall", function () {
if (this.checked) {
// Iterate each checkbox
$('.tblst').each(function () {
this.checked = true;
});
} else {
$('.tblst').each(function () {
this.checked = false;
});
}
});
EDIT
As requested HTML for my DIVs
Table Selector
while ( $row = mysqli_fetch_array ( $tbl_list ) ) {
?>
<input type="checkbox" name="tbl[]" class="tbl_list"
value="<?php echo $row [0]; ?>" />
<?php echo $row [0]; ?>
<br>
Query Builder
<div id="qryDisplay">
<fieldset>
<legend> Query Builder</legend>
<div id="qryView">
<p>SELECT FROM</p>
</div>
</fieldset>
</div>
What I have tried so far
Using .append I can add data to the end of the paragraph so this would be ideal for my Table name. However its a function and i'm not sure how I would implement the code below into my select table function.
$("#qryView > p").append(" " tblName);
Anyway, not considering the logic behind the selection of multiple tables my approach would be to store selections in hidden input fields and at the end construct from the hidden fields the query.
<input type="hidden" value="" name="hiddenTables" id="hiddenTables" />
fill field according to selections in your function from above:
$("input:checkbox[name='tbl[]']:checked").each(function () {
tbls.push($(this).val());
if($('#hiddenTables').val() == ""){
$('#hiddenTables').val($(this).val());
}else{
$('#hiddenTables').val($('#hiddenTables').val()+','+$(this).val());
}
});
At the end create your query:
// hidden field for field selection, same as above.
var fieldselection = '*';
if($('#hiddenFieldselection').val() != ""){
fieldselection = $('#hiddenFieldselection').val();
}
$("#qryView > p").html("SELECT " + fieldselection + " FROM " + $('#hiddenTables').val());
This needs to be adjusted the way you need it of course and I haven't tested any of this... So that's up to you :-)

Categories