Create clickable row of a js populated table - javascript

I've created a table using an AJAX request to the database of items in our inventory displaying a picture/part name/price/stock remaining. When the table displays I would like to be able to click on any part of one of the rows and have it link to the item page associated with that item but it won't work.
I've tried the on.click with a static table written right into the html and it worked fine. Also if I direct the on.click script to just the table id instead of the table id and tr i can make the entire table clickable to the first row's href. So it appears that since the tr doesn't really exist in the html the javascript won't find it. Is there a way to get the script to recognize each 's href attribute?
HTML CODE + on.click script:
<html>
<body>
<table id="ctable">
<tbody id="tbody1" class="tbody1">
</tbody>
</table>
<script>
$('#ctable tr').click(function() {
var href = $(this).find("a").attr("href");
if(href) {
window.location = href;
}
});
</script>
</body>
</html>
.JS File CODE that creates table from .php file/mysql database
document.addEventListener('DOMContentLoaded', function() {
$.post('test.php', function(data) {
$("#tbody1").empty();
$.each(JSON.parse(data), function (index, value){
var eachrow = "<tr>" +
"<td class=\"image\">" + '<img src="images/thumbs/' +
value.image + '">' + "</td>" +
"<td>" + '<a href="' + value.link + '">' + value.part + "
</td>" +
"<td>" + value.price + "</td>"
"<td>" + value.stock + "</td>"
"</tr>";
$('#tbody1').append(eachrow);
});
});
}, false);

If you are dynamically adding rows, you need to either restructure your click event to listen from the context of the parent as in:
$("#tbody1").on("click", "tr", function(e) {
});
Assuming #tbody1 is a good place to start since you probably don't want the header row to be clickable. Or, every time you dynamically add rows, since the code is rebuilding the table, you can reattach the click event handlers:
$("#tbody1").empty();
$.each(JSON.parse(data), function (index, value){
var eachrow = "..
$('#tbody1').append(eachrow);
});
// or .on("click", function() { })
$("#tbody1 tr").click(function() { });
If you attach click handler via on, it would be good to then do an off as in:
$("#tbody1").off("click", "tr");
To remove the existing click handlers.

Related

JavaScript JQuery Why buttons' ID are not being correctly referenced

Hello and thank you for your time.
I have one doubt because I am trying to associate the ID I am reading from the Firebase database to the ID which identifies the button. It is important because of this button leads us to the event's modify page so then the event's ID is the one we use to load its data.
However those buttons' IDs look like they are one position forward let's see:
As you can see button 0 has ID Ejemplo nuevo which is the following row's event and so on.
Events:
Code:
Function's code:
function insertPlans() {
setReferences();
$("#title").html("Planes");
resetAllData();
$("#table thead").html("<tr>" +
"<td>ID</td> <td>Capacidad</td> <td>Fecha</td> <td>Descripción</td> <td>Ubicación</td> " +
"<td>Título</td> <td>Organizador</td> <td>Precio</td> <td>Prioridad</td><td>Asistentes</td>" +
"<td>Visibilidad</td></tr>");
dbRef.child('plans').once('value', function (snap) {
snap.forEach(function (planID) {
dbRef.child('plans/' + planID.key.toString()).once('value', function (snap) {
var row = "<tr><td><button id='new-button' class='btn btn-primary' onclick='saveEventName(this.id)'>Modificar evento</button>" + planID.key.toString() + "</td>";
$("#new-button").attr('id', planID.key.toString());
snap.forEach(function (fields) {
row += "<td>" + fields.val() + "</td>";
});
$("#table").find("tbody").append(row + "</tr>");
});
$("#table").find("tbody").append("</tr>");
});
});
}
Also if I do a console log as:
It prints the correct IDs:
Could you help me please?
$(‘#new-button’) is always referencing the previous row because we haven’t attached the row to the document yet.
You can first insert row then you can use the selector to change its id
Thank you for your help digitil. As you said I was editing the previous row because of the current one was not been added to the document.
The solution:
function insertPlans() {
setReferences();
$("#title").html("Planes");
resetAllData();
$("#table thead").html("<tr>" +
"<td>ID</td> <td>Capacidad</td> <td>Fecha</td> <td>Descripción</td> <td>Ubicación</td> " +
"<td>Título</td> <td>Organizador</td> <td>Precio</td> <td>Prioridad</td><td>Asistentes</td>" +
"<td>Visibilidad</td></tr>");
dbRef.child('plans').once('value', function (snap) {
snap.forEach(function (planID) {
dbRef.child('plans/' + planID.key.toString()).once('value', function (snap) {
var row = "<tr><td><button id='new-button' class='btn btn-primary' onclick='saveEventName(this.id)'>Modificar evento</button>" + planID.key.toString() + "</td>";
snap.forEach(function (fields) {
row += "<td>" + fields.val() + "</td>";
});
$("#table").find("tbody").append(row + "</tr>");
$("#new-button").attr('id', planID.key.toString());
});
$("#table").find("tbody").append("</tr>");
});
});
}

how to put a button inside div where data is filled dynamically through $.each function

This should be very simple but i am struggling here.
I have a parent div which have multiple child div. These child div are generated according to $.each() function. Number of times function run, num of div get generated.Now, i want to write a server side function on button click but i am unable to list that button in these child div.
<div class="div1">
<div class="div2">
// this is the button which i cant see in my div2 div
<button type="input">follow</button>
<script type="text/javascript">
$(document).ready(function() {
$.getJSON("/Home/GetUsers", null, function(data) {
$(".div1").html("");
$.each(data, function(i, item) {
var html = "<div class='div2'>";
html += "Name: " + item.UserName + "<br />";
html += item.ArticleCount;
html += "<img src='" + item.UserImage + "'height='20px' width='20px'/>"
html += "</div>";
$(".div1").append(html);
});
});
});
</script>
</div>
</div>
Any type of guidance appreciated.
If you'd like to add a button per child div you can do it in this way:
$(document).ready(function() {
var parent = $(".div1");
$.getJSON("/Home/GetUsers", null, function(data) {
parent.html("");
$.each(data, function(i, item) {
var html = "<div class='div2'>";
html += "Name: " + item.UserName + "<br />";
html += item.ArticleCount;
html += "<img src='" + item.UserImage + "'height='20px' width='20px'/>";
html += "<button type='button' class='newButton'>Click Me!</button>";
html += "</div>";
parent.append(html);
});
});
// In order to ensure that the button click is handled no matter when it was
// added, we can delegate the handler to the parent.
parent.on('click', '.newButton', function(e) {
var button = $(this);
// Handle the individual button click server side call here.
});
});

Create an editable HTML table

I'm trying to follow the prof's example of creating an editable table on double clicking an entry in a HTML table. So my data method looks like this:
function formatData(message) {
var str = "<table border=1>";
for (var i = 0; i < message.length; i++) {
str += "<tr>" + "<td class='editable'>" + message[i].id + "</td>" +
"<td>" + message[i].name + "</td>" +
"<td class='editable'>" + message[i].url + "</td>" +
"<td class='editable'>" + message[i].desc + "</td>" +
"<td>" + "<a href='#' onclick='deleteRequest(this); return false' id='" + message[i].id + "'>delete</a>" + "</td>" +
" + "</td>" + "</tr>";
}
str += "</table>";
return str;
}
I bind a function edit() to the tags whose attributes are of class 'editable.' Then my edit function does:
function edit(elm) {
/* check to see if we are already editing */
if (elm.firstChild.tagName && elm.firstChild.tagName.toUpperCase() == "INPUT")
return;
/* save original content */
var orig = elm.innerHTML;
/* create edit field */
var input = document.createElement("input");
input.type = "text";
input.value = elm.innerHTML;
input.size = 20;
/* convert content to editable */
elm.innerHTML = '';
elm.appendChild(input);
/* position cursor and focus */
if (input.selectionStart)
input.selectionStart = input.selectionEnd = 0;
else
{
var range = input.createTextRange();
range.move("character", 0);
range.select();
}
input.focus();
/* set save trigger callback */
input.onblur = function(){save(elm, input,orig);};
}
I'm confused on how I would save the information and pass it to the web server to update. I need the id, url, and desc to update the web server. Since they double click on a table entry, that just gives me the element at that value, but I don't have the id. Do I change two lines in my formatData to:
"<td class='editable' id='" + message[i].id + "'>" + message[i].url + "</td>" +
"<td class='editable' id='" + message[i].id +"'>" + message[i].desc + "</td>" +
So that way I can ask the webserver for the url and desc with that id value? That seems like a bad way to do it since now two have the same id, but I'm not sure since I'm relatively new to AJAX, HTML, Javascript. Thanks.
Eh, I'll push a bit of help your way.
Basically, from what I gather you're binding a function to each td tag with editable. Well, you can determine the id inside that function.
B/c you can select the parentNode of the current node being edited, and then select the firstChild of that parentNode, so parentNode.firstChild which should be the first td, since remember on each row each of your td's will have a single parent tr. Then you select the firstChild of that td node, which is the text node it contains, and then grab its value, the id. So parentNode.firstChild.firstChild.nodeValue
This might not follow exactly with your code, as you only show parts of it... but this is the gist of the idea. Basically selecting nodes through the DOM and pulling the right one based on the current context.
I'd suggest playing around with it till you get it.
Here's a little bit of sample code for you to think about if you get stuck still. It's meant to be brief.
Basically, each middle column is tagged with the test function on the onfocus event (clicking inside the input). So it's on the input itself, and it pulls the parentNode td, then the next parentNode tr, then the firstChild of tr which is the first td then the firstChild of the first td which is the input on that row, then finally that input's value attribute.
<script>
function test(elem) {
alert( elem.parentNode.parentNode.firstChild.firstChild.value );
}
</script>
<table>
<tr><td><input value="1"/></td><td><input value="stuff" onfocus="test(this)"/></td><td>other stuff</td></tr>
<tr><td><input value="2"/></td><td><input value="stuff3" onfocus="test(this)"/></td><td>other stuff</td></tr>
<tr><td><input value="3"/></td><td><input value="stuff2" onfocus="test(this)"/></td><td>other stuff</td></tr>
</table>

Javascript DOM Trickiness

I'm having a bit of trouble figuring out how to go about self-referencing a table row in Javascript.
Here's the boiled down code:
$( "#listitems tbody" ).append( "<tr onclick=\"editListItem(this)\">" +
"<td>" + id.val() + "</td>" +
"<td>" + title.val() + "</td>" +
"<td>" + description.val() + "</td>" +
"<td>" + TF + "</td>" +
"<td style=\"visibility: hidden;\">" + id.val() + "</td>" +
"</tr>" );
As you can see, I'm setting the contents of this table row and cells dynamically. However, I need to pass a reference to this table row into its onClick function, which calls this Javascript method:
function editListItem(obj) {
var id = obj.cells[4].innerHTML;
var cells = document.getElementById('listitems').rows[id].cells;
DATA[0] = cells[0].innerHTML;
DATA[1] = cells[1].innerHTML;
DATA[2] = cells[2].innerHTML;
DATA[3] = cells[3].innerHTML;
}
In this method, I need to access the value contained inside the 4th "hidden" cell of the table row that was clicked. I normally would just pass the ID variable into the onClick method, but this table's contents can be sorted and rearranged, so the ID variable will not necessarily correspond to the contents of the row.
I've been Googling for the past four hours but can't find any specific examples for this situation; everything I've tried just triggers a Javascript error proclaiming that obj.cells, obj[4], obj.childNodes, etc, does not exist, depending on which one I'm trying.
Does anyone know how you can access the innerHTML of table cell elements inside a table row element by passing "this" into the table row's onClick?
Please let me know if any part of this was confusing, I'm trying to get this done before I leave today or I know I'll forget it all and have to start all over.
how about:
$( "#listitems tbody" ).append(
$('<tr>....</tr>')
.bind('click', function(){
var tds = $(this).find('td'),
id = tds.eq(4).text();
})
);
And if that's not what you meant, let me know. I'm not 100% sure I understand what you're asking for :)
From the looks of your code, your using jQuery so you can easily grab the 5th td by using
$(this).children('td').eq(4)
and then do whatever you want with that jQuery element
checkout jQuery eq selector for more info
Create your <tr> element on its own first, and use proper JS to register the handler rather than embedding the handler in the element's attributes:
var tr = $('<tr>').click(editListItem);
$("#listitems tbody").append(tr);
$(tr).append( ... );
In editListItem, this will automatically apply to the whole row element:
function editListItem(row) {
var cells = $(this).children('td');
var id = $cells.eq(4).text();
var data = [];
data[0] = cells.eq(0).html();
}

JQuery UnBind Works, Attempt to "re" bind does not

I'm working my way through a JQuery Solution and for the most part it works but I"m stumped on seemingly a small detail I know I'm overlooking. Heck, maybe my implementation/approach needs to be reconsidered.
Here's the flow of what works.
1. Click an anchor that adds to a table.
2. Add CSS Class.
3. Disable (Unbind) click on after preappend().
4. From the table of dynamically added record remove table based on ID.
5. delete class that was added in step 2.
6. Bind 'click'
However, although I can bind the click and alert on it. The expected functionality does not allow me to step through the above process again.
The code in question:
HTML SAMPLE:
link that starts the process:
table that holds new records after click of link
<table id="carrier-table"><tbody></tbody></table>
JQUERY and Custom Javascript Function
<script type="text/javascript" id="removeCarrier">
function removeCarrierFromList(obj) {
var i = obj.parentNode.parentNode.rowIndex;
document.getElementById('carrier-table').deleteRow(i);
$('a#' + obj.id).removeClass('delete-carrier-company');
//alert(obj.id); //.hasClass('add-carrier-company').tostring() ); //
$('a#' + obj.id).bind('click', function() {
//alert('User clicked on ' + obj.id);
});
}
</script>
<script type="text/javascript" id="carrierListJS">
$(function() {
// Link
// This adds a carrier to a list
$('.add-carrier-company').click(
function() {
var target = $(this).attr("id");
alert(target);
$("#carrier-table").prepend("<tr id='carrierRow_" + target + "'>" +
"<td><a href='#' id='" + target + "' class='delete' onclick='removeCarrierFromList(this)'> </a></td>" +
"<td class='carrier-list-text'>" + target + " " + $("#name_" + target).val() + "</td>" +
"</tr>");
return false;
});
$('.add-carrier-company').click(
function() { $(this).addClass('delete-carrier-company').unbind('click'); }
);
});
</script>
There were a few issues I noticed with the code. For one thing, as #RussellUresti mentioned, you create two tags with the same ID. For another thing, if you're using ID's in a selector in jQuery, don't include the tag name, just use the id (ie. use $('#id') not $('a#id')) it will be faster (it won't break your code though).
I have created a jsfiddle to answer your question (though I rewrote most of it). :) I think it's what you're looking for.
Here's the code:
Test HTML
aa
bb
cc
10002
10003
<table id="carrier-table" style="border:1px solid #000"><tbody></tbody></table>
JavaScript
function addCarrier() {
var target = $(this).attr("id");
$("#carrier-table").prepend("<tr id='carrierRow_" + target + "'>" + "<td><a href='#' id='a" + target + "' class='delete'> </a></td>" + "<td class='carrier-list-text'>" + target + " " + $("#name_" + target).val() + "</td>" + "</tr>");
$('#a' + target).click(removeCarrierFromList);
$(this).addClass('delete-carrier-company').unbind('click');
return false;
}
function removeCarrierFromList() {
var $this = $(this);
var id = $this.attr('id').replace("a","");
$this.closest('tr').remove();
$('#' + id).removeClass('delete-carrier-company').click(addCarrier);
}
$(function() {
// Link
// This adds a carrier to a list
$('.add-carrier-company').click(addCarrier);
});

Categories

Resources