I have a table that is created using javascript based on what is put in a list. This works fine in Jquery 3.4, but when I upgrade to 3.5 I am seeing this break.
HTML
<h5>Questions</h5>
<table id="questionTable" class="table q">
<thead>
</thead>
<tbody id="qTable"></tbody>
</table>
<div id="questionDiv">
<input type="button" value="Add Question" onclick="AddNewQuestion()" class="btn btn-primary"/>
</div>
<hr />
<div id="questionDiv">
<input type="submit" value="Submit" class="btn btn-primary" />
</div>
Javascript
<script type="text/javascript">
$(document).ready(function () {
$(function () {
AddCurrentQuestions();
});
});
var table = document.getElementById("qTable");
var rowCount = table.rows.length;
var counter = rowCount.length;
function AddCurrentQuestions() {
var status = #Html.Raw(Json.Encode(Model.isNull));
if (status == false) {
#{ Model.QuestionList.Add(new Performance_Planning.ViewModel.QuestionViewModel.Questions());}
var questionItems = JSON.parse('#Html.Raw(Json.Encode(#Model.QuestionList))');
for (var i = 0; i < questionItems.length - 1; i++) {
var qItem = questionItems[i];
var questionDetail = qItem.Question;
//Create fields
var qTextCell = "<td><textarea id='QuestionList_" + i + "_Question' name='QuestionList[" + i + "].Question' class='Questions' /></td>";
var indexCell = "<td style='display:none'> <input name='QuestionList.Index' type='hidden' value='" + i + "' /></td>";
var removeCell = "<td align='center'><input id='btnDelLine'" + i + "type='button' value='Remove' onclick=\"removeRow('" + i + "')\" class='btn btn-primary' /></td>";
var newRow = "<tr id='qLineItem" + i + "'>" + indexCell + qTextCell + removeCell + "</tr>";
//Add row to table
$('#qTable').append(newRow);
//Add Values
$('#QuestionList_' + i + "_Question").val(questionDetail)
counter = i;
};
} else {
counter = 0;
AddNewQuestion();
}
};
function AddNewQuestion() {
#{ Model.QuestionList.Add(new Performance_Planning.ViewModel.QuestionViewModel.Questions());}
counter++;
//Create field
var indexCell = "<td style='display:none'> <input name='QuestionList.Index' type='hidden' value='" + counter + "' /></td>";
var qTextCell = "<td><textarea id='QuestionList_" + counter + "_Question' name='QuestionList[" + counter + "].Question' class='Questions' /></td>";
var removeCell = "<td align='center'><input id='btnDelLine'" + counter + "type='button' value='Remove' onclick=\"removeRow('" + counter + "')\" class='btn btn-primary' /></td>";
var newRow = "<tr id='qLineItem" + counter + "'>" + indexCell + qTextCell + removeCell + "</tr>";
$('#qTable').append(newRow);
};
function removeRow(id) {
var rowId = "qLineItem" + id;
var row = document.getElementById(rowId);
row.parentNode.removeChild(row);
};
</script>
}
What I end up seeing is that the remove button is treated as text in 3.5.1 but this doesn't occur with 3.4. I am unsure how to solve this issue or if I will need to figure out another way to write this page.
When I view the webpage and inspect the field I see it do the following:
<textarea id="QuestionList_0_Question" name="QuestionList[0].Question" class="Questions">
"</td><td align='center'><input id='btnDelLine'0type='button' value='Remove' onclick="removeRow('0')" class='btn btn-primary' /></td></tr></tbody></table>"
The textarea element should have a separate close tag. It is not allowed to self-close. So this is not valid HTML:
<textarea />
But this is:
<textarea></textarea>
Apparently, jQuery 3.5 is more strict in this. An inspection of the 3.5 changelog reveals that this is a consequence of the security fix they applied:
The main change in this release is a security fix, and it’s possible you will need to change your own code to adapt. Here’s why: jQuery used a regex in its jQuery.htmlPrefilter method to ensure that all closing tags were XHTML-compliant when passed to methods. For example, this prefilter ensured that a call like jQuery("<div class='hot' />") is actually converted to jQuery("<div class='hot'></div>"). Recently, an issue was reported that demonstrated the regex could introduce a cross-site scripting (XSS) vulnerability.
The HTML parser in jQuery <= 3.4.1 usually did the right thing, but there were edge cases where parsing would have unintended consequences. The jQuery team agreed it was necessary to fix this in a minor release, even though some code relies on the previous behavior and may break. The jQuery.htmlPrefilter function does not use a regex in 3.5.0 and passes the string through unchanged.
One can see how before 3.5, jQuery would actually change <textarea /> to <textarea></textarea> on the fly, thereby fixing the error you made. But now with version 3.5 jQuery no longer does that, and so your HTML remains invalid, leading to an unintended rendering where everything after <textarea /> ends up as content to that text area element.
This question already has answers here:
How to use jQuery each() function within append()
(2 answers)
Closed 4 years ago.
Here is my code
$('#payment_detail').append(
'<table class="table table-bordered table-striped">'+
'<thead>'+
'<th>Payment Date</th>'+
'<th>Payment Value</th>'+
'<th>Verified By</th>'+
'</thead>'+
'<tbody>'+
$.each(response.payments, function (key, value) {
return '<td>'+ value.payment_date +'</td> <td>'+ value.payment_value +'</td> <td>'+ value.created_by +'</td>'
})+
'</tbody>'+
'</table>'
);
but the view looks like this
can someone help me? thanks
try this
('#payment_detail').append(
'<table class="table table-bordered table-striped">'+
'<thead>'+
'<th>Payment Date</th>'+
'<th>Payment Value</th>'+
'<th>Verified By</th>'+
'</thead>'+
'<tbody id="dtDetails"></tbody></table>');
$.each(response.payments, function (key, value) {
$("#dtDetails").append('<tr><td>' + value.payment_date + '</td> <td>' + value.payment_value + '</td> <td>' + value.created_by + '</td></tr>');
});
I have an $.ajax() request working properly, but i need to get 4 values(name, clientid, url, id) of < td >. $.val() doesn't work, because it only works on inputs.
I need to get the name, client Id , url and id from dynamically appended rows. I need those values so, when I click on the edit button of the selected row, it saves the changes I made.
How should I get the value? with $.html()? $.text()?
HTML
<div class="row">
<div class="col-md-12 overflow-table">
<table class="table" id="table">
<thead class="head-color thead-inverse">
<tr>
<th style="border-top-left-radius: 10px; border-left:1px solid transparent;">NAME</th>
<th>CLIENT-ID</th>
<th>URL</th>
<th style="border-top-right-radius: 10px; border-right:1px solid transparent;">ACTIONS</th>
</tr>
</thead>
<tbody id='table-redirect'>
<tr class='lightgrey'>
</tr>
<tr class='lightgrey'>
</tr>
<tr class='lightgrey'>
</tr>
<tr class='lightgrey'>
</tr>
</tbody>
</table>
</div>
</div>
JavaScript:
//change table content
$(document).on('click', '#editButton', function(e) {
var url = "http://mobisteinlp.com/redirect/redirect";
var name = $('#name1').val();
console.log(name);
var clientId = $('#client_id1').val();
console.log(clientId);
var redirectUrl = $('#url1').html();
console.log(redirectUrl);
var id = $('#hidden').val()
console.log(id);
var formData = new FormData();
formData.append('name1', name);
formData.append('client_id1', clientId);
formData.append('url1', redirectUrl);
formData.append('id', id);
console.log('test');
$.ajax({
url: url + "/editRedirect",
type: "POST",
dataType: "json",
data: formData,
contentType: false,
cache: false,
processData: false,
success: function(obj) {
var name, clientId, redirectUrl, id;
var rows = '';
$("tbody").empty('');
for (i = 0; i < obj.length; i++) {
rows += "<tr class='lightgrey'><th contenteditable='true'>" + obj[i].name + "</th><td>" + obj[i].client_id + "</td><td contenteditable='true' >" + obj[i].url + "</td><td><button type='button' id='editButton' class='btn btn-info'" + obj[i].client_id + "'><img class='col-md-2 edit nopad float-right' src='http://mobisteinlp.com/redirect/public/img/edit.svg'></button><a href='http://mobisteinlp.com/redirect/public/click.php/?id='" + obj[i].id + "'><img class='col-md-2 link nopad float-right' src='http://mobisteinlp.com/redirect/public/img/copy.svg'></a></td></td></tr>";
console.log('sucess!');
console.log(obj);
}
$("#table").append(rows);
},
error: function() {
console.log('error');
}
}); //END /editRedirect $.ajax()
}); //END $(document).on('click','#change',function(e)
The .text() method will return just the text within the element.
The .html() method will return the text, plus any HTML which might be contained within the element.
e.g. if your <td> looked like this for any reason:
<th class="clientID"><span>12345</span></th>
Then:
$(".clientID").text(); will return 12345
$(".clientID").html(); will return <span>12345</span>
So for your purposes you should use .text() to get just the actual text content to send to the server.
You can check all this in the jQuery documentation easily, as well, and by your own tests.
Now, to get a value within the specifically clicked row, you need to restrict by the row context in the markup. In the "click" event, this will be the button that was clicked, which is within the <tr>. The corresponding data is also within the <tr>.
So you can use the <tr> as the nearest element which encloses both the button and the data. Then if you give each <td> a class corresponding to what it represents (client ID, url, etc) as I've done above, you can do something like:
var tr = $(this).closest("tr"); //get the parent tr
var clientID = tr.find(".clientID").text(); //get the client ID text within the tr
var url = tr.find(".url").text(); //same for url, etc...
Lastly, your button clicks won't work properly because you're duplicating IDs. It will only ever work for the first button.
Change <button type='button' id='editButton' class='btn btn-info' to <button type='button' class='btn btn-info editButton' (use a class instead of an id)
and change $(document).on('click', '#editButton', function(e) { to $(document).on('click', '.editButton', function(e) { (simply, # is changed to .)
1) you appending multiple row with duplicate id . id should be unique for each element . just use class name instead of id .
2) appending one th and extra td
<th contenteditable='true'>" + obj[i].name + "</th>
Updated code with class name
` <tr class='lightgrey'>
<td contenteditable='true' class="name">" + obj[i].name + "</td>
<td class="client_id">" + obj[i].client_id + "</td>
<td contenteditable='true' class="url" >" + obj[i].url + "</td>
<td>
<button type='button' class='btn btn-info editButton'" + obj[i].client_id + "'>
<img class='col-md-2 edit nopad float-right' src='http://mobisteinlp.com/redirect/public/img/edit.svg'>
</button><a href='http://mobisteinlp.com/redirect/public/click.php/?id='" + obj[i].id + "'>
<img class='col-md-2 link nopad float-right' src='http://mobisteinlp.com/redirect/public/img/copy.svg'></a>
</td>
</tr>`
Jquery :
Setup class name for each td and traverse and access it easily like this
`$(document).on('click', '.editButton', function(e) {
var tr = $(this).closest("tr");
var client_id = tr.find(".client_id").text();
var url = tr.find(".url").text();
var name = tr.find(".name").text();
});`
Get the different between these commands, then you can fix your by yourself
The following used to retreive data from a value attribute(normally input tags).
//Here id is id name of your element
$('#id').val();
If you want to get the data from a element you need to use
1. This will return the text inside the element.
$('#id').text()
2. This will return the html inside the element.
$('#id').html()
Hope it helps you.
Try It...
$("#ObjectsTable").find("tr:gt(0)").remove();
var arr = $.parseJSON(data);
$.each(arr, function(index,value) {
$('#ObjectsTable')
.append($("<tr>" +
"<td>" + value.ID + "</td>" +
"<td>" + value.Model + "</td>" +
"<td>" + value.Type + "</td>" +
"<td>" + value.Color + "</td>" +
"<td>" + value.Price + "</td>" +
"</tr>"));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<table id="ObjectsTable" class="responstable">
<tr>
<th>ID</th>
<th>Model</th>
<th>Type</th>
<th>Color</th>
<th>Price</th>
</tr>
</table>
I have some jQuery script in which I'm adding some rows to a table (when the user press a button). My problem is that I want to change the id of the elements inside the rows dynamically. I have set a global variable i which I set as an id to some elements inside my table. The problem is that after some debugging I found out that the id doesn't change at all and stays as the letter i (and not the variable i set to 0 and increase every time the user press the button). Any ideas?
var i=0;
var a1=i.toString().concat("1");
var a2=i.toString().concat("2");
var a3=i.toString().concat("3");
$("#table1").append("<tr><td><center><input id=\"a1\"></input></center></td><td>
center><button id=\"a2\">Load</button></center></td><td ><img id=\"a3\"></td>
</tr>");
$("#a2").click(function(){
$z=$("#a1").val();
$("#a3").attr("src",$z);
i++;
});
That's because you're writing those directly as strings. You need to concatenate them into the actual string. You can concatenate strings together using +.
$("#table1").append(
"<tr>" +
"<td>" +
"<center><input id=\"" + a1 + "\" /></center>" +
"</td>" +
"<td>" +
"<center><input id=\"" + a2 + "\" /></center>" +
"</td>" +
"<td>" +
"<center><input id=\"" + a3 + "\" /></center>" +
"</td>" +
"</tr>"
);
For what it's worth, the <center> tag is deprecated and should not be used. You may also consider creating some kind of template rather than generating your HTML as strings directly inside of JavaScript.
This question already has answers here:
Adding onClick event dynamically using jQuery
(7 answers)
Closed 8 years ago.
I want to fetch the json data from serve and then loop the rows of table. the html code is like:
<table id="topics_list_table">
<thead>
<tr><th>Topic Title</th>
<th>Author Name</th>
<th>Likes</th>
<th>Created Time</th>
<th>Actions</th>
</tr></thead>
<tbody>
</tbody>
</table>
the jQuery part:
$.ajax({
url: some url here,
type:'GET',
success:function(res){
$.each(res, function(index, value){
$('#topics_list_table > tbody:last').
append(
"<tr>" +
"<td>" + value.title + "</td>"+
"<td>" + value.author_name + "</td>"+
"<td>" + value.likes + "</td>"+
"<td>" + value.created + "</td>"+
"<td>" +
"<a href='/components/topics/" + value.id + "' class='mini ui black buttons' id='detail_check'>check</a>"+
"</td>"+
"</tr>"
);
});
}
});
I could get all the data from the remote side, but the key question is this part
<a href='/components/topics/" + value.id + "' class='mini ui black buttons' onclick='somefunction()'>check</a>
I inspect this page and found, sth like
<a href="/components/topics/53cf67fad0c0f7fdda3ef8d5" class="mini ui black buttons" onclick='somefunction()'>check</a>
already exists in the dom.
but
1, the style class="mini ui black buttons" can not be applied.
2, when you try to click the "check" and want to trigger the somefunction(). it doesnt work.
so, why couldn't i get the dom element after appending the rows? OR, is there any other better way to loop rows after fetching the data?
thx
onclick attributes only work in the initial HTML, not in appended elements. See this question.
Instead, add the event handler using .click() or .on('click'):
success:function(res){
$.each(res, function(index, value){
var $row = $("<tr>" +
"<td>" + value.title + "</td>"+
"<td>" + value.author_name + "</td>"+
"<td>" + value.likes + "</td>"+
"<td>" + value.created + "</td>"+
"<td>" +
"<a href='/components/topics/" + value.id + "' class='mini ui black buttons' id='detail_check'>check</a>"+
"</td>"+
"</tr>");
$row.find('.mini.ui.black.buttons').on('click',somefunction);
$('#topics_list_table > tbody:last').
append($row);
});
}
Or, if it's the same function for every such link, just add it using event delegation:
$('#topics_list_table').on('click', '.mini.ui.black.buttons', somefunction);