unable to bind click event to nested li in jquery - javascript

I have done a lot but nothing is working anymore, i would like to do when i click on td then it will take the id of that td and this id will go to the database and it will fetch all the childs of that id. now i want to append those childs to that td based on id. But when i click on the nested td it take the id of parent. Here is my code.
<script type="text/javascript" >
$(document).ready(function() {
var url = document.URL;
var parts = url.split("/");
var t = "";
for(var i=0; i<parts.length-1; i++) {
t += parts[i] + "/";
}
var which_li = "";
$("td").bind('click',function(e) {
e.stopPropagation();
which_li = $(this).attr("id");
$.ajax({
type: "POST",
data : {id : which_li},
cache: false,
url: t+"treeData",
success: function(data){
var childs = data.split(",");
var res = "<table style='border:1px solid #ddd'><tr>";
for(var i=0; i<childs.length; i++ ){
if(childs[i] != "") {
res += "<td id='"+childs[i]+"'>"+childs[i]+"</td>";
}
}
res += "</tr></table>"
$("td[id='" + which_li +"']").append(res);
}
});
});
});
</script>
Html table with default id that will be the root of all the id :
<table id="data" style=" margin:0 auto; border:1px solid #ddd" >
<tr>
<td id='2'>2</td>
</tr>
</table>
it's working only once but after that it only taking the id of parent td not child td.
Please help me to short out this problem.
e.stopPropagation();
Stop Propagation is also not working anymore.
here is my sql table
create table user_login (
id int not null auto_increment,
parent int not null
);
my table structure would be like this :
// this is my table strucutre
<table id="data" >
<tr>
<td id="2">2
<table>
<tr>
<td id="24">24
<table>
<tr>
<td id="29">29</td>
<td id="30">30</td>
</tr>
</table>
</td>
<td id="25">25</td>
<td id="26">26</td>
</tr>
</table>
</td>
</tr>
</table>
when i will click on id 2 then a table will append to td containing childs 24,25,26 and when i will click on 24 then a table will append to td containing childs 29,30 and so on.
but when i want to get the id of 24 or 25 then it's giving me id of parent td that is 2 every time. Please help me.

You are binding, but only to elements that exist when you bind. The event propagates up until it hits an element that was bound, at which point it is stopping propagation. What you need to do is bind the event to an element that exists, and then delegate that event to the one's that may or may not exist yet. Something like this should work:
$("body").on('click', 'td', function(e) {
e.stopPropagation();
which_li = $(this).attr("id");
$.ajax({
type: "POST",
data : {id : which_li},
cache: false,
url: t+"treeData",
success: function(data){
var childs = data.split(",");
var res = "<table style='border:1px solid #ddd'><tr>";
for(var i=0; i<childs.length; i++ ){
if(childs[i] != "") {
res += "<td id='"+childs[i]+"'>"+childs[i]+"</td>";
}
}
res += "</tr></table>"
$("td[id='" + which_li +"']").append(res);
}
});
});

Well first of all, you are not binding the click event to newly added td's.
Secondary, don't bind a click event to a tag, better give a class to a td, and bind the click to that class, this way you will have more flexibility.
Corrected your code a bit:
<script type = "text/javascript" >
$(document).ready(function() {
var url = document.URL;
var parts = url.split("/");
var t = "";
for (var i = 0; i < parts.length - 1; i++) {
t += parts[i] + "/";
}
var which_li = "";
$("#data").on('click', '.closed', function(e) {
var clicked_td = $(this);
$.ajax({
type: "POST",
data: {
id: clicked_td.attr("id")
},
cache: false,
url: t + "treeData",
success: function(data) {
var childs = data.split(",");
var res = "<table style='border:1px solid #ddd'><tr>";
for (var i = 0; i < childs.length; i++) {
if (childs[i] != "") {
res += "<td class='.closed' id='" + childs[i] + "'>" + childs[i] + "</td>"; //added a 'closed' class
}
}
res += "</tr></table>"
clicked_td.removeClass("closed").append(res); //removing the class, so the click event won't fire again
}
});
});
});
</script>
And your html (added a class to td):
<table id="data" style=" margin:0 auto; border:1px solid #ddd" >
<tr>
<td id='2' class='closed'>2</td>
</tr>
</table>
In the future, try to use dataType: 'json', and on your php side you can do something like:
...
$response = array('2', '3', '5', '10');
echo json_encode($response);
Using this method (and it is the right one if you takeajax seriously), you wond have to manually split the values, so instead of:
...
success: function(data) {
var childs = data.split(",");
var res = "<table style='border:1px solid #ddd'><tr>";
for (var i = 0; i < childs.length; i++) {
if (childs[i] != "") {
res += "<td class='.closed' id='" + childs[i] + "'>" + childs[i] + "</td>";
}
}
res += "</tr></table>"
clicked_td.removeClass("closed").append(res);
}
You can do this:
success: function(data) {
var res = "<table style='border:1px solid #ddd'><tr>";
$each(data, function()
res += "<td class='.closed' id='" + this + "'>" + this + "</td>";
});
res += "</tr></table>"
clicked_td.removeClass("closed").append(res);
}

Use live instead of bind if you want to bind to elements that might be added in the future since you are adding elements dynamically (http://api.jquery.com/live/) :
$(document).ready(function() {
var url = document.URL;
var parts = url.split("/");
var t = "";
for(var i=0; i<parts.length-1; i++) {
t += parts[i] + "/";
}
var which_li = "";
$("td").live('click',function(e) {
// snip
Also stopPropogation works fine.

Try
$(document).ready(function() {
var url = document.URL;
var parts = url.split("/");
var t = "";
for(var i=0; i<parts.length-1; i++) {
t += parts[i] + "/";
}
var which_li = "";
$("#data td:not(.child td)").bind('click',function(e) {
e.stopPropagation();
var which_li = $(this).attr("id");
$.ajax({
type: "POST",
data : {id : which_li},
cache: false,
url: t+"treeData",
success: function(data){
var childs = data.split(",");
var res = "<table class='child' style='border:1px solid #ddd'><tr>";
for(var i=0; i<childs.length; i++ ){
if(childs[i] != "") {
res += "<td id='child-"+childs[i]+"'>"+childs[i]+"</td>";
}
}
res += "</tr></table>"
$("#" + which_li).append(res);
}
});
});
});

Related

Blogspot json - load post content on click

$.ajax({
url: 'https://mailliw88.blogspot.com/feeds/posts/default?start-index=1&max-results=2&alt=json-in-script',
type: 'get',
dataType: "jsonp",
success: function(data) {
var entry = data.feed.entry;
for (var i = 0; i < entry.length; i++) {
postTitle = entry[i].title.$t;
postTitleLink = entry[i].title.$t.replace(/\s+/g, '-').toLowerCase();
items = '<div class="items"><h2>' + postTitle + '</h2></div>';
document.getElementById('showlists').innerHTML += items;
postContent = entry[i].content.$t;
content = '<div class="contentWrap"><div id="close">CLOSE</div><h1>' + postTitle + '</h1><div>' + postContent + '</div></div>';
document.getElementById('showlists').innerHTML += content;
}
}
});
h1 {margin:0}
.contentWrap {border:1px solid red;
padding:5px}
#close {color:red;text-align:right}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='showlists'>
</div>
How to load post content only when clicking the title?
I can use .toggle in jquery but I need to load and "unload" content, not just showing and hiding it. I hope i'm making sense.
My skill is limited to css only, thank you for your help.
You can use display:none to <div class="contentWrap"> and on click of a tag you can show the content using closest() and next().And on click of close again use "display", "none" to hide that content div .
Demo Code :
$.ajax({
url: 'https://mailliw88.blogspot.com/feeds/posts/default?start-index=1&max-results=2&alt=json-in-script',
type: 'get',
dataType: "jsonp",
success: function(data) {
var entry = data.feed.entry;
for (var i = 0; i < entry.length; i++) {
postTitle = entry[i].title.$t;
postTitleLink = entry[i].title.$t.replace(/\s+/g, '-').toLowerCase();
items = '<div class="items"><h2>' + postTitle + '</h2></div>';
document.getElementById('showlists').innerHTML += items;
postContent = entry[i].content.$t;
//added display none and added class = close
content = '<div style="display:none"class="contentWrap"><div class="close">CLOSE</div><h1>' + postTitle + '</h1><div>' + postContent + '</div></div>';
document.getElementById('showlists').innerHTML += content;
}
}
});
//on click of a tag show content
$(document).on("click","a",function(){
//a->closest div->next content->show
$(this).closest(".items").next(".contentWrap").css("display", "block");
})
//onclick of close -> hide again
$(document).on("click",".close",function(){
$(this).closest(".contentWrap").css("display", "none");
})
h1 {margin:0}
.contentWrap {border:1px solid red;
padding:5px}
.close {color:red;text-align:right}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='showlists'>
</div>
Update 1 :
You can assign i value some custom attribute and then use same index value to access post content.In below code snippets i have not send again request to server to load json on click of a instead i have use some variable to store content of data.feed.entry in some variable and then use this to add content .
Demo Code :
var datas = "";
$.ajax({
url: 'https://mailliw88.blogspot.com/feeds/posts/default?start-index=1&max-results=2&alt=json-in-script',
type: 'get',
dataType: "jsonp",
success: function(data) {
//adding entry content in datas to use later
datas = data.feed.entry;
var entry = data.feed.entry;
for (var i = 0; i < entry.length; i++) {
postTitle = entry[i].title.$t;
postTitleLink = entry[i].title.$t.replace(/\s+/g, '-').toLowerCase();
//passing index no i.e : " i " in custom attribute
items = '<div class="items"><h2><a data-val=' + i + ' href="#' + postTitleLink + '">' + postTitle + '</a></h2></div>';
document.getElementById('showlists').innerHTML += items;
}
}
});
$(document).on("click", "a", function() {
$(".contentWrap").remove(); //remove previous div
var ids = $(this).attr('data-val');
console.log(ids)
//getting data that index position got from a tag
postTitle = datas[ids].title.$t;
postTitleLink = datas[ids].title.$t.replace(/\s+/g, '-').toLowerCase();
postContent = datas[ids].content.$t;
content = '<div class="contentWrap"><div class="close">CLOSE</div><h1>' + postTitle + '</h1><div>' + postContent + '</div></div>';
document.getElementById('showlists').innerHTML += content;
})
h1 {margin:0}
.contentWrap {border:1px solid red;
padding:5px}
.close {color:red;text-align:right}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="showlists"></div>

Create a TBODY using Array

I have an array that looks like this.
now here is my code for that
success: function(data) {
data = $.parseJSON(data);
for (i = 0; i < data.length; i++) {
console.log(data[i]);
}
}
the console.log displays it
here is my table
<table id "tblreport" class="mytable" style="width: 900px; margin-right: auto; height: 18px;" border="1">
<thead>
//Table Headers here
</thead>
<tbody id = "body">
</tbody>
</table>
my question is using that array how can I make it as a data in tbody?
This code should be working for you.. Put this in your success callback.
demo
var data = [['a','b','c'],['a','b','c'],['a','b','c'],['a','b','c'],['a','b','c']];
var tb = $("#body");
for(i = 0; i < data.length; i++){
var tr = $("<tr />");
for(var x in data[i]){
var td = $("<td />");
td.html(data[i][x]);
tr.append(td);
}
tb.append(tr);
}
Pretty sure you want this:
for(var i=0,a,tr,l=data.length; i<l; i++){
a = data[i]; tr = document.createElement('tr');
for(var n=0,td,c=a.length; n<c; n++){
td = document.createElement('td'); td.innerHTML = a[n]; tr.appendChild(td);
}
$('#body').append(tr);
}
var tbodyHtml = "";
$.each(data, function( index, value ) {
tbodyHtml += "<tr>";
$.each(value, function( i, v ) {
tbodyHtml += "<td>"+v+"<\td>";
});
tbodyHtml += "</tr>";
});
$("#body").html(tbodyHtml);
success: function(data) {
data = $.parseJSON(data);
//variable to hold all incoming data
var htmlData = ''
for (i = 0; i < data.length; i++) {
console.log(data[i]);
$("#body").append('<tr><td>' + data[i] + '</td><tr>');
}
}
let me know if this works.

how to get the value of the clicked table row?

My question is: how do I get the value of the clicked row and column?
The code I have is this:
JS:
$.ajax({
type: 'POST',
url: url,
data: json,
success: function(data) {
var response_array = JSON.parse(data);
var columns = ['id', 'name', 'email', 'telephone', 'website', 'city'];
var table_html = ' <tr>\n' +
'<th id="id">Id</th>\n' +
'<th id="name">Bedrijfnaam</th>\n' +
'<th id="email">E-mail</th>\n' +
'<th id="telephone">Telefoon</th>\n' +
'<th id="website">Website</th>\n' +
'<th id="city">Plaats</th>\n' +
'</tr>';
for (var i = 0; i < response_array.length; i++) {
//create html table row
table_html += '<tr>';
for (var j = 0; j < columns.length; j++) {
//create html table cell, add class to cells to identify columns
table_html += '<td class="' + columns[j] + '" >' + response_array[i][columns[j]] + '</td>'
}
table_html += '</tr>'
};
$("#posts").append(table_html);
},
error: function (jqXHR, textStatus, errorThrown) { alert('ERROR: ' + errorThrown); }
});
Here is the HTML:
<div class="tabel">
<table id="posts">
</table>
</div>
I have tried the following:
$('#posts').click(function(){
console.log("clicked");
var id = $("tr").find(".id").html();
console.log(id);
});
Sadly this will only give me the id of the first row, no matter where I click.
Any help is appreciated!
Ramon
The below approach should be able to find the ID
$('#post').on('click', function(e){
var id = $(e.target).closest('tr').find(".id").html();
console.log(id)
})
HTML content of clicked row
$('#posts tr').click(function(){
$(this).html();
});
text from clicked td
$('#posts tr td').click(function(){
$(this).text();
});
If you are using ajax and you are redrawing elements, you will not catch em via click function. You will need to add on function:
$(document).on('click','#posts tr td','function(){
$(this).text();
});
You may try to use AddEventListener for your table, it will work for sure.
Like this:
let posts = document.getlementById('posts');
posts.addEventListener('click',(e) => {
// anything you need here, for example:
console.log(e.target);
e.preventDefault();
});
As well - it will be fine not to use same IDs for elements in a grid (like id="id" which you have), it should be different.

Update totals in a table

I have:
$('#createStockOrder').click(function () {
modal('create-stock-order', {}, function () {
var $modal = $(this);
var submitted = false;
var model = [];
$('.glyphicon-plus').click(function () {
var product_id = $('#productSelect option:selected').text(),
size_id = $('#sizeSelect option:selected').text(),
colour_id = $('#colourSelect option:selected').text(),
quantity = $('#quantity').val();
// Get index of the element where all the fields matches
var index = getObjectIndex(model, product_id, size_id, colour_id);
// If object found in the array
if (index !== false) {
// Update the quantity in the same element
model[index].quantity = quantity;
} else {
// Add the element in the array
model.push({
product_id: product_id,
size_id: size_id,
colour_id: colour_id,
quantity: quantity
});
}
printStock(model);
});
var form = document.getElementById('create_sale');
var $form = $(form);
$form.on('submit', function (e) {
e.preventDefault();
if (!submitted) {
submitted = true;
$('#create_sale .btn-primary').addClass('disabled');
var formData = new FormData(form);
qwest.post(form.action, formData)
.then(function (resp) {
$modal.modal('hide');
})
.catch(function (xhr, response, e) {
var html = '';
$.each(response, function (i, v) {
html += '<p>' + v + '</p>';
});
$('#create_sale .alert').html(html).removeClass('hide');
$('#create_sale .btn-primary').removeClass('disabled');
submitted = false;
});
}
})
}, {width: 1000});
});
// Currently the function is Static, but it can be changed to dynamic
// by using nested loop and a flag to store the match status
function getObjectIndex(arr, product_id, size_id, colour_id) {
// Loop over array to find the matching element/object
for (var i = 0; i < arr.length; i++) {
var obj = arr[i];
if (obj.product_id === product_id && obj.size_id === size_id && obj.colour_id === colour_id) {
// When all key-value matches return the array index
return i;
}
}
// When no match found, return false
return false;
}
function printStock(model) {
var html = '';
var total_row_quantity = 0;
var total_row_value = 0;
$.each(model, function (i1, v1) {
html += '<tr>';
$.each(v1, function (i2, v2) {
html += '<td>' + v2 + '</td>';
$('#product_totals tr').each(function(i3, v3){
var product_code = $('td', v3).eq(0).html();
if(product_code == v2) {
total_row_quantity += parseInt(model[i1].quantity);
total_row_value += parseFloat($('td', v3).eq(2).html()*model[i1].quantity);
$('td', v3).eq(1).html(total_row_quantity);
$('td', v3).eq(3).html(accounting.formatMoney(total_row_value, ''));
} else {
total_row_quantity = 0;
total_row_value = 0;
}
})
});
html += '</tr>';
});
$('#stock_order tbody').html(html);
}
The HTML is:
<tbody id="product_totals">
<tr data-id="1">
<td>JW1501</td>
<td class="code-quantity-total">0</td>
<td>79.00</td>
<td class="code-cost-total">0</td>
</tr>
<tr data-id="2">
<td>JW1502</td>
<td class="code-quantity-total">0</td>
<td>99.00</td>
<td class="code-cost-total">0</td>
</tr>
<tr data-id="3">
<td>JW1501-1</td>
<td class="code-quantity-total">0</td>
<td>20.00</td>
<td class="code-cost-total">0</td>
</tr>
<tr data-id="4">
<td>JW1502-2</td>
<td class="code-quantity-total">0</td>
<td>25.00</td>
<td class="code-cost-total">0</td>
</tr>
</tbody>
The list of rows (JW1501, JW1502) is dynamic.
The problem I am having is that if a variant of e.g. JW1502 is added, only the total quantity and value is calculated for that one. Any previous different variants of JW1502 are ignored.
How can I fix this?
Example content of var model:
[
{"product_id":"JW1501","size_id":"70A","colour_id":"小豹纹","quantity":"1"},
{"product_id":"JW1501","size_id":"75B","colour_id":"小豹纹","quantity":"2"},
{"product_id":"JW1502","size_id":"85A","colour_id":"黑色","quantity":"1"}
]
The above for JW1501 would show the incorrect quantity of 2, not 3.
...
$('#product_totals tr').each(function (i3, v3) {
console.log(v1, v2, v3)
...
Outputs:
Object {product_id: "JW1501", size_id: "70A", colour_id: "小豹纹", quantity: "2"}
"JW1501"
<tr data-id=​"1">​<td>​JW1501​</td>​<td class=​"code-quantity-total">​2​</td>​<td>​79.00​</td>​<td class=​"code-cost-total">​158.00​</td>​</tr>​
I have completely changed your printStock function to achieve your goal:
function printStock(model) {
$("#product_totals tr").each(function(){
var id = $("td:eq(0)", this).text().trim();
var price = parseFloat($("td:eq(2)", this).text());
var count = 0;
$.each(model, function(i, item){
if (item.product_id == id) count += (+item.quantity);
});
$("td:eq(1)", this).text(count);
$("td:eq(3)", this).text((count * price).toFixed(2));
});
var rows = $.map(model, function(item){
return [
"<td>" + item.product_id + "</td>",
"<td>" + item.size_id + "</td>",
"<td>" + item.colour_id + "</td>",
"<td>" + item.quantity + "</td>"
].join("");
});
var html = "<tr>" + rows.join("</tr><tr>") + "</tr>";
$('#stock_order tbody').html(html);
}
The main difference is that my code groups items in model by product_id for further counting.
Also refer my fiddle.

Adding JSON data to table in AJAX

Ok i have some search results from input box. I used keyup to get results. Then tis results send to AJAX, and i want to append it to table. My problem is because i use append i will get more than one table headers if i have more results, on the other side i cant use html() because script use for loop so i will only get one result. Can someone help me to solve this problem. I try something like this...
$("#search").keyup(function ()
{
var value = $(this).val(); // varijabla iz input polja
// provera za minimalnu duzinu pretrage
if(value.length > 3)
{
$.ajax({
type: "POST",
url: "crud/searching/",
data: { 'var' : value },
dataType: "json",
success: function(response)
{ alert(response);
$('#warning').html(response.msg);;
$('#result').html('');
for(var i=0; i<response.result.length; i++) //petlja za pristup json
{
$('#result').append('<table class="page-list"><thead><tr><th>#</th><th>Naslov</th><th>Autor</th><th>Cena</th><th>Valuta</th></tr><thead><tbody><tr><td>'+ response.result[i].id +'</td><td>'+ response.result[i].naslov +'</td><td>'+ response.result[i].autor +'</td><td>'+ response.result[i].cena +'</td><td>'+ response.result[i].valuta +'</td></tr> </tbody></table> ' );//dodavanje rezultata u div
}
}
})
}
});
Just create the table once and then append trs in the loop to its tbody
$('#warning').html(response.msg);
if (response.result.length) {
var $table = $('<table class="page-list"><thead><tr><th>#</th><th>Naslov</th><th>Autor</th><th>Cena</th><th>Valuta</th></tr><thead><tbody></tbody></table>').appendTo($('#result').html(''));
var $tbody = $table.find('tbody');
for (var i = 0; i < response.result.length; i++) //petlja za pristup json
{
$tbody.append('<tr><td>' + response.result[i].id + '</td><td>' + response.result[i].naslov + '</td><td>' + response.result[i].autor + '</td><td>' + response.result[i].cena + '</td><td>' + response.result[i].valuta + '</td></tr> '); //dodavanje rezultata u div
}
} else {
$('#result').html('')
}
Try this :
$("#search").keyup(function ()
{
var value = $(this).val(); // varijabla iz input polja
// provera za minimalnu duzinu pretrage
if(value.length > 3)
{
$.ajax({
type: "POST",
url: "crud/searching/",
data: { 'var' : value },
dataType: "json",
success: function(response)
{ alert(response);
$('#warning').html(response.msg);
// Store jQuery objects if used more than once
var $table = $('<table class="page-list">').appendTo($('#result')),
$thead = $('<thead><tr><th>#</th><th>Naslov</th><th>Autor</th><th>Cena</th><th>Valuta</th></tr><thead>').appendTo($table),
$tbody = $('<tbody>').appendTo($table);
innerHTML = '';
for(var i=0; i<response.result.length; i++) //petlja za pristup json
{
innerHTML += '<tr><td>'+ response.result[i].id +'</td><td>'+ response.result[i].naslov +'</td><td>'+ response.result[i].autor +'</td><td>'+ response.result[i].cena +'</td><td>'+ response.result[i].valuta +'</td></tr>' );//dodavanje rezultata u div
}
// Append to HTML only once, when you have the full HTML to append
$tbody.append(innerHTML);
}
})
}
});

Categories

Resources